@tokenoftrust/storefront-runner 6.0.0 → 6.0.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.
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tenant binaries never live in the tenant repo. The platform's content-addressed `/_a/<sha256>`
|
|
3
3
|
* pool owns them and the store's repo holds references only. Publication captures source images;
|
|
4
|
-
* go-live requires zero uncaptured images in every type
|
|
5
|
-
*
|
|
4
|
+
* go-live requires zero uncaptured images in every type, or an owner acknowledgement of the exact
|
|
5
|
+
* remaining count, and sampled live owned-image responses. Acknowledged images still load from the
|
|
6
|
+
* source store, so it is never shut down while any remain. This decides,
|
|
6
7
|
* from a listing of the store's `public/` tree, whether the repo is carrying binaries it must not.
|
|
7
8
|
*
|
|
8
9
|
* Findings, each naming its remedy:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|
|
@@ -553,6 +553,9 @@ export function applyCaptureRewrites(
|
|
|
553
553
|
return artifacts.map(createCaptureArtifactRewriter(rewrites));
|
|
554
554
|
}
|
|
555
555
|
|
|
556
|
+
/** Characters of a key's file name used to find which rewrites an artifact can need. */
|
|
557
|
+
const REWRITE_ANCHOR_LENGTH = 12;
|
|
558
|
+
|
|
556
559
|
/** Prepare locator matching once while allowing callers to persist one rewritten artifact at a time. */
|
|
557
560
|
export function createCaptureArtifactRewriter(rewrites: readonly CaptureRewrite[]): (artifact: ImageDependencyArtifact) => ImageDependencyArtifact {
|
|
558
561
|
if (rewrites.length === 0) return (artifact) => ({ ...artifact });
|
|
@@ -570,9 +573,43 @@ export function createCaptureArtifactRewriter(rewrites: readonly CaptureRewrite[
|
|
|
570
573
|
const exact = new Set((rewrite.exactAliases ?? []).flatMap((n) => [n, ...htmlAmpVariants(n)]));
|
|
571
574
|
return { rewrite, needles, key, exact };
|
|
572
575
|
});
|
|
576
|
+
// Trying every rewrite against every artifact is rewrites × artifacts searches: a 10k-image
|
|
577
|
+
// catalog over 3.5k files is ~37M searches, about a minute of CPU, past a Worker's limit. Instead
|
|
578
|
+
// each needle is indexed by the ANCHOR characters that follow its last `/`, and an artifact is read
|
|
579
|
+
// once, at each `/`, to find the only rewrites with a needle that can occur in it: wherever a needle
|
|
580
|
+
// occurs, a `/` is followed by its anchor. A rewrite with a needle lacking an anchor (no slash, or
|
|
581
|
+
// fewer characters after it) is always tried.
|
|
582
|
+
const anchored = new Map<string, number[]>();
|
|
583
|
+
const always: number[] = [];
|
|
584
|
+
prepared.forEach(({ needles }, index) => {
|
|
585
|
+
const anchors = new Set<string>();
|
|
586
|
+
for (const needle of needles) {
|
|
587
|
+
const slash = needle.lastIndexOf("/");
|
|
588
|
+
if (slash < 0 || needle.length - slash - 1 < REWRITE_ANCHOR_LENGTH) {
|
|
589
|
+
always.push(index);
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
anchors.add(needle.substr(slash + 1, REWRITE_ANCHOR_LENGTH));
|
|
593
|
+
}
|
|
594
|
+
for (const anchor of anchors) {
|
|
595
|
+
const list = anchored.get(anchor);
|
|
596
|
+
if (list) list.push(index);
|
|
597
|
+
else anchored.set(anchor, [index]);
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
const candidatesIn = (content: string): number[] => {
|
|
601
|
+
if (anchored.size === 0) return always;
|
|
602
|
+
const found = new Set<number>(always);
|
|
603
|
+
for (let at = content.indexOf("/"); at !== -1; at = content.indexOf("/", at + 1)) {
|
|
604
|
+
const list = anchored.get(content.substr(at + 1, REWRITE_ANCHOR_LENGTH));
|
|
605
|
+
if (list) for (const index of list) found.add(index);
|
|
606
|
+
}
|
|
607
|
+
return [...found].sort((a, b) => a - b);
|
|
608
|
+
};
|
|
573
609
|
return (artifact) => {
|
|
574
610
|
let content = artifact.content;
|
|
575
|
-
for (const
|
|
611
|
+
for (const index of candidatesIn(content)) {
|
|
612
|
+
const { rewrite, needles, key, exact } = prepared[index]!;
|
|
576
613
|
if (key !== null && !content.includes(key)) continue;
|
|
577
614
|
for (const needle of needles) {
|
|
578
615
|
content = replaceAllLocatorTokens(content, needle, rewrite.platformUrl, exact.has(needle));
|