@frockbot/applet-sdk 0.7.126 → 0.7.127
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 +1 -1
- package/src/build/artifacts.ts +5 -64
- package/src/build/module-paths.ts +72 -0
- package/src/build/plugin.ts +3 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/applet-sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.127",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Authoring SDK for FrockBot Applets: schema-first Durable Object server, TanStack DB client, component kit, linter, and the build pipeline.",
|
package/src/build/artifacts.ts
CHANGED
|
@@ -21,13 +21,12 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { createHash, randomUUID } from "node:crypto";
|
|
24
|
-
import { realpathSync } from "node:fs";
|
|
25
|
-
import { relative, resolve } from "node:path";
|
|
26
24
|
|
|
27
|
-
import { build as esbuild
|
|
25
|
+
import { build as esbuild } from "esbuild";
|
|
28
26
|
|
|
29
27
|
import type { AppletDescriptionV1 } from "../server/applet.js";
|
|
30
28
|
import { readDescriptor, type AppletBuildManifestV1 } from "./manifest.js";
|
|
29
|
+
import { stableModulePaths } from "./module-paths.js";
|
|
31
30
|
import { bundlerNodePaths, SDK_ENTRIES, SDK_ROOT } from "./paths.js";
|
|
32
31
|
import { withOneMoreBoot } from "./boot.js";
|
|
33
32
|
import { startAppletRuntime } from "./runtime.js";
|
|
@@ -42,66 +41,6 @@ function sha256(text: string): string {
|
|
|
42
41
|
return createHash("sha256").update(text, "utf8").digest("hex");
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
/** esbuild reports real paths; a temp directory is often a symlink to one. */
|
|
46
|
-
function real(path: string): string {
|
|
47
|
-
try {
|
|
48
|
-
return realpathSync(resolve(path));
|
|
49
|
-
} catch {
|
|
50
|
-
return resolve(path);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Where a bundled module came from, said the same way everywhere.
|
|
56
|
-
*
|
|
57
|
-
* An Applet's directory, the SDK's directory and the working directory are all
|
|
58
|
-
* different on an author's machine and in the build container — and esbuild
|
|
59
|
-
* writes each module's path into the unminified output as a comment. Left
|
|
60
|
-
* alone, identical source bundled in two places produces two different files
|
|
61
|
-
* and therefore two different content hashes, which would give R2 a new object
|
|
62
|
-
* on every publish of unchanged code.
|
|
63
|
-
*/
|
|
64
|
-
function moduleLabel(absolute: string, appletRoot: string): string {
|
|
65
|
-
for (const [root, prefix] of [
|
|
66
|
-
[appletRoot, ""],
|
|
67
|
-
[real(SDK_ROOT), "applet-sdk/"],
|
|
68
|
-
] as const) {
|
|
69
|
-
const inside = relative(root, absolute);
|
|
70
|
-
if (!inside.startsWith("..") && inside !== "") return prefix + inside;
|
|
71
|
-
}
|
|
72
|
-
const dependency = absolute.lastIndexOf("node_modules/");
|
|
73
|
-
return dependency === -1 ? absolute : absolute.slice(dependency);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Rewrites esbuild's module comments to those stable labels.
|
|
78
|
-
*
|
|
79
|
-
* The paths come from the metafile rather than from a pattern over the output,
|
|
80
|
-
* so only lines esbuild actually wrote are touched and a comment in someone's
|
|
81
|
-
* own source is left alone.
|
|
82
|
-
*/
|
|
83
|
-
function stableModulePaths(
|
|
84
|
-
text: string,
|
|
85
|
-
metafile: Metafile,
|
|
86
|
-
appletRoot: string,
|
|
87
|
-
): string {
|
|
88
|
-
const root = real(appletRoot);
|
|
89
|
-
const labels = new Map(
|
|
90
|
-
Object.keys(metafile.inputs).map((input) => [
|
|
91
|
-
input,
|
|
92
|
-
moduleLabel(real(input), root),
|
|
93
|
-
]),
|
|
94
|
-
);
|
|
95
|
-
return text
|
|
96
|
-
.split("\n")
|
|
97
|
-
.map((line) => {
|
|
98
|
-
if (!line.startsWith("// ")) return line;
|
|
99
|
-
const label = labels.get(line.slice(3));
|
|
100
|
-
return label === undefined ? line : `// ${label}`;
|
|
101
|
-
})
|
|
102
|
-
.join("\n");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
44
|
async function bundle(options: {
|
|
106
45
|
stdin: string;
|
|
107
46
|
resolveDir: string;
|
|
@@ -136,7 +75,9 @@ async function bundle(options: {
|
|
|
136
75
|
});
|
|
137
76
|
const file = result.outputFiles?.[0];
|
|
138
77
|
if (!file) throw new Error("The bundler produced no output");
|
|
139
|
-
return stableModulePaths(file.text, result.metafile, options.resolveDir
|
|
78
|
+
return stableModulePaths(file.text, result.metafile, options.resolveDir, [
|
|
79
|
+
{ directory: SDK_ROOT, prefix: "applet-sdk/" },
|
|
80
|
+
]);
|
|
140
81
|
}
|
|
141
82
|
|
|
142
83
|
function page(title: string, script: string): string {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { Metafile } from "esbuild";
|
|
5
|
+
|
|
6
|
+
export interface StableModuleRoot {
|
|
7
|
+
directory: string;
|
|
8
|
+
prefix: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** esbuild reports real paths; a temp directory is often a symlink to one. */
|
|
12
|
+
function real(path: string): string {
|
|
13
|
+
try {
|
|
14
|
+
return realpathSync(resolve(path));
|
|
15
|
+
} catch {
|
|
16
|
+
return resolve(path);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function portable(path: string): string {
|
|
21
|
+
return path.split(sep).join("/").replaceAll("\\", "/");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function moduleLabel(absolute: string, roots: readonly StableModuleRoot[]) {
|
|
25
|
+
for (const { directory, prefix } of roots) {
|
|
26
|
+
const inside = relative(directory, absolute);
|
|
27
|
+
const outside =
|
|
28
|
+
inside === ".." || inside.startsWith(`..${sep}`) || isAbsolute(inside);
|
|
29
|
+
if (!outside && inside !== "") return prefix + portable(inside);
|
|
30
|
+
}
|
|
31
|
+
const path = portable(absolute);
|
|
32
|
+
const dependency = path.lastIndexOf("node_modules/");
|
|
33
|
+
return dependency === -1 ? path : path.slice(dependency);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Rewrites esbuild's module comments to location-independent labels.
|
|
38
|
+
*
|
|
39
|
+
* The paths come from the metafile rather than from a pattern over the output,
|
|
40
|
+
* so only lines esbuild actually wrote are touched and a comment in authored
|
|
41
|
+
* source is left alone. Callers name any additional source roots that belong
|
|
42
|
+
* to their artifact; dependencies under `node_modules` are stable by package
|
|
43
|
+
* path automatically.
|
|
44
|
+
*/
|
|
45
|
+
export function stableModulePaths(
|
|
46
|
+
text: string,
|
|
47
|
+
metafile: Metafile,
|
|
48
|
+
sourceRoot: string,
|
|
49
|
+
additionalRoots: readonly StableModuleRoot[] = [],
|
|
50
|
+
): string {
|
|
51
|
+
const roots = [
|
|
52
|
+
{ directory: real(sourceRoot), prefix: "" },
|
|
53
|
+
...additionalRoots.map(({ directory, prefix }) => ({
|
|
54
|
+
directory: real(directory),
|
|
55
|
+
prefix,
|
|
56
|
+
})),
|
|
57
|
+
];
|
|
58
|
+
const labels = new Map(
|
|
59
|
+
Object.keys(metafile.inputs).map((input) => [
|
|
60
|
+
input,
|
|
61
|
+
moduleLabel(real(input), roots),
|
|
62
|
+
]),
|
|
63
|
+
);
|
|
64
|
+
return text
|
|
65
|
+
.split("\n")
|
|
66
|
+
.map((line) => {
|
|
67
|
+
if (!line.startsWith("// ")) return line;
|
|
68
|
+
const label = labels.get(line.slice(3));
|
|
69
|
+
return label === undefined ? line : `// ${label}`;
|
|
70
|
+
})
|
|
71
|
+
.join("\n");
|
|
72
|
+
}
|
package/src/build/plugin.ts
CHANGED
|
@@ -30,6 +30,7 @@ import ts from "typescript";
|
|
|
30
30
|
|
|
31
31
|
import type { AppletDiagnostic } from "../lint/index.js";
|
|
32
32
|
import { bootedWithin, withOneMoreBoot } from "./boot.js";
|
|
33
|
+
import { stableModulePaths } from "./module-paths.js";
|
|
33
34
|
import { APPLET_COMPATIBILITY_DATE } from "./runtime.js";
|
|
34
35
|
import { SDK_PLUGIN_TYPES } from "./paths.js";
|
|
35
36
|
|
|
@@ -241,20 +242,12 @@ export async function bundlePlugin(directory: string): Promise<string> {
|
|
|
241
242
|
},
|
|
242
243
|
],
|
|
243
244
|
define: { "process.env.NODE_ENV": '"production"' },
|
|
245
|
+
metafile: true,
|
|
244
246
|
logLevel: "silent",
|
|
245
247
|
});
|
|
246
248
|
const file = result.outputFiles?.[0];
|
|
247
249
|
if (!file) throw new Error("The bundler produced no output");
|
|
248
|
-
|
|
249
|
-
// function of the source alone, as the Applet build does.
|
|
250
|
-
return file.text
|
|
251
|
-
.split("\n")
|
|
252
|
-
.map((line) =>
|
|
253
|
-
line.startsWith("// ") && line.includes(directory)
|
|
254
|
-
? `// ${relative(directory, line.slice(3))}`
|
|
255
|
-
: line,
|
|
256
|
-
)
|
|
257
|
-
.join("\n");
|
|
250
|
+
return stableModulePaths(file.text, result.metafile, directory);
|
|
258
251
|
}
|
|
259
252
|
|
|
260
253
|
/**
|