oc 0.50.57 → 0.50.59

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 (64) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/.turbo/turbo-test-silent.log +7 -7
  3. package/.turbo/turbo-test.log +1750 -1748
  4. package/CHANGELOG.md +20 -0
  5. package/dist/cli/facade/dev.d.ts +2 -140
  6. package/dist/components/oc-client/_package/package.json +4 -4
  7. package/dist/components/oc-client/_package/server.js +1 -1
  8. package/dist/components/oc-client/package.json +1 -1
  9. package/dist/index.d.ts +2 -0
  10. package/dist/registry/domain/events-handler.d.ts +1 -0
  11. package/dist/registry/domain/events-handler.js +3 -0
  12. package/dist/registry/domain/extract-package.d.ts +3 -2
  13. package/dist/registry/domain/http-server/express-adapter.d.ts +3 -0
  14. package/dist/registry/domain/http-server/express-adapter.js +202 -0
  15. package/dist/registry/domain/http-server/types.d.ts +108 -0
  16. package/dist/registry/domain/http-server/types.js +2 -0
  17. package/dist/registry/domain/nested-renderer.js +16 -16
  18. package/dist/registry/domain/options-sanitiser.d.ts +3 -2
  19. package/dist/registry/domain/options-sanitiser.js +13 -0
  20. package/dist/registry/domain/server-adapter.d.ts +4 -0
  21. package/dist/registry/domain/server-adapter.js +20 -0
  22. package/dist/registry/domain/validators/plugins-requirements.d.ts +1 -1
  23. package/dist/registry/domain/validators/plugins-requirements.js +4 -2
  24. package/dist/registry/domain/validators/uploaded-package.d.ts +5 -4
  25. package/dist/registry/domain/version-handler.js +8 -6
  26. package/dist/registry/index.d.ts +10 -68
  27. package/dist/registry/index.js +14 -16
  28. package/dist/registry/middleware/base-url-handler.d.ts +3 -2
  29. package/dist/registry/middleware/base-url-handler.js +3 -4
  30. package/dist/registry/middleware/compression.d.ts +2 -2
  31. package/dist/registry/middleware/compression.js +1 -1
  32. package/dist/registry/middleware/cors.d.ts +3 -2
  33. package/dist/registry/middleware/cors.js +7 -8
  34. package/dist/registry/middleware/discovery-handler.d.ts +3 -2
  35. package/dist/registry/middleware/discovery-handler.js +3 -4
  36. package/dist/registry/middleware/index.d.ts +2 -2
  37. package/dist/registry/middleware/index.js +42 -36
  38. package/dist/registry/router.d.ts +2 -2
  39. package/dist/registry/router.js +33 -27
  40. package/dist/registry/routes/component-info.d.ts +2 -2
  41. package/dist/registry/routes/component-info.js +1 -1
  42. package/dist/registry/routes/component-preview.d.ts +2 -2
  43. package/dist/registry/routes/component.d.ts +2 -2
  44. package/dist/registry/routes/component.js +3 -5
  45. package/dist/registry/routes/components.d.ts +2 -2
  46. package/dist/registry/routes/components.js +23 -22
  47. package/dist/registry/routes/dependencies.d.ts +2 -2
  48. package/dist/registry/routes/helpers/get-component-fallback.d.ts +3 -3
  49. package/dist/registry/routes/helpers/get-component.d.ts +2 -1
  50. package/dist/registry/routes/helpers/get-component.js +121 -62
  51. package/dist/registry/routes/history.d.ts +2 -2
  52. package/dist/registry/routes/history.js +1 -1
  53. package/dist/registry/routes/index.d.ts +2 -2
  54. package/dist/registry/routes/plugins.d.ts +2 -2
  55. package/dist/registry/routes/publish.d.ts +2 -2
  56. package/dist/registry/routes/static-redirector.d.ts +3 -2
  57. package/dist/registry/routes/static-redirector.js +8 -12
  58. package/dist/registry/routes/validate.d.ts +2 -2
  59. package/dist/types.d.ts +9 -1
  60. package/package.json +7 -7
  61. package/dist/registry/middleware/file-uploads.d.ts +0 -2
  62. package/dist/registry/middleware/file-uploads.js +0 -23
  63. package/dist/registry/middleware/request-handler.d.ts +0 -2
  64. package/dist/registry/middleware/request-handler.js +0 -30
