@holo-js/cli 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.
Files changed (56) hide show
  1. package/dist/bin/holo.mjs +533 -4616
  2. package/dist/broadcast-CSSARTSA.mjs +84 -0
  3. package/dist/broadcast-YSIJCL3R.mjs +85 -0
  4. package/dist/cache-4G6QGIZO.mjs +66 -0
  5. package/dist/cache-OWQY4E7W.mjs +67 -0
  6. package/dist/cache-migrations-NATT5WPQ.mjs +154 -0
  7. package/dist/cache-migrations-RVEA6CEU.mjs +155 -0
  8. package/dist/chunk-3OTCSFDG.mjs +849 -0
  9. package/dist/chunk-66FHW725.mjs +465 -0
  10. package/dist/chunk-BWW5TDFI.mjs +4 -0
  11. package/dist/chunk-CUL4RJTG.mjs +22 -0
  12. package/dist/chunk-D4GG556Y.mjs +23 -0
  13. package/dist/chunk-D7O4SU6N.mjs +2 -0
  14. package/dist/chunk-DMH2B4UQ.mjs +343 -0
  15. package/dist/chunk-ET7UXHHQ.mjs +166 -0
  16. package/dist/chunk-EUIVXVJL.mjs +25 -0
  17. package/dist/chunk-G5ADO27Q.mjs +463 -0
  18. package/dist/chunk-GSQ3HTRO.mjs +165 -0
  19. package/dist/chunk-H7TJ4FB3.mjs +848 -0
  20. package/dist/chunk-ICJR7TS4.mjs +66 -0
  21. package/dist/chunk-JX2ZH6XY.mjs +270 -0
  22. package/dist/chunk-M7J3YTHR.mjs +26 -0
  23. package/dist/chunk-MZXN2YMI.mjs +3236 -0
  24. package/dist/chunk-Q5F6C2D4.mjs +65 -0
  25. package/dist/chunk-QFUSWV3J.mjs +3237 -0
  26. package/dist/chunk-QYLSMF7V.mjs +539 -0
  27. package/dist/chunk-S7P7EBM3.mjs +787 -0
  28. package/dist/chunk-SRWJU3A5.mjs +11 -0
  29. package/dist/chunk-URK7C3VQ.mjs +538 -0
  30. package/dist/chunk-VT5IDQG6.mjs +788 -0
  31. package/dist/chunk-XUYKPU5Q.mjs +272 -0
  32. package/dist/chunk-ZLRO7HXY.mjs +342 -0
  33. package/dist/chunk-ZXDU7RHU.mjs +9 -0
  34. package/dist/config-DMWBMMGD.mjs +26 -0
  35. package/dist/config-LS5USBRB.mjs +25 -0
  36. package/dist/dev-KQFT7RHR.mjs +43 -0
  37. package/dist/dev-LZ3O2E3U.mjs +42 -0
  38. package/dist/discovery-GBLAUTXS.mjs +28 -0
  39. package/dist/discovery-R733D2PO.mjs +29 -0
  40. package/dist/generators-DSN4GWJI.mjs +425 -0
  41. package/dist/generators-WX45BI4U.mjs +426 -0
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.mjs +536 -4618
  44. package/dist/queue-6OG7VJ34.mjs +626 -0
  45. package/dist/queue-FV35LLPR.mjs +625 -0
  46. package/dist/queue-migrations-NK2EYX3J.mjs +163 -0
  47. package/dist/queue-migrations-SSIYKK5S.mjs +162 -0
  48. package/dist/runtime-4BV3JODY.mjs +56 -0
  49. package/dist/runtime-ANBO7VQM.mjs +33 -0
  50. package/dist/runtime-EFZ5H5IL.mjs +55 -0
  51. package/dist/runtime-OOSJ5JBY.mjs +32 -0
  52. package/dist/scaffold-7OTDH4UR.mjs +121 -0
  53. package/dist/scaffold-DRKBGS2K.mjs +120 -0
  54. package/dist/security-ATKDC26E.mjs +68 -0
  55. package/dist/security-R7VH6W5H.mjs +69 -0
  56. package/package.json +12 -11
