@superblocksteam/sdk 2.0.115-next.0 → 2.0.115-next.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/.turbo/turbo-build.log +1 -1
- package/dist/cli-replacement/dev-s3-restore.test.d.mts +2 -0
- package/dist/cli-replacement/dev-s3-restore.test.d.mts.map +1 -0
- package/dist/cli-replacement/dev-s3-restore.test.mjs +457 -0
- package/dist/cli-replacement/dev-s3-restore.test.mjs.map +1 -0
- package/dist/cli-replacement/dev.d.mts +7 -0
- package/dist/cli-replacement/dev.d.mts.map +1 -1
- package/dist/cli-replacement/dev.mjs +142 -3
- package/dist/cli-replacement/dev.mjs.map +1 -1
- package/dist/cli-replacement/package-json-snapshot.d.mts +26 -0
- package/dist/cli-replacement/package-json-snapshot.d.mts.map +1 -0
- package/dist/cli-replacement/package-json-snapshot.mjs +222 -0
- package/dist/cli-replacement/package-json-snapshot.mjs.map +1 -0
- package/dist/cli-replacement/package-json-snapshot.test.d.mts +2 -0
- package/dist/cli-replacement/package-json-snapshot.test.d.mts.map +1 -0
- package/dist/cli-replacement/package-json-snapshot.test.mjs +207 -0
- package/dist/cli-replacement/package-json-snapshot.test.mjs.map +1 -0
- package/dist/dev-utils/dev-server-persist.test.d.mts +2 -0
- package/dist/dev-utils/dev-server-persist.test.d.mts.map +1 -0
- package/dist/dev-utils/dev-server-persist.test.mjs +77 -0
- package/dist/dev-utils/dev-server-persist.test.mjs.map +1 -0
- package/dist/dev-utils/dev-server.d.mts +1 -0
- package/dist/dev-utils/dev-server.d.mts.map +1 -1
- package/dist/dev-utils/dev-server.mjs +85 -55
- package/dist/dev-utils/dev-server.mjs.map +1 -1
- package/dist/dev-utils/vite-dev-server-diagnostics.d.mts +61 -0
- package/dist/dev-utils/vite-dev-server-diagnostics.d.mts.map +1 -0
- package/dist/dev-utils/vite-dev-server-diagnostics.mjs +133 -0
- package/dist/dev-utils/vite-dev-server-diagnostics.mjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/telemetry/logging.d.ts.map +1 -1
- package/dist/telemetry/logging.js +22 -10
- package/dist/telemetry/logging.js.map +1 -1
- package/dist/telemetry/logging.test.d.ts +2 -0
- package/dist/telemetry/logging.test.d.ts.map +1 -0
- package/dist/telemetry/logging.test.js +104 -0
- package/dist/telemetry/logging.test.js.map +1 -0
- package/package.json +7 -7
- package/src/cli-replacement/dev-s3-restore.test.mts +599 -0
- package/src/cli-replacement/dev.mts +202 -6
- package/src/cli-replacement/package-json-snapshot.mts +328 -0
- package/src/cli-replacement/package-json-snapshot.test.mts +250 -0
- package/src/dev-utils/dev-server-persist.test.mts +96 -0
- package/src/dev-utils/dev-server.mts +106 -75
- package/src/dev-utils/vite-dev-server-diagnostics.mts +213 -0
- package/src/index.ts +15 -0
- package/src/telemetry/logging.test.ts +142 -0
- package/src/telemetry/logging.ts +30 -10
- package/test/vite-dev-server-diagnostics.test.mts +336 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/turbo.json +1 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
didPackageJsonSnapshotChange,
|
|
9
|
+
packageJsonSnapshot,
|
|
10
|
+
readPackageJsonSnapshotWithSource,
|
|
11
|
+
restoreManagedPackageDependencies,
|
|
12
|
+
} from "./package-json-snapshot.mjs";
|
|
13
|
+
|
|
14
|
+
describe("packageJsonSnapshot", () => {
|
|
15
|
+
it("is stable for object key order changes", () => {
|
|
16
|
+
const before = packageJsonSnapshot({
|
|
17
|
+
dependencies: {
|
|
18
|
+
"@superblocksteam/library": "2.0.0",
|
|
19
|
+
react: "19.0.0",
|
|
20
|
+
},
|
|
21
|
+
scripts: {
|
|
22
|
+
dev: "vite",
|
|
23
|
+
build: "vite build",
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const after = packageJsonSnapshot({
|
|
28
|
+
scripts: {
|
|
29
|
+
build: "vite build",
|
|
30
|
+
dev: "vite",
|
|
31
|
+
},
|
|
32
|
+
dependencies: {
|
|
33
|
+
react: "19.0.0",
|
|
34
|
+
"@superblocksteam/library": "2.0.0",
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(false);
|
|
39
|
+
expect(before.diagnostic.sha256).toBe(after.diagnostic.sha256);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("detects dependency version changes", () => {
|
|
43
|
+
const before = packageJsonSnapshot({
|
|
44
|
+
dependencies: {
|
|
45
|
+
"@superblocksteam/library": "1.0.0",
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
const after = packageJsonSnapshot({
|
|
49
|
+
dependencies: {
|
|
50
|
+
"@superblocksteam/library": "2.0.0",
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(true);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("ignores non-dependency package metadata", () => {
|
|
58
|
+
const before = packageJsonSnapshot({
|
|
59
|
+
name: "warm-template",
|
|
60
|
+
version: "1.0.0",
|
|
61
|
+
scripts: {
|
|
62
|
+
dev: "vite",
|
|
63
|
+
},
|
|
64
|
+
dependencies: {
|
|
65
|
+
react: "19.0.0",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
const after = packageJsonSnapshot({
|
|
69
|
+
name: "restored-app",
|
|
70
|
+
version: "2.0.0",
|
|
71
|
+
scripts: {
|
|
72
|
+
dev: "vite --host 0.0.0.0",
|
|
73
|
+
},
|
|
74
|
+
dependencies: {
|
|
75
|
+
react: "19.0.0",
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("detects install-relevant package metadata changes", () => {
|
|
83
|
+
const basePackageJson = {
|
|
84
|
+
dependencies: {
|
|
85
|
+
react: "19.0.0",
|
|
86
|
+
},
|
|
87
|
+
overrides: {
|
|
88
|
+
lodash: "4.17.20",
|
|
89
|
+
},
|
|
90
|
+
pnpm: {
|
|
91
|
+
overrides: {
|
|
92
|
+
axios: "1.12.0",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const before = packageJsonSnapshot(basePackageJson);
|
|
98
|
+
const after = packageJsonSnapshot({
|
|
99
|
+
...basePackageJson,
|
|
100
|
+
overrides: {
|
|
101
|
+
lodash: "4.17.21",
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("detects package-manager-specific install metadata changes", () => {
|
|
109
|
+
const before = packageJsonSnapshot({
|
|
110
|
+
dependencies: {
|
|
111
|
+
react: "19.0.0",
|
|
112
|
+
},
|
|
113
|
+
pnpm: {
|
|
114
|
+
overrides: {
|
|
115
|
+
axios: "1.12.0",
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const after = packageJsonSnapshot({
|
|
121
|
+
dependencies: {
|
|
122
|
+
react: "19.0.0",
|
|
123
|
+
},
|
|
124
|
+
pnpm: {
|
|
125
|
+
overrides: {
|
|
126
|
+
axios: "1.13.2",
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("detects devEngines package manager changes", () => {
|
|
135
|
+
const before = packageJsonSnapshot({
|
|
136
|
+
dependencies: {
|
|
137
|
+
react: "19.0.0",
|
|
138
|
+
},
|
|
139
|
+
devEngines: {
|
|
140
|
+
packageManager: {
|
|
141
|
+
name: "npm",
|
|
142
|
+
version: "10.0.0",
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const after = packageJsonSnapshot({
|
|
148
|
+
dependencies: {
|
|
149
|
+
react: "19.0.0",
|
|
150
|
+
},
|
|
151
|
+
devEngines: {
|
|
152
|
+
packageManager: {
|
|
153
|
+
name: "pnpm",
|
|
154
|
+
version: "10.0.0",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("omits undefined object values when serializing snapshots", () => {
|
|
163
|
+
const before = packageJsonSnapshot({
|
|
164
|
+
dependencies: {
|
|
165
|
+
react: "19.0.0",
|
|
166
|
+
removed: undefined,
|
|
167
|
+
},
|
|
168
|
+
pnpm: {
|
|
169
|
+
onlyBuiltDependencies: ["esbuild", undefined],
|
|
170
|
+
overrides: undefined,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
const after = packageJsonSnapshot({
|
|
174
|
+
dependencies: {
|
|
175
|
+
react: "19.0.0",
|
|
176
|
+
},
|
|
177
|
+
pnpm: {
|
|
178
|
+
onlyBuiltDependencies: ["esbuild", null],
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
expect(before.value).not.toContain("undefined");
|
|
183
|
+
expect(didPackageJsonSnapshotChange(before, after)).toBe(false);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("matches read-pkg bundle dependency alias normalization", async () => {
|
|
187
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "pkg-json-"));
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
await fs.writeFile(
|
|
191
|
+
path.join(tmpDir, "package.json"),
|
|
192
|
+
JSON.stringify({
|
|
193
|
+
name: "test-app",
|
|
194
|
+
version: "1.0.0",
|
|
195
|
+
dependencies: {
|
|
196
|
+
react: "19.0.0",
|
|
197
|
+
},
|
|
198
|
+
bundledDependencies: ["react"],
|
|
199
|
+
}),
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
const before = await readPackageJsonSnapshotWithSource(tmpDir);
|
|
203
|
+
const { readPackage } = await import("read-pkg");
|
|
204
|
+
const after = packageJsonSnapshot(await readPackage({ cwd: tmpDir }));
|
|
205
|
+
|
|
206
|
+
expect(didPackageJsonSnapshotChange(before.snapshot, after)).toBe(false);
|
|
207
|
+
} finally {
|
|
208
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe("restoreManagedPackageDependencies", () => {
|
|
214
|
+
it("preserves the restored package.json indentation when rewriting managed packages", async () => {
|
|
215
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "pkg-json-"));
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
await fs.writeFile(
|
|
219
|
+
path.join(tmpDir, "package.json"),
|
|
220
|
+
JSON.stringify(
|
|
221
|
+
{
|
|
222
|
+
name: "restored-app",
|
|
223
|
+
dependencies: {
|
|
224
|
+
"@superblocksteam/library": "1.0.0",
|
|
225
|
+
react: "19.0.0",
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
null,
|
|
229
|
+
4,
|
|
230
|
+
) + "\n",
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
await restoreManagedPackageDependencies(tmpDir, {
|
|
234
|
+
dependencies: {
|
|
235
|
+
"@superblocksteam/library": "2.0.0",
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const restored = await fs.readFile(
|
|
240
|
+
path.join(tmpDir, "package.json"),
|
|
241
|
+
"utf-8",
|
|
242
|
+
);
|
|
243
|
+
expect(restored).toContain('\n "dependencies"');
|
|
244
|
+
expect(restored).toContain('\n "@superblocksteam/library"');
|
|
245
|
+
expect(restored.endsWith("\n")).toBe(true);
|
|
246
|
+
} finally {
|
|
247
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type * as NodeChildProcess from "node:child_process";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { PassThrough } from "node:stream";
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
const { spawnMock } = vi.hoisted(() => ({
|
|
8
|
+
spawnMock: vi.fn(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
vi.mock("node:child_process", async () => {
|
|
12
|
+
const actual =
|
|
13
|
+
await vi.importActual<typeof NodeChildProcess>("node:child_process");
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
...actual,
|
|
17
|
+
default: {
|
|
18
|
+
...actual,
|
|
19
|
+
spawn: spawnMock,
|
|
20
|
+
},
|
|
21
|
+
spawn: spawnMock,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function createMockProcess() {
|
|
26
|
+
return Object.assign(new EventEmitter(), {
|
|
27
|
+
stdin: new PassThrough(),
|
|
28
|
+
stdout: new PassThrough(),
|
|
29
|
+
stderr: new PassThrough(),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe("createWorkspacePersistArchive", () => {
|
|
34
|
+
it("excludes node_modules from the tar archive", async () => {
|
|
35
|
+
const tarProc = createMockProcess();
|
|
36
|
+
const zstdProc = createMockProcess();
|
|
37
|
+
spawnMock.mockImplementation((command: string) => {
|
|
38
|
+
if (command === "tar") {
|
|
39
|
+
queueMicrotask(() => tarProc.emit("close", 0));
|
|
40
|
+
return tarProc;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
queueMicrotask(() => {
|
|
44
|
+
zstdProc.stdout.emit("data", Buffer.from("archive"));
|
|
45
|
+
zstdProc.emit("close", 0);
|
|
46
|
+
});
|
|
47
|
+
return zstdProc;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const { createWorkspacePersistArchive } = await import("./dev-server.mjs");
|
|
51
|
+
|
|
52
|
+
await expect(createWorkspacePersistArchive("/workspace")).resolves.toEqual(
|
|
53
|
+
Buffer.from("archive"),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const tarCall = spawnMock.mock.calls.find(([command]) => command === "tar");
|
|
57
|
+
expect(tarCall).toBeDefined();
|
|
58
|
+
expect(tarCall?.[1]).toEqual([
|
|
59
|
+
"cf",
|
|
60
|
+
"-",
|
|
61
|
+
"--exclude",
|
|
62
|
+
".git",
|
|
63
|
+
"--exclude",
|
|
64
|
+
"node_modules",
|
|
65
|
+
"--exclude",
|
|
66
|
+
".superblocks",
|
|
67
|
+
"-C",
|
|
68
|
+
"/workspace",
|
|
69
|
+
".",
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("rejects if tar fails after zstd closes successfully", async () => {
|
|
74
|
+
const tarProc = createMockProcess();
|
|
75
|
+
const zstdProc = createMockProcess();
|
|
76
|
+
spawnMock.mockImplementation((command: string) => {
|
|
77
|
+
if (command === "tar") {
|
|
78
|
+
return tarProc;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
queueMicrotask(() => {
|
|
82
|
+
zstdProc.emit("close", 0);
|
|
83
|
+
zstdProc.stderr.emit("data", Buffer.from("zstd diagnostic"));
|
|
84
|
+
tarProc.stderr.emit("data", Buffer.from("tar failed"));
|
|
85
|
+
tarProc.emit("close", 2);
|
|
86
|
+
});
|
|
87
|
+
return zstdProc;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const { createWorkspacePersistArchive } = await import("./dev-server.mjs");
|
|
91
|
+
|
|
92
|
+
await expect(
|
|
93
|
+
createWorkspacePersistArchive("/workspace"),
|
|
94
|
+
).rejects.toThrowError(/^tar archival failed \(code 2\): tar failed$/);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -48,6 +48,10 @@ import {
|
|
|
48
48
|
customComponentsPlugin,
|
|
49
49
|
isCustomComponentsEnabled,
|
|
50
50
|
} from "./custom-build.mjs";
|
|
51
|
+
import {
|
|
52
|
+
formatViteDevServerStartedLog,
|
|
53
|
+
logViteBuildError,
|
|
54
|
+
} from "./vite-dev-server-diagnostics.mjs";
|
|
51
55
|
import { buildManifestStubPlugin } from "./vite-plugin-build-manifest-stub.mjs";
|
|
52
56
|
import { ddRumPlugin } from "./vite-plugin-dd-rum.mjs";
|
|
53
57
|
|
|
@@ -119,6 +123,96 @@ function vitePlugins(
|
|
|
119
123
|
];
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
export async function createWorkspacePersistArchive(root: string) {
|
|
127
|
+
// Warm pods already have template dependencies installed, so persist only
|
|
128
|
+
// user workspace files and let startup reconcile package drift if needed.
|
|
129
|
+
return new Promise<Buffer>((resolveArchive, rejectArchive) => {
|
|
130
|
+
const tarProc = child_process.spawn(
|
|
131
|
+
"tar",
|
|
132
|
+
[
|
|
133
|
+
"cf",
|
|
134
|
+
"-",
|
|
135
|
+
"--exclude",
|
|
136
|
+
".git",
|
|
137
|
+
"--exclude",
|
|
138
|
+
"node_modules",
|
|
139
|
+
"--exclude",
|
|
140
|
+
".superblocks",
|
|
141
|
+
"-C",
|
|
142
|
+
root,
|
|
143
|
+
".",
|
|
144
|
+
],
|
|
145
|
+
{ stdio: ["ignore", "pipe", "pipe"] },
|
|
146
|
+
);
|
|
147
|
+
const zstdProc = child_process.spawn("zstd", ["-1", "--no-progress"], {
|
|
148
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
149
|
+
});
|
|
150
|
+
let settled = false;
|
|
151
|
+
let tarExitCode: number | null | undefined;
|
|
152
|
+
let zstdExitCode: number | null | undefined;
|
|
153
|
+
const rejectOnce = (error: Error) => {
|
|
154
|
+
if (settled) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
settled = true;
|
|
158
|
+
rejectArchive(error);
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
tarProc.stdout.pipe(zstdProc.stdin);
|
|
162
|
+
|
|
163
|
+
// Attach error handlers on the piped stdin. ChildProcess-level 'error'
|
|
164
|
+
// events don't catch stream errors like EPIPE from writing to a closed
|
|
165
|
+
// pipe if the downstream process crashes.
|
|
166
|
+
zstdProc.stdin.on("error", (err) => {
|
|
167
|
+
rejectOnce(new Error(`zstd stdin stream error: ${err.message}`));
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
const chunks: Buffer[] = [];
|
|
171
|
+
zstdProc.stdout.on("data", (chunk: Buffer) => chunks.push(chunk));
|
|
172
|
+
|
|
173
|
+
let tarStderr = "";
|
|
174
|
+
let zstdStderr = "";
|
|
175
|
+
tarProc.stderr.on("data", (chunk: Buffer) => {
|
|
176
|
+
tarStderr += chunk.toString();
|
|
177
|
+
});
|
|
178
|
+
zstdProc.stderr.on("data", (chunk: Buffer) => {
|
|
179
|
+
zstdStderr += chunk.toString();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const finishIfClosed = () => {
|
|
183
|
+
if (settled || tarExitCode === undefined || zstdExitCode === undefined) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
settled = true;
|
|
187
|
+
if (zstdExitCode !== 0) {
|
|
188
|
+
rejectArchive(
|
|
189
|
+
new Error(
|
|
190
|
+
`zstd compression failed (code ${zstdExitCode}): ${zstdStderr}`,
|
|
191
|
+
),
|
|
192
|
+
);
|
|
193
|
+
} else if (tarExitCode !== 0) {
|
|
194
|
+
rejectArchive(
|
|
195
|
+
new Error(`tar archival failed (code ${tarExitCode}): ${tarStderr}`),
|
|
196
|
+
);
|
|
197
|
+
} else {
|
|
198
|
+
resolveArchive(Buffer.concat(chunks));
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
tarProc.on("close", (code) => {
|
|
203
|
+
tarExitCode = code;
|
|
204
|
+
finishIfClosed();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
zstdProc.on("close", (code) => {
|
|
208
|
+
zstdExitCode = code;
|
|
209
|
+
finishIfClosed();
|
|
210
|
+
});
|
|
211
|
+
tarProc.on("error", rejectOnce);
|
|
212
|
+
zstdProc.on("error", rejectOnce);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
122
216
|
export const RESTART_EXIT_CODE = 98;
|
|
123
217
|
|
|
124
218
|
function getJwksUriWithBaseUrl(superblocksBaseUrl?: string): string {
|
|
@@ -587,79 +681,7 @@ export async function createDevServer({
|
|
|
587
681
|
|
|
588
682
|
logger.info("/_sb_persist: archiving and uploading workspace to S3...");
|
|
589
683
|
|
|
590
|
-
|
|
591
|
-
// then stream directly to S3 via presigned PUT URL.
|
|
592
|
-
const archive = await new Promise<Buffer>(
|
|
593
|
-
(resolveArchive, rejectArchive) => {
|
|
594
|
-
const tarProc = child_process.spawn(
|
|
595
|
-
"tar",
|
|
596
|
-
[
|
|
597
|
-
"cf",
|
|
598
|
-
"-",
|
|
599
|
-
"--exclude",
|
|
600
|
-
".git",
|
|
601
|
-
"--exclude",
|
|
602
|
-
"node_modules/.cache",
|
|
603
|
-
"--exclude",
|
|
604
|
-
".superblocks",
|
|
605
|
-
"-C",
|
|
606
|
-
process.cwd(),
|
|
607
|
-
".",
|
|
608
|
-
],
|
|
609
|
-
{ stdio: ["ignore", "pipe", "pipe"] },
|
|
610
|
-
);
|
|
611
|
-
const zstdProc = child_process.spawn(
|
|
612
|
-
"zstd",
|
|
613
|
-
["-1", "--no-progress"],
|
|
614
|
-
{
|
|
615
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
616
|
-
},
|
|
617
|
-
);
|
|
618
|
-
|
|
619
|
-
tarProc.stdout.pipe(zstdProc.stdin);
|
|
620
|
-
|
|
621
|
-
// Attach error handlers on the piped stdin. ChildProcess-level 'error'
|
|
622
|
-
// events don't catch stream errors like EPIPE from writing to a closed
|
|
623
|
-
// pipe if the downstream process crashes.
|
|
624
|
-
zstdProc.stdin.on("error", (err) => {
|
|
625
|
-
rejectArchive(new Error(`zstd stdin stream error: ${err.message}`));
|
|
626
|
-
});
|
|
627
|
-
|
|
628
|
-
const chunks: Buffer[] = [];
|
|
629
|
-
zstdProc.stdout.on("data", (chunk: Buffer) => chunks.push(chunk));
|
|
630
|
-
|
|
631
|
-
let stderr = "";
|
|
632
|
-
tarProc.stderr.on("data", (chunk: Buffer) => {
|
|
633
|
-
stderr += chunk.toString();
|
|
634
|
-
});
|
|
635
|
-
zstdProc.stderr.on("data", (chunk: Buffer) => {
|
|
636
|
-
stderr += chunk.toString();
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
let tarExitCode: number | null = null;
|
|
640
|
-
tarProc.on("close", (code) => {
|
|
641
|
-
tarExitCode = code;
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
zstdProc.on("close", (code) => {
|
|
645
|
-
if (code !== 0) {
|
|
646
|
-
rejectArchive(
|
|
647
|
-
new Error(`zstd compression failed (code ${code}): ${stderr}`),
|
|
648
|
-
);
|
|
649
|
-
} else if (tarExitCode !== null && tarExitCode !== 0) {
|
|
650
|
-
rejectArchive(
|
|
651
|
-
new Error(
|
|
652
|
-
`tar archival failed (code ${tarExitCode}): ${stderr}`,
|
|
653
|
-
),
|
|
654
|
-
);
|
|
655
|
-
} else {
|
|
656
|
-
resolveArchive(Buffer.concat(chunks));
|
|
657
|
-
}
|
|
658
|
-
});
|
|
659
|
-
tarProc.on("error", rejectArchive);
|
|
660
|
-
zstdProc.on("error", rejectArchive);
|
|
661
|
-
},
|
|
662
|
-
);
|
|
684
|
+
const archive = await createWorkspacePersistArchive(process.cwd());
|
|
663
685
|
|
|
664
686
|
logger.info(
|
|
665
687
|
`/_sb_persist: archive created (${(archive.length / 1024 / 1024).toFixed(1)}MB) in ${Date.now() - persistStart}ms, uploading...`,
|
|
@@ -833,7 +855,11 @@ async function startVite({
|
|
|
833
855
|
logger.warn(msg);
|
|
834
856
|
};
|
|
835
857
|
viteLogger.error = (msg: string) => {
|
|
836
|
-
logger
|
|
858
|
+
logViteBuildError(logger, {
|
|
859
|
+
rawMessage: msg,
|
|
860
|
+
sdkVersion: pkg.version,
|
|
861
|
+
viteRootBasename: path.basename(root),
|
|
862
|
+
});
|
|
837
863
|
};
|
|
838
864
|
|
|
839
865
|
viteLogger.clearScreen = () => {};
|
|
@@ -954,7 +980,12 @@ async function startVite({
|
|
|
954
980
|
|
|
955
981
|
const routeIndex = (app._router as IRouter).stack.length;
|
|
956
982
|
app.use(viteServer.middlewares);
|
|
957
|
-
logger.info(
|
|
983
|
+
logger.info(
|
|
984
|
+
`${formatViteDevServerStartedLog({
|
|
985
|
+
sdkVersion: pkg.version,
|
|
986
|
+
viteRootBasename: path.basename(root),
|
|
987
|
+
})} Dev server created and middleware attached successfully`,
|
|
988
|
+
);
|
|
958
989
|
|
|
959
990
|
return {
|
|
960
991
|
viteServer,
|