@@ -4,8 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = components;
7
- const async_1 = __importDefault(require("async"));
8
7
  const resources_1 = __importDefault(require("../../resources"));
8
+ const pLimit_1 = __importDefault(require("../../utils/pLimit"));
9
9
  const get_component_1 = __importDefault(require("./helpers/get-component"));
10
10
  function components(conf, repository) {
11
11
  const getComponent = (0, get_component_1.default)(conf, repository);
@@ -13,7 +13,9 @@ function components(conf, repository) {
13
13
  if (results?.length !== 1 || !results[0] || !res.set) {
14
14
  return;
15
15
  }
16
- res.set(results[0].headers);
16
+ if (results[0].headers) {
17
+ res.set(results[0].headers);
18
+ }
17
19
  };
18
20
  const setCookies = (results, res) => {
19
21
  if (results?.length !== 1 || !results[0] || !res.cookie) {
@@ -55,7 +57,8 @@ function components(conf, repository) {
55
57
  return returnError(errors.join(', '));
56
58
  }
57
59
  }
58
- async_1.default.map(components, (component, callback) => {
60
+ const limit = (0, pLimit_1.default)(10);
61
+ Promise.all(components.map((component) => limit(() => new Promise((resolve) => {
59
62
  getComponent({
60
63
  conf: res.conf,
61
64
  action: component.action,
@@ -63,31 +66,29 @@ function components(conf, repository) {
63
66
  headers: req.headers,
64
67
  ip: req.ip,
65
68
  omitHref: !!req.body.omitHref,
66
- parameters: { ...req.body.parameters, ...component.parameters },
69
+ parameters: {
70
+ ...req.body.parameters,
71
+ ...component.parameters
72
+ },
67
73
  version: component.version
68
- }, (result) => callback(null, result));
69
- },
70
- // @ts-expect-error
71
- (_err, results) => {
74
+ }, resolve);
75
+ })))).then((results) => {
72
76
  try {
73
77
  setHeaders(results, res);
74
78
  setCookies(results, res);
75
- res.status(200).json(results);
79
+ res
80
+ .status(200)
81
+ .json(results.map((result) => result.response.renderMode && !result.headers
82
+ ? { ...result, headers: {} }
83
+ : result));
76
84
  }
77
85
  catch (e) {
78
- // @ts-expect-error I think this will never reach (how can setHeaders throw?)
79
- if (results.code && results.error) {
80
- // @ts-expect-error
81
- res.status(500).json({ code: results.code, error: results.error });
82
- }
83
- else {
84
- res.status(500).json({
85
- code: 'RENDER_ERROR',
86
- error: resources_1.default.errors.registry.RENDER_ERROR(results
87
- .map((x) => `${x.response.name}@${x.response.version}`)
88
- .join(', '), String(e))
89
- });
90
- }
86
+ res.status(500).json({
87
+ code: 'RENDER_ERROR',
88
+ error: resources_1.default.errors.registry.RENDER_ERROR(results
89
+ .map((x) => `${x.response.name}@${x.response.version}`)
90
+ .join(', '), String(e))
91
+ });
91
92
  }
92
93
  });
93
94
  };
@@ -1,3 +1,3 @@
1
- import type { Request, Response } from 'express';
2
1
  import type { Config } from '../../types';
3
- export default function dependencies(conf: Config): (_req: Request, res: Response) => void;
2
+ import type { OcHandler } from '../domain/http-server/types';
3
+ export default function dependencies(conf: Config): OcHandler;
@@ -1,6 +1,6 @@
1
1
  import type { IncomingHttpHeaders } from 'node:http';
2
- import type { Request, Response } from 'express';
3
2
  import type { Component, Config } from '../../../types';
3
+ import type { OcRequest, OcResponse } from '../../domain/http-server/types';
4
4
  import type { GetComponentResult } from './get-component';
5
5
  type ComponentCallback = (err: {
6
6
  registryError: any;
@@ -11,6 +11,6 @@ export declare function getComponent(fallbackRegistryUrl: string, headers: Incom
11
11
  version: string;
12
12
  parameters: IncomingHttpHeaders;
13
13
  }, callback: (result: GetComponentResult) => void): void;
14
- export declare function getComponentPreview(conf: Config, req: Request, res: Response, registryError: string | null, callback: ComponentCallback): void;
15
- export declare function getComponentInfo(conf: Config, req: Request, res: Response, registryError: string | null, callback: ComponentCallback): void;
14
+ export declare function getComponentPreview(conf: Config, req: OcRequest, res: OcResponse, registryError: string | null, callback: ComponentCallback): void;
15
+ export declare function getComponentInfo(conf: Config, req: OcRequest, res: OcResponse, registryError: string | null, callback: ComponentCallback): void;
16
16
  export {};
@@ -1,6 +1,6 @@
1
1
  import type { IncomingHttpHeaders } from 'node:http';
2
- import type { CookieOptions } from 'express';
3
2
  import type { Config } from '../../../types';
3
+ import type { CookieOptions } from '../../domain/http-server/types';
4
4
  import type { Repository } from '../../domain/repository';
5
5
  export interface RendererOptions {
6
6
  action?: string;
@@ -27,6 +27,7 @@ export interface GetComponentResult {
27
27
  error?: unknown;
28
28
  version?: string;
29
29
  html?: string;
30
+ renderMode?: string;
30
31
  requestVersion?: string;
31
32
  name?: string;
32
33
  details?: {
@@ -123,21 +123,53 @@ function getComponent(conf, repository) {
123
123
  refreshInterval: conf.refreshInterval
124
124
  });
125
125
  const convertPlugins = pluginConverter(conf.plugins);
126
+ const customHeadersByConfig = new WeakMap();
127
+ const pluginNamesByConfig = new WeakMap();
128
+ const getCustomHeadersToSkip = (config) => {
129
+ if (!customHeadersByConfig.has(config)) {
130
+ customHeadersByConfig.set(config, config.customHeadersToSkipOnWeakVersion?.length
131
+ ? new Set(config.customHeadersToSkipOnWeakVersion)
132
+ : undefined);
133
+ }
134
+ return customHeadersByConfig.get(config);
135
+ };
136
+ const getRegistryPluginNames = (config) => {
137
+ let names = pluginNamesByConfig.get(config);
138
+ if (!names) {
139
+ names = new Set(Object.keys(config.plugins || {}));
140
+ pluginNamesByConfig.set(config, names);
141
+ }
142
+ return names;
143
+ };
144
+ const inFlight = new Map();
145
+ const singleFlight = (key, operation) => {
146
+ const pending = inFlight.get(key);
147
+ if (pending) {
148
+ return pending;
149
+ }
150
+ const promise = operation().finally(() => {
151
+ inFlight.delete(key);
152
+ });
153
+ inFlight.set(key, promise);
154
+ return promise;
155
+ };
126
156
  const getEnv = async (component) => {
127
157
  const cacheKey = `${component.name}/${component.version}/.env`;
128
158
  const cached = cache.get('file-contents', cacheKey);
129
159
  if (cached)
130
160
  return cached;
131
- const env = component.oc.files.env
132
- ? await repository.getEnv(component.name, component.version)
133
- : {};
134
- cache.set('file-contents', cacheKey, env);
135
- return env;
161
+ return singleFlight(cacheKey, async () => {
162
+ const env = component.oc.files.env
163
+ ? await repository.getEnv(component.name, component.version)
164
+ : {};
165
+ cache.set('file-contents', cacheKey, env);
166
+ return env;
167
+ });
136
168
  };
137
169
  const renderer = async (options, cb) => {
138
170
  const nestedRenderer = (0, nested_renderer_1.default)(renderer, options.conf);
139
171
  const retrievingInfo = (0, get_component_retrieving_info_1.default)(options);
140
- let responseHeaders = {};
172
+ let responseHeaders;
141
173
  const responseCookies = [];
142
174
  const getLanguage = () => {
143
175
  const paramOverride = !!options.parameters && options.parameters['__ocAcceptLanguage'];
@@ -159,11 +191,8 @@ function getComponent(conf, repository) {
159
191
  return cb(result);
160
192
  };
161
193
  let componentCallbackDone = false;
194
+ let callbackTimeout;
162
195
  const conf = options.conf;
163
- const customHeadersToSkipSet = conf.customHeadersToSkipOnWeakVersion?.length
164
- ? new Set(conf.customHeadersToSkipOnWeakVersion)
165
- : undefined;
166
- const acceptLanguage = getLanguage();
167
196
  const requestedComponent = {
168
197
  name: options.name,
169
198
  version: options.version || '',
@@ -196,7 +225,7 @@ function getComponent(conf, repository) {
196
225
  });
197
226
  }
198
227
  // check component requirements are satisfied by registry
199
- const pluginsCompatibility = validator.validatePluginsRequirements(component.oc.plugins, conf.plugins);
228
+ const pluginsCompatibility = validator.validatePluginsRequirements(component.oc.plugins, getRegistryPluginNames(conf));
200
229
  if (!pluginsCompatibility.isValid) {
201
230
  return callback({
202
231
  status: 501,
@@ -249,7 +278,10 @@ function getComponent(conf, repository) {
249
278
  });
250
279
  }
251
280
  const filterCustomHeaders = (headers, requestedVersion, actualVersion) => {
252
- if (!customHeadersToSkipSet || requestedVersion === actualVersion) {
281
+ const customHeadersToSkipSet = getCustomHeadersToSkip(conf);
282
+ if (!headers ||
283
+ !customHeadersToSkipSet ||
284
+ requestedVersion === actualVersion) {
253
285
  return headers;
254
286
  }
255
287
  let filteredHeaders;
@@ -259,28 +291,32 @@ function getComponent(conf, repository) {
259
291
  filteredHeaders[key] = headers[key];
260
292
  }
261
293
  }
262
- return filteredHeaders || {};
294
+ return filteredHeaders;
263
295
  };
264
296
  const returnComponent = async (err, data) => {
265
297
  if (componentCallbackDone) {
266
298
  return;
267
299
  }
268
300
  componentCallbackDone = true;
301
+ if (callbackTimeout) {
302
+ clearTimeout(callbackTimeout);
303
+ callbackTimeout = undefined;
304
+ }
269
305
  const componentHref = urlBuilder.component({
270
306
  name: component.name,
271
307
  version: requestedComponent.version,
272
308
  parameters: params
273
309
  }, conf.baseUrl);
274
310
  const isUnrendered = options.headers.accept === settings_1.default.registry.acceptUnrenderedHeader;
275
- const isValidClientRequest = options.headers['user-agent'] &&
276
- !!options.headers['user-agent'].match('oc-client-');
277
- const supportedTemplates = options.headers['templates']
278
- ? parseTemplatesHeader(options.headers['templates'])
279
- : [];
280
- const isTemplateSupportedByClient = Boolean(isValidClientRequest &&
281
- options.headers['templates'] &&
282
- (supportedTemplates.includes(component.oc.files.template.type) ||
283
- supportedTemplates.includes(templateType)));
311
+ const isValidClientRequest = String(options.headers['user-agent'] || '').includes('oc-client-');
312
+ const templatesHeader = options.headers['templates'];
313
+ let isTemplateSupportedByClient = false;
314
+ if (isUnrendered && isValidClientRequest && templatesHeader) {
315
+ const supportedTemplates = parseTemplatesHeader(templatesHeader);
316
+ isTemplateSupportedByClient =
317
+ supportedTemplates.includes(component.oc.files.template.type) ||
318
+ supportedTemplates.includes(templateType);
319
+ }
284
320
  let renderMode = options.action ? 'unrendered' : 'rendered';
285
321
  if (isUnrendered) {
286
322
  renderMode = 'unrendered';
@@ -356,7 +392,7 @@ function getComponent(conf, repository) {
356
392
  if (renderMode === 'unrendered') {
357
393
  callback({
358
394
  status: 200,
359
- headers: responseHeaders,
395
+ ...(responseHeaders ? { headers: responseHeaders } : {}),
360
396
  response: Object.assign(response, {
361
397
  data: data,
362
398
  template: {
@@ -396,7 +432,7 @@ function getComponent(conf, repository) {
396
432
  }
397
433
  callback({
398
434
  status: 200,
399
- headers: responseHeaders,
435
+ ...(responseHeaders ? { headers: responseHeaders } : {}),
400
436
  response: Object.assign(response, { html })
401
437
  });
402
438
  });
@@ -405,11 +441,22 @@ function getComponent(conf, repository) {
405
441
  returnResult(cached);
406
442
  }
407
443
  else {
408
- (0, universalify_1.fromPromise)(repository.getCompiledView)(component.name, component.version, (_err, templateText) => {
444
+ const loadTemplate = async () => {
445
+ const templateText = await repository.getCompiledView(component.name, component.version);
409
446
  const template = ocTemplate.getCompiledTemplate(templateText, key);
410
447
  cache.set('file-contents', cacheKey, template);
411
- returnResult(template);
412
- });
448
+ return template;
449
+ };
450
+ const templatePromise = conf.hotReloading
451
+ ? loadTemplate()
452
+ : singleFlight(cacheKey, loadTemplate);
453
+ templatePromise.then(returnResult).catch((error) => callback({
454
+ status: 500,
455
+ response: {
456
+ code: 'INTERNAL_SERVER_ERROR',
457
+ error
458
+ }
459
+ }));
413
460
  }
414
461
  }
415
462
  };
@@ -440,9 +487,13 @@ function getComponent(conf, repository) {
440
487
  const cached = cache.get('file-contents', cacheKey);
441
488
  const domain = node_domain_1.default.create();
442
489
  const setEmptyResponse = oc_empty_response_handler_1.default.contextDecorator(returnComponent);
490
+ let parsedAcceptLanguage;
443
491
  const contextObj = {
444
492
  action: options.action,
445
- acceptLanguage: accept_language_parser_1.default.parse(acceptLanguage),
493
+ get acceptLanguage() {
494
+ parsedAcceptLanguage ??= accept_language_parser_1.default.parse(getLanguage());
495
+ return parsedAcceptLanguage;
496
+ },
446
497
  baseUrl: conf.baseUrl,
447
498
  env: { ...conf.env, ...env },
448
499
  params,
@@ -479,7 +530,7 @@ function getComponent(conf, repository) {
479
530
  const setCallbackTimeout = () => {
480
531
  const executionTimeout = conf.executionTimeout;
481
532
  if (executionTimeout) {
482
- setTimeout(() => {
533
+ callbackTimeout = setTimeout(() => {
483
534
  const message = `timeout (${executionTimeout * 1000}ms)`;
484
535
  returnComponent({ message }, undefined);
485
536
  domain.exit();
@@ -490,8 +541,8 @@ function getComponent(conf, repository) {
490
541
  domain.on('error', returnComponent);
491
542
  try {
492
543
  domain.run(() => {
493
- cached(contextObj, returnComponent);
494
544
  setCallbackTimeout();
545
+ cached(contextObj, returnComponent);
495
546
  });
496
547
  }
497
548
  catch (e) {
@@ -499,17 +550,36 @@ function getComponent(conf, repository) {
499
550
  }
500
551
  }
501
552
  else {
502
- (0, universalify_1.fromPromise)(repository.getDataProvider)(component.name, component.version, (err, dataProvider) => {
503
- if (err) {
553
+ const handleError = (err) => {
554
+ if (err.code === 'DATA_RESOLVING_ERROR') {
504
555
  componentCallbackDone = true;
505
556
  return callback({
506
557
  status: 502,
507
558
  response: {
508
- code: 'DATA_RESOLVING_ERROR',
559
+ code: err.code,
509
560
  error: resources_1.default.errors.registry.RESOLVING_ERROR
510
561
  }
511
562
  });
512
563
  }
564
+ if (err.code === 'DEPENDENCY_MISSING_FROM_REGISTRY') {
565
+ componentCallbackDone = true;
566
+ return callback({
567
+ status: 501,
568
+ response: {
569
+ code: err.code,
570
+ error: resources_1.default.errors.registry.DEPENDENCY_NOT_FOUND(err.missing.join(', ')),
571
+ missingDependencies: err.missing
572
+ }
573
+ });
574
+ }
575
+ returnComponent(err, undefined);
576
+ };
577
+ const loadDataProvider = async () => {
578
+ const dataProvider = await repository
579
+ .getDataProvider(component.name, component.version)
580
+ .catch(() => {
581
+ throw { code: 'DATA_RESOLVING_ERROR', missing: [] };
582
+ });
513
583
  const context = {
514
584
  require: (0, require_wrapper_1.default)(conf.dependencies),
515
585
  module: {
@@ -538,40 +608,29 @@ function getComponent(conf, repository) {
538
608
  }
539
609
  }
540
610
  };
541
- const handleError = (err) => {
542
- if (err.code === 'DEPENDENCY_MISSING_FROM_REGISTRY') {
543
- componentCallbackDone = true;
544
- return callback({
545
- status: 501,
546
- response: {
547
- code: err.code,
548
- error: resources_1.default.errors.registry.DEPENDENCY_NOT_FOUND(err.missing.join(', ')),
549
- missingDependencies: err.missing
550
- }
551
- });
552
- }
553
- returnComponent(err, undefined);
554
- };
555
- const options = conf.local
611
+ const vmOptions = conf.local
556
612
  ? {
557
613
  displayErrors: true,
558
614
  filename: dataProvider.filePath
559
615
  }
560
616
  : {};
561
- try {
562
- node_vm_1.default.runInNewContext(dataProvider.content, context, options);
563
- const processData = context.module.exports['data'] || context.exports['data'];
564
- cache.set('file-contents', cacheKey, processData);
565
- domain.on('error', handleError);
566
- domain.run(() => {
567
- processData(contextObj, returnComponent);
568
- setCallbackTimeout();
569
- });
570
- }
571
- catch (err) {
572
- handleError(err);
573
- }
574
- });
617
+ node_vm_1.default.runInNewContext(dataProvider.content, context, vmOptions);
618
+ const processData = context.module.exports['data'] || context.exports['data'];
619
+ cache.set('file-contents', cacheKey, processData);
620
+ return processData;
621
+ };
622
+ const dataProviderPromise = conf.hotReloading
623
+ ? loadDataProvider()
624
+ : singleFlight(cacheKey, loadDataProvider);
625
+ dataProviderPromise
626
+ .then((processData) => {
627
+ domain.on('error', handleError);
628
+ domain.run(() => {
629
+ setCallbackTimeout();
630
+ processData(contextObj, returnComponent);
631
+ });
632
+ })
633
+ .catch(handleError);
575
634
  }
576
635
  });
577
636
  }
@@ -1,3 +1,3 @@
1
- import type { Request, Response } from 'express';
1
+ import type { OcHandler } from '../domain/http-server/types';
2
2
  import type { Repository } from '../domain/repository';
3
- export default function history(repository: Repository): (_req: Request, res: Response) => Promise<void>;
3
+ export default function history(repository: Repository): OcHandler;
@@ -11,7 +11,7 @@ function history(repository) {
11
11
  if (res.conf.discovery.ui && !res.conf.local) {
12
12
  const details = await repository.getComponentsDetails();
13
13
  const componentsHistory = (0, get_components_history_1.default)(details);
14
- res.setHeader('Cache-Control', 'public, max-age=600');
14
+ res.set('Cache-Control', 'public, max-age=600');
15
15
  res.status(200).json({ componentsHistory });
16
16
  }
17
17
  else {
@@ -1,3 +1,3 @@
1
- import type { Request, Response } from 'express';
1
+ import type { OcHandler } from '../domain/http-server/types';
2
2
  import type { Repository } from '../domain/repository';
3
- export default function (repository: Repository): (req: Request, res: Response) => Promise<void>;
3
+ export default function (repository: Repository): OcHandler;
@@ -1,3 +1,3 @@
1
- import type { Request, Response } from 'express';
2
1
  import type { Config } from '../../types';
3
- export default function plugins(conf: Config): (_req: Request, res: Response) => void;
2
+ import type { OcHandler } from '../domain/http-server/types';
3
+ export default function plugins(conf: Config): OcHandler;
@@ -1,3 +1,3 @@
1
- import type { Request, Response } from 'express';
1
+ import type { OcHandler } from '../domain/http-server/types';
2
2
  import type { Repository } from '../domain/repository';
3
- export default function publish(repository: Repository): (req: Request, res: Response) => Promise<void>;
3
+ export default function publish(repository: Repository): OcHandler;
@@ -1,3 +1,4 @@
1
- import type { Request, Response } from 'express';
1
+ import type { OcHandler } from '../domain/http-server/types';
2
2
  import type { Repository } from '../domain/repository';
3
- export default function staticRedirector(repository: Repository): (req: Request, res: Response) => void;
3
+ export type StaticRedirectorRouteId = 'client' | 'dev-client' | 'client-map' | 'local-static';
4
+ export default function staticRedirector(repository: Repository, routeId: StaticRedirectorRouteId): OcHandler;
@@ -41,13 +41,10 @@ const node_path_1 = __importDefault(require("node:path"));
41
41
  const fs_extra_1 = __importDefault(require("fs-extra"));
42
42
  const storageUtils = __importStar(require("oc-storage-adapters-utils"));
43
43
  const compression_1 = __importDefault(require("../middleware/compression"));
44
- function staticRedirector(repository) {
44
+ function staticRedirector(repository, routeId) {
45
45
  return (req, res) => {
46
46
  let filePath;
47
- const clientPath = `${res.conf.prefix || '/'}oc-client/client.js`;
48
- const devClientPath = `${res.conf.prefix || '/'}oc-client/client.dev.js`;
49
- const clientMapPath = `${res.conf.prefix || '/'}oc-client/oc-client.min.map`;
50
- if (req.route.path === clientPath || req.route.path === devClientPath) {
47
+ if (routeId === 'client' || routeId === 'dev-client') {
51
48
  if (res.conf.local) {
52
49
  if (res.conf.compiledClient) {
53
50
  res.type('application/javascript');
@@ -59,7 +56,7 @@ function staticRedirector(repository) {
59
56
  else {
60
57
  if (res.conf.compiledClient) {
61
58
  res.type('application/javascript');
62
- if (req.route.path === clientPath) {
59
+ if (routeId === 'client') {
63
60
  (0, compression_1.default)({
64
61
  uncompressed: res.conf.compiledClient.code.minified,
65
62
  brotli: res.conf.compiledClient.code.brotli,
@@ -71,11 +68,11 @@ function staticRedirector(repository) {
71
68
  }
72
69
  return;
73
70
  }
74
- res.redirect(repository.getStaticClientPath(req.route.path === devClientPath));
71
+ res.redirect(repository.getStaticClientPath(routeId === 'dev-client'));
75
72
  return;
76
73
  }
77
74
  }
78
- else if (req.route.path === clientMapPath) {
75
+ else if (routeId === 'client-map') {
79
76
  if (res.conf.local) {
80
77
  filePath = node_path_1.default.join(__dirname, '../../components/oc-client/_package/src/oc-client.min.map');
81
78
  }
@@ -90,14 +87,13 @@ function staticRedirector(repository) {
90
87
  }
91
88
  }
92
89
  else if (req.params['componentName'] === 'oc-client') {
93
- filePath = node_path_1.default.join(__dirname, '../../components/oc-client/_package/' +
94
- req.params['splat'].join('/'));
90
+ filePath = node_path_1.default.join(__dirname, '../../components/oc-client/_package/' + req.params['splat']);
95
91
  }
96
92
  else {
97
93
  filePath =
98
94
  node_path_1.default.join(res.conf.path, req.params['componentName']) +
99
95
  '/_package/' +
100
- req.params['splat'].join('/');
96
+ req.params['splat'];
101
97
  }
102
98
  if (!fs_extra_1.default.existsSync(filePath)) {
103
99
  res.errorDetails = `File ${filePath} not found`;
@@ -119,7 +115,7 @@ function staticRedirector(repository) {
119
115
  res.set('Content-Encoding', 'gzip');
120
116
  }
121
117
  fileStream.on('open', () => {
122
- fileStream.pipe(res);
118
+ res.stream(fileStream);
123
119
  });
124
120
  };
125
121
  }
@@ -1,2 +1,2 @@
1
- import type { Request, Response } from 'express';
2
- export default function validate(): (req: Request, res: Response) => Promise<void>;
1
+ import type { OcHandler } from '../domain/http-server/types';
2
+ export default function validate(): OcHandler;
package/dist/types.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { NextFunction, Request, Response } from 'express';
2
2
  import type { MetadataStore as MetadataStoreType } from 'oc-metadata-adapters-utils';
3
3
  import type { StorageAdapter } from 'oc-storage-adapters-utils';
4
4
  import type { PackageJson } from 'type-fest';
5
+ import type { HttpServerAdapterFactory, HttpServerAdapterOptions } from './registry/domain/http-server/types';
5
6
  export type { ComponentRow, MetadataStore } from 'oc-metadata-adapters-utils';
6
7
  type Middleware = (req: Request, res: Response, next: NextFunction) => void;
7
8
  export interface Author {
@@ -179,7 +180,7 @@ export type PublishAuthConfig = {
179
180
  } | ({
180
181
  type: string | Authentication;
181
182
  } & Record<string, any>);
182
- export interface Config<T = any> {
183
+ export interface Config<T = any, TServerAdapter extends HttpServerAdapterFactory = HttpServerAdapterFactory> {
183
184
  /**
184
185
  * Public base URL where the registry is reachable by consumers.
185
186
  *
@@ -420,6 +421,13 @@ export interface Config<T = any> {
420
421
  componentsDir: string;
421
422
  };
422
423
  };
424
+ /**
425
+ * Low-level HTTP server adapter used by the registry.
426
+ */
427
+ server: {
428
+ adapter: TServerAdapter;
429
+ options?: HttpServerAdapterOptions<TServerAdapter>;
430
+ };
423
431
  /**
424
432
  * Directory used by the registry for temporary files.
425
433
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oc",
3
- "version": "0.50.57",
3
+ "version": "0.50.59",
4
4
  "description": "A framework for developing and distributing html components",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,8 +11,8 @@
11
11
  "preview": "bun run preview/uiPreview.ts",
12
12
  "prebuild": "rimraf dist",
13
13
  "build": "npm run lint && tsc && node tasks/build.js",
14
- "test": "npm run build && node tasks/mochaTest.js",
15
- "test-silent": "npm run build && node tasks/mochaTest.js --silent",
14
+ "test": "node tasks/mochaTest.js",
15
+ "test-silent": "node tasks/mochaTest.js --silent",
16
16
  "bench": "node tasks/benchmarks/server-benchmark.js --repetitions=5",
17
17
  "bench:quick": "node tasks/benchmarks/server-benchmark.js --repetitions=3",
18
18
  "bench:update-baseline": "node tasks/benchmarks/server-benchmark.js --repetitions=5 --update-baseline=true",
@@ -95,12 +95,12 @@
95
95
  "multer": "^2.0.2",
96
96
  "nice-cache": "^0.0.5",
97
97
  "oc-client": "^4.0.3",
98
- "oc-client-browser": "2.1.11",
98
+ "oc-client-browser": "^2.1.12",
99
99
  "oc-empty-response-handler": "^1.0.2",
100
100
  "oc-get-unix-utc-timestamp": "^1.0.6",
101
101
  "oc-metadata-adapters-utils": "^0.1.1",
102
- "oc-s3-storage-adapter": "*",
103
- "oc-storage-adapters-utils": "*",
102
+ "oc-s3-storage-adapter": "^2.2.3",
103
+ "oc-storage-adapters-utils": "^2.1.2",
104
104
  "oc-template-es6": "^2.0.0",
105
105
  "oc-template-es6-compiler": "^7.1.4",
106
106
  "oc-template-handlebars": "^6.0.26",
@@ -118,7 +118,7 @@
118
118
  "source-map": "^0.7.6",
119
119
  "targz": "^1.0.1",
120
120
  "try-require": "^1.2.1",
121
- "undici": "^8.4.1",
121
+ "undici": "^8.5.0",
122
122
  "universalify": "^2.0.1",
123
123
  "yargs": "^17.7.2"
124
124
  }
@@ -1,2 +0,0 @@
1
- import type { NextFunction, Request, Response } from 'express';
2
- export default function fileUpload(req: Request, res: Response, next: NextFunction): any;