@@ -0,0 +1,343 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ prepareProjectDiscovery
4
+ } from "./chunk-VT5IDQG6.mjs";
5
+ import {
6
+ syncManagedDriverDependencies
7
+ } from "./chunk-QFUSWV3J.mjs";
8
+ import {
9
+ ensureProjectConfig
10
+ } from "./chunk-ET7UXHHQ.mjs";
11
+ import {
12
+ readTextFile
13
+ } from "./chunk-66FHW725.mjs";
14
+
15
+ // src/dev.ts
16
+ import { spawnSync, spawn } from "child_process";
17
+ import { watch } from "fs";
18
+ import { readdir, stat } from "fs/promises";
19
+ import { dirname, join, relative, resolve } from "path";
20
+ async function fileExists(path) {
21
+ try {
22
+ await stat(path);
23
+ return true;
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ async function resolveProjectPackageManager(projectRoot) {
29
+ const packageJsonPath = join(projectRoot, "package.json");
30
+ const packageJson = await readTextFile(packageJsonPath);
31
+ if (packageJson) {
32
+ try {
33
+ const parsed = JSON.parse(packageJson);
34
+ const packageManager = typeof parsed.packageManager === "string" ? parsed.packageManager.split("@")[0] : void 0;
35
+ if (packageManager === "bun" || packageManager === "npm" || packageManager === "pnpm" || packageManager === "yarn") {
36
+ return packageManager;
37
+ }
38
+ } catch {
39
+ }
40
+ }
41
+ if (await fileExists(join(projectRoot, "bun.lock"))) {
42
+ return "bun";
43
+ }
44
+ if (await fileExists(join(projectRoot, "pnpm-lock.yaml"))) {
45
+ return "pnpm";
46
+ }
47
+ if (await fileExists(join(projectRoot, "yarn.lock"))) {
48
+ return "yarn";
49
+ }
50
+ if (await fileExists(join(projectRoot, "package-lock.json"))) {
51
+ return "npm";
52
+ }
53
+ return "bun";
54
+ }
55
+ async function resolvePackageManagerCommand(projectRoot, scriptName) {
56
+ const packageManager = await resolveProjectPackageManager(projectRoot);
57
+ return {
58
+ command: packageManager,
59
+ args: ["run", scriptName]
60
+ };
61
+ }
62
+ async function resolvePackageManagerInstallInvocation(projectRoot) {
63
+ const packageManager = await resolveProjectPackageManager(projectRoot);
64
+ return {
65
+ command: packageManager,
66
+ args: ["install"]
67
+ };
68
+ }
69
+ async function runProjectLifecycleScript(io, projectRoot, scriptName, spawn2 = spawnSync) {
70
+ const invocation = await resolvePackageManagerCommand(projectRoot, scriptName);
71
+ const result = spawn2(invocation.command, [...invocation.args], {
72
+ cwd: projectRoot,
73
+ encoding: "utf8",
74
+ env: process.env
75
+ });
76
+ if (result.stdout) {
77
+ io.stdout.write(result.stdout);
78
+ }
79
+ if (result.stderr) {
80
+ io.stderr.write(result.stderr);
81
+ }
82
+ if (result.status !== 0) {
83
+ throw new Error(result.stderr?.trim() || result.stdout?.trim() || `Project script "${scriptName}" failed.`);
84
+ }
85
+ }
86
+ async function runProjectDependencyInstall(io, projectRoot, spawn2 = spawnSync) {
87
+ const invocation = await resolvePackageManagerInstallInvocation(projectRoot);
88
+ const result = spawn2(invocation.command, [...invocation.args], {
89
+ cwd: projectRoot,
90
+ encoding: "utf8",
91
+ env: process.env
92
+ });
93
+ if (result.stdout) {
94
+ io.stdout.write(result.stdout);
95
+ }
96
+ if (result.stderr) {
97
+ io.stderr.write(result.stderr);
98
+ }
99
+ if (result.status !== 0) {
100
+ throw new Error(result.stderr?.trim() || result.stdout?.trim() || "Project dependency installation failed.");
101
+ }
102
+ }
103
+ async function runProjectPrepare(projectRoot, io) {
104
+ const project = await ensureProjectConfig(projectRoot);
105
+ await prepareProjectDiscovery(projectRoot, project.config);
106
+ const updatedDependencies = await syncManagedDriverDependencies(projectRoot);
107
+ if (updatedDependencies && io) {
108
+ await runProjectDependencyInstall(io, projectRoot);
109
+ await prepareProjectDiscovery(projectRoot, project.config);
110
+ }
111
+ }
112
+ function toPosixSlashes(value) {
113
+ return value.replaceAll("\\", "/");
114
+ }
115
+ function isDiscoveryRelevantPath(filePath, project) {
116
+ const normalized = toPosixSlashes(filePath);
117
+ const authorizationPoliciesPath = project.config.paths.authorizationPolicies || "server/policies";
118
+ const authorizationAbilitiesPath = project.config.paths.authorizationAbilities || "server/abilities";
119
+ const roots = [
120
+ project.config.paths.models,
121
+ project.config.paths.migrations,
122
+ project.config.paths.seeders,
123
+ project.config.paths.commands,
124
+ project.config.paths.jobs,
125
+ project.config.paths.events,
126
+ project.config.paths.listeners,
127
+ authorizationPoliciesPath,
128
+ authorizationAbilitiesPath,
129
+ "server/broadcast",
130
+ "server/channels",
131
+ project.config.paths.generatedSchema,
132
+ "config",
133
+ ".holo-js/generated"
134
+ ];
135
+ if (normalized === ".env" || normalized.startsWith(".env.")) {
136
+ return true;
137
+ }
138
+ return roots.some((root) => normalized === root || normalized.startsWith(`${toPosixSlashes(root)}/`));
139
+ }
140
+ function isRecursiveWatchUnsupported(error) {
141
+ return error instanceof Error && (error.message.includes("recursive") || "code" in error && error.code === "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM");
142
+ }
143
+ function isIgnorableWatchError(error) {
144
+ return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "EPERM");
145
+ }
146
+ async function collectDirectoryTree(rootPath, directories) {
147
+ const rootStats = await stat(rootPath).catch(() => void 0);
148
+ if (!rootStats?.isDirectory()) {
149
+ return;
150
+ }
151
+ directories.add(rootPath);
152
+ const entries = await readdir(rootPath, { withFileTypes: true }).catch(() => []);
153
+ for (const entry of entries) {
154
+ if (!entry.isDirectory()) {
155
+ continue;
156
+ }
157
+ await collectDirectoryTree(join(rootPath, entry.name), directories);
158
+ }
159
+ }
160
+ async function collectDiscoveryWatchRoots(projectRoot, project) {
161
+ const directories = /* @__PURE__ */ new Set();
162
+ const authorizationPoliciesPath = project.config.paths.authorizationPolicies || "server/policies";
163
+ const authorizationAbilitiesPath = project.config.paths.authorizationAbilities || "server/abilities";
164
+ const roots = [
165
+ projectRoot,
166
+ resolve(projectRoot, "config"),
167
+ resolve(projectRoot, ".holo-js/generated"),
168
+ resolve(projectRoot, project.config.paths.models),
169
+ resolve(projectRoot, project.config.paths.migrations),
170
+ resolve(projectRoot, project.config.paths.seeders),
171
+ resolve(projectRoot, project.config.paths.commands),
172
+ resolve(projectRoot, project.config.paths.jobs),
173
+ resolve(projectRoot, project.config.paths.events),
174
+ resolve(projectRoot, project.config.paths.listeners),
175
+ resolve(projectRoot, authorizationPoliciesPath),
176
+ resolve(projectRoot, authorizationAbilitiesPath),
177
+ resolve(projectRoot, "server/broadcast"),
178
+ resolve(projectRoot, "server/channels"),
179
+ dirname(resolve(projectRoot, project.config.paths.generatedSchema))
180
+ ];
181
+ for (const rootPath of roots) {
182
+ await collectDirectoryTree(rootPath, directories);
183
+ }
184
+ return [...directories];
185
+ }
186
+ function normalizeWatchedFilePath(projectRoot, watchedRoot, fileName) {
187
+ return toPosixSlashes(relative(projectRoot, resolve(watchedRoot, fileName)));
188
+ }
189
+ async function runProjectDevServer(io, projectRoot, spawnProcess = spawn, createWatcher = watch, prepare = runProjectPrepare) {
190
+ let project = await ensureProjectConfig(projectRoot);
191
+ let refreshNonRecursiveWatchers;
192
+ let requestChildRestart;
193
+ const prepareDiscovery = async () => {
194
+ await prepare(projectRoot, io);
195
+ project = await ensureProjectConfig(projectRoot);
196
+ await refreshNonRecursiveWatchers?.();
197
+ };
198
+ await prepareDiscovery();
199
+ let pendingPrepare;
200
+ let queued = false;
201
+ let shuttingDown = false;
202
+ const rerunPrepare = () => {
203
+ if (shuttingDown) {
204
+ return;
205
+ }
206
+ if (pendingPrepare) {
207
+ queued = true;
208
+ return;
209
+ }
210
+ pendingPrepare = prepareDiscovery().then(() => {
211
+ requestChildRestart?.();
212
+ }).catch((error) => {
213
+ io.stderr.write(`${error instanceof Error ? error.message : String(error)}
214
+ `);
215
+ }).finally(() => {
216
+ pendingPrepare = void 0;
217
+ if (queued) {
218
+ queued = false;
219
+ rerunPrepare();
220
+ }
221
+ });
222
+ };
223
+ const closeWatchers = (() => {
224
+ try {
225
+ const watcher = createWatcher(projectRoot, { recursive: true }, (_eventType, fileName) => {
226
+ if (shuttingDown || typeof fileName !== "string" || !isDiscoveryRelevantPath(fileName, project)) {
227
+ return;
228
+ }
229
+ rerunPrepare();
230
+ });
231
+ return () => watcher.close();
232
+ } catch (error) {
233
+ if (!isRecursiveWatchUnsupported(error)) {
234
+ throw error;
235
+ }
236
+ const watchers = [];
237
+ const closeAllWatchers = () => {
238
+ while (watchers.length > 0) {
239
+ watchers.pop()?.close();
240
+ }
241
+ };
242
+ refreshNonRecursiveWatchers = async () => {
243
+ closeAllWatchers();
244
+ const watchRoots = await collectDiscoveryWatchRoots(projectRoot, project);
245
+ for (const watchRoot of watchRoots) {
246
+ try {
247
+ watchers.push(createWatcher(watchRoot, { recursive: false }, (_eventType, fileName) => {
248
+ if (shuttingDown || typeof fileName !== "string") {
249
+ return;
250
+ }
251
+ const normalizedPath = normalizeWatchedFilePath(projectRoot, watchRoot, fileName);
252
+ if (!isDiscoveryRelevantPath(normalizedPath, project)) {
253
+ return;
254
+ }
255
+ rerunPrepare();
256
+ }));
257
+ } catch (watchError) {
258
+ if (!isIgnorableWatchError(watchError)) {
259
+ throw watchError;
260
+ }
261
+ }
262
+ }
263
+ };
264
+ return () => closeAllWatchers();
265
+ }
266
+ })();
267
+ await refreshNonRecursiveWatchers?.();
268
+ const invocation = await resolvePackageManagerCommand(projectRoot, "holo:dev");
269
+ while (!shuttingDown) {
270
+ const child = spawnProcess(invocation.command, [...invocation.args], {
271
+ cwd: projectRoot,
272
+ env: process.env,
273
+ stdio: ["pipe", "pipe", "pipe"]
274
+ });
275
+ child.stdout?.on("data", (chunk) => io.stdout.write(chunk));
276
+ child.stderr?.on("data", (chunk) => io.stderr.write(chunk));
277
+ if (child.stdin) {
278
+ io.stdin.pipe(child.stdin);
279
+ }
280
+ const result = await new Promise((resolvePromise) => {
281
+ let restartRequested = false;
282
+ requestChildRestart = () => {
283
+ if (restartRequested || shuttingDown || typeof child.kill !== "function") {
284
+ return;
285
+ }
286
+ restartRequested = true;
287
+ child.kill("SIGTERM");
288
+ };
289
+ child.on("error", (error) => {
290
+ if (child.stdin) {
291
+ io.stdin.unpipe(child.stdin);
292
+ }
293
+ requestChildRestart = void 0;
294
+ if (restartRequested) {
295
+ resolvePromise({ kind: "restart" });
296
+ return;
297
+ }
298
+ resolvePromise({ kind: "error", error });
299
+ });
300
+ child.on("close", (code) => {
301
+ if (child.stdin) {
302
+ io.stdin.unpipe(child.stdin);
303
+ }
304
+ requestChildRestart = void 0;
305
+ if (restartRequested) {
306
+ resolvePromise({ kind: "restart" });
307
+ return;
308
+ }
309
+ resolvePromise({ kind: "close", code });
310
+ });
311
+ });
312
+ if (result.kind === "restart") {
313
+ continue;
314
+ }
315
+ shuttingDown = true;
316
+ closeWatchers();
317
+ await Promise.resolve(pendingPrepare);
318
+ if (result.kind === "error") {
319
+ throw result.error;
320
+ }
321
+ if (result.code === 0) {
322
+ return;
323
+ }
324
+ throw new Error(`Project script "holo:dev" failed with exit code ${result.code ?? "unknown"}.`);
325
+ }
326
+ }
327
+
328
+ export {
329
+ resolveProjectPackageManager,
330
+ resolvePackageManagerCommand,
331
+ resolvePackageManagerInstallInvocation,
332
+ runProjectLifecycleScript,
333
+ runProjectDependencyInstall,
334
+ runProjectPrepare,
335
+ toPosixSlashes,
336
+ isDiscoveryRelevantPath,
337
+ isRecursiveWatchUnsupported,
338
+ isIgnorableWatchError,
339
+ collectDirectoryTree,
340
+ collectDiscoveryWatchRoots,
341
+ normalizeWatchedFilePath,
342
+ runProjectDevServer
343
+ };
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ loadGeneratedProjectRegistry
4
+ } from "./chunk-3OTCSFDG.mjs";
5
+ import {
6
+ APP_CONFIG_FILE_NAMES,
7
+ DATABASE_CONFIG_FILE_NAMES,
8
+ isModulePackage,
9
+ pathExists,
10
+ resolveFirstExistingPath
11
+ } from "./chunk-66FHW725.mjs";
12
+
13
+ // src/project/config.ts
14
+ import { mkdir, writeFile } from "fs/promises";
15
+ import { dirname, extname, join, resolve } from "path";
16
+ import {
17
+ loadConfigDirectory,
18
+ holoAppDefaults,
19
+ holoDatabaseDefaults
20
+ } from "@holo-js/config";
21
+ import {
22
+ DEFAULT_HOLO_PROJECT_PATHS,
23
+ normalizeHoloProjectConfig,
24
+ renderGeneratedSchemaPlaceholder
25
+ } from "@holo-js/db";
26
+ async function loadProjectConfig(projectRoot, options = {}) {
27
+ const appConfigPath = await resolveFirstExistingPath(projectRoot, APP_CONFIG_FILE_NAMES);
28
+ if (!appConfigPath) {
29
+ if (options.required) {
30
+ throw new Error(`Missing config/app.(ts|mts|js|mjs) in ${projectRoot}. Run a generator command first to create it.`);
31
+ }
32
+ return {
33
+ config: normalizeHoloProjectConfig()
34
+ };
35
+ }
36
+ const loaded = await loadConfigDirectory(projectRoot, {
37
+ processEnv: process.env
38
+ });
39
+ const baseConfig = normalizeHoloProjectConfig({
40
+ paths: loaded.app.paths,
41
+ database: loaded.database
42
+ });
43
+ const registry = await loadGeneratedProjectRegistry(projectRoot);
44
+ return {
45
+ manifestPath: appConfigPath,
46
+ config: registry ? normalizeHoloProjectConfig({
47
+ paths: baseConfig.paths,
48
+ models: registry.models.map((entry) => entry.sourcePath),
49
+ migrations: registry.migrations.map((entry) => entry.sourcePath),
50
+ seeders: registry.seeders.map((entry) => entry.sourcePath),
51
+ database: loaded.database
52
+ }) : baseConfig
53
+ };
54
+ }
55
+ async function serializeProjectConfig(projectRoot, config, manifestPath) {
56
+ const loaded = await loadConfigDirectory(projectRoot, {
57
+ processEnv: process.env
58
+ }).catch(() => void 0);
59
+ const appConfig = loaded?.app ?? holoAppDefaults;
60
+ const contents = JSON.stringify({
61
+ name: appConfig.name,
62
+ key: appConfig.key,
63
+ url: appConfig.url,
64
+ debug: appConfig.debug,
65
+ env: appConfig.env,
66
+ paths: config.paths
67
+ }, null, 2);
68
+ const extension = extname(manifestPath);
69
+ const isCommonJs = extension === ".js" && !await isModulePackage(projectRoot);
70
+ if (isCommonJs) {
71
+ return [
72
+ "const { defineAppConfig } = require('@holo-js/config')",
73
+ "",
74
+ "module.exports = defineAppConfig(",
75
+ contents,
76
+ ")",
77
+ ""
78
+ ].join("\n");
79
+ }
80
+ return [
81
+ "import { defineAppConfig } from '@holo-js/config'",
82
+ "",
83
+ "export default defineAppConfig(",
84
+ contents,
85
+ ")",
86
+ ""
87
+ ].join("\n");
88
+ }
89
+ async function serializeDatabaseConfig(projectRoot, _targetPath) {
90
+ const loaded = await loadConfigDirectory(projectRoot, {
91
+ processEnv: process.env
92
+ }).catch(() => void 0);
93
+ const databaseConfig = loaded?.database ?? holoDatabaseDefaults;
94
+ const contents = JSON.stringify({
95
+ defaultConnection: databaseConfig.defaultConnection,
96
+ connections: databaseConfig.connections
97
+ }, null, 2);
98
+ return [
99
+ "import { defineDatabaseConfig } from '@holo-js/config'",
100
+ "",
101
+ "export default defineDatabaseConfig(",
102
+ contents,
103
+ ")",
104
+ ""
105
+ ].join("\n");
106
+ }
107
+ async function writeProjectConfig(projectRoot, config, manifestPath) {
108
+ const targetPath = manifestPath ?? join(projectRoot, "config/app.ts");
109
+ await mkdir(dirname(targetPath), { recursive: true });
110
+ await writeFile(targetPath, await serializeProjectConfig(projectRoot, config, targetPath), "utf8");
111
+ return targetPath;
112
+ }
113
+ function resolveGeneratedSchemaPath(projectRoot, config) {
114
+ return resolve(projectRoot, config.paths.generatedSchema);
115
+ }
116
+ async function ensureGeneratedSchemaPlaceholder(projectRoot, config) {
117
+ const filePath = resolveGeneratedSchemaPath(projectRoot, config);
118
+ if (await pathExists(filePath)) {
119
+ return filePath;
120
+ }
121
+ await mkdir(dirname(filePath), { recursive: true });
122
+ await writeFile(filePath, renderGeneratedSchemaPlaceholder(), "utf8");
123
+ return filePath;
124
+ }
125
+ async function ensureProjectConfig(projectRoot) {
126
+ const loaded = await loadProjectConfig(projectRoot);
127
+ if (loaded.manifestPath) {
128
+ await ensureDatabaseConfig(projectRoot);
129
+ return loaded;
130
+ }
131
+ const manifestPath = await writeProjectConfig(projectRoot, normalizeHoloProjectConfig());
132
+ await ensureDatabaseConfig(projectRoot);
133
+ return {
134
+ manifestPath,
135
+ config: normalizeHoloProjectConfig()
136
+ };
137
+ }
138
+ async function ensureDatabaseConfig(projectRoot) {
139
+ const existingPath = await resolveFirstExistingPath(projectRoot, DATABASE_CONFIG_FILE_NAMES);
140
+ if (existingPath) {
141
+ return existingPath;
142
+ }
143
+ const targetPath = join(projectRoot, "config/database.ts");
144
+ await mkdir(dirname(targetPath), { recursive: true });
145
+ await writeFile(targetPath, await serializeDatabaseConfig(projectRoot, targetPath), "utf8");
146
+ return targetPath;
147
+ }
148
+ function defaultProjectConfig() {
149
+ return normalizeHoloProjectConfig({
150
+ paths: DEFAULT_HOLO_PROJECT_PATHS,
151
+ models: [],
152
+ migrations: [],
153
+ seeders: []
154
+ });
155
+ }
156
+
157
+ export {
158
+ loadProjectConfig,
159
+ serializeProjectConfig,
160
+ serializeDatabaseConfig,
161
+ writeProjectConfig,
162
+ resolveGeneratedSchemaPath,
163
+ ensureGeneratedSchemaPlaceholder,
164
+ ensureProjectConfig,
165
+ defaultProjectConfig
166
+ };
@@ -0,0 +1,25 @@
1
+ import {
2
+ readTextFile
3
+ } from "./chunk-G5ADO27Q.mjs";
4
+
5
+ // src/fs-utils.ts
6
+ import { stat } from "fs/promises";
7
+ async function fileExists(path) {
8
+ try {
9
+ await stat(path);
10
+ return true;
11
+ } catch {
12
+ return false;
13
+ }
14
+ }
15
+ async function ensureAbsent(path) {
16
+ const existing = await readTextFile(path);
17
+ if (typeof existing !== "undefined") {
18
+ throw new TypeError(`Refusing to overwrite existing file: ${path}`);
19
+ }
20
+ }
21
+
22
+ export {
23
+ fileExists,
24
+ ensureAbsent
25
+ };