@holo-js/core 0.1.2 → 0.1.4
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/dist/chunk-4VPELMZN.mjs +2747 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.mjs +31 -15
- package/dist/runtime/index.d.ts +805 -3
- package/dist/runtime/index.mjs +13 -1
- package/package.json +59 -7
- package/dist/chunk-SVCNZBIQ.mjs +0 -703
package/dist/chunk-SVCNZBIQ.mjs
DELETED
|
@@ -1,703 +0,0 @@
|
|
|
1
|
-
// src/portable/dbRuntime.ts
|
|
2
|
-
import {
|
|
3
|
-
createAdapter,
|
|
4
|
-
createDialect,
|
|
5
|
-
createRuntimeConnectionOptions,
|
|
6
|
-
createRuntimeLogger,
|
|
7
|
-
isSupportedDatabaseDriver,
|
|
8
|
-
parseDatabaseDriver,
|
|
9
|
-
resolveRuntimeConnectionManagerOptions
|
|
10
|
-
} from "@holo-js/db";
|
|
11
|
-
|
|
12
|
-
// src/portable/registry.ts
|
|
13
|
-
import { readFile } from "fs/promises";
|
|
14
|
-
import { resolve } from "path";
|
|
15
|
-
import { DEFAULT_HOLO_PROJECT_PATHS } from "@holo-js/db";
|
|
16
|
-
function isRecord(value) {
|
|
17
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
18
|
-
}
|
|
19
|
-
function normalizeLegacyGeneratedProjectRegistry(value) {
|
|
20
|
-
const paths = isRecord(value.paths) ? value.paths : void 0;
|
|
21
|
-
if (paths && typeof paths.jobs !== "string") {
|
|
22
|
-
paths.jobs = DEFAULT_HOLO_PROJECT_PATHS.jobs;
|
|
23
|
-
}
|
|
24
|
-
if (paths && typeof paths.events !== "string") {
|
|
25
|
-
paths.events = DEFAULT_HOLO_PROJECT_PATHS.events;
|
|
26
|
-
}
|
|
27
|
-
if (paths && typeof paths.listeners !== "string") {
|
|
28
|
-
paths.listeners = DEFAULT_HOLO_PROJECT_PATHS.listeners;
|
|
29
|
-
}
|
|
30
|
-
if (!Array.isArray(value.jobs)) {
|
|
31
|
-
value.jobs = [];
|
|
32
|
-
}
|
|
33
|
-
if (!Array.isArray(value.events)) {
|
|
34
|
-
value.events = [];
|
|
35
|
-
}
|
|
36
|
-
if (!Array.isArray(value.listeners)) {
|
|
37
|
-
value.listeners = [];
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function isGeneratedProjectRegistry(value) {
|
|
41
|
-
if (!isRecord(value)) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
normalizeLegacyGeneratedProjectRegistry(value);
|
|
45
|
-
return value.version === 1 && isRecord(value.paths) && Array.isArray(value.models) && Array.isArray(value.migrations) && Array.isArray(value.seeders) && Array.isArray(value.commands) && Array.isArray(value.jobs) && Array.isArray(value.events) && Array.isArray(value.listeners);
|
|
46
|
-
}
|
|
47
|
-
function resolveGeneratedProjectRegistryPath(projectRoot) {
|
|
48
|
-
return resolve(projectRoot, ".holo-js", "generated", "registry.json");
|
|
49
|
-
}
|
|
50
|
-
async function loadGeneratedProjectRegistry(projectRoot) {
|
|
51
|
-
const filePath = resolveGeneratedProjectRegistryPath(projectRoot);
|
|
52
|
-
const contents = await readFile(filePath, "utf8").catch(() => void 0);
|
|
53
|
-
if (!contents) {
|
|
54
|
-
return void 0;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const parsed = JSON.parse(contents);
|
|
58
|
-
return isGeneratedProjectRegistry(parsed) ? parsed : void 0;
|
|
59
|
-
} catch {
|
|
60
|
-
return void 0;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
var registryInternals = {
|
|
64
|
-
isGeneratedProjectRegistry,
|
|
65
|
-
normalizeLegacyGeneratedProjectRegistry
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
// src/portable/holo.ts
|
|
69
|
-
import { resolve as resolve3 } from "path";
|
|
70
|
-
import {
|
|
71
|
-
config as globalConfig,
|
|
72
|
-
configureConfigRuntime,
|
|
73
|
-
createConfigAccessors,
|
|
74
|
-
loadConfigDirectory,
|
|
75
|
-
resetConfigRuntime,
|
|
76
|
-
useConfig as globalUseConfig
|
|
77
|
-
} from "@holo-js/config";
|
|
78
|
-
import {
|
|
79
|
-
configureDB,
|
|
80
|
-
resetDB
|
|
81
|
-
} from "@holo-js/db";
|
|
82
|
-
import {
|
|
83
|
-
configureQueueRuntime,
|
|
84
|
-
getRegisteredQueueJob,
|
|
85
|
-
getQueueRuntime,
|
|
86
|
-
isQueueJobDefinition,
|
|
87
|
-
normalizeQueueJobDefinition,
|
|
88
|
-
registerQueueJob,
|
|
89
|
-
shutdownQueueRuntime,
|
|
90
|
-
unregisterQueueJob
|
|
91
|
-
} from "@holo-js/queue";
|
|
92
|
-
import {
|
|
93
|
-
ensureEventsQueueJobRegistered,
|
|
94
|
-
getRegisteredEvent,
|
|
95
|
-
getRegisteredListener,
|
|
96
|
-
isEventDefinition,
|
|
97
|
-
isListenerDefinition,
|
|
98
|
-
normalizeListenerDefinition,
|
|
99
|
-
registerEvent,
|
|
100
|
-
registerListener,
|
|
101
|
-
unregisterEvent,
|
|
102
|
-
unregisterListener
|
|
103
|
-
} from "@holo-js/events";
|
|
104
|
-
import { createQueueDbRuntimeOptions } from "@holo-js/queue-db";
|
|
105
|
-
import { resetStorageRuntime } from "@holo-js/storage/runtime";
|
|
106
|
-
|
|
107
|
-
// src/runtimeModule.ts
|
|
108
|
-
import { mkdtemp, mkdir, rm, stat, writeFile } from "fs/promises";
|
|
109
|
-
import { basename, extname, join } from "path";
|
|
110
|
-
import { pathToFileURL } from "url";
|
|
111
|
-
var ESBUILD_MODULE_ID = "esbuild";
|
|
112
|
-
async function importModule(specifier) {
|
|
113
|
-
if (process.env.VITEST) {
|
|
114
|
-
return import(
|
|
115
|
-
/* @vite-ignore */
|
|
116
|
-
specifier
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
const indirectEval = globalThis.eval;
|
|
120
|
-
return indirectEval(`import(${JSON.stringify(specifier)})`);
|
|
121
|
-
}
|
|
122
|
-
async function pathExists(path) {
|
|
123
|
-
try {
|
|
124
|
-
await stat(path);
|
|
125
|
-
return true;
|
|
126
|
-
} catch {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async function writeLoaderTsconfig(projectRoot, tempDir) {
|
|
131
|
-
const projectTsconfigPath = join(projectRoot, "tsconfig.json");
|
|
132
|
-
if (await pathExists(projectTsconfigPath)) {
|
|
133
|
-
return projectTsconfigPath;
|
|
134
|
-
}
|
|
135
|
-
const tsconfigPath = join(tempDir, "tsconfig.json");
|
|
136
|
-
const contents = JSON.stringify({
|
|
137
|
-
compilerOptions: {
|
|
138
|
-
baseUrl: projectRoot,
|
|
139
|
-
paths: {
|
|
140
|
-
"~/*": ["./*"],
|
|
141
|
-
"@/*": ["./*"]
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}, null, 2);
|
|
145
|
-
await writeFile(tsconfigPath, `${contents}
|
|
146
|
-
`, "utf8");
|
|
147
|
-
return tsconfigPath;
|
|
148
|
-
}
|
|
149
|
-
async function bundleRuntimeModule(projectRoot, entryPath) {
|
|
150
|
-
const runtimeTempRoot = join(projectRoot, ".holo-js", "runtime");
|
|
151
|
-
await mkdir(runtimeTempRoot, { recursive: true });
|
|
152
|
-
const tempDir = await mkdtemp(join(runtimeTempRoot, "bundle-"));
|
|
153
|
-
const tsconfigPath = await writeLoaderTsconfig(projectRoot, tempDir);
|
|
154
|
-
const outfile = join(tempDir, `${basename(entryPath, extname(entryPath))}.mjs`);
|
|
155
|
-
const cleanup = async () => {
|
|
156
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
157
|
-
};
|
|
158
|
-
try {
|
|
159
|
-
await runtimeModuleInternals.runEsbuild({
|
|
160
|
-
absWorkingDir: projectRoot,
|
|
161
|
-
bundle: true,
|
|
162
|
-
entryPoints: [entryPath],
|
|
163
|
-
outfile,
|
|
164
|
-
format: "esm",
|
|
165
|
-
logLevel: "silent",
|
|
166
|
-
packages: "external",
|
|
167
|
-
platform: "node",
|
|
168
|
-
target: "node20",
|
|
169
|
-
tsconfig: tsconfigPath,
|
|
170
|
-
sourcemap: false
|
|
171
|
-
});
|
|
172
|
-
return {
|
|
173
|
-
path: outfile,
|
|
174
|
-
cleanup
|
|
175
|
-
};
|
|
176
|
-
} catch (error) {
|
|
177
|
-
await cleanup();
|
|
178
|
-
if (error && typeof error === "object" && Array.isArray(error.errors)) {
|
|
179
|
-
const message = error.errors.map((entry) => {
|
|
180
|
-
if (typeof entry.text === "string" && entry.text.trim()) {
|
|
181
|
-
return entry.text;
|
|
182
|
-
}
|
|
183
|
-
if (typeof entry.message === "string" && entry.message.trim()) {
|
|
184
|
-
return entry.message;
|
|
185
|
-
}
|
|
186
|
-
return "Unknown build error.";
|
|
187
|
-
}).join("\n");
|
|
188
|
-
throw new Error(message);
|
|
189
|
-
}
|
|
190
|
-
if (error instanceof Error && error.message) {
|
|
191
|
-
throw error;
|
|
192
|
-
}
|
|
193
|
-
throw new Error(`Failed to load ${entryPath}.`);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
async function importBundledRuntimeModule(projectRoot, entryPath) {
|
|
197
|
-
const bundled = await bundleRuntimeModule(projectRoot, entryPath);
|
|
198
|
-
try {
|
|
199
|
-
return await runtimeModuleInternals.importModule(
|
|
200
|
-
`${pathToFileURL(bundled.path).href}?t=${Date.now()}`
|
|
201
|
-
);
|
|
202
|
-
} finally {
|
|
203
|
-
await bundled.cleanup();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
async function loadEsbuild() {
|
|
207
|
-
return importModule(ESBUILD_MODULE_ID);
|
|
208
|
-
}
|
|
209
|
-
async function runEsbuild(options) {
|
|
210
|
-
const esbuild = await runtimeModuleInternals.loadEsbuild();
|
|
211
|
-
return esbuild.build(options);
|
|
212
|
-
}
|
|
213
|
-
var runtimeModuleInternals = {
|
|
214
|
-
bundleRuntimeModule,
|
|
215
|
-
importModule,
|
|
216
|
-
loadEsbuild,
|
|
217
|
-
pathExists,
|
|
218
|
-
runEsbuild,
|
|
219
|
-
writeLoaderTsconfig
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// src/storageRuntime.ts
|
|
223
|
-
import { mkdir as mkdir2, readFile as readFile2, readdir, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
224
|
-
import { dirname, join as join2, resolve as resolve2 } from "path";
|
|
225
|
-
import { normalizeModuleOptions } from "@holo-js/storage";
|
|
226
|
-
import {
|
|
227
|
-
configureStorageRuntime
|
|
228
|
-
} from "@holo-js/storage/runtime";
|
|
229
|
-
import createS3Driver from "@holo-js/storage/runtime/drivers/s3";
|
|
230
|
-
function resolveStorageKeyPath(root, key) {
|
|
231
|
-
const segments = key.split(":").filter(Boolean);
|
|
232
|
-
if (segments.includes("..")) {
|
|
233
|
-
throw new Error('[Holo Storage] Storage paths must not contain ".." segments.');
|
|
234
|
-
}
|
|
235
|
-
return resolve2(root, ...segments);
|
|
236
|
-
}
|
|
237
|
-
function createFileStorageBackend(root) {
|
|
238
|
-
async function listStorageKeys(currentRoot, prefix = "") {
|
|
239
|
-
const entries = await readdir(currentRoot, { withFileTypes: true }).catch(() => []);
|
|
240
|
-
const keys = [];
|
|
241
|
-
for (const entry of entries) {
|
|
242
|
-
const nextPrefix = prefix ? `${prefix}:${entry.name}` : entry.name;
|
|
243
|
-
const entryPath = join2(currentRoot, entry.name);
|
|
244
|
-
if (entry.isDirectory()) {
|
|
245
|
-
keys.push(...await listStorageKeys(entryPath, nextPrefix));
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
if (entry.isFile()) {
|
|
249
|
-
keys.push(nextPrefix);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return keys;
|
|
253
|
-
}
|
|
254
|
-
return {
|
|
255
|
-
async getItem(key) {
|
|
256
|
-
const value = await this.getItemRaw(key);
|
|
257
|
-
if (value === null) {
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
const serialized = Buffer.isBuffer(value) ? value.toString("utf8") : value instanceof Uint8Array ? Buffer.from(value).toString("utf8") : value instanceof ArrayBuffer ? Buffer.from(value).toString("utf8") : String(value);
|
|
261
|
-
return JSON.parse(serialized);
|
|
262
|
-
},
|
|
263
|
-
async getItemRaw(key) {
|
|
264
|
-
const targetPath = resolveStorageKeyPath(root, key);
|
|
265
|
-
try {
|
|
266
|
-
return await readFile2(targetPath);
|
|
267
|
-
} catch {
|
|
268
|
-
return null;
|
|
269
|
-
}
|
|
270
|
-
},
|
|
271
|
-
async setItem(key, value) {
|
|
272
|
-
await this.setItemRaw(key, JSON.stringify(value));
|
|
273
|
-
},
|
|
274
|
-
async setItemRaw(key, value) {
|
|
275
|
-
const targetPath = resolveStorageKeyPath(root, key);
|
|
276
|
-
await mkdir2(dirname(targetPath), { recursive: true });
|
|
277
|
-
await writeFile2(
|
|
278
|
-
targetPath,
|
|
279
|
-
value instanceof ArrayBuffer ? new Uint8Array(value) : value
|
|
280
|
-
);
|
|
281
|
-
},
|
|
282
|
-
async hasItem(key) {
|
|
283
|
-
return await this.getItemRaw(key) !== null;
|
|
284
|
-
},
|
|
285
|
-
async removeItem(key) {
|
|
286
|
-
const targetPath = resolveStorageKeyPath(root, key);
|
|
287
|
-
await rm2(targetPath, { force: true });
|
|
288
|
-
await rm2(`${targetPath}$`, { force: true });
|
|
289
|
-
},
|
|
290
|
-
async getKeys(base = "") {
|
|
291
|
-
const prefix = base.replace(/:+$/, "");
|
|
292
|
-
const keys = await listStorageKeys(root);
|
|
293
|
-
return keys.filter((key) => {
|
|
294
|
-
if (!prefix) {
|
|
295
|
-
return true;
|
|
296
|
-
}
|
|
297
|
-
return key === prefix || key.startsWith(`${prefix}:`);
|
|
298
|
-
});
|
|
299
|
-
},
|
|
300
|
-
async getMeta(key) {
|
|
301
|
-
return this.getItem(`${key}$`);
|
|
302
|
-
},
|
|
303
|
-
async setMeta(key, value) {
|
|
304
|
-
await this.setItem(`${key}$`, value);
|
|
305
|
-
},
|
|
306
|
-
async removeMeta(key) {
|
|
307
|
-
await this.removeItem(`${key}$`);
|
|
308
|
-
},
|
|
309
|
-
async clear(base = "") {
|
|
310
|
-
const prefix = base.replace(/:+$/, "");
|
|
311
|
-
const targetPath = prefix ? resolveStorageKeyPath(root, prefix) : root;
|
|
312
|
-
await rm2(targetPath, { recursive: true, force: true });
|
|
313
|
-
if (!prefix) {
|
|
314
|
-
await mkdir2(root, { recursive: true });
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
function createS3StorageBackend(disk) {
|
|
320
|
-
const driver = createS3Driver({
|
|
321
|
-
bucket: disk.bucket,
|
|
322
|
-
region: disk.region,
|
|
323
|
-
endpoint: disk.endpoint,
|
|
324
|
-
accessKeyId: disk.accessKeyId,
|
|
325
|
-
secretAccessKey: disk.secretAccessKey,
|
|
326
|
-
sessionToken: disk.sessionToken,
|
|
327
|
-
forcePathStyleEndpoint: disk.forcePathStyleEndpoint
|
|
328
|
-
});
|
|
329
|
-
return {
|
|
330
|
-
getItem(key) {
|
|
331
|
-
return driver.getItem(key);
|
|
332
|
-
},
|
|
333
|
-
getItemRaw: driver.getItemRaw,
|
|
334
|
-
setItem: driver.setItem,
|
|
335
|
-
setItemRaw: driver.setItemRaw,
|
|
336
|
-
hasItem: driver.hasItem,
|
|
337
|
-
removeItem: driver.removeItem,
|
|
338
|
-
getKeys: driver.getKeys,
|
|
339
|
-
getMeta(key) {
|
|
340
|
-
return driver.getMeta(key);
|
|
341
|
-
},
|
|
342
|
-
clear: driver.clear
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
function configurePlainNodeStorageRuntime(projectRoot, loadedConfig) {
|
|
346
|
-
const normalizedStorage = normalizeModuleOptions({
|
|
347
|
-
defaultDisk: loadedConfig.storage.defaultDisk,
|
|
348
|
-
routePrefix: loadedConfig.storage.routePrefix,
|
|
349
|
-
disks: loadedConfig.storage.disks
|
|
350
|
-
});
|
|
351
|
-
const backends = /* @__PURE__ */ new Map();
|
|
352
|
-
configureStorageRuntime({
|
|
353
|
-
getRuntimeConfig: () => ({
|
|
354
|
-
holoStorage: normalizedStorage,
|
|
355
|
-
holo: { appUrl: loadedConfig.app.url }
|
|
356
|
-
}),
|
|
357
|
-
getStorage: (base) => {
|
|
358
|
-
const diskName = base.replace(/^holo:/, "");
|
|
359
|
-
const disk = normalizedStorage.disks[diskName];
|
|
360
|
-
if (!disk) {
|
|
361
|
-
throw new Error(`[Holo Storage] Disk "${diskName}" is not configured.`);
|
|
362
|
-
}
|
|
363
|
-
const existing = backends.get(diskName);
|
|
364
|
-
if (existing) {
|
|
365
|
-
return existing;
|
|
366
|
-
}
|
|
367
|
-
const backend = disk.driver === "s3" ? createS3StorageBackend(disk) : createFileStorageBackend(
|
|
368
|
-
resolve2(projectRoot, disk.root)
|
|
369
|
-
);
|
|
370
|
-
backends.set(diskName, backend);
|
|
371
|
-
return backend;
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// src/portable/holo.ts
|
|
377
|
-
function getRuntimeState() {
|
|
378
|
-
const runtime = globalThis;
|
|
379
|
-
runtime.__holoRuntime__ ??= {};
|
|
380
|
-
return runtime.__holoRuntime__;
|
|
381
|
-
}
|
|
382
|
-
function resolveQueueJobExport(moduleValue) {
|
|
383
|
-
const exports = moduleValue;
|
|
384
|
-
if (isQueueJobDefinition(exports.default)) {
|
|
385
|
-
return exports.default;
|
|
386
|
-
}
|
|
387
|
-
return Object.values(exports).find((value) => isQueueJobDefinition(value));
|
|
388
|
-
}
|
|
389
|
-
var HOLO_EVENT_DEFINITION_MARKER = /* @__PURE__ */ Symbol.for("holo-js.events.definition");
|
|
390
|
-
var HOLO_LISTENER_DEFINITION_MARKER = /* @__PURE__ */ Symbol.for("holo-js.events.listener");
|
|
391
|
-
function hasEventDefinitionMarker(value) {
|
|
392
|
-
return !!value && typeof value === "object" && HOLO_EVENT_DEFINITION_MARKER in value;
|
|
393
|
-
}
|
|
394
|
-
function hasListenerDefinitionMarker(value) {
|
|
395
|
-
return !!value && typeof value === "object" && HOLO_LISTENER_DEFINITION_MARKER in value;
|
|
396
|
-
}
|
|
397
|
-
function resolveEventExport(moduleValue) {
|
|
398
|
-
const exports = moduleValue;
|
|
399
|
-
if (hasEventDefinitionMarker(exports.default)) {
|
|
400
|
-
return exports.default;
|
|
401
|
-
}
|
|
402
|
-
return Object.values(exports).find((value) => hasEventDefinitionMarker(value));
|
|
403
|
-
}
|
|
404
|
-
function resolveListenerExport(moduleValue) {
|
|
405
|
-
const exports = moduleValue;
|
|
406
|
-
if (hasListenerDefinitionMarker(exports.default) || isListenerDefinition(exports.default)) {
|
|
407
|
-
return exports.default;
|
|
408
|
-
}
|
|
409
|
-
return Object.values(exports).find((value) => hasListenerDefinitionMarker(value) || isListenerDefinition(value));
|
|
410
|
-
}
|
|
411
|
-
async function importRuntimeModule(projectRoot, filePath) {
|
|
412
|
-
return importBundledRuntimeModule(projectRoot, filePath);
|
|
413
|
-
}
|
|
414
|
-
async function registerProjectQueueJobs(projectRoot, registry) {
|
|
415
|
-
if (!registry || registry.jobs.length === 0) {
|
|
416
|
-
return Object.freeze([]);
|
|
417
|
-
}
|
|
418
|
-
const registeredJobNames = [];
|
|
419
|
-
try {
|
|
420
|
-
for (const entry of registry.jobs) {
|
|
421
|
-
const existing = getRegisteredQueueJob(entry.name);
|
|
422
|
-
if (existing && !existing.sourcePath) {
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
const moduleValue = await importRuntimeModule(projectRoot, resolve3(projectRoot, entry.sourcePath));
|
|
426
|
-
const job = resolveQueueJobExport(moduleValue);
|
|
427
|
-
if (!job) {
|
|
428
|
-
throw new Error(`Discovered job "${entry.sourcePath}" does not export a Holo job.`);
|
|
429
|
-
}
|
|
430
|
-
registerQueueJob(normalizeQueueJobDefinition(job), {
|
|
431
|
-
name: entry.name,
|
|
432
|
-
sourcePath: entry.sourcePath,
|
|
433
|
-
replaceExisting: !!existing?.sourcePath
|
|
434
|
-
});
|
|
435
|
-
registeredJobNames.push(entry.name);
|
|
436
|
-
}
|
|
437
|
-
} catch (error) {
|
|
438
|
-
unregisterProjectQueueJobs(registeredJobNames);
|
|
439
|
-
throw error;
|
|
440
|
-
}
|
|
441
|
-
return Object.freeze(registeredJobNames);
|
|
442
|
-
}
|
|
443
|
-
function unregisterProjectQueueJobs(jobNames) {
|
|
444
|
-
for (const jobName of jobNames) {
|
|
445
|
-
unregisterQueueJob(jobName);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
async function registerProjectEventsAndListeners(projectRoot, registry) {
|
|
449
|
-
if (!registry || registry.events.length === 0 && registry.listeners.length === 0) {
|
|
450
|
-
return Object.freeze({
|
|
451
|
-
eventNames: Object.freeze([]),
|
|
452
|
-
listenerIds: Object.freeze([])
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
const registeredEventNames = [];
|
|
456
|
-
const registeredListenerIds = [];
|
|
457
|
-
try {
|
|
458
|
-
for (const entry of registry.events) {
|
|
459
|
-
const existing = getRegisteredEvent(entry.name);
|
|
460
|
-
if (existing && !existing.sourcePath) {
|
|
461
|
-
continue;
|
|
462
|
-
}
|
|
463
|
-
const moduleValue = await importRuntimeModule(projectRoot, resolve3(projectRoot, entry.sourcePath));
|
|
464
|
-
const event = resolveEventExport(moduleValue);
|
|
465
|
-
if (!event || !isEventDefinition(event)) {
|
|
466
|
-
throw new Error(`Discovered event "${entry.sourcePath}" does not export a Holo event.`);
|
|
467
|
-
}
|
|
468
|
-
registerEvent(event, {
|
|
469
|
-
name: entry.name,
|
|
470
|
-
sourcePath: entry.sourcePath,
|
|
471
|
-
replaceExisting: !!existing?.sourcePath
|
|
472
|
-
});
|
|
473
|
-
registeredEventNames.push(entry.name);
|
|
474
|
-
}
|
|
475
|
-
for (const entry of registry.listeners) {
|
|
476
|
-
const existing = getRegisteredListener(entry.id);
|
|
477
|
-
if (existing && !existing.sourcePath) {
|
|
478
|
-
continue;
|
|
479
|
-
}
|
|
480
|
-
const moduleValue = await importRuntimeModule(projectRoot, resolve3(projectRoot, entry.sourcePath));
|
|
481
|
-
const listener = resolveListenerExport(moduleValue);
|
|
482
|
-
if (!listener) {
|
|
483
|
-
throw new Error(`Discovered listener "${entry.sourcePath}" does not export a Holo listener.`);
|
|
484
|
-
}
|
|
485
|
-
const normalizedListener = normalizeListenerDefinition(listener);
|
|
486
|
-
registerListener({
|
|
487
|
-
...normalizedListener,
|
|
488
|
-
listensTo: entry.eventNames
|
|
489
|
-
}, {
|
|
490
|
-
id: entry.id,
|
|
491
|
-
sourcePath: entry.sourcePath,
|
|
492
|
-
replaceExisting: !!existing?.sourcePath
|
|
493
|
-
});
|
|
494
|
-
registeredListenerIds.push(entry.id);
|
|
495
|
-
}
|
|
496
|
-
} catch (error) {
|
|
497
|
-
unregisterProjectEventsAndListeners(registeredEventNames, registeredListenerIds);
|
|
498
|
-
throw error;
|
|
499
|
-
}
|
|
500
|
-
return Object.freeze({
|
|
501
|
-
eventNames: Object.freeze(registeredEventNames),
|
|
502
|
-
listenerIds: Object.freeze(registeredListenerIds)
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
function unregisterProjectEventsAndListeners(eventNames, listenerIds) {
|
|
506
|
-
for (const listenerId of listenerIds) {
|
|
507
|
-
unregisterListener(listenerId);
|
|
508
|
-
}
|
|
509
|
-
for (const eventName of eventNames) {
|
|
510
|
-
unregisterEvent(eventName);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
async function createHolo(projectRoot, options = {}) {
|
|
514
|
-
const loadedConfig = await loadConfigDirectory(projectRoot, {
|
|
515
|
-
envName: options.envName,
|
|
516
|
-
preferCache: options.preferCache,
|
|
517
|
-
processEnv: options.processEnv
|
|
518
|
-
});
|
|
519
|
-
const runtimeConfig = {
|
|
520
|
-
db: loadedConfig.database,
|
|
521
|
-
queue: loadedConfig.queue
|
|
522
|
-
};
|
|
523
|
-
const manager = resolveRuntimeConnectionManagerOptions(runtimeConfig);
|
|
524
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot);
|
|
525
|
-
const accessors = createConfigAccessors(loadedConfig.all);
|
|
526
|
-
const runtimeOwnedQueueJobNames = [];
|
|
527
|
-
const runtimeOwnedEventNames = [];
|
|
528
|
-
const runtimeOwnedListenerIds = [];
|
|
529
|
-
const runtime = {
|
|
530
|
-
projectRoot,
|
|
531
|
-
loadedConfig,
|
|
532
|
-
registry,
|
|
533
|
-
manager,
|
|
534
|
-
runtimeConfig,
|
|
535
|
-
get queue() {
|
|
536
|
-
return getQueueRuntime();
|
|
537
|
-
},
|
|
538
|
-
initialized: false,
|
|
539
|
-
useConfig: accessors.useConfig,
|
|
540
|
-
config: accessors.config,
|
|
541
|
-
async initialize() {
|
|
542
|
-
if (runtime.initialized) {
|
|
543
|
-
throw new Error("Holo runtime is already initialized.");
|
|
544
|
-
}
|
|
545
|
-
if (getRuntimeState().current) {
|
|
546
|
-
throw new Error("A Holo runtime is already initialized for this process.");
|
|
547
|
-
}
|
|
548
|
-
configureConfigRuntime(loadedConfig.all);
|
|
549
|
-
configureDB(manager);
|
|
550
|
-
try {
|
|
551
|
-
await manager.initializeAll();
|
|
552
|
-
configureQueueRuntime({
|
|
553
|
-
config: loadedConfig.queue,
|
|
554
|
-
...createQueueDbRuntimeOptions()
|
|
555
|
-
});
|
|
556
|
-
ensureEventsQueueJobRegistered();
|
|
557
|
-
configurePlainNodeStorageRuntime(projectRoot, loadedConfig);
|
|
558
|
-
const eventRegistration = await registerProjectEventsAndListeners(projectRoot, registry);
|
|
559
|
-
runtimeOwnedEventNames.splice(0, runtimeOwnedEventNames.length, ...eventRegistration.eventNames);
|
|
560
|
-
runtimeOwnedListenerIds.splice(0, runtimeOwnedListenerIds.length, ...eventRegistration.listenerIds);
|
|
561
|
-
if (options.registerProjectQueueJobs === true) {
|
|
562
|
-
runtimeOwnedQueueJobNames.splice(0, runtimeOwnedQueueJobNames.length);
|
|
563
|
-
runtimeOwnedQueueJobNames.push(...await registerProjectQueueJobs(projectRoot, registry));
|
|
564
|
-
}
|
|
565
|
-
runtime.initialized = true;
|
|
566
|
-
getRuntimeState().current = runtime;
|
|
567
|
-
} catch (error) {
|
|
568
|
-
unregisterProjectEventsAndListeners(runtimeOwnedEventNames, runtimeOwnedListenerIds);
|
|
569
|
-
runtimeOwnedEventNames.splice(0, runtimeOwnedEventNames.length);
|
|
570
|
-
runtimeOwnedListenerIds.splice(0, runtimeOwnedListenerIds.length);
|
|
571
|
-
unregisterProjectQueueJobs(runtimeOwnedQueueJobNames);
|
|
572
|
-
runtimeOwnedQueueJobNames.splice(0, runtimeOwnedQueueJobNames.length);
|
|
573
|
-
await manager.disconnectAll().catch(() => {
|
|
574
|
-
});
|
|
575
|
-
resetDB();
|
|
576
|
-
resetStorageRuntime();
|
|
577
|
-
await shutdownQueueRuntime();
|
|
578
|
-
resetConfigRuntime();
|
|
579
|
-
getRuntimeState().current = void 0;
|
|
580
|
-
throw error;
|
|
581
|
-
}
|
|
582
|
-
},
|
|
583
|
-
async shutdown() {
|
|
584
|
-
try {
|
|
585
|
-
if (runtime.initialized) {
|
|
586
|
-
await manager.disconnectAll();
|
|
587
|
-
}
|
|
588
|
-
} finally {
|
|
589
|
-
runtime.initialized = false;
|
|
590
|
-
if (getRuntimeState().current === runtime) {
|
|
591
|
-
getRuntimeState().current = void 0;
|
|
592
|
-
}
|
|
593
|
-
unregisterProjectEventsAndListeners(runtimeOwnedEventNames, runtimeOwnedListenerIds);
|
|
594
|
-
runtimeOwnedEventNames.splice(0, runtimeOwnedEventNames.length);
|
|
595
|
-
runtimeOwnedListenerIds.splice(0, runtimeOwnedListenerIds.length);
|
|
596
|
-
unregisterProjectQueueJobs(runtimeOwnedQueueJobNames);
|
|
597
|
-
runtimeOwnedQueueJobNames.splice(0, runtimeOwnedQueueJobNames.length);
|
|
598
|
-
resetDB();
|
|
599
|
-
resetStorageRuntime();
|
|
600
|
-
await shutdownQueueRuntime();
|
|
601
|
-
resetConfigRuntime();
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
};
|
|
605
|
-
return runtime;
|
|
606
|
-
}
|
|
607
|
-
async function initializeHolo(projectRoot, options = {}) {
|
|
608
|
-
const state = getRuntimeState();
|
|
609
|
-
const resolvedProjectRoot = resolve3(projectRoot);
|
|
610
|
-
const current = state.current;
|
|
611
|
-
if (current) {
|
|
612
|
-
if (resolve3(current.projectRoot) !== resolvedProjectRoot) {
|
|
613
|
-
throw new Error(`A Holo runtime is already initialized for "${current.projectRoot}".`);
|
|
614
|
-
}
|
|
615
|
-
return current;
|
|
616
|
-
}
|
|
617
|
-
if (state.pending) {
|
|
618
|
-
if (state.pendingProjectRoot && resolve3(state.pendingProjectRoot) !== resolvedProjectRoot) {
|
|
619
|
-
throw new Error(`A Holo runtime is already initializing for "${state.pendingProjectRoot}".`);
|
|
620
|
-
}
|
|
621
|
-
return state.pending;
|
|
622
|
-
}
|
|
623
|
-
const pending = (async () => {
|
|
624
|
-
const runtime = await createHolo(projectRoot, options);
|
|
625
|
-
await runtime.initialize();
|
|
626
|
-
return runtime;
|
|
627
|
-
})();
|
|
628
|
-
state.pending = pending;
|
|
629
|
-
state.pendingProjectRoot = resolvedProjectRoot;
|
|
630
|
-
try {
|
|
631
|
-
return await pending;
|
|
632
|
-
} finally {
|
|
633
|
-
if (state.pending === pending) {
|
|
634
|
-
state.pending = void 0;
|
|
635
|
-
state.pendingProjectRoot = void 0;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
function peekHolo() {
|
|
640
|
-
return getRuntimeState().current;
|
|
641
|
-
}
|
|
642
|
-
async function ensureHolo(projectRoot, options = {}) {
|
|
643
|
-
const current = peekHolo();
|
|
644
|
-
if (!current) {
|
|
645
|
-
return initializeHolo(projectRoot, options);
|
|
646
|
-
}
|
|
647
|
-
if (resolve3(current.projectRoot) !== resolve3(projectRoot)) {
|
|
648
|
-
throw new Error(`A Holo runtime is already initialized for "${current.projectRoot}".`);
|
|
649
|
-
}
|
|
650
|
-
return current;
|
|
651
|
-
}
|
|
652
|
-
function getHolo() {
|
|
653
|
-
const current = getRuntimeState().current;
|
|
654
|
-
if (!current) {
|
|
655
|
-
throw new Error("Holo runtime is not initialized.");
|
|
656
|
-
}
|
|
657
|
-
return current;
|
|
658
|
-
}
|
|
659
|
-
async function resetHoloRuntime() {
|
|
660
|
-
const current = getRuntimeState().current;
|
|
661
|
-
getRuntimeState().pending = void 0;
|
|
662
|
-
getRuntimeState().pendingProjectRoot = void 0;
|
|
663
|
-
if (!current) {
|
|
664
|
-
resetDB();
|
|
665
|
-
resetStorageRuntime();
|
|
666
|
-
await shutdownQueueRuntime();
|
|
667
|
-
resetConfigRuntime();
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
await current.shutdown();
|
|
671
|
-
}
|
|
672
|
-
function getConfigValue(path) {
|
|
673
|
-
return globalConfig(path);
|
|
674
|
-
}
|
|
675
|
-
function getConfigSection(key) {
|
|
676
|
-
return globalUseConfig(key);
|
|
677
|
-
}
|
|
678
|
-
var holoRuntimeInternals = {
|
|
679
|
-
getConfigSection,
|
|
680
|
-
getConfigValue
|
|
681
|
-
};
|
|
682
|
-
|
|
683
|
-
export {
|
|
684
|
-
createAdapter,
|
|
685
|
-
createDialect,
|
|
686
|
-
createRuntimeConnectionOptions,
|
|
687
|
-
createRuntimeLogger,
|
|
688
|
-
isSupportedDatabaseDriver,
|
|
689
|
-
parseDatabaseDriver,
|
|
690
|
-
resolveRuntimeConnectionManagerOptions,
|
|
691
|
-
resolveGeneratedProjectRegistryPath,
|
|
692
|
-
loadGeneratedProjectRegistry,
|
|
693
|
-
registryInternals,
|
|
694
|
-
resolveStorageKeyPath,
|
|
695
|
-
configurePlainNodeStorageRuntime,
|
|
696
|
-
createHolo,
|
|
697
|
-
initializeHolo,
|
|
698
|
-
peekHolo,
|
|
699
|
-
ensureHolo,
|
|
700
|
-
getHolo,
|
|
701
|
-
resetHoloRuntime,
|
|
702
|
-
holoRuntimeInternals
|
|
703
|
-
};
|