oc 0.50.55 → 0.50.57-beta.0

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.
Files changed (78) hide show
  1. package/.turbo/turbo-build.log +16 -18
  2. package/.turbo/turbo-lint.log +2 -2
  3. package/.turbo/turbo-test-silent.log +28 -46
  4. package/.turbo/turbo-test.log +17 -1627
  5. package/CHANGELOG.md +14 -0
  6. package/README.md +180 -0
  7. package/dist/cli/commands.d.ts +8 -0
  8. package/dist/cli/commands.js +8 -0
  9. package/dist/cli/facade/dev.d.ts +2 -2
  10. package/dist/cli/facade/registry-migrate-metadata.d.ts +20 -0
  11. package/dist/cli/facade/registry-migrate-metadata.js +105 -0
  12. package/dist/cli/index.js +2 -0
  13. package/dist/components/oc-client/_package/package.json +1 -38
  14. package/dist/components/oc-client/_package/server.js +1 -1
  15. package/dist/components/oc-client/package.json +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/registry/domain/components-cache/index.d.ts +3 -1
  18. package/dist/registry/domain/components-cache/index.js +28 -5
  19. package/dist/registry/domain/components-details.d.ts +3 -1
  20. package/dist/registry/domain/components-details.js +26 -5
  21. package/dist/registry/domain/extract-package.d.ts +3 -2
  22. package/dist/registry/domain/http-server/express-adapter.d.ts +2 -0
  23. package/dist/registry/domain/http-server/express-adapter.js +196 -0
  24. package/dist/registry/domain/http-server/types.d.ts +99 -0
  25. package/dist/registry/domain/http-server/types.js +2 -0
  26. package/dist/registry/domain/metadata-adapter-options.d.ts +6 -0
  27. package/dist/registry/domain/metadata-adapter-options.js +12 -0
  28. package/dist/registry/domain/metadata-index.d.ts +15 -0
  29. package/dist/registry/domain/metadata-index.js +132 -0
  30. package/dist/registry/domain/metadata-migration.d.ts +38 -0
  31. package/dist/registry/domain/metadata-migration.js +128 -0
  32. package/dist/registry/domain/options-sanitiser.js +13 -0
  33. package/dist/registry/domain/repository.d.ts +1 -0
  34. package/dist/registry/domain/repository.js +106 -7
  35. package/dist/registry/domain/server-adapter.d.ts +4 -0
  36. package/dist/registry/domain/server-adapter.js +20 -0
  37. package/dist/registry/domain/validators/registry-configuration.js +21 -0
  38. package/dist/registry/domain/validators/uploaded-package.d.ts +5 -4
  39. package/dist/registry/index.d.ts +3 -3
  40. package/dist/registry/index.js +19 -17
  41. package/dist/registry/middleware/base-url-handler.d.ts +3 -2
  42. package/dist/registry/middleware/base-url-handler.js +3 -4
  43. package/dist/registry/middleware/compression.d.ts +2 -2
  44. package/dist/registry/middleware/compression.js +1 -1
  45. package/dist/registry/middleware/cors.d.ts +3 -2
  46. package/dist/registry/middleware/cors.js +7 -8
  47. package/dist/registry/middleware/discovery-handler.d.ts +3 -2
  48. package/dist/registry/middleware/discovery-handler.js +3 -4
  49. package/dist/registry/middleware/index.d.ts +2 -2
  50. package/dist/registry/middleware/index.js +39 -36
  51. package/dist/registry/router.d.ts +2 -2
  52. package/dist/registry/router.js +33 -27
  53. package/dist/registry/routes/component-info.d.ts +2 -2
  54. package/dist/registry/routes/component-info.js +1 -1
  55. package/dist/registry/routes/component-preview.d.ts +2 -2
  56. package/dist/registry/routes/component.d.ts +2 -2
  57. package/dist/registry/routes/component.js +3 -5
  58. package/dist/registry/routes/components.d.ts +2 -2
  59. package/dist/registry/routes/components.js +3 -1
  60. package/dist/registry/routes/dependencies.d.ts +2 -2
  61. package/dist/registry/routes/helpers/get-component-fallback.d.ts +3 -3
  62. package/dist/registry/routes/helpers/get-component.d.ts +1 -1
  63. package/dist/registry/routes/history.d.ts +2 -2
  64. package/dist/registry/routes/history.js +1 -1
  65. package/dist/registry/routes/index.d.ts +2 -2
  66. package/dist/registry/routes/plugins.d.ts +2 -2
  67. package/dist/registry/routes/publish.d.ts +2 -2
  68. package/dist/registry/routes/static-redirector.d.ts +3 -2
  69. package/dist/registry/routes/static-redirector.js +8 -12
  70. package/dist/registry/routes/validate.d.ts +2 -2
  71. package/dist/resources/index.d.ts +3 -0
  72. package/dist/resources/index.js +3 -0
  73. package/dist/types.d.ts +49 -1
  74. package/package.json +7 -6
  75. package/dist/registry/middleware/file-uploads.d.ts +0 -2
  76. package/dist/registry/middleware/file-uploads.js +0 -23
  77. package/dist/registry/middleware/request-handler.d.ts +0 -2
  78. package/dist/registry/middleware/request-handler.js +0 -30
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = createExpressAdapter;
7
+ const node_http_1 = __importDefault(require("node:http"));
8
+ const cookie_parser_1 = __importDefault(require("cookie-parser"));
9
+ const errorhandler_1 = __importDefault(require("errorhandler"));
10
+ const express_1 = __importDefault(require("express"));
11
+ const morgan_1 = __importDefault(require("morgan"));
12
+ const multer_1 = __importDefault(require("multer"));
13
+ const response_time_1 = __importDefault(require("response-time"));
14
+ const expressMiddleware = Symbol('expressMiddleware');
15
+ const ocResponseSym = Symbol('ocResponse');
16
+ const ocParamsSym = Symbol('ocParams');
17
+ function stream(readable) {
18
+ readable.pipe(this.raw);
19
+ }
20
+ function normaliseParams(raw) {
21
+ const params = { ...raw };
22
+ const splat = raw['splat'];
23
+ if (Array.isArray(splat)) {
24
+ params['splat'] = splat.join('/');
25
+ }
26
+ return params;
27
+ }
28
+ function createExpressAdapter(options) {
29
+ const adapterOptions = options;
30
+ return new ExpressHttpServerAdapter(typeof adapterOptions === 'object' ? adapterOptions.port : adapterOptions);
31
+ }
32
+ class ExpressHttpServerAdapter {
33
+ name = 'express';
34
+ app;
35
+ server;
36
+ serverErrorHandlers = [];
37
+ constructor(port) {
38
+ this.app = (0, express_1.default)();
39
+ if (typeof port !== 'undefined') {
40
+ this.app.set('port', port);
41
+ }
42
+ this.app.set('json spaces', 0);
43
+ this.app.set('etag', 'strong');
44
+ }
45
+ enableBodyParser(opts) {
46
+ this.app.use(express_1.default.json({
47
+ inflate: true,
48
+ limit: opts.limit
49
+ }));
50
+ this.app.use(express_1.default.urlencoded({
51
+ extended: true,
52
+ limit: opts.limit
53
+ }));
54
+ }
55
+ enableCookies() {
56
+ this.app.use((0, cookie_parser_1.default)());
57
+ }
58
+ enableFileUploads(opts) {
59
+ const upload = (0, multer_1.default)({
60
+ limits: {
61
+ fieldSize: 10
62
+ },
63
+ storage: multer_1.default.diskStorage({
64
+ destination: opts.tempDir,
65
+ filename: (_req, file, cb) => cb(null, opts.filename(file.originalname))
66
+ })
67
+ });
68
+ this.app.use(upload.any());
69
+ }
70
+ enableRequestTiming(onDone) {
71
+ this.app.use((0, response_time_1.default)((req, res, time) => {
72
+ onDone(this.toOcRequest(req), this.toOcResponse(res), time);
73
+ }));
74
+ }
75
+ enableLogging(opts) {
76
+ this.app.use((0, morgan_1.default)('dev', {
77
+ skip: (req, res) => opts.skip(this.toOcRequest(req), this.toOcResponse(res))
78
+ }));
79
+ }
80
+ enableErrorHandler() {
81
+ this.app.use((0, errorhandler_1.default)());
82
+ }
83
+ use(handler) {
84
+ this.app.use(this.toExpressHandler(handler, true));
85
+ }
86
+ route(method, path, id, handlers) {
87
+ const setRouteId = (req, _res, next) => {
88
+ req.routeId = id;
89
+ next();
90
+ };
91
+ this.app[method](path, setRouteId, ...handlers.map((handler) => this.toExpressHandler(handler)));
92
+ }
93
+ fromConnect(handler) {
94
+ const wrapped = (req, res) => new Promise((resolve, reject) => {
95
+ handler(req.raw ?? req, res.raw ?? res, (err) => {
96
+ if (err) {
97
+ reject(err);
98
+ }
99
+ else {
100
+ resolve();
101
+ }
102
+ });
103
+ });
104
+ wrapped[expressMiddleware] = handler;
105
+ return wrapped;
106
+ }
107
+ listen(opts, cb) {
108
+ this.server = node_http_1.default.createServer(this.app);
109
+ this.server.timeout = opts.timeout;
110
+ if (opts.keepAliveTimeout) {
111
+ this.server.keepAliveTimeout = opts.keepAliveTimeout;
112
+ }
113
+ for (const handler of this.serverErrorHandlers) {
114
+ this.server.on('error', handler);
115
+ }
116
+ this.server.listen(opts.port, cb);
117
+ }
118
+ onServerError(cb) {
119
+ this.serverErrorHandlers.push(cb);
120
+ this.server?.on('error', cb);
121
+ }
122
+ close(cb) {
123
+ this.server?.close(cb);
124
+ }
125
+ isListening() {
126
+ return !!this.server?.listening;
127
+ }
128
+ native() {
129
+ return this.app;
130
+ }
131
+ httpServer() {
132
+ if (!this.server) {
133
+ throw new Error('HTTP server has not been started');
134
+ }
135
+ return this.server;
136
+ }
137
+ toExpressHandler(handler, continueWhenNotSent = false) {
138
+ const native = handler[expressMiddleware];
139
+ if (native) {
140
+ return native;
141
+ }
142
+ return (req, res, next) => {
143
+ let result;
144
+ try {
145
+ result = handler(this.toOcRequest(req), this.toOcResponse(res));
146
+ }
147
+ catch (err) {
148
+ next(err);
149
+ return;
150
+ }
151
+ if (result && typeof result.then === 'function') {
152
+ result
153
+ .then(() => {
154
+ if (continueWhenNotSent && !res.headersSent) {
155
+ next();
156
+ }
157
+ })
158
+ .catch(next);
159
+ }
160
+ else if (continueWhenNotSent && !res.headersSent) {
161
+ next();
162
+ }
163
+ };
164
+ }
165
+ toOcRequest(req) {
166
+ const memo = req[ocParamsSym];
167
+ const current = (req.params ?? {});
168
+ if (memo && memo.source === current) {
169
+ return req;
170
+ }
171
+ if (!memo) {
172
+ Object.assign(req, {
173
+ raw: req,
174
+ routeId: req.routeId ?? ''
175
+ });
176
+ }
177
+ const normalized = normaliseParams(current);
178
+ Object.assign(req, { params: normalized });
179
+ req[ocParamsSym] = {
180
+ source: normalized
181
+ };
182
+ return req;
183
+ }
184
+ toOcResponse(res) {
185
+ const cached = res[ocResponseSym];
186
+ if (cached) {
187
+ return cached;
188
+ }
189
+ const ocRes = Object.assign(res, {
190
+ raw: res,
191
+ stream
192
+ });
193
+ res[ocResponseSym] = ocRes;
194
+ return ocRes;
195
+ }
196
+ }
@@ -0,0 +1,99 @@
1
+ import type http from 'node:http';
2
+ import type { IncomingHttpHeaders } from 'node:http';
3
+ import type { Config } from '../../../types';
4
+ export interface CookieOptions {
5
+ domain?: string;
6
+ encode?: (value: string) => string;
7
+ expires?: Date;
8
+ httpOnly?: boolean;
9
+ maxAge?: number;
10
+ partitioned?: boolean;
11
+ path?: string;
12
+ priority?: 'low' | 'medium' | 'high';
13
+ sameSite?: boolean | 'lax' | 'strict' | 'none';
14
+ secure?: boolean;
15
+ signed?: boolean;
16
+ }
17
+ export type Method = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete';
18
+ export interface UploadedFile {
19
+ fieldname: string;
20
+ originalname: string;
21
+ encoding: string;
22
+ mimetype: string;
23
+ size: number;
24
+ destination: string;
25
+ filename: string;
26
+ path: string;
27
+ buffer?: Buffer;
28
+ stream?: NodeJS.ReadableStream;
29
+ truncated?: boolean;
30
+ }
31
+ export interface OcRequest {
32
+ method: string;
33
+ url: string;
34
+ path: string;
35
+ originalUrl: string;
36
+ protocol: string;
37
+ secure: boolean;
38
+ ip: string;
39
+ headers: IncomingHttpHeaders;
40
+ params: Record<string, string>;
41
+ query: Record<string, unknown>;
42
+ body: any;
43
+ cookies: Record<string, string>;
44
+ files?: UploadedFile[] | Record<string, UploadedFile[]>;
45
+ user?: string;
46
+ routeId: string;
47
+ get(header: string): string | undefined;
48
+ raw: http.IncomingMessage;
49
+ }
50
+ export interface OcResponse {
51
+ conf: Config;
52
+ errorCode?: string;
53
+ errorDetails?: string;
54
+ statusCode: number;
55
+ status(code: number): this;
56
+ json(body: unknown): void;
57
+ send(body: unknown): void;
58
+ set(field: string | Record<string, string>, value?: string): this;
59
+ header(name: string, value: string): this;
60
+ setHeader(name: string, value: string): this;
61
+ removeHeader(name: string): this;
62
+ type(mime: string): this;
63
+ cookie(name: string, value: string, opts?: CookieOptions): this;
64
+ redirect(url: string): void;
65
+ end(chunk?: unknown): void;
66
+ stream(readable: NodeJS.ReadableStream): void;
67
+ raw: http.ServerResponse;
68
+ }
69
+ export type OcHandler = (req: OcRequest, res: OcResponse) => void | Promise<void>;
70
+ export type ExpressMiddleware = (req: any, res: any, next: (err?: unknown) => void) => void;
71
+ export interface HttpServerAdapter {
72
+ name: string;
73
+ enableBodyParser(opts: {
74
+ limit?: number | string;
75
+ }): void;
76
+ enableCookies(): void;
77
+ enableFileUploads(opts: {
78
+ tempDir: string;
79
+ filename: (originalName: string) => string;
80
+ }): void;
81
+ enableRequestTiming(onDone: (req: OcRequest, res: OcResponse, ms: number) => void): void;
82
+ enableLogging(opts: {
83
+ skip: (req: OcRequest, res: OcResponse) => boolean;
84
+ }): void;
85
+ enableErrorHandler(): void;
86
+ use(handler: OcHandler): void;
87
+ route(method: Method, path: string, id: string, handlers: OcHandler[]): void;
88
+ fromConnect(handler: ExpressMiddleware): OcHandler;
89
+ listen(opts: {
90
+ port: number | string;
91
+ timeout: number;
92
+ keepAliveTimeout?: number;
93
+ }, cb: (err?: Error) => void): void;
94
+ onServerError(cb: (err: Error) => void): void;
95
+ close(cb: (err?: Error) => void): void;
96
+ isListening(): boolean;
97
+ native(): unknown;
98
+ httpServer(): http.Server;
99
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import type { MetadataConfig } from '../../types';
2
+ type MetadataOptionsConfig = {
3
+ metadata?: Pick<MetadataConfig, 'manageSchema' | 'options'>;
4
+ };
5
+ declare const getMetadataAdapterOptions: (conf: MetadataOptionsConfig) => any;
6
+ export default getMetadataAdapterOptions;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const getMetadataAdapterOptions = (conf) => {
4
+ if (typeof conf.metadata?.manageSchema === 'undefined') {
5
+ return conf.metadata?.options;
6
+ }
7
+ return {
8
+ ...(conf.metadata.options || {}),
9
+ manageSchema: conf.metadata.manageSchema
10
+ };
11
+ };
12
+ exports.default = getMetadataAdapterOptions;
@@ -0,0 +1,15 @@
1
+ import type { Component, ComponentRow, ComponentsDetails, ComponentsList, MetadataStore } from '../../types';
2
+ export declare const getComponentsListFromRows: (rows: ComponentRow[]) => ComponentsList;
3
+ export declare const getComponentsDetailsFromRows: (rows: ComponentRow[]) => ComponentsDetails;
4
+ export declare const getComponentRow: (name: string, version: string, component: Component) => ComponentRow;
5
+ export interface MetadataSnapshot {
6
+ componentsList: ComponentsList;
7
+ componentsDetails: ComponentsDetails;
8
+ }
9
+ export interface MetadataIndex {
10
+ get(): MetadataSnapshot | undefined;
11
+ add(row: ComponentRow): MetadataSnapshot;
12
+ refresh(): Promise<MetadataSnapshot>;
13
+ getOrRefresh(): Promise<MetadataSnapshot>;
14
+ }
15
+ export declare const createMetadataIndex: (metadataStore: MetadataStore) => MetadataIndex;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createMetadataIndex = exports.getComponentRow = exports.getComponentsDetailsFromRows = exports.getComponentsListFromRows = void 0;
7
+ const semver_1 = __importDefault(require("semver"));
8
+ // Derive `lastEdit` from the data itself (the most recent publish) rather than
9
+ // the wall-clock time the snapshot happened to be built. This keeps the value
10
+ // semantically meaningful (it only advances when something is actually
11
+ // published) so the poll's `data.lastEdit > cached.lastEdit` guard works and
12
+ // the exported legacy `components.json` reflects the real last edit.
13
+ const getLastEditFromRows = (rows) => rows.reduce((max, row) => (row.publishDate > max ? row.publishDate : max), 0);
14
+ const getComponentsListFromRows = (rows) => {
15
+ const components = {};
16
+ for (const row of rows) {
17
+ const versions = components[row.name] || [];
18
+ versions.push(row.version);
19
+ components[row.name] = versions;
20
+ }
21
+ for (const versions of Object.values(components)) {
22
+ versions.sort(semver_1.default.compare);
23
+ }
24
+ return {
25
+ lastEdit: getLastEditFromRows(rows),
26
+ components
27
+ };
28
+ };
29
+ exports.getComponentsListFromRows = getComponentsListFromRows;
30
+ const getComponentsDetailsFromRows = (rows) => {
31
+ const components = {};
32
+ for (const row of rows) {
33
+ const componentDetails = components[row.name] || {};
34
+ componentDetails[row.version] = { publishDate: row.publishDate };
35
+ if (row.templateSize !== undefined) {
36
+ componentDetails[row.version].templateSize = row.templateSize;
37
+ }
38
+ components[row.name] = componentDetails;
39
+ }
40
+ return {
41
+ lastEdit: getLastEditFromRows(rows),
42
+ components
43
+ };
44
+ };
45
+ exports.getComponentsDetailsFromRows = getComponentsDetailsFromRows;
46
+ const getComponentRow = (name, version, component) => ({
47
+ name,
48
+ version,
49
+ publishDate: component.oc.date || 0,
50
+ templateSize: component.oc.files.template.size
51
+ });
52
+ exports.getComponentRow = getComponentRow;
53
+ const FORCED_REFRESH_INTERVAL_MS = 5 * 60 * 1000;
54
+ const buildSnapshot = (rows) => ({
55
+ componentsList: (0, exports.getComponentsListFromRows)(rows),
56
+ componentsDetails: (0, exports.getComponentsDetailsFromRows)(rows)
57
+ });
58
+ const createMetadataIndex = (metadataStore) => {
59
+ let snapshot;
60
+ let lastChangeToken;
61
+ let lastForcedRefreshAt = 0;
62
+ let localAddGeneration = 0;
63
+ const refresh = async () => {
64
+ const refreshGeneration = localAddGeneration;
65
+ const changeToken = metadataStore.getChangeToken
66
+ ? await metadataStore.getChangeToken()
67
+ : undefined;
68
+ const now = Date.now();
69
+ if (snapshot &&
70
+ changeToken !== undefined &&
71
+ changeToken === lastChangeToken &&
72
+ now - lastForcedRefreshAt < FORCED_REFRESH_INTERVAL_MS) {
73
+ return snapshot;
74
+ }
75
+ const rows = await metadataStore.getAllComponents();
76
+ if (snapshot && refreshGeneration !== localAddGeneration) {
77
+ return snapshot;
78
+ }
79
+ snapshot = buildSnapshot(rows);
80
+ lastChangeToken = changeToken;
81
+ lastForcedRefreshAt = now;
82
+ return snapshot;
83
+ };
84
+ const add = (row) => {
85
+ // No snapshot yet: build one from the single row.
86
+ if (!snapshot) {
87
+ snapshot = buildSnapshot([row]);
88
+ localAddGeneration += 1;
89
+ return snapshot;
90
+ }
91
+ const { name, version } = row;
92
+ const prevList = snapshot.componentsList.components;
93
+ const prevDetails = snapshot.componentsDetails.components;
94
+ // Already present: keep the snapshot unchanged (mirrors the unique-constraint
95
+ // guarantee, so a duplicate publish doesn't disturb the cache).
96
+ if (prevDetails[name]?.[version]) {
97
+ return snapshot;
98
+ }
99
+ // Only the published component is rebuilt; every other component entry is
100
+ // shared by reference, so the cost is O(versions-of-this-component) rather
101
+ // than O(registry). New container objects are produced (rather than mutating
102
+ // in place) so in-flight readers keep a consistent view of the old snapshot.
103
+ const versions = [...(prevList[name] ?? []), version].sort(semver_1.default.compare);
104
+ const detail = {
105
+ ...(prevDetails[name] ?? {}),
106
+ [version]: { publishDate: row.publishDate }
107
+ };
108
+ if (row.templateSize !== undefined) {
109
+ detail[version].templateSize = row.templateSize;
110
+ }
111
+ const lastEdit = Math.max(snapshot.componentsList.lastEdit, row.publishDate);
112
+ snapshot = {
113
+ componentsList: {
114
+ lastEdit,
115
+ components: { ...prevList, [name]: versions }
116
+ },
117
+ componentsDetails: {
118
+ lastEdit,
119
+ components: { ...prevDetails, [name]: detail }
120
+ }
121
+ };
122
+ localAddGeneration += 1;
123
+ return snapshot;
124
+ };
125
+ return {
126
+ get: () => snapshot,
127
+ add,
128
+ refresh,
129
+ getOrRefresh: () => (snapshot ? Promise.resolve(snapshot) : refresh())
130
+ };
131
+ };
132
+ exports.createMetadataIndex = createMetadataIndex;
@@ -0,0 +1,38 @@
1
+ import type { StorageAdapter } from 'oc-storage-adapters-utils';
2
+ import type { ComponentRow, ComponentsDetails, MetadataStore } from '../../types';
3
+ export interface MetadataMigrationResult {
4
+ scanned: number;
5
+ inserted: number;
6
+ skipped: number;
7
+ }
8
+ export interface MetadataExportResult {
9
+ exported: number;
10
+ files: string[];
11
+ }
12
+ export declare const getComponentRowsFromComponentsDetails: (componentsDetails: ComponentsDetails) => ComponentRow[];
13
+ export declare const backfillMetadataRows: (metadataStore: MetadataStore, rows: ComponentRow[]) => Promise<MetadataMigrationResult>;
14
+ export declare const backfillMetadataFromComponentsDetails: (metadataStore: MetadataStore, componentsDetails: ComponentsDetails) => Promise<MetadataMigrationResult>;
15
+ export declare const getComponentRowsFromStorageDirectories: (options: {
16
+ cdn: StorageAdapter;
17
+ componentsDir: string;
18
+ }) => Promise<ComponentRow[]>;
19
+ export declare const backfillMetadataFromStorageDirectories: (options: {
20
+ metadataStore: MetadataStore;
21
+ cdn: StorageAdapter;
22
+ componentsDir: string;
23
+ }) => Promise<MetadataMigrationResult>;
24
+ export declare const reconcileMetadataFromStorage: (options: {
25
+ metadataStore: MetadataStore;
26
+ cdn: StorageAdapter;
27
+ componentsDir: string;
28
+ }) => Promise<MetadataMigrationResult>;
29
+ export declare const exportLegacyMetadataFiles: (options: {
30
+ metadataStore: MetadataStore;
31
+ cdn: StorageAdapter;
32
+ componentsDir: string;
33
+ }) => Promise<MetadataExportResult>;
34
+ export declare const backfillMetadataFromStorageDetails: (options: {
35
+ metadataStore: MetadataStore;
36
+ cdn: StorageAdapter;
37
+ componentsDir: string;
38
+ }) => Promise<MetadataMigrationResult>;
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.backfillMetadataFromStorageDetails = exports.exportLegacyMetadataFiles = exports.reconcileMetadataFromStorage = exports.backfillMetadataFromStorageDirectories = exports.getComponentRowsFromStorageDirectories = exports.backfillMetadataFromComponentsDetails = exports.backfillMetadataRows = exports.getComponentRowsFromComponentsDetails = void 0;
7
+ const oc_metadata_adapters_utils_1 = require("oc-metadata-adapters-utils");
8
+ const pLimit_1 = __importDefault(require("../../utils/pLimit"));
9
+ const metadata_index_1 = require("./metadata-index");
10
+ const isNotFoundError = (err, code) => err === code || err?.code === code;
11
+ const getTemplateSize = (component) => component.oc.files.template.size;
12
+ const getComponentRowsFromComponentsDetails = (componentsDetails) => {
13
+ const rows = [];
14
+ for (const [name, versions] of Object.entries(componentsDetails.components || {})) {
15
+ for (const [version, details] of Object.entries(versions)) {
16
+ const row = {
17
+ name,
18
+ version,
19
+ publishDate: details.publishDate
20
+ };
21
+ if (details.templateSize !== undefined) {
22
+ row.templateSize = details.templateSize;
23
+ }
24
+ rows.push(row);
25
+ }
26
+ }
27
+ return rows;
28
+ };
29
+ exports.getComponentRowsFromComponentsDetails = getComponentRowsFromComponentsDetails;
30
+ const backfillMetadataRows = async (metadataStore, rows) => {
31
+ const result = {
32
+ scanned: rows.length,
33
+ inserted: 0,
34
+ skipped: 0
35
+ };
36
+ const limit = (0, pLimit_1.default)(10);
37
+ await Promise.all(rows.map((row) => limit(async () => {
38
+ try {
39
+ await metadataStore.addVersion(row);
40
+ result.inserted += 1;
41
+ }
42
+ catch (err) {
43
+ if (err?.code === oc_metadata_adapters_utils_1.VERSION_ALREADY_EXISTS ||
44
+ err?.code === oc_metadata_adapters_utils_1.VERSION_PUBLISH_IN_PROGRESS) {
45
+ result.skipped += 1;
46
+ }
47
+ else {
48
+ throw err;
49
+ }
50
+ }
51
+ })));
52
+ return result;
53
+ };
54
+ exports.backfillMetadataRows = backfillMetadataRows;
55
+ const backfillMetadataFromComponentsDetails = async (metadataStore, componentsDetails) => (0, exports.backfillMetadataRows)(metadataStore, (0, exports.getComponentRowsFromComponentsDetails)(componentsDetails));
56
+ exports.backfillMetadataFromComponentsDetails = backfillMetadataFromComponentsDetails;
57
+ const getComponentRowsFromStorageDirectories = async (options) => {
58
+ let components;
59
+ try {
60
+ components = await options.cdn.listSubDirectories(options.componentsDir);
61
+ }
62
+ catch (err) {
63
+ if (isNotFoundError(err, 'dir_not_found')) {
64
+ return [];
65
+ }
66
+ throw err;
67
+ }
68
+ const maxConcurrentRequests = options.cdn.maxConcurrentRequests || 10;
69
+ const componentLimit = (0, pLimit_1.default)(maxConcurrentRequests);
70
+ const packageLimit = (0, pLimit_1.default)(maxConcurrentRequests);
71
+ const rowsByComponent = await Promise.all(components.map((name) => componentLimit(async () => {
72
+ const versions = await options.cdn.listSubDirectories(`${options.componentsDir}/${name}`);
73
+ const rows = await Promise.all(versions.map((version) => packageLimit(async () => {
74
+ try {
75
+ const component = await options.cdn.getJson(`${options.componentsDir}/${name}/${version}/package.json`, true);
76
+ const row = {
77
+ name,
78
+ version,
79
+ publishDate: component.oc.date || 0
80
+ };
81
+ const templateSize = getTemplateSize(component);
82
+ if (templateSize !== undefined) {
83
+ row.templateSize = templateSize;
84
+ }
85
+ return row;
86
+ }
87
+ catch (err) {
88
+ if (isNotFoundError(err, 'file_not_found')) {
89
+ return null;
90
+ }
91
+ throw err;
92
+ }
93
+ })));
94
+ return rows.filter((row) => row !== null);
95
+ })));
96
+ return rowsByComponent.flat();
97
+ };
98
+ exports.getComponentRowsFromStorageDirectories = getComponentRowsFromStorageDirectories;
99
+ const backfillMetadataFromStorageDirectories = async (options) => (0, exports.backfillMetadataRows)(options.metadataStore, await (0, exports.getComponentRowsFromStorageDirectories)(options));
100
+ exports.backfillMetadataFromStorageDirectories = backfillMetadataFromStorageDirectories;
101
+ exports.reconcileMetadataFromStorage = exports.backfillMetadataFromStorageDirectories;
102
+ const exportLegacyMetadataFiles = async (options) => {
103
+ const rows = await options.metadataStore.getAllComponents();
104
+ const componentsListPath = `${options.componentsDir}/components.json`;
105
+ const componentsDetailsPath = `${options.componentsDir}/components-details.json`;
106
+ await Promise.all([
107
+ options.cdn.putFileContent(JSON.stringify((0, metadata_index_1.getComponentsListFromRows)(rows)), componentsListPath, true),
108
+ options.cdn.putFileContent(JSON.stringify((0, metadata_index_1.getComponentsDetailsFromRows)(rows)), componentsDetailsPath, true)
109
+ ]);
110
+ return {
111
+ exported: rows.length,
112
+ files: [componentsListPath, componentsDetailsPath]
113
+ };
114
+ };
115
+ exports.exportLegacyMetadataFiles = exportLegacyMetadataFiles;
116
+ const backfillMetadataFromStorageDetails = async (options) => {
117
+ try {
118
+ const componentsDetails = await options.cdn.getJson(`${options.componentsDir}/components-details.json`, true);
119
+ return (0, exports.backfillMetadataFromComponentsDetails)(options.metadataStore, componentsDetails);
120
+ }
121
+ catch (err) {
122
+ if (isNotFoundError(err, 'file_not_found')) {
123
+ return (0, exports.backfillMetadataFromStorageDirectories)(options);
124
+ }
125
+ throw err;
126
+ }
127
+ };
128
+ exports.backfillMetadataFromStorageDetails = backfillMetadataFromStorageDetails;
@@ -41,6 +41,7 @@ const node_zlib_1 = __importDefault(require("node:zlib"));
41
41
  const oc_client_browser_1 = require("oc-client-browser");
42
42
  const settings_1 = __importDefault(require("../../resources/settings"));
43
43
  const auth = __importStar(require("./authentication"));
44
+ const express_adapter_1 = __importDefault(require("./http-server/express-adapter"));
44
45
  const DEFAULT_NODE_KEEPALIVE_MS = 5000;
45
46
  function optionsSanitiser(input) {
46
47
  const options = { ...input };
@@ -165,6 +166,18 @@ function optionsSanitiser(input) {
165
166
  options.timeout = options.timeout || 1000 * 60 * 2;
166
167
  options.keepAliveTimeout =
167
168
  options.keepAliveTimeout || DEFAULT_NODE_KEEPALIVE_MS;
169
+ if (!options.server) {
170
+ options.server = {
171
+ adapter: express_adapter_1.default,
172
+ options: { port: options.port }
173
+ };
174
+ }
175
+ if (!options.server.adapter) {
176
+ options.server.adapter = express_adapter_1.default;
177
+ }
178
+ if (typeof options.server.options === 'undefined') {
179
+ options.server.options = { port: options.port };
180
+ }
168
181
  if (options.s3) {
169
182
  options.storage = {
170
183
  adapter: require('oc-s3-storage-adapter'),
@@ -28,5 +28,6 @@ export default function repository(conf: Config): {
28
28
  dryRun?: boolean;
29
29
  user?: string;
30
30
  }): Promise<void>;
31
+ close(): Promise<void>;
31
32
  };
32
33
  export type Repository = ReturnType<typeof repository>;