@xgsd/workers 0.1.0-beta.0
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/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/chunk-QLD3WJX5.js +45 -0
- package/dist/chunk-QLD3WJX5.js.map +1 -0
- package/dist/index.cjs +211 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +180 -0
- package/dist/index.js.map +1 -0
- package/dist/process/workers.process.cjs +382 -0
- package/dist/process/workers.process.cjs.map +1 -0
- package/dist/process/workers.process.d.cts +8 -0
- package/dist/process/workers.process.d.ts +8 -0
- package/dist/process/workers.process.js +325 -0
- package/dist/process/workers.process.js.map +1 -0
- package/dist/types-Buhg0r3s.d.cts +57 -0
- package/dist/types-Buhg0r3s.d.ts +57 -0
- package/package.json +52 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pathExists,
|
|
3
|
+
pathExistsSync,
|
|
4
|
+
readJsonSync,
|
|
5
|
+
writeJsonSync
|
|
6
|
+
} from "../chunk-QLD3WJX5.js";
|
|
7
|
+
|
|
8
|
+
// src/process/workers.process.ts
|
|
9
|
+
import { join as join2 } from "path";
|
|
10
|
+
|
|
11
|
+
// src/bundler.ts
|
|
12
|
+
import { createHash, timingSafeEqual } from "crypto";
|
|
13
|
+
import path, { join, relative, sep } from "path";
|
|
14
|
+
import { readdir, readFile, stat } from "fs/promises";
|
|
15
|
+
import { createRequire } from "module";
|
|
16
|
+
async function createBundle({
|
|
17
|
+
project,
|
|
18
|
+
dist,
|
|
19
|
+
cwd,
|
|
20
|
+
entry,
|
|
21
|
+
cacheStrategy,
|
|
22
|
+
log
|
|
23
|
+
}) {
|
|
24
|
+
const start = performance.now();
|
|
25
|
+
const xgsd = join(project, dist ?? ".xgsd");
|
|
26
|
+
const out = join(xgsd, "bundle.js");
|
|
27
|
+
const entryFile = join(project, entry);
|
|
28
|
+
const packageJsonPath = join(project, "package.json");
|
|
29
|
+
const outPathRel = join(dist ?? ".xgsd", "bundle.js");
|
|
30
|
+
const hash = await calculateProjectHash(project);
|
|
31
|
+
const outdir = path.dirname(out);
|
|
32
|
+
const packageJson = await readJsonSync(packageJsonPath);
|
|
33
|
+
const outPackageJsonPath = join(outdir, "package.json");
|
|
34
|
+
const cacheFilesExist = pathExistsSync(outPackageJsonPath) && pathExistsSync(out);
|
|
35
|
+
if (cacheFilesExist && cacheStrategy === "always") {
|
|
36
|
+
console.log(`${outPathRel} loaded from cache (set cache.strategy = "never" if this is unintentional)`);
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
if (cacheFilesExist && cacheStrategy === "change") {
|
|
40
|
+
const outPackageJson = readJsonSync(outPackageJsonPath);
|
|
41
|
+
if (outPackageJson.hash && safeHashCompare(outPackageJson.hash, hash)) {
|
|
42
|
+
console.log(`${outPathRel} loaded from cache (set cache.strategy = "never" if this is unintentional)`);
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const dependencies = Object.entries(readJsonSync(packageJsonPath).dependencies).map((d) => d[0]);
|
|
47
|
+
const generated = (/* @__PURE__ */ new Date()).toISOString();
|
|
48
|
+
await bundle({
|
|
49
|
+
entry: entryFile,
|
|
50
|
+
out,
|
|
51
|
+
banner: {
|
|
52
|
+
generated,
|
|
53
|
+
hash
|
|
54
|
+
},
|
|
55
|
+
format: "esm",
|
|
56
|
+
dependencies
|
|
57
|
+
});
|
|
58
|
+
writeJsonSync(path.join(outdir, "package.json"), {
|
|
59
|
+
...packageJson,
|
|
60
|
+
hash,
|
|
61
|
+
generated,
|
|
62
|
+
type: "module"
|
|
63
|
+
});
|
|
64
|
+
const ms = performance.now() - start;
|
|
65
|
+
console.log(`[bundler] copied package.json to ${join(dist ?? ".xgsd", "package.json")}`);
|
|
66
|
+
console.log(`[bundler] ${entry} bundled to ${outPathRel}`);
|
|
67
|
+
console.log(`[bundler] completed in ${ms.toFixed(2)}ms.`);
|
|
68
|
+
if (cacheStrategy === "never") {
|
|
69
|
+
console.warn(`[bundler] (warn) you can speed this up with bundler.cache.strategy = always|change.`);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
function bannerLines(object) {
|
|
74
|
+
const lines = [];
|
|
75
|
+
lines.push(" * xGSD bundle.js");
|
|
76
|
+
for (const key of Object.keys(object)) {
|
|
77
|
+
lines.push(` * ${key}: ${object[key]}`);
|
|
78
|
+
}
|
|
79
|
+
lines.push(" * WARNING: this file is generated. Do not edit manually.");
|
|
80
|
+
return lines.join("\r\n");
|
|
81
|
+
}
|
|
82
|
+
function resolveDependency(dependency, projectRoot) {
|
|
83
|
+
try {
|
|
84
|
+
const require2 = createRequire(projectRoot);
|
|
85
|
+
return require2(dependency);
|
|
86
|
+
} catch {
|
|
87
|
+
}
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Could not resolve ${dependency}.
|
|
90
|
+
Install it with \`yarn add ${dependency}\` or re-install @xgsd/cli
|
|
91
|
+
Path: ${projectRoot}.`
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
async function calculateProjectHash(project) {
|
|
95
|
+
const hashes = await collectProjectHashes(project, {
|
|
96
|
+
ignore: ["node_modules", ".xgsd", "dist", ".git"],
|
|
97
|
+
filter: (path2) => path2.endsWith(".js") || path2.endsWith(".ts")
|
|
98
|
+
});
|
|
99
|
+
const normalised = hashes.map((h) => h.hash.trim().slice(0, 9)).sort().join("|");
|
|
100
|
+
return createHash("sha256").update(normalised).digest("hex");
|
|
101
|
+
}
|
|
102
|
+
async function collectProjectHashes(projectPath, options = {}) {
|
|
103
|
+
const { ignore = ["node_modules"], filter = () => true } = options;
|
|
104
|
+
const files = [];
|
|
105
|
+
const ignored = new Set(ignore);
|
|
106
|
+
const shouldIgnore = (target) => {
|
|
107
|
+
const parts = relative(projectPath, target).split(sep);
|
|
108
|
+
return parts.some((part) => ignored.has(part));
|
|
109
|
+
};
|
|
110
|
+
const hashFile = async (filePath) => {
|
|
111
|
+
const buffer = await readFile(filePath);
|
|
112
|
+
return createHash("sha256").update(buffer).digest("hex");
|
|
113
|
+
};
|
|
114
|
+
const visit = async (current) => {
|
|
115
|
+
if (shouldIgnore(current)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const entries = await readdir(current);
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
const fullPath = join(current, entry);
|
|
121
|
+
if (shouldIgnore(fullPath)) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const info = await stat(fullPath);
|
|
125
|
+
if (info.isDirectory()) {
|
|
126
|
+
await visit(fullPath);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (!info.isFile()) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const path2 = relative(projectPath, fullPath);
|
|
133
|
+
if (!filter(path2)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
files.push({
|
|
137
|
+
path: path2,
|
|
138
|
+
hash: await hashFile(fullPath),
|
|
139
|
+
size: info.size
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
await visit(projectPath);
|
|
144
|
+
return files.sort((a, b) => a.path.localeCompare(b.path));
|
|
145
|
+
}
|
|
146
|
+
function safeHashCompare(a, b) {
|
|
147
|
+
const abuf = Buffer.from(a, "hex");
|
|
148
|
+
const bbuf = Buffer.from(b, "hex");
|
|
149
|
+
return timingSafeEqual(abuf, bbuf);
|
|
150
|
+
}
|
|
151
|
+
async function bundle(options) {
|
|
152
|
+
const { dependencies } = options;
|
|
153
|
+
const esbuild = resolveDependency("esbuild", path.dirname(options.entry));
|
|
154
|
+
if (esbuild.version) {
|
|
155
|
+
console.log(`[bundler] building with esbuild@${esbuild.version}`);
|
|
156
|
+
}
|
|
157
|
+
return esbuild.build({
|
|
158
|
+
keepNames: true,
|
|
159
|
+
entryPoints: [options.entry],
|
|
160
|
+
bundle: true,
|
|
161
|
+
platform: "node",
|
|
162
|
+
outfile: options.out,
|
|
163
|
+
format: options.format,
|
|
164
|
+
minify: false,
|
|
165
|
+
sourcemap: false,
|
|
166
|
+
external: dependencies,
|
|
167
|
+
banner: {
|
|
168
|
+
js: `
|
|
169
|
+
/**
|
|
170
|
+
${bannerLines(options.banner)}
|
|
171
|
+
*/
|
|
172
|
+
`.trim()
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/compose.ts
|
|
178
|
+
function compose(middleware) {
|
|
179
|
+
return async function run(ctx2) {
|
|
180
|
+
let index = -1;
|
|
181
|
+
let res = {
|
|
182
|
+
version: "v1",
|
|
183
|
+
ok: void 0,
|
|
184
|
+
result: void 0,
|
|
185
|
+
error: void 0,
|
|
186
|
+
duration: void 0
|
|
187
|
+
};
|
|
188
|
+
const { execute } = resolveDependency("@xgsd/engine", ctx2.cwd);
|
|
189
|
+
async function dispatch2(i) {
|
|
190
|
+
if (i <= index) {
|
|
191
|
+
throw new Error("next() called multiple times");
|
|
192
|
+
}
|
|
193
|
+
index = i;
|
|
194
|
+
const fn = middleware[i];
|
|
195
|
+
if (!fn) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const executeWrapper = async (ctx3) => {
|
|
199
|
+
await fn(ctx3, async () => {
|
|
200
|
+
await dispatch2(i + 1);
|
|
201
|
+
});
|
|
202
|
+
return ctx3;
|
|
203
|
+
};
|
|
204
|
+
const result = await execute(ctx2, executeWrapper);
|
|
205
|
+
if (result.error || result.data?.error) {
|
|
206
|
+
res.ok = false;
|
|
207
|
+
res.code = ctx2.code;
|
|
208
|
+
res.result = null;
|
|
209
|
+
res.error = result.error ?? result.data?.error;
|
|
210
|
+
}
|
|
211
|
+
if (result.data && result.data.result) {
|
|
212
|
+
res.ok = true;
|
|
213
|
+
res.code = ctx2.code;
|
|
214
|
+
res.result = result.data.result;
|
|
215
|
+
res.error = result.error ?? result.data?.error;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
await dispatch2(0);
|
|
219
|
+
return res;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/process/workers.process.ts
|
|
224
|
+
function dispatch(event, payload) {
|
|
225
|
+
process.send?.({
|
|
226
|
+
type: event,
|
|
227
|
+
...payload
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
function startHeartbeat(interval = 50) {
|
|
231
|
+
return setInterval(() => {
|
|
232
|
+
const memory = process.memoryUsage();
|
|
233
|
+
dispatch("ALIVE", {
|
|
234
|
+
pid: process.pid,
|
|
235
|
+
uptime: process.uptime(),
|
|
236
|
+
memory: {
|
|
237
|
+
rss: memory.rss,
|
|
238
|
+
heapUsed: memory.heapUsed,
|
|
239
|
+
heapTotal: memory.heapTotal,
|
|
240
|
+
external: memory.external
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}, interval);
|
|
244
|
+
}
|
|
245
|
+
function wrapper(fn) {
|
|
246
|
+
const { execute } = resolveDependency("@xgsd/engine", ctx.cwd);
|
|
247
|
+
return async (ctx2, next) => {
|
|
248
|
+
const res = await execute(ctx2.data, fn);
|
|
249
|
+
ctx2.result = res.data;
|
|
250
|
+
ctx2.error = res.error;
|
|
251
|
+
await next();
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
async function main(ctx2) {
|
|
255
|
+
const heartbeat = startHeartbeat();
|
|
256
|
+
const { entry, cwd } = ctx2;
|
|
257
|
+
let entryFile = join2(cwd ?? "", entry);
|
|
258
|
+
try {
|
|
259
|
+
if (!await pathExists(entryFile)) {
|
|
260
|
+
const error = {
|
|
261
|
+
code: "CODE_INVALID_ENTRY_FILE" /* CODE_INVALID_ENTRY_FILE */,
|
|
262
|
+
message: "entry file not found",
|
|
263
|
+
type: "user"
|
|
264
|
+
};
|
|
265
|
+
dispatch("ERROR", { error });
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
if (ctx2.bundler?.enabled) {
|
|
269
|
+
entryFile = await createBundle({
|
|
270
|
+
project: cwd,
|
|
271
|
+
dist: ctx2.dist,
|
|
272
|
+
entry,
|
|
273
|
+
cacheStrategy: ctx2.bundler?.cache?.strategy ?? "never"
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
let mod = void 0;
|
|
277
|
+
try {
|
|
278
|
+
mod = await import(entryFile);
|
|
279
|
+
} catch (error) {
|
|
280
|
+
}
|
|
281
|
+
if (!mod || !mod.default || typeof mod.default !== "function") {
|
|
282
|
+
const error = {
|
|
283
|
+
code: "CODE_INVALID_DEFAULT_FUNCTION" /* CODE_INVALID_DEFAULT_FUNCTION */,
|
|
284
|
+
message: "default must be a function",
|
|
285
|
+
type: "user"
|
|
286
|
+
};
|
|
287
|
+
dispatch("ERROR", { error });
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
let middleware = [];
|
|
291
|
+
if (mod.middleware && typeof mod.middleware === "function") {
|
|
292
|
+
const start2 = performance.now();
|
|
293
|
+
middleware = mod.middleware() ?? [];
|
|
294
|
+
if (!Array.isArray(middleware) || middleware.filter((m) => typeof m !== "function").length > 0) {
|
|
295
|
+
const error = {
|
|
296
|
+
code: "CODE_INVALID_MIDDLEWARE_FUNCTION" /* CODE_INVALID_MIDDLEWARE_FUNCTION */,
|
|
297
|
+
message: "middleware not configured correctly",
|
|
298
|
+
type: "user"
|
|
299
|
+
};
|
|
300
|
+
dispatch("ERROR", { error });
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const dt = (performance.now() - start2).toFixed(2);
|
|
304
|
+
console.log(`[middleware] ${middleware.length} functions registered in ${dt} ms`);
|
|
305
|
+
}
|
|
306
|
+
const runtime = compose([...middleware, wrapper(mod.default)]);
|
|
307
|
+
console.log(`[runtime] started running worker`);
|
|
308
|
+
const start = performance.now();
|
|
309
|
+
const result = await runtime(ctx2);
|
|
310
|
+
const ms = performance.now() - start;
|
|
311
|
+
console.log(`[runtime] finished running worker took ${ms.toFixed(2)} ms`);
|
|
312
|
+
if (result.error) {
|
|
313
|
+
console.warn(`[runtime] finished with errors (error: ${ctx2.error?.message ?? "unknown"})`);
|
|
314
|
+
}
|
|
315
|
+
dispatch("DONE", { result });
|
|
316
|
+
} finally {
|
|
317
|
+
clearInterval(heartbeat);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
var ctx = JSON.parse(process.env.XGSD_CTX);
|
|
321
|
+
main(ctx);
|
|
322
|
+
export {
|
|
323
|
+
wrapper
|
|
324
|
+
};
|
|
325
|
+
//# sourceMappingURL=workers.process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/process/workers.process.ts","../../src/bundler.ts","../../src/compose.ts"],"sourcesContent":["import {join} from 'path'\nimport {createBundle, resolveDependency} from '../bundler'\nimport {compose, Next} from '../compose'\nimport {WorkerContext, WorkerError, WorkerErrorCode} from '../types'\nimport {pathExists} from '../util/fs'\n\nexport type RunFn<T> = (data: T) => Promise<any>\n\nfunction dispatch(event: 'ALIVE' | 'DONE' | 'ERROR', payload: any) {\n process.send?.({\n type: event,\n ...payload,\n })\n}\n\nfunction startHeartbeat(interval = 50) {\n return setInterval(() => {\n const memory = process.memoryUsage()\n\n dispatch('ALIVE', {\n pid: process.pid,\n uptime: process.uptime(),\n memory: {\n rss: memory.rss,\n heapUsed: memory.heapUsed,\n heapTotal: memory.heapTotal,\n external: memory.external,\n },\n })\n }, interval)\n}\n\nexport function wrapper(fn: RunFn<unknown>) {\n const {execute} = resolveDependency('@xgsd/engine', ctx.cwd!)\n\n return async (ctx: WorkerContext, next: Next) => {\n const res = await execute(ctx.data as any, fn)\n\n ctx.result = res.data\n ctx.error = res.error\n\n await next()\n }\n}\n\nasync function main(ctx: WorkerContext) {\n const heartbeat = startHeartbeat()\n\n const {entry, cwd} = ctx\n let entryFile = join(cwd ?? '', entry)\n\n try {\n if (!(await pathExists(entryFile))) {\n const error: WorkerError = {\n code: WorkerErrorCode.CODE_INVALID_ENTRY_FILE,\n message: 'entry file not found',\n type: 'user',\n }\n\n dispatch('ERROR', {error})\n return\n }\n\n // bundler\n if (ctx.bundler?.enabled) {\n entryFile = await createBundle({\n project: cwd!,\n dist: ctx.dist,\n entry,\n cacheStrategy: ctx.bundler?.cache?.strategy ?? 'never',\n })\n }\n\n let mod = undefined\n try {\n mod = await import(entryFile)\n } catch (error) {}\n\n if (!mod || !mod.default || typeof mod.default !== 'function') {\n const error: WorkerError = {\n code: WorkerErrorCode.CODE_INVALID_DEFAULT_FUNCTION,\n message: 'default must be a function',\n type: 'user',\n }\n\n dispatch('ERROR', {error})\n return\n }\n\n // load middleware\n let middleware = []\n if (mod.middleware && typeof mod.middleware === 'function') {\n const start = performance.now()\n middleware = mod.middleware() ?? []\n\n if (!Array.isArray(middleware) || middleware.filter((m) => typeof m !== 'function').length > 0) {\n const error: WorkerError = {\n code: WorkerErrorCode.CODE_INVALID_MIDDLEWARE_FUNCTION,\n message: 'middleware not configured correctly',\n type: 'user',\n }\n\n dispatch('ERROR', {error})\n return\n }\n\n const dt = (performance.now() - start).toFixed(2)\n console.log(`[middleware] ${middleware.length} functions registered in ${dt} ms`)\n }\n\n // runtime\n const runtime = compose([...middleware, wrapper(mod.default)])\n\n console.log(`[runtime] started running worker`)\n\n const start = performance.now()\n\n const result = await runtime(ctx)\n\n const ms = performance.now() - start\n console.log(`[runtime] finished running worker took ${ms.toFixed(2)} ms`)\n\n if (result.error) {\n console.warn(`[runtime] finished with errors (error: ${ctx.error?.message ?? 'unknown'})`)\n }\n\n dispatch('DONE', {result})\n } finally {\n clearInterval(heartbeat)\n }\n}\n\nconst ctx = JSON.parse(process.env.XGSD_CTX!) as WorkerContext\nmain(ctx)\n","import {createHash, timingSafeEqual} from 'crypto'\nimport path, {join, relative, sep} from 'path'\nimport {readdir, readFile, stat} from 'fs/promises'\nimport {pathExistsSync, readJsonSync, writeJsonSync} from './util/fs'\nimport {createRequire} from 'module'\n\nexport async function createBundle({\n project,\n dist,\n cwd,\n entry,\n cacheStrategy,\n log,\n}: {\n project: string\n dist?: string\n cwd?: string\n entry: string\n cacheStrategy: 'always' | 'change' | 'never'\n log?: boolean\n}): Promise<string> {\n const start = performance.now()\n\n const xgsd = join(project, dist ?? '.xgsd')\n const out = join(xgsd, 'bundle.js')\n const entryFile = join(project, entry)\n const packageJsonPath = join(project, 'package.json')\n const outPathRel = join(dist ?? '.xgsd', 'bundle.js')\n\n // v0.7 note\n // dont do this as it adds 20-30MB of memory before anything even runs\n // bundling is fine but current AST parsing/traversal is unneeded\n // instead split into two concerns: dependencies (from package.json) and code changes (from hashes)\n // do this instead:\n const hash = await calculateProjectHash(project)\n const outdir = path.dirname(out)\n\n const packageJson = await readJsonSync(packageJsonPath)\n\n const outPackageJsonPath = join(outdir, 'package.json')\n const cacheFilesExist = pathExistsSync(outPackageJsonPath) && pathExistsSync(out)\n\n if (cacheFilesExist && cacheStrategy === 'always') {\n console.log(`${outPathRel} loaded from cache (set cache.strategy = \"never\" if this is unintentional)`)\n\n return out\n }\n\n if (cacheFilesExist && cacheStrategy === 'change') {\n const outPackageJson = readJsonSync(outPackageJsonPath)\n\n if (outPackageJson.hash && safeHashCompare(outPackageJson.hash, hash)) {\n // cache hit\n\n console.log(`${outPathRel} loaded from cache (set cache.strategy = \"never\" if this is unintentional)`)\n\n return out\n }\n }\n\n const dependencies = Object.entries(readJsonSync(packageJsonPath).dependencies).map((d) => d[0])\n const generated = new Date().toISOString()\n\n // for now let esbuild notify of errors\n await bundle({\n entry: entryFile,\n out,\n banner: {\n generated,\n hash,\n },\n format: 'esm',\n dependencies,\n })\n\n writeJsonSync(path.join(outdir, 'package.json'), {\n ...packageJson,\n hash,\n generated,\n type: 'module',\n })\n\n const ms = performance.now() - start\n\n console.log(`[bundler] copied package.json to ${join(dist ?? '.xgsd', 'package.json')}`)\n console.log(`[bundler] ${entry} bundled to ${outPathRel}`)\n console.log(`[bundler] completed in ${ms.toFixed(2)}ms.`)\n\n if (cacheStrategy === 'never') {\n console.warn(`[bundler] (warn) you can speed this up with bundler.cache.strategy = always|change.`)\n }\n\n return out\n}\n\nfunction bannerLines(object: Record<string, string>) {\n const lines = []\n lines.push(' * xGSD bundle.js')\n for (const key of Object.keys(object)) {\n lines.push(` * ${key}: ${object[key]}`)\n }\n lines.push(' * WARNING: this file is generated. Do not edit manually.')\n return lines.join('\\r\\n')\n}\n\nexport function resolvePath(moduleName: string, root: string): string {\n return require.resolve(moduleName, {\n paths: [root],\n })\n}\n\nexport function resolveDependency(dependency: string, projectRoot: string): any {\n try {\n const require = createRequire(projectRoot)\n return require(dependency)\n } catch {}\n\n throw new Error(\n `Could not resolve ${dependency}.\\nInstall it with \\`yarn add ${dependency}\\` or re-install @xgsd/cli\\nPath: ${projectRoot}.`,\n )\n}\n\nexport type WalkedFile = {\n path: string\n hash: string\n size: number\n}\n\ntype WalkOptions = {\n ignore?: string[]\n filter?: (path: string) => boolean\n}\n\nexport async function calculateProjectHash(project: string): Promise<string> {\n const hashes = await collectProjectHashes(project, {\n ignore: ['node_modules', '.xgsd', 'dist', '.git'],\n filter: (path) => path.endsWith('.js') || path.endsWith('.ts'),\n })\n\n const normalised = hashes\n .map((h) => h.hash.trim().slice(0, 9))\n .sort()\n .join('|')\n\n return createHash('sha256').update(normalised).digest('hex')\n}\n\nexport async function collectProjectHashes(projectPath: string, options: WalkOptions = {}): Promise<WalkedFile[]> {\n const {ignore = ['node_modules'], filter = () => true} = options\n\n const files: WalkedFile[] = []\n\n const ignored = new Set(ignore)\n\n const shouldIgnore = (target: string) => {\n const parts = relative(projectPath, target).split(sep)\n\n return parts.some((part) => ignored.has(part))\n }\n\n const hashFile = async (filePath: string) => {\n const buffer = await readFile(filePath)\n\n return createHash('sha256').update(buffer).digest('hex')\n }\n\n const visit = async (current: string): Promise<void> => {\n if (shouldIgnore(current)) {\n return\n }\n\n const entries = await readdir(current)\n\n for (const entry of entries) {\n const fullPath = join(current, entry)\n\n if (shouldIgnore(fullPath)) {\n continue\n }\n\n const info = await stat(fullPath)\n\n if (info.isDirectory()) {\n await visit(fullPath)\n continue\n }\n\n if (!info.isFile()) {\n continue\n }\n\n const path = relative(projectPath, fullPath)\n\n if (!filter(path)) {\n continue\n }\n\n files.push({\n path,\n hash: await hashFile(fullPath),\n size: info.size,\n })\n }\n }\n\n await visit(projectPath)\n\n return files.sort((a, b) => a.path.localeCompare(b.path))\n}\n\nexport function safeHashCompare(a: string, b: string): boolean {\n const abuf = Buffer.from(a, 'hex')\n const bbuf = Buffer.from(b, 'hex')\n\n return timingSafeEqual(abuf, bbuf)\n}\n\nexport async function bundle(options: {\n entry: string\n out: string\n format: 'esm' | 'cjs'\n banner: Record<string, string>\n dependencies: string[]\n}) {\n const {dependencies} = options\n\n const esbuild = resolveDependency('esbuild', path.dirname(options.entry))\n\n if (esbuild.version) {\n console.log(`[bundler] building with esbuild@${esbuild.version}`)\n }\n\n return esbuild.build({\n keepNames: true,\n entryPoints: [options.entry],\n bundle: true,\n platform: 'node',\n outfile: options.out,\n format: options.format,\n minify: false,\n sourcemap: false,\n external: dependencies,\n banner: {\n js: `\n/**\n${bannerLines(options.banner)}\n */\n`.trim(),\n },\n })\n}\n","import {resolveDependency} from './bundler'\nimport {WorkerContext, WorkerResult} from './types'\n\nexport type Next = () => Promise<void>\n\nexport type Middleware = (ctx: WorkerContext, next: Next) => Promise<void>\n\nexport type ComposedMiddleware = (ctx: WorkerContext) => Promise<WorkerResult<unknown>>\n\nexport function compose(middleware: Middleware[]): ComposedMiddleware {\n return async function run(ctx: WorkerContext): Promise<WorkerResult<unknown>> {\n let index = -1\n\n let res: any = {\n version: 'v1',\n ok: undefined,\n result: undefined,\n error: undefined,\n duration: undefined,\n }\n\n const {execute} = resolveDependency('@xgsd/engine', ctx.cwd!)\n\n async function dispatch(i: number): Promise<void> {\n if (i <= index) {\n throw new Error('next() called multiple times')\n }\n\n index = i\n\n const fn = middleware[i]\n\n if (!fn) {\n return\n }\n\n const executeWrapper = async (ctx: WorkerContext) => {\n await fn(ctx, async () => {\n await dispatch(i + 1)\n })\n\n return ctx\n }\n\n const result = await execute(ctx, executeWrapper)\n\n if (result.error || result.data?.error) {\n res.ok = false\n res.code = ctx.code\n res.result = null\n res.error = result.error ?? result.data?.error\n }\n\n if (result.data && result.data.result) {\n res.ok = true\n res.code = ctx.code\n res.result = result.data.result\n res.error = result.error ?? result.data?.error\n }\n }\n\n await dispatch(0)\n\n return res\n }\n}\n"],"mappings":"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","names":["join","require","path","ctx","dispatch","ctx","join","start"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
declare enum WorkerErrorCode {
|
|
2
|
+
CODE_WORKER_GUARD = "CODE_WORKER_GUARD",
|
|
3
|
+
CODE_INVALID_ENTRY_FILE = "CODE_INVALID_ENTRY_FILE",
|
|
4
|
+
CODE_INVALID_DEFAULT_FUNCTION = "CODE_INVALID_DEFAULT_FUNCTION",
|
|
5
|
+
CODE_INVALID_MIDDLEWARE_FUNCTION = "CODE_INVALID_MIDDLEWARE_FUNCTION",
|
|
6
|
+
CODE_BUNDLE_ERROR = "CODE_BUNDLE_ERROR"
|
|
7
|
+
}
|
|
8
|
+
type WorkerErrorType = 'user' | 'system' | 'unknown';
|
|
9
|
+
type WorkerError = {
|
|
10
|
+
code?: WorkerErrorCode;
|
|
11
|
+
message?: string;
|
|
12
|
+
type?: WorkerErrorType;
|
|
13
|
+
};
|
|
14
|
+
type WorkerResult<T> = {
|
|
15
|
+
version: 'v1';
|
|
16
|
+
ok: true;
|
|
17
|
+
code?: number;
|
|
18
|
+
result: T;
|
|
19
|
+
error: null;
|
|
20
|
+
duration: number;
|
|
21
|
+
} | {
|
|
22
|
+
version: 'v1';
|
|
23
|
+
ok: false;
|
|
24
|
+
code?: number;
|
|
25
|
+
result: null;
|
|
26
|
+
error: WorkerError;
|
|
27
|
+
duration: number;
|
|
28
|
+
};
|
|
29
|
+
type WorkerConfig = {
|
|
30
|
+
entry: string;
|
|
31
|
+
dist?: string;
|
|
32
|
+
bundler?: {
|
|
33
|
+
enabled?: boolean;
|
|
34
|
+
cache?: {
|
|
35
|
+
strategy: 'never';
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
http?: {
|
|
39
|
+
enabled?: boolean;
|
|
40
|
+
};
|
|
41
|
+
limits?: {
|
|
42
|
+
ttl?: number;
|
|
43
|
+
memory?: number;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
type WorkerContext<T = unknown> = WorkerConfig & {
|
|
47
|
+
id?: string;
|
|
48
|
+
data: T;
|
|
49
|
+
cwd: string;
|
|
50
|
+
result?: any;
|
|
51
|
+
error?: any;
|
|
52
|
+
code?: number;
|
|
53
|
+
env?: Record<string, any>;
|
|
54
|
+
pid?: number;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type { WorkerResult as W, WorkerConfig as a, WorkerContext as b };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
declare enum WorkerErrorCode {
|
|
2
|
+
CODE_WORKER_GUARD = "CODE_WORKER_GUARD",
|
|
3
|
+
CODE_INVALID_ENTRY_FILE = "CODE_INVALID_ENTRY_FILE",
|
|
4
|
+
CODE_INVALID_DEFAULT_FUNCTION = "CODE_INVALID_DEFAULT_FUNCTION",
|
|
5
|
+
CODE_INVALID_MIDDLEWARE_FUNCTION = "CODE_INVALID_MIDDLEWARE_FUNCTION",
|
|
6
|
+
CODE_BUNDLE_ERROR = "CODE_BUNDLE_ERROR"
|
|
7
|
+
}
|
|
8
|
+
type WorkerErrorType = 'user' | 'system' | 'unknown';
|
|
9
|
+
type WorkerError = {
|
|
10
|
+
code?: WorkerErrorCode;
|
|
11
|
+
message?: string;
|
|
12
|
+
type?: WorkerErrorType;
|
|
13
|
+
};
|
|
14
|
+
type WorkerResult<T> = {
|
|
15
|
+
version: 'v1';
|
|
16
|
+
ok: true;
|
|
17
|
+
code?: number;
|
|
18
|
+
result: T;
|
|
19
|
+
error: null;
|
|
20
|
+
duration: number;
|
|
21
|
+
} | {
|
|
22
|
+
version: 'v1';
|
|
23
|
+
ok: false;
|
|
24
|
+
code?: number;
|
|
25
|
+
result: null;
|
|
26
|
+
error: WorkerError;
|
|
27
|
+
duration: number;
|
|
28
|
+
};
|
|
29
|
+
type WorkerConfig = {
|
|
30
|
+
entry: string;
|
|
31
|
+
dist?: string;
|
|
32
|
+
bundler?: {
|
|
33
|
+
enabled?: boolean;
|
|
34
|
+
cache?: {
|
|
35
|
+
strategy: 'never';
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
http?: {
|
|
39
|
+
enabled?: boolean;
|
|
40
|
+
};
|
|
41
|
+
limits?: {
|
|
42
|
+
ttl?: number;
|
|
43
|
+
memory?: number;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
type WorkerContext<T = unknown> = WorkerConfig & {
|
|
47
|
+
id?: string;
|
|
48
|
+
data: T;
|
|
49
|
+
cwd: string;
|
|
50
|
+
result?: any;
|
|
51
|
+
error?: any;
|
|
52
|
+
code?: number;
|
|
53
|
+
env?: Record<string, any>;
|
|
54
|
+
pid?: number;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type { WorkerResult as W, WorkerConfig as a, WorkerContext as b };
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xgsd/workers",
|
|
3
|
+
"description": "Super lightweight alternative to standard xGSD runtime. Optimised for queues/serverless vs project orchestration.",
|
|
4
|
+
"version": "0.1.0-beta.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"repository": "https://github.com/Isolated-/xgsd-workers",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"require": "./dist/index.cjs",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./process/workers.process": {
|
|
18
|
+
"require": "./dist/process/workers.process.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "yarn clean && tsup",
|
|
26
|
+
"clean": "rm -rf dist",
|
|
27
|
+
"test": "jest ./src",
|
|
28
|
+
"test:integration": "jest ./tests",
|
|
29
|
+
"test:e2e": "jest ./e2e"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@oclif/prettier-config": "^0.2.1",
|
|
33
|
+
"@types/jest": "^30.0.0",
|
|
34
|
+
"jest": "^29.x",
|
|
35
|
+
"ts-jest": "^29.x",
|
|
36
|
+
"ts-node": "^10.9.2",
|
|
37
|
+
"tsup": "^8.5.1",
|
|
38
|
+
"typescript": "^5.x"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"esbuild": "^0.28.0",
|
|
42
|
+
"@xgsd/engine": "^1.0.0-stable"
|
|
43
|
+
},
|
|
44
|
+
"peerDependenciesMeta": {
|
|
45
|
+
"esbuild": {
|
|
46
|
+
"optional": false
|
|
47
|
+
},
|
|
48
|
+
"@xgsd/engine": {
|
|
49
|
+
"optional": false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|