@salesforce/storefront-next-dev 1.1.0-alpha.0 → 1.1.0-alpha.2
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/dist/commands/create-storefront.js +37 -6
- package/dist/dependency-utils.js +56 -4
- package/dist/entry/server.d.ts +1 -1
- package/dist/entry/server.js +62 -21
- package/dist/entry/server.js.map +1 -1
- package/dist/index.d.ts +58 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +107 -105
- package/dist/index.js.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/manage-extensions.js +1 -1
- package/dist/mrt/ssr.mjs +48 -48
- package/dist/mrt/ssr.mjs.map +1 -1
- package/dist/mrt/streamingHandler.mjs +57 -57
- package/dist/mrt/streamingHandler.mjs.map +1 -1
- package/dist/server.js +74 -28
- package/package.json +10 -8
package/dist/server.js
CHANGED
|
@@ -12,12 +12,12 @@ import compression from "compression";
|
|
|
12
12
|
import zlib from "node:zlib";
|
|
13
13
|
import morgan from "morgan";
|
|
14
14
|
import { minimatch } from "minimatch";
|
|
15
|
-
import { ROOT_CONTEXT, SpanStatusCode, context,
|
|
15
|
+
import { ROOT_CONTEXT, SpanKind, SpanStatusCode, context, trace } from "@opentelemetry/api";
|
|
16
|
+
import { ExportResultCode, W3CTraceContextPropagator, hrTimeToTimeStamp, parseTraceParent } from "@opentelemetry/core";
|
|
17
|
+
import { ATTR_HTTP_REQUEST_METHOD, ATTR_HTTP_RESPONSE_STATUS_CODE, ATTR_SERVICE_NAME, ATTR_URL_PATH } from "@opentelemetry/semantic-conventions";
|
|
16
18
|
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
17
19
|
import { AlwaysOnSampler, ConsoleSpanExporter, ParentBasedSampler, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
18
|
-
import { ExportResultCode, W3CTraceContextPropagator, hrTimeToTimeStamp } from "@opentelemetry/core";
|
|
19
20
|
import { Resource } from "@opentelemetry/resources";
|
|
20
|
-
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
|
21
21
|
import { registerInstrumentations } from "@opentelemetry/instrumentation";
|
|
22
22
|
import { UndiciInstrumentation } from "@opentelemetry/instrumentation-undici";
|
|
23
23
|
|
|
@@ -403,6 +403,43 @@ var MrtConsoleSpanExporter = class extends ConsoleSpanExporter {
|
|
|
403
403
|
|
|
404
404
|
//#endregion
|
|
405
405
|
//#region src/otel/setup.ts
|
|
406
|
+
/**
|
|
407
|
+
* A privately-held W3C Trace Context propagator, used to inject `traceparent` onto
|
|
408
|
+
* outbound fetches WITHOUT going through OpenTelemetry's global propagator registry.
|
|
409
|
+
*
|
|
410
|
+
* ## Why not the global propagator?
|
|
411
|
+
*
|
|
412
|
+
* `UndiciInstrumentation` injects outbound headers by calling the *global* registered
|
|
413
|
+
* propagator (`propagation.inject()`). Registering one with `setGlobalPropagator()`
|
|
414
|
+
* works locally, but is a silent no-op on Managed Runtime (MRT):
|
|
415
|
+
*
|
|
416
|
+
* - The MRT Lambda wrapper bundles its own copy of `@opentelemetry/api` (declared
|
|
417
|
+
* `^1.9.1`, with core/sdk at 2.x) and boots first, creating the version-keyed
|
|
418
|
+
* global registry object (`globalThis[Symbol.for('opentelemetry.js.api.1')]`,
|
|
419
|
+
* stamped `version: "1.9.1"`).
|
|
420
|
+
* - Our SDK bundle ships a *different* copy of `@opentelemetry/api` (`1.9.0`). When
|
|
421
|
+
* our code calls `setGlobalPropagator()`, OTel's `registerGlobal()` compares the
|
|
422
|
+
* registry's recorded version against ours with an EXACT string match — `"1.9.1"
|
|
423
|
+
* !== "1.9.0"` — refuses the registration, and reports the error only to OTel's
|
|
424
|
+
* internal diag channel (which we do not wire up). The propagation slot stays
|
|
425
|
+
* empty, so undici's `propagation.inject()` injects nothing and no `traceparent`
|
|
426
|
+
* reaches SCAPI. Proven on soak: `propagation.fields() === []`, 0/198 outbound
|
|
427
|
+
* requests carried a header.
|
|
428
|
+
*
|
|
429
|
+
* This is the same multi-instance split that makes inbound `propagation.extract()`
|
|
430
|
+
* fail (see `express/middleware.ts`, which bypasses it with `parseTraceParent` +
|
|
431
|
+
* `trace.setSpanContext`). MRT's own data-plane tracer solves it the same way: it
|
|
432
|
+
* holds a private `new W3CTraceContextPropagator()` and calls `inject()`/`extract()`
|
|
433
|
+
* on it directly, never touching the global registry.
|
|
434
|
+
*
|
|
435
|
+
* Holding our own instance and injecting it ourselves (in the undici `requestHook`)
|
|
436
|
+
* makes outbound propagation deterministic and independent of MRT's bundle, its OTel
|
|
437
|
+
* version, and its boot order. We deliberately do NOT call `setGlobalPropagator()` —
|
|
438
|
+
* leaving the global propagator as the default no-op guarantees undici's own
|
|
439
|
+
* `propagation.inject()` (which runs right after our hook) adds nothing, so the
|
|
440
|
+
* `traceparent` is written exactly once in every environment.
|
|
441
|
+
*/
|
|
442
|
+
const outboundPropagator = new W3CTraceContextPropagator();
|
|
406
443
|
const SERVICE_NAME = "storefront-next";
|
|
407
444
|
/**
|
|
408
445
|
* Initializes OpenTelemetry and returns a Tracer from the provider directly.
|
|
@@ -430,17 +467,20 @@ function initTelemetry() {
|
|
|
430
467
|
sampler: new ParentBasedSampler({ root: new AlwaysOnSampler() })
|
|
431
468
|
});
|
|
432
469
|
provider.addSpanProcessor(new SimpleSpanProcessor(new MrtConsoleSpanExporter()));
|
|
433
|
-
provider.register();
|
|
434
|
-
propagation.setGlobalPropagator(new W3CTraceContextPropagator());
|
|
470
|
+
provider.register({ propagator: null });
|
|
435
471
|
if (!globalThis[UNDICI_REGISTERED_KEY]) {
|
|
436
472
|
globalThis[UNDICI_REGISTERED_KEY] = true;
|
|
437
473
|
registerInstrumentations({
|
|
438
474
|
tracerProvider: provider,
|
|
439
475
|
instrumentations: [new UndiciInstrumentation({ requestHook(span, request) {
|
|
440
476
|
try {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
477
|
+
span.updateName("sfnext.fetch");
|
|
478
|
+
} catch {}
|
|
479
|
+
try {
|
|
480
|
+
const ctx = trace.setSpan(context.active(), span);
|
|
481
|
+
outboundPropagator.inject(ctx, request, { set(req, key, value) {
|
|
482
|
+
req.addHeader?.(key, value);
|
|
483
|
+
} });
|
|
444
484
|
} catch {}
|
|
445
485
|
} })]
|
|
446
486
|
});
|
|
@@ -463,44 +503,50 @@ function createOtelExpressMiddleware() {
|
|
|
463
503
|
try {
|
|
464
504
|
const url = new URL(req.originalUrl || req.url, "http://localhost").pathname;
|
|
465
505
|
const method = req.method;
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
506
|
+
const traceparent = req.headers.traceparent;
|
|
507
|
+
const inboundSpanContext = typeof traceparent === "string" ? parseTraceParent(traceparent) : null;
|
|
508
|
+
const parentContext = inboundSpanContext ? trace.setSpanContext(ROOT_CONTEXT, {
|
|
509
|
+
...inboundSpanContext,
|
|
510
|
+
isRemote: true
|
|
511
|
+
}) : ROOT_CONTEXT;
|
|
512
|
+
tracer.startActiveSpan("sfnext.request", {
|
|
513
|
+
kind: SpanKind.SERVER,
|
|
514
|
+
attributes: {
|
|
515
|
+
[ATTR_HTTP_REQUEST_METHOD]: method,
|
|
516
|
+
[ATTR_URL_PATH]: url
|
|
517
|
+
}
|
|
518
|
+
}, parentContext, (serverSpan) => {
|
|
471
519
|
try {
|
|
472
520
|
const spanContext = trace.getSpan(context.active())?.spanContext();
|
|
473
521
|
if (spanContext) {
|
|
474
522
|
const flags = spanContext.traceFlags.toString(16).padStart(2, "0");
|
|
475
|
-
const
|
|
476
|
-
res.setHeader("traceparent",
|
|
523
|
+
const responseTraceparent = `00-${spanContext.traceId}-${spanContext.spanId}-${flags}`;
|
|
524
|
+
res.setHeader("traceparent", responseTraceparent);
|
|
477
525
|
}
|
|
478
526
|
} catch {}
|
|
479
527
|
const serverCtx = context.active();
|
|
480
528
|
const startTime = performance.now();
|
|
481
529
|
let streamingSpan = null;
|
|
482
|
-
let
|
|
530
|
+
let firstByteMs = 0;
|
|
483
531
|
let ended = false;
|
|
484
|
-
function
|
|
532
|
+
function startStreamingSpan() {
|
|
485
533
|
if (streamingSpan) return;
|
|
486
534
|
try {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
"url.path": url,
|
|
492
|
-
"sfnext.ttfb_ms": ttfbMs
|
|
535
|
+
firstByteMs = Math.round(performance.now() - startTime);
|
|
536
|
+
streamingSpan = tracer.startSpan("sfnext.response_streaming", { attributes: {
|
|
537
|
+
[ATTR_HTTP_REQUEST_METHOD]: method,
|
|
538
|
+
[ATTR_URL_PATH]: url
|
|
493
539
|
} }, serverCtx);
|
|
494
540
|
} catch {}
|
|
495
541
|
}
|
|
496
542
|
const origWriteHead = res.writeHead.bind(res);
|
|
497
543
|
res.writeHead = ((...args) => {
|
|
498
|
-
|
|
544
|
+
startStreamingSpan();
|
|
499
545
|
return origWriteHead(...args);
|
|
500
546
|
});
|
|
501
547
|
const origWrite = res.write.bind(res);
|
|
502
548
|
res.write = ((...args) => {
|
|
503
|
-
|
|
549
|
+
startStreamingSpan();
|
|
504
550
|
return origWrite(...args);
|
|
505
551
|
});
|
|
506
552
|
function endSpans() {
|
|
@@ -510,12 +556,12 @@ function createOtelExpressMiddleware() {
|
|
|
510
556
|
const totalMs = Math.round(performance.now() - startTime);
|
|
511
557
|
const statusCode = res.statusCode;
|
|
512
558
|
if (streamingSpan) {
|
|
513
|
-
streamingSpan.setAttribute("http.streaming_duration_ms", totalMs -
|
|
514
|
-
streamingSpan.setAttribute(
|
|
559
|
+
streamingSpan.setAttribute("http.streaming_duration_ms", totalMs - firstByteMs);
|
|
560
|
+
streamingSpan.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode);
|
|
515
561
|
if (statusCode >= 500) streamingSpan.setStatus({ code: SpanStatusCode.ERROR });
|
|
516
562
|
streamingSpan.end();
|
|
517
563
|
}
|
|
518
|
-
serverSpan.setAttribute(
|
|
564
|
+
serverSpan.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode);
|
|
519
565
|
serverSpan.setAttribute("http.total_duration_ms", totalMs);
|
|
520
566
|
if (statusCode >= 500) serverSpan.setStatus({ code: SpanStatusCode.ERROR });
|
|
521
567
|
serverSpan.end();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/storefront-next-dev",
|
|
3
|
-
"version": "1.1.0-alpha.
|
|
3
|
+
"version": "1.1.0-alpha.2",
|
|
4
4
|
"description": "Dev and build tools for SFCC Storefront Next",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -118,7 +118,8 @@
|
|
|
118
118
|
},
|
|
119
119
|
"devDependencies": {
|
|
120
120
|
"@oclif/test": "^4.1.15",
|
|
121
|
-
"@react-router/dev": "7.
|
|
121
|
+
"@react-router/dev": "7.18.0",
|
|
122
|
+
"@react-router/node": "7.18.0",
|
|
122
123
|
"@serverless/event-mocks": "1.1.1",
|
|
123
124
|
"@types/archiver": "^6.0.2",
|
|
124
125
|
"@types/aws-lambda": "8.10.159",
|
|
@@ -139,19 +140,19 @@
|
|
|
139
140
|
"@types/react": "19.1.13",
|
|
140
141
|
"@types/react-dom": "19.1.9",
|
|
141
142
|
"@types/semver": "7.7.1",
|
|
142
|
-
"@vitest/coverage-v8": "4.
|
|
143
|
+
"@vitest/coverage-v8": "4.1.8",
|
|
143
144
|
"fs-extra": "11.3.2",
|
|
144
145
|
"jest": "^29.7.0",
|
|
145
146
|
"memfs": "^4.42.0",
|
|
146
147
|
"react": "19.2.3",
|
|
147
148
|
"react-dom": "19.2.3",
|
|
148
|
-
"react-router": "7.
|
|
149
|
+
"react-router": "7.18.0",
|
|
149
150
|
"shx": "^0.4.0",
|
|
150
151
|
"ts-jest": "29.4.1",
|
|
151
152
|
"tsdown": "^0.15.4",
|
|
152
153
|
"typescript": "^5.6.0",
|
|
153
|
-
"vite": "7.
|
|
154
|
-
"vitest": "4.
|
|
154
|
+
"vite": "7.3.5",
|
|
155
|
+
"vitest": "4.1.8"
|
|
155
156
|
},
|
|
156
157
|
"dependencies": {
|
|
157
158
|
"@babel/generator": "7.28.5",
|
|
@@ -172,7 +173,7 @@
|
|
|
172
173
|
"@opentelemetry/sdk-trace-base": "^1.30.0",
|
|
173
174
|
"@opentelemetry/sdk-trace-node": "^1.30.0",
|
|
174
175
|
"@opentelemetry/semantic-conventions": "^1.28.0",
|
|
175
|
-
"@react-router/express": "7.
|
|
176
|
+
"@react-router/express": "7.18.0",
|
|
176
177
|
"@salesforce/b2c-tooling-sdk": "^1.15.0",
|
|
177
178
|
"archiver": "^7.0.1",
|
|
178
179
|
"babel-dead-code-elimination": "1.0.12",
|
|
@@ -191,11 +192,12 @@
|
|
|
191
192
|
"negotiator": "1.0.0",
|
|
192
193
|
"npm-run-path": "6.0.0",
|
|
193
194
|
"openapi-typescript": "7.10.1",
|
|
195
|
+
"prettier": "3.6.2",
|
|
194
196
|
"prompts": "2.4.2",
|
|
195
197
|
"ts-morph": "^24.0.0",
|
|
196
198
|
"tsdown": "^0.15.4",
|
|
197
199
|
"tsx": "^4.20.5",
|
|
198
|
-
"undici": "
|
|
200
|
+
"undici": "7.28.0",
|
|
199
201
|
"yaml": "^2.8.2",
|
|
200
202
|
"zod": "4.1.13"
|
|
201
203
|
},
|