oc 0.50.63 → 0.50.64

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.
@@ -52,14 +52,12 @@ const is_template_legacy_1 = __importDefault(require("../../../utils/is-template
52
52
  const events_handler_1 = __importDefault(require("../../domain/events-handler"));
53
53
  const nested_renderer_1 = __importDefault(require("../../domain/nested-renderer"));
54
54
  const require_wrapper_1 = __importDefault(require("../../domain/require-wrapper"));
55
- const sanitiser = __importStar(require("../../domain/sanitiser"));
56
55
  const urlBuilder = __importStar(require("../../domain/url-builder"));
57
56
  const validator = __importStar(require("../../domain/validators"));
58
57
  const validators_1 = require("../../domain/validators");
59
- const apply_default_values_1 = __importDefault(require("./apply-default-values"));
58
+ const component_parameter_processor_1 = require("./component-parameter-processor");
60
59
  const format_error_stack_1 = require("./format-error-stack");
61
60
  const getComponentFallback = __importStar(require("./get-component-fallback"));
62
- const get_component_retrieving_info_1 = __importDefault(require("./get-component-retrieving-info"));
63
61
  exports.stream = Symbol('stream');
64
62
  const MAX_ARTIFACT_CACHE_ENTRIES = 1000;
65
63
  const noop = () => { };
@@ -140,6 +138,24 @@ function getComponent(conf, repository) {
140
138
  return names;
141
139
  };
142
140
  const inFlight = new Map();
141
+ const parameterSchemaCache = new WeakMap();
142
+ const emptyParameterSchema = (0, component_parameter_processor_1.compileParameterSchema)(undefined);
143
+ const getCompiledParameterSchema = (expectedParameters) => {
144
+ if (!expectedParameters || typeof expectedParameters !== 'object') {
145
+ return emptyParameterSchema;
146
+ }
147
+ let compiled = parameterSchemaCache.get(expectedParameters);
148
+ if (compiled) {
149
+ return compiled;
150
+ }
151
+ if (Object.keys(expectedParameters).length === 0) {
152
+ parameterSchemaCache.set(expectedParameters, emptyParameterSchema);
153
+ return emptyParameterSchema;
154
+ }
155
+ compiled = (0, component_parameter_processor_1.compileParameterSchema)(expectedParameters);
156
+ parameterSchemaCache.set(expectedParameters, compiled);
157
+ return compiled;
158
+ };
143
159
  const singleFlight = (key, operation) => {
144
160
  const pending = inFlight.get(key);
145
161
  if (pending) {
@@ -151,41 +167,89 @@ function getComponent(conf, repository) {
151
167
  inFlight.set(key, promise);
152
168
  return promise;
153
169
  };
154
- const getEnv = async (component) => {
170
+ const lookupEnv = (component, cb) => {
155
171
  const cacheKey = `${component.name}/${component.version}/.env`;
156
172
  const cached = cache.get('file-contents', cacheKey);
157
- if (cached !== undefined)
158
- return cached;
159
- return singleFlight(cacheKey, async () => {
173
+ if (cached !== undefined) {
174
+ cb(null, cached);
175
+ return;
176
+ }
177
+ singleFlight(cacheKey, async () => {
160
178
  const env = component.oc.files.env
161
179
  ? await repository.getEnv(component.name, component.version)
162
180
  : {};
163
181
  cache.set('file-contents', cacheKey, env);
164
182
  return env;
165
- });
183
+ }).then((env) => cb(null, env), cb);
166
184
  };
167
- const renderer = async (options, cb) => {
168
- const nestedRenderer = (0, nested_renderer_1.default)(renderer, options.conf);
169
- const retrievingInfo = (0, get_component_retrieving_info_1.default)(options);
185
+ const enrichLocalErrorStack = async (component, err, response) => {
186
+ try {
187
+ const { content } = await repository
188
+ .getDataProvider(component.name, component.version)
189
+ .catch(() => ({ content: null }));
190
+ if (!content || !err.stack || !response.response.details) {
191
+ return;
192
+ }
193
+ const processedStack = await (0, format_error_stack_1.processStackTrace)({
194
+ stackTrace: err.stack,
195
+ code: content
196
+ }).catch(() => null);
197
+ if (!processedStack) {
198
+ return;
199
+ }
200
+ response.response.details.stack = processedStack.stack;
201
+ response.response.details.frame = processedStack.frame;
202
+ console.log(`Error rendering component ${component.name} ${component.version}`);
203
+ console.log(processedStack.stack);
204
+ console.log(processedStack.frame);
205
+ }
206
+ catch {
207
+ // keep the original error stack when local diagnostics fail
208
+ }
209
+ };
210
+ const renderer = (options, cb) => {
211
+ const retrievalStart = process.hrtime.bigint();
212
+ let retrievedHref;
213
+ let retrievedVersion;
214
+ let retrievedRenderMode;
170
215
  let responseHeaders;
171
216
  const responseCookies = [];
172
217
  const getLanguage = () => {
173
218
  const paramOverride = !!options.parameters && options.parameters['__ocAcceptLanguage'];
174
219
  return paramOverride || options.headers['accept-language'];
175
220
  };
221
+ const fireComponentRetrievedEvent = (result) => {
222
+ if (!events_handler_1.default.hasListeners('component-retrieved')) {
223
+ return;
224
+ }
225
+ const eventData = {
226
+ headers: options.headers,
227
+ name: options.name,
228
+ parameters: options.parameters,
229
+ requestVersion: options.version || ''
230
+ };
231
+ if (retrievedHref !== undefined) {
232
+ eventData['href'] = retrievedHref;
233
+ eventData['version'] = retrievedVersion;
234
+ eventData['renderMode'] = retrievedRenderMode;
235
+ }
236
+ if (result.response.error) {
237
+ Object.assign(eventData, result.response);
238
+ }
239
+ eventData['status'] = result.status;
240
+ eventData['duration'] =
241
+ Number(process.hrtime.bigint() - retrievalStart) / 1e3;
242
+ events_handler_1.default.fire('component-retrieved', eventData);
243
+ };
176
244
  const callback = (result) => {
177
245
  if (responseCookies.length > 0 && !result.cookies) {
178
246
  result.cookies = responseCookies;
179
247
  }
180
- if (result.response.error) {
181
- retrievingInfo.extend(result.response);
182
- }
183
- retrievingInfo.extend({ status: result.status });
184
248
  Object.assign(result.response, {
185
249
  name: options.name,
186
250
  requestVersion: options.version || ''
187
251
  });
188
- events_handler_1.default.fire('component-retrieved', retrievingInfo.getData());
252
+ fireComponentRetrievedEvent(result);
189
253
  return cb(result);
190
254
  };
191
255
  let componentCallbackDone = false;
@@ -196,7 +260,7 @@ function getComponent(conf, repository) {
196
260
  version: options.version || '',
197
261
  parameters: options.parameters
198
262
  };
199
- (0, universalify_1.fromPromise)(repository.getComponent)(requestedComponent.name, requestedComponent.version, (err, component) => {
263
+ getComponentCb(requestedComponent.name, requestedComponent.version, (err, component) => {
200
264
  // check route exist for component and version
201
265
  if (err) {
202
266
  if (conf.fallbackRegistryUrl) {
@@ -234,10 +298,9 @@ function getComponent(conf, repository) {
234
298
  }
235
299
  });
236
300
  }
237
- // sanitise and check params
238
- const appliedParams = (0, apply_default_values_1.default)(requestedComponent.parameters, component.oc.parameters);
239
- const params = sanitiser.sanitiseComponentParameters(appliedParams, component.oc.parameters);
240
- const validationResult = validator.validateComponentParameters(params, component.oc.parameters);
301
+ // sanitise and check params (compiled schema + single scan)
302
+ const compiledParameterSchema = getCompiledParameterSchema(component.oc.parameters);
303
+ const { params, validation: validationResult } = (0, component_parameter_processor_1.processParameters)(requestedComponent.parameters, compiledParameterSchema);
241
304
  if (!options.action && !validationResult.isValid) {
242
305
  return callback({
243
306
  status: 400,
@@ -291,7 +354,7 @@ function getComponent(conf, repository) {
291
354
  }
292
355
  return filteredHeaders;
293
356
  };
294
- const returnComponent = async (err, data) => {
357
+ const returnComponent = (err, data) => {
295
358
  if (componentCallbackDone) {
296
359
  return;
297
360
  }
@@ -324,11 +387,9 @@ function getComponent(conf, repository) {
324
387
  renderMode = 'rendered';
325
388
  }
326
389
  }
327
- retrievingInfo.extend({
328
- href: componentHref,
329
- version: component.version,
330
- renderMode
331
- });
390
+ retrievedHref = componentHref;
391
+ retrievedVersion = component.version;
392
+ retrievedRenderMode = renderMode;
332
393
  if (err || !data) {
333
394
  err =
334
395
  err ||
@@ -356,22 +417,10 @@ function getComponent(conf, repository) {
356
417
  }
357
418
  };
358
419
  if (conf.local && err.stack) {
359
- const { content } = await repository
360
- .getDataProvider(component.name, component.version)
361
- .catch(() => ({ content: null }));
362
- if (content) {
363
- const processedStack = await (0, format_error_stack_1.processStackTrace)({
364
- stackTrace: err.stack,
365
- code: content
366
- }).catch(() => null);
367
- if (processedStack) {
368
- response.response.details.stack = processedStack.stack;
369
- response.response.details.frame = processedStack.frame;
370
- console.log(`Error rendering component ${component.name} ${component.version}`);
371
- console.log(processedStack.stack);
372
- console.log(processedStack.frame);
373
- }
374
- }
420
+ enrichLocalErrorStack(component, err, response)
421
+ .catch(() => { })
422
+ .then(() => callback(response));
423
+ return;
375
424
  }
376
425
  return callback(response);
377
426
  }
@@ -471,7 +520,7 @@ function getComponent(conf, repository) {
471
520
  returnComponent(null, { component: { props } });
472
521
  }
473
522
  else {
474
- (0, universalify_1.fromPromise)(getEnv)(component, (err, env) => {
523
+ lookupEnv(component, (err, env) => {
475
524
  if (err) {
476
525
  componentCallbackDone = true;
477
526
  return callback({
@@ -494,14 +543,14 @@ function getComponent(conf, repository) {
494
543
  return parsedAcceptLanguage;
495
544
  },
496
545
  baseUrl: conf.baseUrl,
497
- env: { ...conf.env, ...env },
546
+ env: { ...conf.env, ...(env || {}) },
498
547
  params,
499
548
  plugins: convertPlugins({
500
549
  name: component.name,
501
550
  version: component.version
502
551
  }),
503
- renderComponent: (0, universalify_1.fromPromise)(nestedRenderer.renderComponent),
504
- renderComponents: (0, universalify_1.fromPromise)(nestedRenderer.renderComponents),
552
+ renderComponent: nestedRenderComponent,
553
+ renderComponents: nestedRenderComponents,
505
554
  requestHeaders: options.headers,
506
555
  requestIp: options.ip,
507
556
  setEmptyResponse,
@@ -636,5 +685,9 @@ function getComponent(conf, repository) {
636
685
  }
637
686
  });
638
687
  };
688
+ const nestedRenderer = (0, nested_renderer_1.default)(renderer, conf);
689
+ const nestedRenderComponent = (0, universalify_1.fromPromise)(nestedRenderer.renderComponent);
690
+ const nestedRenderComponents = (0, universalify_1.fromPromise)(nestedRenderer.renderComponents);
691
+ const getComponentCb = (0, universalify_1.fromPromise)(repository.getComponent);
639
692
  return renderer;
640
693
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oc",
3
- "version": "0.50.63",
3
+ "version": "0.50.64",
4
4
  "description": "A framework for developing and distributing html components",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -97,8 +97,8 @@
97
97
  "oc-empty-response-handler": "^1.0.2",
98
98
  "oc-get-unix-utc-timestamp": "^1.0.6",
99
99
  "oc-metadata-adapters-utils": "^0.1.1",
100
- "oc-s3-storage-adapter": "^2.2.4",
101
- "oc-storage-adapters-utils": "^2.1.2",
100
+ "oc-s3-storage-adapter": "^2.2.5",
101
+ "oc-storage-adapters-utils": "^2.1.3",
102
102
  "oc-template-es6": "^2.0.0",
103
103
  "oc-template-es6-compiler": "^7.1.4",
104
104
  "oc-template-handlebars": "^6.0.26",
@@ -117,7 +117,7 @@
117
117
  "source-map": "^0.7.6",
118
118
  "targz": "^1.0.1",
119
119
  "try-require": "^1.2.1",
120
- "undici": "^8.5.0",
120
+ "undici": "^8.9.0",
121
121
  "universalify": "^2.0.1",
122
122
  "yargs": "^17.7.2"
123
123
  }
@@ -1,19 +0,0 @@
1
- import type { IncomingHttpHeaders } from 'node:http';
2
- interface Options {
3
- headers: IncomingHttpHeaders;
4
- name: string;
5
- parameters: IncomingHttpHeaders;
6
- version: string;
7
- }
8
- interface EventData {
9
- headers: IncomingHttpHeaders;
10
- name: string;
11
- parameters: IncomingHttpHeaders;
12
- requestVersion: string;
13
- duration: number;
14
- }
15
- export default function getComponentRetrievingInfo(options: Options): {
16
- extend(obj: unknown): void;
17
- getData(): EventData;
18
- };
19
- export {};
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = getComponentRetrievingInfo;
4
- function getComponentRetrievingInfo(options) {
5
- const eventData = {
6
- headers: options.headers,
7
- name: options.name,
8
- parameters: options.parameters,
9
- requestVersion: options.version || '',
10
- duration: 0
11
- };
12
- const start = process.hrtime();
13
- return {
14
- extend(obj) {
15
- Object.assign(eventData, obj);
16
- },
17
- getData() {
18
- const delta = process.hrtime(start);
19
- const nanosec = delta[0] * 1e9 + delta[1];
20
- eventData.duration = nanosec / 1e3;
21
- return eventData;
22
- }
23
- };
24
- }