oc 0.50.61 → 0.50.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +5 -5
- package/.turbo/turbo-lint.log +2 -2
- package/.turbo/turbo-test-silent.log +12 -11
- package/.turbo/turbo-test.log +1806 -1750
- package/CHANGELOG.md +13 -0
- package/README.md +16 -0
- package/dist/cli/domain/local.js +7 -4
- package/dist/components/oc-client/_package/package.json +4 -4
- package/dist/components/oc-client/_package/server.js +1 -1
- package/dist/components/oc-client/package.json +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/registry/domain/events-handler.d.ts +2 -5
- package/dist/registry/domain/http-server/express-adapter.d.ts +2 -2
- package/dist/registry/domain/http-server/express-adapter.js +47 -2
- package/dist/registry/domain/http-server/types.d.ts +21 -7
- package/dist/registry/domain/metadata-migration.js +8 -1
- package/dist/registry/domain/options-sanitiser.d.ts +8 -2
- package/dist/registry/domain/options-sanitiser.js +2 -0
- package/dist/registry/domain/plugins-initialiser.js +41 -5
- package/dist/registry/domain/repository.js +100 -19
- package/dist/registry/domain/validators/registry-configuration.d.ts +5 -2
- package/dist/registry/domain/validators/registry-configuration.js +5 -0
- package/dist/registry/index.js +50 -29
- package/dist/registry/middleware/cors.d.ts +4 -0
- package/dist/registry/middleware/cors.js +62 -4
- package/dist/registry/router.js +4 -2
- package/dist/registry/routes/component-info.js +3 -2
- package/dist/registry/routes/component-preview.js +3 -2
- package/dist/registry/routes/component.d.ts +2 -1
- package/dist/registry/routes/component.js +1 -2
- package/dist/registry/routes/components.d.ts +2 -1
- package/dist/registry/routes/components.js +1 -2
- package/dist/registry/routes/helpers/get-component.d.ts +2 -1
- package/dist/registry/routes/helpers/get-component.js +7 -8
- package/dist/registry/routes/index.js +11 -7
- package/dist/resources/index.d.ts +5 -1
- package/dist/resources/index.js +5 -1
- package/dist/types.d.ts +31 -3
- package/dist/utils/bounded-cache.d.ts +10 -0
- package/dist/utils/bounded-cache.js +31 -0
- package/js-library-optimization-playbook.md +1379 -0
- package/package.json +4 -3
- package/tsconfig.types.json +10 -0
package/dist/registry/index.js
CHANGED
|
@@ -48,6 +48,7 @@ const server_adapter_1 = __importDefault(require("./domain/server-adapter"));
|
|
|
48
48
|
const validator = __importStar(require("./domain/validators"));
|
|
49
49
|
const middleware = __importStar(require("./middleware"));
|
|
50
50
|
const router_1 = require("./router");
|
|
51
|
+
const SERVER_ERROR_CODE = 'SERVER_ERROR';
|
|
51
52
|
const warnAboutCallback = () => (0, deprecate_1.default)({
|
|
52
53
|
id: 'registry-lifecycle-callbacks',
|
|
53
54
|
subject: 'Registry lifecycle callbacks',
|
|
@@ -71,13 +72,26 @@ function registry(inputOptions) {
|
|
|
71
72
|
const adapter = middleware.bind((0, server_adapter_1.default)(options.server.adapter, options.server.options), options);
|
|
72
73
|
const app = adapter.native();
|
|
73
74
|
const repository = (0, repository_1.default)(options);
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
const listenAdapter = (serverOptions) => {
|
|
76
|
+
if (adapter.supportsPromiseLifecycle) {
|
|
77
|
+
return adapter.listen(serverOptions);
|
|
78
|
+
}
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
adapter.listen(serverOptions, (err) => {
|
|
81
|
+
if (err) {
|
|
82
|
+
reject(err);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
resolve();
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
const closeAdapter = () => {
|
|
91
|
+
if (adapter.supportsPromiseLifecycle) {
|
|
92
|
+
return adapter.close();
|
|
93
|
+
}
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
81
95
|
adapter.close((err) => {
|
|
82
96
|
if (err) {
|
|
83
97
|
reject(err);
|
|
@@ -87,6 +101,16 @@ function registry(inputOptions) {
|
|
|
87
101
|
}
|
|
88
102
|
});
|
|
89
103
|
});
|
|
104
|
+
};
|
|
105
|
+
const closePromise = () => {
|
|
106
|
+
const closeMetadataStore = () => Promise.resolve(repository.close?.()).catch(() => undefined);
|
|
107
|
+
const closeServer = new Promise((resolve, reject) => {
|
|
108
|
+
if (!adapter.isListening()) {
|
|
109
|
+
reject('not opened');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
closeAdapter().then(resolve, reject);
|
|
113
|
+
});
|
|
90
114
|
return closeServer.finally(closeMetadataStore);
|
|
91
115
|
};
|
|
92
116
|
const close = (callback) => {
|
|
@@ -116,35 +140,32 @@ function registry(inputOptions) {
|
|
|
116
140
|
(0, router_1.create)(adapter, options, repository);
|
|
117
141
|
const componentsInfo = await repository.init();
|
|
118
142
|
await (0, app_start_1.default)(repository, options);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (err) {
|
|
126
|
-
reject(toError(err));
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
events_handler_1.default.fire('start', {});
|
|
130
|
-
if (options.verbosity) {
|
|
131
|
-
ok(`Registry started at port http://localhost:${options.port}${options.prefix}`);
|
|
132
|
-
if (componentsInfo) {
|
|
133
|
-
const componentsNumber = Object.keys(componentsInfo.components).length;
|
|
134
|
-
const componentsReleases = Object.values(componentsInfo.components).reduce((acc, component) => acc + Object.keys(component).length, 0);
|
|
135
|
-
ok(`Registry serving ${componentsNumber} components for a total of ${componentsReleases} releases.`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
resolve({ app, server: adapter.httpServer() });
|
|
139
|
-
});
|
|
143
|
+
const listenPromise = listenAdapter({
|
|
144
|
+
port: options.port,
|
|
145
|
+
timeout: options.timeout,
|
|
146
|
+
keepAliveTimeout: options.keepAliveTimeout
|
|
147
|
+
});
|
|
148
|
+
const serverError = new Promise((_resolve, reject) => {
|
|
140
149
|
adapter.onServerError((error) => {
|
|
141
150
|
events_handler_1.default.fire('error', {
|
|
142
|
-
code:
|
|
151
|
+
code: SERVER_ERROR_CODE,
|
|
143
152
|
message: error?.message ?? String(error)
|
|
144
153
|
});
|
|
145
154
|
reject(toError(error));
|
|
146
155
|
});
|
|
147
156
|
});
|
|
157
|
+
void serverError.catch(() => undefined);
|
|
158
|
+
await Promise.race([listenPromise, serverError]);
|
|
159
|
+
events_handler_1.default.fire('start', {});
|
|
160
|
+
if (options.verbosity) {
|
|
161
|
+
ok(`Registry started at port http://localhost:${options.port}${options.prefix}`);
|
|
162
|
+
if (componentsInfo) {
|
|
163
|
+
const componentsNumber = Object.keys(componentsInfo.components).length;
|
|
164
|
+
const componentsReleases = Object.values(componentsInfo.components).reduce((acc, component) => acc + Object.keys(component).length, 0);
|
|
165
|
+
ok(`Registry serving ${componentsNumber} components for a total of ${componentsReleases} releases.`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return { app, server: adapter.httpServer() };
|
|
148
169
|
}
|
|
149
170
|
catch (err) {
|
|
150
171
|
throw toError(err);
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type { CorsConfig, CorsOptions } from '../../types';
|
|
1
2
|
import type { OcHandler } from '../domain/http-server/types';
|
|
3
|
+
export declare const DEFAULT_CORS_CONFIG: CorsConfig;
|
|
4
|
+
export declare const normaliseCorsConfig: (options?: CorsOptions | null) => CorsConfig;
|
|
5
|
+
export declare const validateCorsConfig: (options: unknown) => string | undefined;
|
|
2
6
|
declare const cors: OcHandler;
|
|
3
7
|
export default cors;
|
|
@@ -1,10 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateCorsConfig = exports.normaliseCorsConfig = exports.DEFAULT_CORS_CONFIG = void 0;
|
|
7
|
+
const resources_1 = __importDefault(require("../../resources"));
|
|
8
|
+
exports.DEFAULT_CORS_CONFIG = {
|
|
9
|
+
origin: '*',
|
|
10
|
+
credentials: true,
|
|
11
|
+
allowedHeaders: 'Origin, X-Requested-With, Content-Type, Accept, traceparent',
|
|
12
|
+
methods: 'GET, OPTIONS, PUT, POST'
|
|
13
|
+
};
|
|
14
|
+
const asHeaderValue = (value, fallback) => (Array.isArray(value) ? value.join(', ') : (value ?? fallback));
|
|
15
|
+
const normaliseCorsConfig = (options) => ({
|
|
16
|
+
origin: options?.origin ?? exports.DEFAULT_CORS_CONFIG.origin,
|
|
17
|
+
credentials: options?.credentials ?? exports.DEFAULT_CORS_CONFIG.credentials,
|
|
18
|
+
allowedHeaders: asHeaderValue(options?.allowedHeaders, exports.DEFAULT_CORS_CONFIG.allowedHeaders),
|
|
19
|
+
methods: asHeaderValue(options?.methods, exports.DEFAULT_CORS_CONFIG.methods)
|
|
20
|
+
});
|
|
21
|
+
exports.normaliseCorsConfig = normaliseCorsConfig;
|
|
22
|
+
const isStringArray = (value) => Array.isArray(value) && value.every((item) => typeof item === 'string');
|
|
23
|
+
const validateCorsConfig = (options) => {
|
|
24
|
+
if (typeof options === 'undefined') {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
if (options === null ||
|
|
28
|
+
typeof options !== 'object' ||
|
|
29
|
+
Array.isArray(options)) {
|
|
30
|
+
return resources_1.default.errors.registry.CONFIGURATION_CORS_MUST_BE_OBJECT;
|
|
31
|
+
}
|
|
32
|
+
const config = options;
|
|
33
|
+
if (typeof config.origin !== 'undefined' &&
|
|
34
|
+
(typeof config.origin !== 'string' || config.origin.length === 0)) {
|
|
35
|
+
return resources_1.default.errors.registry.CONFIGURATION_CORS_ORIGIN_MUST_BE_STRING;
|
|
36
|
+
}
|
|
37
|
+
if (typeof config.credentials !== 'undefined' &&
|
|
38
|
+
typeof config.credentials !== 'boolean') {
|
|
39
|
+
return resources_1.default.errors.registry
|
|
40
|
+
.CONFIGURATION_CORS_CREDENTIALS_MUST_BE_BOOLEAN;
|
|
41
|
+
}
|
|
42
|
+
if (typeof config.allowedHeaders !== 'undefined' &&
|
|
43
|
+
typeof config.allowedHeaders !== 'string' &&
|
|
44
|
+
!isStringArray(config.allowedHeaders)) {
|
|
45
|
+
return resources_1.default.errors.registry
|
|
46
|
+
.CONFIGURATION_CORS_ALLOWED_HEADERS_MUST_BE_STRING_ARRAY;
|
|
47
|
+
}
|
|
48
|
+
if (typeof config.methods !== 'undefined' &&
|
|
49
|
+
typeof config.methods !== 'string' &&
|
|
50
|
+
!isStringArray(config.methods)) {
|
|
51
|
+
return resources_1.default.errors.registry
|
|
52
|
+
.CONFIGURATION_CORS_METHODS_MUST_BE_STRING_ARRAY;
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
};
|
|
56
|
+
exports.validateCorsConfig = validateCorsConfig;
|
|
3
57
|
const cors = (_req, res) => {
|
|
58
|
+
const options = (0, exports.normaliseCorsConfig)(res.conf?.cors);
|
|
4
59
|
res.removeHeader('X-Powered-By');
|
|
5
|
-
res.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
60
|
+
res.removeHeader('Access-Control-Allow-Credentials');
|
|
61
|
+
if (options.credentials) {
|
|
62
|
+
res.set('Access-Control-Allow-Credentials', 'true');
|
|
63
|
+
}
|
|
64
|
+
res.set('Access-Control-Allow-Origin', options.origin);
|
|
65
|
+
res.set('Access-Control-Allow-Headers', options.allowedHeaders);
|
|
66
|
+
res.set('Access-Control-Allow-Methods', options.methods);
|
|
9
67
|
};
|
|
10
68
|
exports.default = cors;
|
package/dist/registry/router.js
CHANGED
|
@@ -11,6 +11,7 @@ const component_info_1 = __importDefault(require("./routes/component-info"));
|
|
|
11
11
|
const component_preview_1 = __importDefault(require("./routes/component-preview"));
|
|
12
12
|
const components_1 = __importDefault(require("./routes/components"));
|
|
13
13
|
const dependencies_1 = __importDefault(require("./routes/dependencies"));
|
|
14
|
+
const get_component_1 = __importDefault(require("./routes/helpers/get-component"));
|
|
14
15
|
const history_1 = __importDefault(require("./routes/history"));
|
|
15
16
|
const plugins_1 = __importDefault(require("./routes/plugins"));
|
|
16
17
|
const publish_1 = __importDefault(require("./routes/publish"));
|
|
@@ -18,9 +19,10 @@ const static_redirector_1 = __importDefault(require("./routes/static-redirector"
|
|
|
18
19
|
const validate_1 = __importDefault(require("./routes/validate"));
|
|
19
20
|
function create(adapter, conf, repository) {
|
|
20
21
|
const route = (method, path, id, ...handlers) => adapter.route(method, path, id, handlers);
|
|
22
|
+
const renderComponent = (0, get_component_1.default)(conf, repository);
|
|
21
23
|
const routes = {
|
|
22
|
-
component: (0, component_1.default)(conf, repository),
|
|
23
|
-
components: (0, components_1.default)(conf, repository),
|
|
24
|
+
component: (0, component_1.default)(conf, repository, renderComponent),
|
|
25
|
+
components: (0, components_1.default)(conf, repository, renderComponent),
|
|
24
26
|
componentInfo: (0, component_info_1.default)(conf, repository),
|
|
25
27
|
componentPreview: (0, component_preview_1.default)(conf, repository),
|
|
26
28
|
index: (0, routes_1.default)(repository),
|
|
@@ -100,9 +100,10 @@ function componentInfo(err, req, res, component, componentDetail) {
|
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
102
|
else if (res.conf.discovery.api) {
|
|
103
|
-
res.status(200).json(
|
|
103
|
+
res.status(200).json({
|
|
104
|
+
...component,
|
|
104
105
|
requestVersion: req.params['componentVersion'] || ''
|
|
105
|
-
})
|
|
106
|
+
});
|
|
106
107
|
}
|
|
107
108
|
else {
|
|
108
109
|
res.status(401);
|
|
@@ -71,9 +71,10 @@ function componentPreview(err, req, res, component, templates) {
|
|
|
71
71
|
}));
|
|
72
72
|
}
|
|
73
73
|
else {
|
|
74
|
-
res.status(200).json(
|
|
74
|
+
res.status(200).json({
|
|
75
|
+
...component,
|
|
75
76
|
requestVersion: req.params['componentVersion'] || ''
|
|
76
|
-
})
|
|
77
|
+
});
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
function componentPreviewRoute(conf, repository) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Config } from '../../types';
|
|
2
2
|
import type { OcHandler } from '../domain/http-server/types';
|
|
3
3
|
import type { Repository } from '../domain/repository';
|
|
4
|
-
|
|
4
|
+
import { type RenderComponent } from './helpers/get-component';
|
|
5
|
+
export default function component(conf: Config, repository: Repository, getComponent?: RenderComponent): OcHandler;
|
|
@@ -42,8 +42,7 @@ const turbo_stream_1 = require("@rdevis/turbo-stream");
|
|
|
42
42
|
const serialize_error_1 = require("serialize-error");
|
|
43
43
|
const resources_1 = __importDefault(require("../../resources"));
|
|
44
44
|
const get_component_1 = __importStar(require("./helpers/get-component"));
|
|
45
|
-
function component(conf, repository) {
|
|
46
|
-
const getComponent = (0, get_component_1.default)(conf, repository);
|
|
45
|
+
function component(conf, repository, getComponent = (0, get_component_1.default)(conf, repository)) {
|
|
47
46
|
return (req, res) => {
|
|
48
47
|
let parameters = req.query;
|
|
49
48
|
if (req.method === 'POST') {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Config } from '../../types';
|
|
2
2
|
import type { OcHandler } from '../domain/http-server/types';
|
|
3
3
|
import type { Repository } from '../domain/repository';
|
|
4
|
-
|
|
4
|
+
import { type RenderComponent } from './helpers/get-component';
|
|
5
|
+
export default function components(conf: Config, repository: Repository, getComponent?: RenderComponent): OcHandler;
|
|
@@ -7,8 +7,7 @@ exports.default = components;
|
|
|
7
7
|
const resources_1 = __importDefault(require("../../resources"));
|
|
8
8
|
const pLimit_1 = __importDefault(require("../../utils/pLimit"));
|
|
9
9
|
const get_component_1 = __importDefault(require("./helpers/get-component"));
|
|
10
|
-
function components(conf, repository) {
|
|
11
|
-
const getComponent = (0, get_component_1.default)(conf, repository);
|
|
10
|
+
function components(conf, repository, getComponent = (0, get_component_1.default)(conf, repository)) {
|
|
12
11
|
const setHeaders = (results, res) => {
|
|
13
12
|
if (results?.length !== 1 || !results[0] || !res.set) {
|
|
14
13
|
return;
|
|
@@ -39,5 +39,6 @@ export interface GetComponentResult {
|
|
|
39
39
|
missingDependencies?: string[];
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
export type RenderComponent = (options: RendererOptions, cb: (result: GetComponentResult) => void) => void;
|
|
42
43
|
export declare const stream: unique symbol;
|
|
43
|
-
export default function getComponent(conf: Config, repository: Repository):
|
|
44
|
+
export default function getComponent(conf: Config, repository: Repository): RenderComponent;
|
|
@@ -42,12 +42,12 @@ const node_crypto_1 = require("node:crypto");
|
|
|
42
42
|
const node_domain_1 = __importDefault(require("node:domain"));
|
|
43
43
|
const node_vm_1 = __importDefault(require("node:vm"));
|
|
44
44
|
const accept_language_parser_1 = __importDefault(require("accept-language-parser"));
|
|
45
|
-
const nice_cache_1 = __importDefault(require("nice-cache"));
|
|
46
45
|
const oc_client_1 = __importDefault(require("oc-client"));
|
|
47
46
|
const oc_empty_response_handler_1 = __importDefault(require("oc-empty-response-handler"));
|
|
48
47
|
const universalify_1 = require("universalify");
|
|
49
48
|
const resources_1 = __importDefault(require("../../../resources"));
|
|
50
49
|
const settings_1 = __importDefault(require("../../../resources/settings"));
|
|
50
|
+
const bounded_cache_1 = __importDefault(require("../../../utils/bounded-cache"));
|
|
51
51
|
const is_template_legacy_1 = __importDefault(require("../../../utils/is-template-legacy"));
|
|
52
52
|
const events_handler_1 = __importDefault(require("../../domain/events-handler"));
|
|
53
53
|
const nested_renderer_1 = __importDefault(require("../../domain/nested-renderer"));
|
|
@@ -61,6 +61,7 @@ const format_error_stack_1 = require("./format-error-stack");
|
|
|
61
61
|
const getComponentFallback = __importStar(require("./get-component-fallback"));
|
|
62
62
|
const get_component_retrieving_info_1 = __importDefault(require("./get-component-retrieving-info"));
|
|
63
63
|
exports.stream = Symbol('stream');
|
|
64
|
+
const MAX_ARTIFACT_CACHE_ENTRIES = 1000;
|
|
64
65
|
const noop = () => { };
|
|
65
66
|
const noopConsole = Object.fromEntries(Object.keys(console).map((key) => [key, noop]));
|
|
66
67
|
const parseTemplatesHeader = (templates) => {
|
|
@@ -118,10 +119,7 @@ function pluginConverter(plugins = {}) {
|
|
|
118
119
|
}
|
|
119
120
|
function getComponent(conf, repository) {
|
|
120
121
|
const client = (0, oc_client_1.default)({ templates: conf.templates });
|
|
121
|
-
const cache = new
|
|
122
|
-
verbose: !!conf.verbosity,
|
|
123
|
-
refreshInterval: conf.refreshInterval
|
|
124
|
-
});
|
|
122
|
+
const cache = new bounded_cache_1.default(MAX_ARTIFACT_CACHE_ENTRIES);
|
|
125
123
|
const convertPlugins = pluginConverter(conf.plugins);
|
|
126
124
|
const customHeadersByConfig = new WeakMap();
|
|
127
125
|
const pluginNamesByConfig = new WeakMap();
|
|
@@ -156,7 +154,7 @@ function getComponent(conf, repository) {
|
|
|
156
154
|
const getEnv = async (component) => {
|
|
157
155
|
const cacheKey = `${component.name}/${component.version}/.env`;
|
|
158
156
|
const cached = cache.get('file-contents', cacheKey);
|
|
159
|
-
if (cached)
|
|
157
|
+
if (cached !== undefined)
|
|
160
158
|
return cached;
|
|
161
159
|
return singleFlight(cacheKey, async () => {
|
|
162
160
|
const env = component.oc.files.env
|
|
@@ -437,7 +435,7 @@ function getComponent(conf, repository) {
|
|
|
437
435
|
});
|
|
438
436
|
});
|
|
439
437
|
};
|
|
440
|
-
if (cached && !conf.hotReloading) {
|
|
438
|
+
if (cached !== undefined && !conf.hotReloading) {
|
|
441
439
|
returnResult(cached);
|
|
442
440
|
}
|
|
443
441
|
else {
|
|
@@ -538,7 +536,7 @@ function getComponent(conf, repository) {
|
|
|
538
536
|
}, executionTimeout * 1000);
|
|
539
537
|
}
|
|
540
538
|
};
|
|
541
|
-
if (cached && !conf.hotReloading) {
|
|
539
|
+
if (cached !== undefined && !conf.hotReloading) {
|
|
542
540
|
domain.on('error', returnComponent);
|
|
543
541
|
try {
|
|
544
542
|
domain.run(() => {
|
|
@@ -589,6 +587,7 @@ function getComponent(conf, repository) {
|
|
|
589
587
|
exports: {},
|
|
590
588
|
console: conf.local ? console : noopConsole,
|
|
591
589
|
setTimeout,
|
|
590
|
+
clearTimeout,
|
|
592
591
|
Buffer,
|
|
593
592
|
Error,
|
|
594
593
|
AbortController: globalThis?.AbortController,
|
|
@@ -16,7 +16,16 @@ const getParsedAuthor = (author) => {
|
|
|
16
16
|
author = author || {};
|
|
17
17
|
return typeof author === 'string' ? (0, parse_author_1.default)(author) : author;
|
|
18
18
|
};
|
|
19
|
-
const mapComponentDetails = (component) =>
|
|
19
|
+
const mapComponentDetails = (component) => ({
|
|
20
|
+
...component,
|
|
21
|
+
author: getParsedAuthor(component.author),
|
|
22
|
+
oc: component.oc.date
|
|
23
|
+
? {
|
|
24
|
+
...component.oc,
|
|
25
|
+
stringifiedDate: (0, date_stringify_1.default)(new Date(component.oc.date))
|
|
26
|
+
}
|
|
27
|
+
: component.oc
|
|
28
|
+
});
|
|
20
29
|
const isHtmlRequest = (headers) => !!headers.accept && headers.accept.indexOf('text/html') >= 0;
|
|
21
30
|
const excludedMeta = ['dependencies', 'devDependencies'];
|
|
22
31
|
function default_1(repository) {
|
|
@@ -37,12 +46,7 @@ function default_1(repository) {
|
|
|
37
46
|
};
|
|
38
47
|
const componentDetails = await Promise.all(componentNames.map((componentName) => repository.getComponent(componentName, undefined)));
|
|
39
48
|
if (isHtmlRequest(req.headers) && res.conf.discovery.ui) {
|
|
40
|
-
const processedComponents = componentDetails.map(
|
|
41
|
-
if (component.oc?.date) {
|
|
42
|
-
component.oc.stringifiedDate = (0, date_stringify_1.default)(new Date(component.oc.date));
|
|
43
|
-
}
|
|
44
|
-
return mapComponentDetails(component);
|
|
45
|
-
});
|
|
49
|
+
const processedComponents = componentDetails.map(mapComponentDetails);
|
|
46
50
|
const totalReleases = componentDetails.reduce((sum, component) => sum + component.allVersions.length, 0);
|
|
47
51
|
const stateCounts = {};
|
|
48
52
|
const componentsList = processedComponents.map((component) => {
|
|
@@ -27,6 +27,11 @@ declare const _default: {
|
|
|
27
27
|
COMPONENT_SET_HEADER_PARAMETERS_NOT_VALID: string;
|
|
28
28
|
COMPONENT_SET_COOKIE_PARAMETERS_NOT_VALID: string;
|
|
29
29
|
CONFIGURATION_DEPENDENCIES_MUST_BE_ARRAY: string;
|
|
30
|
+
CONFIGURATION_CORS_MUST_BE_OBJECT: string;
|
|
31
|
+
CONFIGURATION_CORS_ORIGIN_MUST_BE_STRING: string;
|
|
32
|
+
CONFIGURATION_CORS_CREDENTIALS_MUST_BE_BOOLEAN: string;
|
|
33
|
+
CONFIGURATION_CORS_ALLOWED_HEADERS_MUST_BE_STRING_ARRAY: string;
|
|
34
|
+
CONFIGURATION_CORS_METHODS_MUST_BE_STRING_ARRAY: string;
|
|
30
35
|
CONFIGURATION_EMPTY: string;
|
|
31
36
|
CONFIGURATION_METADATA_NOT_VALID: (adapterType: string) => string;
|
|
32
37
|
CONFIGURATION_METADATA_EXPORT_INTERVAL_NOT_VALID: string;
|
|
@@ -108,7 +113,6 @@ declare const _default: {
|
|
|
108
113
|
initSuccess: (componentName: string, componentPath: string) => string;
|
|
109
114
|
installCompiler: (compiler: string) => string;
|
|
110
115
|
installCompilerSuccess: (template: string, compiler: string, version: string) => string;
|
|
111
|
-
legacyTemplateDeprecationWarning: (legacyType: string, newType: string) => string;
|
|
112
116
|
CHANGES_DETECTED: (file: string) => string;
|
|
113
117
|
CHECKING_DEPENDENCIES: string;
|
|
114
118
|
COMPRESSING: (path: string) => string;
|
package/dist/resources/index.js
CHANGED
|
@@ -76,6 +76,11 @@ exports.default = {
|
|
|
76
76
|
COMPONENT_SET_HEADER_PARAMETERS_NOT_VALID: 'context.setHeader parameters must be strings',
|
|
77
77
|
COMPONENT_SET_COOKIE_PARAMETERS_NOT_VALID: 'context.setCookie parameters are not valid',
|
|
78
78
|
CONFIGURATION_DEPENDENCIES_MUST_BE_ARRAY: 'Registry configuration is not valid: dependencies must be an array',
|
|
79
|
+
CONFIGURATION_CORS_MUST_BE_OBJECT: 'Registry configuration is not valid: cors must be an object',
|
|
80
|
+
CONFIGURATION_CORS_ORIGIN_MUST_BE_STRING: 'Registry configuration is not valid: cors.origin must be a non-empty string',
|
|
81
|
+
CONFIGURATION_CORS_CREDENTIALS_MUST_BE_BOOLEAN: 'Registry configuration is not valid: cors.credentials must be a boolean',
|
|
82
|
+
CONFIGURATION_CORS_ALLOWED_HEADERS_MUST_BE_STRING_ARRAY: 'Registry configuration is not valid: cors.allowedHeaders must be a string or an array of strings',
|
|
83
|
+
CONFIGURATION_CORS_METHODS_MUST_BE_STRING_ARRAY: 'Registry configuration is not valid: cors.methods must be a string or an array of strings',
|
|
79
84
|
CONFIGURATION_EMPTY: 'Registry configuration is empty',
|
|
80
85
|
CONFIGURATION_METADATA_NOT_VALID: (adapterType) => `Registry configuration is not valid: ${adapterType} is not a valid metadata adapter`,
|
|
81
86
|
CONFIGURATION_METADATA_EXPORT_INTERVAL_NOT_VALID: 'Registry configuration is not valid: metadata.exportLegacyFilesInterval must be a positive number',
|
|
@@ -157,7 +162,6 @@ exports.default = {
|
|
|
157
162
|
initSuccess,
|
|
158
163
|
installCompiler: (compiler) => `Installing ${compiler} from npm...`,
|
|
159
164
|
installCompilerSuccess: (template, compiler, version) => `${(0, colors_1.green)('✔')} Installed ${compiler} [${template} v${version}]`,
|
|
160
|
-
legacyTemplateDeprecationWarning: (legacyType, newType) => `Template-type "${legacyType}" has been deprecated and is now replaced by "${newType}"`,
|
|
161
165
|
CHANGES_DETECTED: (file) => `Changes detected on file: ${file}`,
|
|
162
166
|
CHECKING_DEPENDENCIES: 'Ensuring dependencies are loaded...',
|
|
163
167
|
COMPRESSING: (path) => `Compressing -> ${path}`,
|
package/dist/types.d.ts
CHANGED
|
@@ -5,6 +5,27 @@ import type { PackageJson } from 'type-fest';
|
|
|
5
5
|
import type { HttpServerAdapterFactory, HttpServerAdapterOptions } from './registry/domain/http-server/types';
|
|
6
6
|
export type { ComponentRow, MetadataStore } from 'oc-metadata-adapters-utils';
|
|
7
7
|
type Middleware = (req: Request, res: Response, next: NextFunction) => void;
|
|
8
|
+
export interface RegistryErrorEvent {
|
|
9
|
+
/**
|
|
10
|
+
* Stable registry error category. Server adapter failures use
|
|
11
|
+
* `SERVER_ERROR`, regardless of the configured adapter.
|
|
12
|
+
*/
|
|
13
|
+
code: string;
|
|
14
|
+
/** The original error message reported by the failing registry operation. */
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
export interface CorsConfig {
|
|
18
|
+
origin: string;
|
|
19
|
+
credentials: boolean;
|
|
20
|
+
allowedHeaders: string;
|
|
21
|
+
methods: string;
|
|
22
|
+
}
|
|
23
|
+
export interface CorsOptions {
|
|
24
|
+
origin?: string;
|
|
25
|
+
credentials?: boolean;
|
|
26
|
+
allowedHeaders?: string | string[];
|
|
27
|
+
methods?: string | string[];
|
|
28
|
+
}
|
|
8
29
|
export interface Author {
|
|
9
30
|
email?: string;
|
|
10
31
|
name?: string;
|
|
@@ -192,6 +213,12 @@ export interface Config<T = any, TServerAdapter extends HttpServerAdapterFactory
|
|
|
192
213
|
* @example "https://components.mycompany.com/"
|
|
193
214
|
*/
|
|
194
215
|
baseUrl: string;
|
|
216
|
+
/**
|
|
217
|
+
* CORS response headers sent by the registry.
|
|
218
|
+
*
|
|
219
|
+
* @default Existing registry CORS headers
|
|
220
|
+
*/
|
|
221
|
+
cors?: CorsConfig;
|
|
195
222
|
/**
|
|
196
223
|
* Pre-compiled version of the `oc-client` library generated automatically
|
|
197
224
|
* at runtime when `compileClient` is enabled (default).
|
|
@@ -486,12 +513,13 @@ export interface Template {
|
|
|
486
513
|
getInfo: () => TemplateInfo;
|
|
487
514
|
render: (options: any, cb: (err: Error | null, data: string) => void) => void;
|
|
488
515
|
}
|
|
516
|
+
export type PluginRegistration<T = any> = (options: T, dependencies: any, next: (error?: Error) => void) => void | Promise<void>;
|
|
489
517
|
interface BasePLugin<T = any> {
|
|
490
518
|
description?: string;
|
|
491
519
|
name: string;
|
|
492
520
|
options?: T;
|
|
493
521
|
register: {
|
|
494
|
-
register:
|
|
522
|
+
register: PluginRegistration<T>;
|
|
495
523
|
dependencies?: string[];
|
|
496
524
|
};
|
|
497
525
|
}
|
|
@@ -515,7 +543,7 @@ export type Plugin<T = any> = BasePLugin<T> & ({
|
|
|
515
543
|
*/
|
|
516
544
|
context?: false | undefined;
|
|
517
545
|
register: {
|
|
518
|
-
register:
|
|
546
|
+
register: PluginRegistration<T>;
|
|
519
547
|
execute: (...args: any[]) => any;
|
|
520
548
|
dependencies?: string[];
|
|
521
549
|
};
|
|
@@ -534,7 +562,7 @@ export type Plugin<T = any> = BasePLugin<T> & ({
|
|
|
534
562
|
*/
|
|
535
563
|
context: true;
|
|
536
564
|
register: {
|
|
537
|
-
register:
|
|
565
|
+
register: PluginRegistration<T>;
|
|
538
566
|
execute: (context: PluginContext) => (params: any) => any;
|
|
539
567
|
dependencies?: string[];
|
|
540
568
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default class BoundedCache {
|
|
2
|
+
private readonly cache;
|
|
3
|
+
constructor(maxEntries: number);
|
|
4
|
+
get<T>(namespace: string, key: string): T | undefined;
|
|
5
|
+
set<T>(namespace: string, key: string, value: T): void;
|
|
6
|
+
delete(namespace: string, key: string): boolean;
|
|
7
|
+
clear(): void;
|
|
8
|
+
get size(): number;
|
|
9
|
+
private toKey;
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const lru_cache_1 = require("lru-cache");
|
|
4
|
+
class BoundedCache {
|
|
5
|
+
cache;
|
|
6
|
+
constructor(maxEntries) {
|
|
7
|
+
if (!Number.isInteger(maxEntries) || maxEntries <= 0) {
|
|
8
|
+
throw new Error('Cache capacity must be a positive integer');
|
|
9
|
+
}
|
|
10
|
+
this.cache = new lru_cache_1.LRUCache({ max: maxEntries });
|
|
11
|
+
}
|
|
12
|
+
get(namespace, key) {
|
|
13
|
+
return this.cache.get(this.toKey(namespace, key));
|
|
14
|
+
}
|
|
15
|
+
set(namespace, key, value) {
|
|
16
|
+
this.cache.set(this.toKey(namespace, key), value);
|
|
17
|
+
}
|
|
18
|
+
delete(namespace, key) {
|
|
19
|
+
return this.cache.delete(this.toKey(namespace, key));
|
|
20
|
+
}
|
|
21
|
+
clear() {
|
|
22
|
+
this.cache.clear();
|
|
23
|
+
}
|
|
24
|
+
get size() {
|
|
25
|
+
return this.cache.size;
|
|
26
|
+
}
|
|
27
|
+
toKey(namespace, key) {
|
|
28
|
+
return JSON.stringify([namespace, key]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = BoundedCache;
|