Skip to content

Commit

Permalink
V4-RC (#423)
Browse files Browse the repository at this point in the history
* chore: add v4-rc to on: CI rules

* feat: allow specifying custom no content statuses

* test: custom empty body statuses

* chore: fix eslint

* fix: pass noContentStatuses where needed

* chore: improve test name

* 🆙 lib

* chore: improve types near Array.concat()

* chore: explicitly handle all cases in statusesContainStatus()

* 🆙 lib

* chore: update docs about new option `noContentStatuses`

* chore: add a TODO about noContentStatusCodes

* chore: update changelogs

* 🆙 lib

* chore: up version to 4.0.0-rc.38

* [v4] Composition engine (#404)

* 🆙 4.0.0-alpha.39

* Fix bad changelog

* fix(composition-engine): incorrect import from `core/status-codes` (#426)

* 🆙 4.0.0-alpha.40

* Publish package as public access

* Use npm publish instead of yarn npm publish

* Add step to build standalone before publish

* Bump version to test CI

---------

Co-authored-by: Mikhail Kormanovskii <[email protected]>
Co-authored-by: Magomed Chemurziev <[email protected]>
Co-authored-by: Magomed Chemurziev <[email protected]>
Co-authored-by: Abdelrahman Aly Abounegm <[email protected]>
Co-authored-by: Abdelrahman Abounegm <[email protected]>
Co-authored-by: kholstinin <[email protected]>
  • Loading branch information
7 people authored Jul 29, 2024
1 parent 6c8fa6d commit 1d8c03f
Show file tree
Hide file tree
Showing 50 changed files with 2,042 additions and 72 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ jobs:

- run: yarn install

- name: Build standalone version
run: yarn build:standalone

- uses: actions/github-script@v7
name: Extract tag
id: extract-tag
Expand All @@ -44,6 +47,6 @@ jobs:
const tag = prerelease[0];
return typeof tag === 'string' ? tag : DEFAULT_TAG;
- run: yarn npm publish --access public --tag "${{ steps.extract-tag.outputs.result }}"
- run: npm publish --access public --tag "${{ steps.extract-tag.outputs.result }}"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: build

on:
push:
branches: [master, v4]
branches: [master, v4, v4-rc]

pull_request:
branches: [master, v4]
branches: [master, v4, v4-rc]

jobs:
linters:
Expand Down
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,33 @@ Changelog
_Note: Gaps between patch versions are faulty, broken or test releases._

## v4.0.0-alpha.38 (2024-07-29)
## v4.0.0-alpha.42 (2024-07-29)

#### :bug: Bug Fix

* Fixed memory leak with singleton providers cache `core/data/modules`

## v4.0.0-alpha.40 (2024-07-02)

#### :bug: Bug Fix

* Fixed an incorrect import from `core/status-codes`. `core/request/engines/composition`

## v4.0.0-alpha.39 (2024-07-01)

#### :rocket: New Feature

* Added a new engine for the request module - `compositionEngine`. `compositionEngine` allows you to solve problems
composition of requests in more complex structures (such as Provider). `core/request/engines/composition`

## v4.0.0-alpha.38 (2024-06-28)

#### :rocket: New Feature

* Added a new option `noContentStatuses`. This option allows to pass custom status code, array or range of status codes
which indicate a no-content response. By default, an array `[...Range(100, 199), 204, 304]` is used, but it may be useful
to override this value if your backend uses different status codes for no-content responses. `core/request`

## v4.0.0-alpha.37 (2024-06-03)

#### :bug: Bug Fix
Expand Down
2 changes: 1 addition & 1 deletion jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/** @type {import('ts-jest').InitialOptionsTsJest} */
export default {
projects: ['<rootDir>'],
testMatch: ['<rootDir>/dist/server/**/*[sS]pec.js', '<rootDir>/src/**/*[sS]pec.ts'],
testMatch: ['<rootDir>/dist/server/**/*[sS]pec.js', '<rootDir>/src/**/*[sS]pec.ts', '<rootDir>/src/**/?(*.)+(spec).ts'],
rootDir: './',
testTimeout: 20000,
testEnvironment: 'node',
Expand Down
2 changes: 1 addition & 1 deletion lib/core/async/modules/base/helpers.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export declare function isAsyncOptions<T extends object = AsyncOptions>(value: u
* @deprecated
* @see isAsyncOptions
*/
export declare const isParams: import("../../../functools").WarnedFn<[value: unknown], boolean>;
export declare const isParams: import("../../../../core/functools").WarnedFn<[value: unknown], boolean>;
7 changes: 0 additions & 7 deletions lib/core/async/modules/base/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,6 @@ export default class Async<CTX extends object = Async<any>> {
* @param [opts] - additional options for the operation
*/
unsuspendAll(opts?: ClearOptions): this;
/**
* Returns a cache object by the specified name
*
* @param name
* @param [promise] - if true, the namespace is marked as promisified
*/
protected resolveTaskName(name: string, promise?: boolean): string;
/**
* Returns a cache object by the specified name
*
Expand Down
1 change: 1 addition & 0 deletions lib/core/data/middlewares/attach-mock/attach-mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async function attachMock(params) {
status: customResponse.status ?? mock.status ?? 200,
responseType: customResponse.responseType ?? mock.responseType ?? opts.responseType,
okStatuses: opts.okStatuses,
noContentStatuses: opts.noContentStatuses,
decoder: mock.decoders === false ? undefined : customResponse.decoders ?? ctx.decoders,
headers: customResponse.headers ?? mock.headers
});
Expand Down
2 changes: 1 addition & 1 deletion lib/core/log/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export * from '../../core/log/config';
* API for logging
* @defaultExport
*/
declare const logger: import("./interface").ExtendedLogger;
declare const logger: import("../../core/log/interface").ExtendedLogger;
export default logger;
2 changes: 1 addition & 1 deletion lib/core/perf/timer/engines/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
*/
export * from '../../../../core/perf/timer/engines/interface';
declare const engines: {
console: import("./interface").PerfTimerEngine;
console: import("../../../../core/perf/timer/engines/interface").PerfTimerEngine;
};
export default engines;
1 change: 1 addition & 0 deletions lib/core/request/engines/fetch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const request = params => {
parent: p.parent,
important: p.important,
okStatuses: p.okStatuses,
noContentStatuses: p.noContentStatuses,
status: res.status,
statusText: res.statusText,
headers: res.headers,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/request/engines/provider/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", {
exports.deniedProviderParams = exports.availableParams = void 0;
const deniedProviderParams = ['socket'];
exports.deniedProviderParams = deniedProviderParams;
const availableParams = ['url', 'method', 'contentType', 'body', 'query', 'headers', 'okStatuses', 'timeout', 'important', 'meta', 'parent'];
const availableParams = ['url', 'method', 'contentType', 'body', 'query', 'headers', 'okStatuses', 'noContentStatuses', 'timeout', 'important', 'meta', 'parent'];
exports.availableParams = availableParams;
1 change: 1 addition & 0 deletions lib/core/request/engines/provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ function createProviderEngine(src, methodsMapping = {}) {
parent: params.parent,
important: providerResponse.important,
okStatuses: providerResponse.okStatuses,
noContentStatuses: providerResponse.noContentStatuses,
status: providerResponse.status,
statusText: providerResponse.statusText,
headers: providerResponse.headers,
Expand Down
5 changes: 3 additions & 2 deletions lib/core/request/engines/provider/interface.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
import type AbortablePromise from '../../../../core/promise/abortable';
import type { Provider, ModelMethod } from '../../../../core/data';
import type { OkStatuses, RequestBody, RequestMethod, RequestQuery } from '../../../../core/request';
import type { Statuses, RequestBody, RequestMethod, RequestQuery } from '../../../../core/request';
/**
* Meta parameters for the engine
*/
Expand All @@ -26,7 +26,8 @@ export interface AvailableOptions {
body?: RequestBody;
timeout?: number;
contentType?: string;
okStatuses?: OkStatuses;
okStatuses?: Statuses;
noContentStatuses?: Statuses;
meta: Meta;
important?: boolean;
parent?: AbortablePromise;
Expand Down
1 change: 1 addition & 0 deletions lib/core/request/engines/xhr/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ const request = params => {
parent: p.parent,
important: p.important,
okStatuses: p.okStatuses,
noContentStatuses: p.noContentStatuses,
status: xhr.status,
statusText: xhr.statusText,
headers: xhr.getAllResponseHeaders(),
Expand Down
1 change: 1 addition & 0 deletions lib/core/request/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import type { CreateRequestOptions, RequestPromise, RequestResolver, RequestFunctionResponse } from '../../core/request/interface';
export * from '../../core/request/helpers';
export * from '../../core/request/interface';
export * from '../../core/request/response/helpers';
export * from '../../core/request/response/interface';
export { globalOpts, cache, pendingCache } from '../../core/request/const';
export { default as RequestError } from '../../core/request/error';
Expand Down
12 changes: 12 additions & 0 deletions lib/core/request/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ Object.keys(_interface).forEach(function (key) {
}
});
});
var _helpers2 = require("../../core/request/response/helpers");
Object.keys(_helpers2).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _helpers2[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _helpers2[key];
}
});
});
var _interface2 = require("../../core/request/response/interface");
Object.keys(_interface2).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
Expand Down
15 changes: 12 additions & 3 deletions lib/core/request/interface.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export declare type CacheType = 'memory' | 'offline';
export declare type RequestQuery = Dictionary | unknown[] | string;
export declare type RequestBody = string | number | boolean | Dictionary | FormData | ArrayBuffer | Blob;
export declare type NormalizedRequestBody = Exclude<RequestBody, number | boolean | Dictionary>;
export declare type OkStatuses = Range<number> | StatusCodes | StatusCodes[];
export declare type Statuses = Range<number> | StatusCodes | StatusCodes[];
export interface GlobalOptions {
api?: Nullable<string>;
meta: Dictionary;
Expand Down Expand Up @@ -204,7 +204,15 @@ export interface CreateRequestOptions<D = unknown> {
*
* @default `new Range(200, 299)`
*/
okStatuses?: OkStatuses;
okStatuses?: Statuses;
/**
* A list of status codes (or a single code) that match response with no content.
* Also, you can pass a range of codes.
*
* @default `[statusCodes.NO_CONTENT, statusCodes.NOT_MODIFIED]
* .concat(new Range<number>(100, 199).toArray(1))`
*/
noContentStatuses?: Statuses;
/**
* Value in milliseconds for a request timeout
*/
Expand Down Expand Up @@ -569,7 +577,8 @@ export interface RequestOptions {
readonly emitter: EventEmitter;
readonly parent: AbortablePromise;
readonly timeout?: number;
readonly okStatuses?: OkStatuses;
readonly okStatuses?: Statuses;
readonly noContentStatuses?: Statuses;
readonly contentType?: string;
readonly responseType?: ResponseType;
readonly forceResponseType?: boolean;
Expand Down
19 changes: 11 additions & 8 deletions lib/core/request/response/const.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,23 @@
*/
import Range from '../../../core/range';
import type { ResponseType } from '../../../core/request';
/**
* Status codes that cannot contain any content according to the HTTP standard
*
* 1xx - https://tools.ietf.org/html/rfc7231#section-6.2
* 204 - https://tools.ietf.org/html/rfc7231#section-6.3.5
* 304 - https://tools.ietf.org/html/rfc7232#section-4.1
*
* TODO: https://github.com/V4Fire/Core/issues/421
*/
export declare const noContentStatusCodes: number[];
export declare const defaultResponseOpts: {
url: string;
redirected: boolean;
status: number;
statusText: string;
okStatuses: Range<200 | 299>;
noContentStatuses: number[];
responseType: ResponseType;
headers: {};
};
/**
* Status codes that cannot contain any content according to the HTTP standard
*
* 1xx - https://tools.ietf.org/html/rfc7231#section-6.2
* 204 - https://tools.ietf.org/html/rfc7231#section-6.3.5
* 304 - https://tools.ietf.org/html/rfc7232#section-4.1
*/
export declare const noContentStatusCodes: number[];
7 changes: 4 additions & 3 deletions lib/core/request/response/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ Object.defineProperty(exports, "__esModule", {
exports.noContentStatusCodes = exports.defaultResponseOpts = void 0;
var _range = _interopRequireDefault(require("../../../core/range"));
var _statusCodes = _interopRequireDefault(require("../../../core/status-codes"));
const noContentStatusCodes = [_statusCodes.default.NO_CONTENT, _statusCodes.default.NOT_MODIFIED].concat(new _range.default(100, 199).toArray(1));
exports.noContentStatusCodes = noContentStatusCodes;
const defaultResponseOpts = {
url: '',
redirected: false,
status: 200,
statusText: 'OK',
okStatuses: new _range.default(200, 299),
noContentStatuses: noContentStatusCodes,
responseType: 'text',
headers: {}
};
exports.defaultResponseOpts = defaultResponseOpts;
const noContentStatusCodes = [_statusCodes.default.NO_CONTENT, _statusCodes.default.NOT_MODIFIED].concat(new _range.default(100, 199).toArray(1));
exports.noContentStatusCodes = noContentStatusCodes;
exports.defaultResponseOpts = defaultResponseOpts;
9 changes: 9 additions & 0 deletions lib/core/request/response/helpers.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { StatusCodes } from '../../../core/status-codes';
import type { Statuses } from '../../../core/request/interface';
/**
* Returns true if specified `statuses` contain specified `statusCode`
*
* @param statuses
* @param statusCode
*/
export declare function statusesContainStatus(statuses: Statuses, statusCode: StatusCodes): boolean;
17 changes: 17 additions & 0 deletions lib/core/request/response/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.statusesContainStatus = statusesContainStatus;
var _range = _interopRequireDefault(require("../../../core/range"));
function statusesContainStatus(statuses, statusCode) {
if (statuses instanceof _range.default) {
return statuses.contains(statusCode);
}
if (Object.isArray(statuses)) {
return statuses.includes(statusCode);
}
return statuses === statusCode;
}
15 changes: 13 additions & 2 deletions lib/core/request/response/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ import { EventEmitter2 as EventEmitter } from 'eventemitter2';
import { Token } from '../../../core/json/stream/parser';
import AbortablePromise from '../../../core/promise/abortable';
import Headers from '../../../core/request/headers';
import type { OkStatuses, RequestResponseChunk, WrappedDecoder, WrappedStreamDecoder } from '../../../core/request/interface';
import type { Statuses, RequestResponseChunk, WrappedDecoder, WrappedStreamDecoder } from '../../../core/request/interface';
import type { ResponseType, ResponseTypeValue, ResponseTypeValueP, ResponseModeType, ResponseOptions, JSONLikeValue } from '../../../core/request/response/interface';
export * from '../../../core/request/headers';
export * from '../../../core/request/response/const';
export * from '../../../core/request/response/interface';
export * from '../../../core/request/response/helpers';
export declare const $$: StrictDictionary<symbol>;
/**
* Class to work with server response data
Expand Down Expand Up @@ -71,11 +72,21 @@ export default class Response<D extends Nullable<string | JSONLikeValue | ArrayB
* (by default it should match range from 200 to 299)
*/
readonly ok: boolean;
/**
* True if the response status matches with no content status codes
* (by default it should match range from 100 to 199, 204 or 304)
*/
readonly hasNoContent: boolean;
/**
* A list of status codes (or a single code) that match successful operation.
* Also, you can pass a range of codes.
*/
readonly okStatuses: OkStatuses;
readonly okStatuses: Statuses;
/**
* A list of status codes (or a single code) that match a response with no content.
* Also, you can pass a range of codes.
*/
readonly noContentStatuses: Statuses;
/**
* Set of response headers
*/
Expand Down
Loading

0 comments on commit 1d8c03f

Please sign in to comment.