@teamscala/service-boot 0.23.556 → 0.23.559
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/package.json
CHANGED
|
@@ -18,6 +18,8 @@ const HYDRATE_BASE = "hydrate";
|
|
|
18
18
|
export interface HydrateBundleResult {
|
|
19
19
|
/** Served entry path (`/assets/hydrate-<hash>.js`), or null when no entry exists. */
|
|
20
20
|
hydratePath: string | null;
|
|
21
|
+
/** Chunk URLs the entry itself can load, for modulepreload emission. */
|
|
22
|
+
preloads: string[];
|
|
21
23
|
/** The VERIFIED source-map upload outcome for this build's release. */
|
|
22
24
|
sourceMaps: SourceMapUploadResult;
|
|
23
25
|
}
|
|
@@ -195,8 +197,30 @@ export async function buildHydrateBundle(
|
|
|
195
197
|
.filter((o) => o.kind === "chunk")
|
|
196
198
|
.map((o) => o.path.split("/").pop() as string),
|
|
197
199
|
);
|
|
200
|
+
const entryText = await Bun.file(hashedPath).text();
|
|
201
|
+
const preloads = [
|
|
202
|
+
...new Set(
|
|
203
|
+
[...entryText.matchAll(/["'](\/assets\/[A-Za-z0-9-]+\.js)["']/g)].map(
|
|
204
|
+
(m) => m[1],
|
|
205
|
+
),
|
|
206
|
+
),
|
|
207
|
+
].sort();
|
|
208
|
+
const unknownPreloads = preloads.filter(
|
|
209
|
+
(url) =>
|
|
210
|
+
url !== `${ASSET_PUBLIC_PREFIX}${hashedName}` &&
|
|
211
|
+
!currentChunks.has(url.replace(/^\/assets\//, "")),
|
|
212
|
+
);
|
|
213
|
+
if (unknownPreloads.length > 0) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`[build-client-assets] entry references chunk URL(s) Bun did not emit: ${unknownPreloads.join(", ")} — refusing a manifest whose preloads name unbuilt assets`,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
198
218
|
const sourceMaps = await uploadSourceMaps(cwd, outDir, hash, log, currentOutputs);
|
|
199
|
-
return {
|
|
219
|
+
return {
|
|
220
|
+
hydratePath: `${ASSET_PUBLIC_PREFIX}${hashedName}`,
|
|
221
|
+
preloads,
|
|
222
|
+
sourceMaps,
|
|
223
|
+
};
|
|
200
224
|
}
|
|
201
225
|
|
|
202
226
|
async function removeStaleChunks(
|
|
@@ -12,6 +12,7 @@ export const MANIFEST_FILE = "asset-manifest.json";
|
|
|
12
12
|
export interface AssetManifest {
|
|
13
13
|
stylesPath?: string;
|
|
14
14
|
hydratePath?: string;
|
|
15
|
+
preloads?: string[];
|
|
15
16
|
sourceMaps?: SourceMapUploadResult;
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -47,6 +48,7 @@ export async function readManifestState(outDir: string): Promise<ManifestState>
|
|
|
47
48
|
manifest: {
|
|
48
49
|
stylesPath: parsed.stylesPath,
|
|
49
50
|
hydratePath: parsed.hydratePath,
|
|
51
|
+
preloads: parsed.preloads,
|
|
50
52
|
sourceMaps: parsed.sourceMaps,
|
|
51
53
|
},
|
|
52
54
|
};
|
|
@@ -96,10 +98,12 @@ export async function verifyClientBuildAssets(
|
|
|
96
98
|
const verdict = verifyManifestState(await readManifestState(outDir), outDir);
|
|
97
99
|
if (!verdict.ok) return verdict;
|
|
98
100
|
const manifest = verdict.manifest;
|
|
99
|
-
|
|
101
|
+
const named: Array<readonly [string, string]> = [
|
|
100
102
|
["stylesheet", manifest.stylesPath],
|
|
101
103
|
["hydrate bundle", manifest.hydratePath],
|
|
102
|
-
]
|
|
104
|
+
];
|
|
105
|
+
for (const url of manifest.preloads ?? []) named.push(["preload chunk", url]);
|
|
106
|
+
for (const [label, url] of named) {
|
|
103
107
|
const file = join(outDir, url.replace(/^\/assets\//, ""));
|
|
104
108
|
if (!(await Bun.file(file).exists())) {
|
|
105
109
|
return {
|
|
@@ -20,12 +20,12 @@ export async function resolveProposalAuthorizedEmails(
|
|
|
20
20
|
UNION
|
|
21
21
|
SELECT lower(cd.primary_email) AS email
|
|
22
22
|
FROM client_database cd
|
|
23
|
-
WHERE cd.id = (SELECT contact_id FROM proposals WHERE id = ${proposalId})
|
|
23
|
+
WHERE cd.id = (SELECT contact_id::text FROM proposals WHERE id = ${proposalId})
|
|
24
24
|
AND cd.primary_email IS NOT NULL
|
|
25
25
|
UNION
|
|
26
26
|
SELECT lower(cd.primary_email) AS email
|
|
27
27
|
FROM client_database cd
|
|
28
|
-
WHERE cd.company_id = (SELECT partner_id FROM proposals WHERE id = ${proposalId})
|
|
28
|
+
WHERE cd.company_id::text = (SELECT partner_id FROM proposals WHERE id = ${proposalId})
|
|
29
29
|
AND cd.primary_email IS NOT NULL
|
|
30
30
|
` as { email: string }[];
|
|
31
31
|
return new Set(
|
|
@@ -11,6 +11,7 @@ import { join } from "node:path";
|
|
|
11
11
|
interface TemplateManifest {
|
|
12
12
|
stylesPath: string;
|
|
13
13
|
hydratePath: string;
|
|
14
|
+
preloads: string[];
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const PAGE_DOCUMENT = `<!doctype html>
|
|
@@ -22,6 +23,7 @@ const PAGE_DOCUMENT = `<!doctype html>
|
|
|
22
23
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
23
24
|
<!--theme-fonts-->
|
|
24
25
|
<link rel="stylesheet" href="{{stylesPath}}" />
|
|
26
|
+
<!--module-preloads-->
|
|
25
27
|
<!--head-outlet-->
|
|
26
28
|
</head>
|
|
27
29
|
<body>
|
|
@@ -56,7 +58,11 @@ async function manifestMtimeMs(): Promise<number> {
|
|
|
56
58
|
async function loadManifest(): Promise<TemplateManifest | null> {
|
|
57
59
|
const manifest = await readManifest(join(process.cwd(), "dist", "client"));
|
|
58
60
|
if (!manifest?.stylesPath || !manifest.hydratePath) return null;
|
|
59
|
-
return {
|
|
61
|
+
return {
|
|
62
|
+
stylesPath: manifest.stylesPath,
|
|
63
|
+
hydratePath: manifest.hydratePath,
|
|
64
|
+
preloads: manifest.preloads ?? [],
|
|
65
|
+
};
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
function manifestCacheKey(): string {
|
|
@@ -78,6 +84,16 @@ export async function readHtmlTemplate(): Promise<string> {
|
|
|
78
84
|
let html = PAGE_DOCUMENT
|
|
79
85
|
.replace(/\{\{stylesPath\}\}/g, manifest.stylesPath)
|
|
80
86
|
.replace(/\{\{hydratePath\}\}/g, manifest.hydratePath)
|
|
87
|
+
.replace(
|
|
88
|
+
"<!--module-preloads-->",
|
|
89
|
+
() =>
|
|
90
|
+
manifest.preloads
|
|
91
|
+
.map(
|
|
92
|
+
(url) =>
|
|
93
|
+
`<link rel="modulepreload" href="${url}" />`,
|
|
94
|
+
)
|
|
95
|
+
.join("\n\t\t"),
|
|
96
|
+
)
|
|
81
97
|
.replace("<!--theme-fonts-->", () => themeFontsLink());
|
|
82
98
|
htmlCache.set(manifestCacheKey(), { html, manifestMtime });
|
|
83
99
|
return html;
|