@holo-js/cli 0.1.3 → 0.1.5

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 +192 -35
  2. package/dist/{broadcast-YZS4OFCM.mjs → broadcast-RT5KVZWP.mjs} +5 -5
  3. package/dist/{cache-V43YMG4K.mjs → cache-NHCCHT44.mjs} +5 -5
  4. package/dist/{cache-migrations-ZUOI2A7N.mjs → cache-migrations-R2RL2RVD.mjs} +15 -16
  5. package/dist/{chunk-EUIVXVJL.mjs → chunk-57SJ566R.mjs} +1 -1
  6. package/dist/chunk-5BLEC66P.mjs +284 -0
  7. package/dist/{chunk-JX2ZH6XY.mjs → chunk-5EU32E7X.mjs} +3 -3
  8. package/dist/{chunk-Q5F6C2D4.mjs → chunk-BAFQ2GOA.mjs} +1 -1
  9. package/dist/{chunk-CUL4RJTG.mjs → chunk-F4MT6GBK.mjs} +1 -1
  10. package/dist/{chunk-3OTCSFDG.mjs → chunk-MXKNQACM.mjs} +544 -82
  11. package/dist/{chunk-QYLSMF7V.mjs → chunk-OZUDZEAW.mjs} +142 -28
  12. package/dist/{chunk-66FHW725.mjs → chunk-R6BWRY3E.mjs} +28 -2
  13. package/dist/{chunk-RB65DLR4.mjs → chunk-SCCPDJGO.mjs} +156 -16
  14. package/dist/{chunk-VT5IDQG6.mjs → chunk-UZTDQKIY.mjs} +61 -44
  15. package/dist/{chunk-HE6FYNVN.mjs → chunk-VCEO6N5T.mjs} +3563 -2505
  16. package/dist/{config-LS5USBRB.mjs → config-5JSC6KJG.mjs} +3 -3
  17. package/dist/{dev-KGRIGLJY.mjs → dev-OSLYSBTL.mjs} +7 -7
  18. package/dist/{discovery-GBLAUTXS.mjs → discovery-JLT2EOGH.mjs} +3 -3
  19. package/dist/{generators-WSF23UKM.mjs → generators-ZIWACCBE.mjs} +134 -16
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.mjs +189 -32
  22. package/dist/media-migrations-UBAL2YVV.mjs +117 -0
  23. package/dist/{queue-6N7HQMRL.mjs → queue-I66EISVS.mjs} +14 -14
  24. package/dist/{queue-migrations-O6QSSDPQ.mjs → queue-migrations-UIAMAB6E.mjs} +24 -20
  25. package/dist/{runtime-RI4OWTIT.mjs → runtime-MMQGO4PP.mjs} +9 -7
  26. package/dist/{runtime-OOSJ5JBY.mjs → runtime-ZKD6URAV.mjs} +1 -1
  27. package/dist/{scaffold-IYWZKT3W.mjs → scaffold-ISDVICNQ.mjs} +18 -4
  28. package/dist/{security-AE6LGNC4.mjs → security-OZXTMYXF.mjs} +10 -7
  29. package/package.json +13 -12
  30. package/dist/broadcast-ZYFKUFM5.mjs +0 -85
  31. package/dist/cache-ODBZT6IP.mjs +0 -67
  32. package/dist/cache-migrations-KPOEH6GP.mjs +0 -155
  33. package/dist/chunk-BWW5TDFI.mjs +0 -4
  34. package/dist/chunk-D4GG556Y.mjs +0 -23
  35. package/dist/chunk-ET7UXHHQ.mjs +0 -166
  36. package/dist/chunk-G5ADO27Q.mjs +0 -463
  37. package/dist/chunk-GSQ3HTRO.mjs +0 -165
  38. package/dist/chunk-H7TJ4FB3.mjs +0 -848
  39. package/dist/chunk-ICJR7TS4.mjs +0 -66
  40. package/dist/chunk-ICKN56JY.mjs +0 -342
  41. package/dist/chunk-M7J3YTHR.mjs +0 -26
  42. package/dist/chunk-S7P7EBM3.mjs +0 -787
  43. package/dist/chunk-SRWJU3A5.mjs +0 -11
  44. package/dist/chunk-T4OVZZEE.mjs +0 -3204
  45. package/dist/chunk-URK7C3VQ.mjs +0 -538
  46. package/dist/chunk-XUYKPU5Q.mjs +0 -272
  47. package/dist/config-DMWBMMGD.mjs +0 -26
  48. package/dist/dev-LVHDCPVS.mjs +0 -43
  49. package/dist/discovery-R733D2PO.mjs +0 -29
  50. package/dist/generators-32R45P6Z.mjs +0 -426
  51. package/dist/queue-QG5EXOG4.mjs +0 -626
  52. package/dist/queue-migrations-JWKU45Y3.mjs +0 -163
  53. package/dist/runtime-ANBO7VQM.mjs +0 -33
  54. package/dist/runtime-ZRPK5DIT.mjs +0 -56
  55. package/dist/scaffold-ULATB4CA.mjs +0 -121
  56. package/dist/security-OCOPEH2V.mjs +0 -69
@@ -0,0 +1,284 @@
1
+ import {
2
+ loadGeneratedProjectRegistry
3
+ } from "./chunk-MXKNQACM.mjs";
4
+ import {
5
+ APP_CONFIG_FILE_NAMES,
6
+ DATABASE_CONFIG_FILE_NAMES,
7
+ bundleProjectModule,
8
+ isModulePackage,
9
+ pathExists,
10
+ resolveFirstExistingPath
11
+ } from "./chunk-R6BWRY3E.mjs";
12
+
13
+ // src/project/config.ts
14
+ import { createHash } from "crypto";
15
+ import { mkdir, readFile, writeFile } from "fs/promises";
16
+ import { dirname, extname, join, resolve } from "path";
17
+ import { pathToFileURL } from "url";
18
+ import {
19
+ loadConfigDirectory,
20
+ holoAppDefaults,
21
+ holoDatabaseDefaults,
22
+ loadEnvironment,
23
+ normalizeAppConfig,
24
+ normalizeDatabaseConfig
25
+ } from "@holo-js/config";
26
+ import {
27
+ DEFAULT_HOLO_PROJECT_PATHS,
28
+ normalizeHoloProjectConfig,
29
+ renderGeneratedSchemaPlaceholder
30
+ } from "@holo-js/db";
31
+ function isObject(value) {
32
+ return !!value && typeof value === "object" && !Array.isArray(value);
33
+ }
34
+ function resolveConfigExport(moduleValue) {
35
+ if (isObject(moduleValue) && isObject(moduleValue.default)) {
36
+ return moduleValue.default;
37
+ }
38
+ if (isObject(moduleValue) && isObject(moduleValue.config)) {
39
+ return moduleValue.config;
40
+ }
41
+ if (isObject(moduleValue) && ("default" in moduleValue || "config" in moduleValue)) {
42
+ return {};
43
+ }
44
+ if (isObject(moduleValue)) {
45
+ return moduleValue;
46
+ }
47
+ return {};
48
+ }
49
+ var projectConfigImportStates = /* @__PURE__ */ new Map();
50
+ var projectConfigImportLock = Promise.resolve();
51
+ var projectConfigImportNonce = 0;
52
+ async function withProjectConfigImportLock(callback) {
53
+ const previousLock = projectConfigImportLock;
54
+ let releaseLock = () => {
55
+ };
56
+ projectConfigImportLock = new Promise((resolveLock) => {
57
+ releaseLock = resolveLock;
58
+ });
59
+ await previousLock;
60
+ try {
61
+ return await callback();
62
+ } finally {
63
+ releaseLock();
64
+ }
65
+ }
66
+ function hashProjectConfigImportInputs(fileContents, environmentValues) {
67
+ const hash = createHash("sha256").update(fileContents).update("\0");
68
+ const keys = Object.keys(environmentValues).sort();
69
+ for (const key of keys) {
70
+ hash.update(key).update("\0").update(environmentValues[key] ?? "").update("\0");
71
+ }
72
+ return hash.digest("hex").slice(0, 16);
73
+ }
74
+ async function resolveProjectConfigImportUrl(filePath, environmentValues) {
75
+ const fileUrl = pathToFileURL(filePath).href;
76
+ const hash = hashProjectConfigImportInputs(await readFile(filePath, "utf8"), environmentValues);
77
+ const previous = projectConfigImportStates.get(filePath);
78
+ if (previous?.hash === hash) {
79
+ return `${fileUrl}?t=${previous.nonce}`;
80
+ }
81
+ projectConfigImportNonce += 1;
82
+ const next = {
83
+ hash,
84
+ nonce: projectConfigImportNonce
85
+ };
86
+ projectConfigImportStates.set(filePath, next);
87
+ return `${fileUrl}?t=${next.nonce}`;
88
+ }
89
+ async function importProjectConfigFile(projectRoot, filePath, environmentValues) {
90
+ return withProjectConfigImportLock(async () => {
91
+ const previousEnvEntries = /* @__PURE__ */ new Map();
92
+ const importUrl = await resolveProjectConfigImportUrl(filePath, environmentValues);
93
+ const configExtension = extname(filePath);
94
+ const bundled = configExtension === ".ts" || configExtension === ".mts" ? await bundleProjectModule(projectRoot, filePath) : void 0;
95
+ const resolvedImportUrl = bundled ? `${pathToFileURL(bundled.path).href}${new URL(importUrl).search}` : importUrl;
96
+ try {
97
+ for (const [key, value] of Object.entries(environmentValues)) {
98
+ previousEnvEntries.set(key, process.env[key]);
99
+ process.env[key] = value;
100
+ }
101
+ return resolveConfigExport(await import(resolvedImportUrl));
102
+ } finally {
103
+ for (const [key, value] of previousEnvEntries) {
104
+ if (typeof value === "string") {
105
+ process.env[key] = value;
106
+ continue;
107
+ }
108
+ Reflect.deleteProperty(process.env, key);
109
+ }
110
+ await bundled?.cleanup();
111
+ }
112
+ });
113
+ }
114
+ async function loadCachedProjectSourceConfig(projectRoot, environmentName) {
115
+ const cachePath = join(projectRoot, ".holo-js/generated/config-cache.json");
116
+ if (environmentName !== "production" || !await pathExists(cachePath)) {
117
+ return void 0;
118
+ }
119
+ const loaded = await loadConfigDirectory(projectRoot, {
120
+ processEnv: process.env
121
+ });
122
+ return {
123
+ app: loaded.app,
124
+ database: loaded.database
125
+ };
126
+ }
127
+ async function loadProjectConfig(projectRoot, options = {}) {
128
+ const appConfigPath = await resolveFirstExistingPath(projectRoot, APP_CONFIG_FILE_NAMES);
129
+ if (!appConfigPath) {
130
+ if (options.required) {
131
+ throw new Error(`Missing config/app.(ts|mts|js|mjs) in ${projectRoot}. Run a generator command first to create it.`);
132
+ }
133
+ return {
134
+ config: normalizeHoloProjectConfig()
135
+ };
136
+ }
137
+ const databaseConfigPath = await resolveFirstExistingPath(projectRoot, DATABASE_CONFIG_FILE_NAMES);
138
+ const environment = await loadEnvironment({
139
+ cwd: projectRoot,
140
+ processEnv: process.env
141
+ });
142
+ const cachedConfig = await loadCachedProjectSourceConfig(projectRoot, environment.name);
143
+ const app = cachedConfig?.app ?? normalizeAppConfig(await importProjectConfigFile(projectRoot, appConfigPath, environment.values));
144
+ const database = cachedConfig?.database ?? normalizeDatabaseConfig(databaseConfigPath ? await importProjectConfigFile(projectRoot, databaseConfigPath, environment.values) : void 0);
145
+ const baseConfig = normalizeHoloProjectConfig({
146
+ paths: app.paths,
147
+ models: app.models,
148
+ migrations: app.migrations,
149
+ seeders: app.seeders,
150
+ database
151
+ });
152
+ const registry = await loadGeneratedProjectRegistry(projectRoot);
153
+ return {
154
+ manifestPath: appConfigPath,
155
+ config: registry ? normalizeHoloProjectConfig({
156
+ paths: baseConfig.paths,
157
+ models: [.../* @__PURE__ */ new Set([
158
+ ...baseConfig.models,
159
+ ...registry.models.map((entry) => entry.sourcePath)
160
+ ])],
161
+ migrations: [.../* @__PURE__ */ new Set([
162
+ ...baseConfig.migrations,
163
+ ...registry.migrations.map((entry) => entry.sourcePath)
164
+ ])],
165
+ seeders: [.../* @__PURE__ */ new Set([
166
+ ...baseConfig.seeders,
167
+ ...registry.seeders.map((entry) => entry.sourcePath)
168
+ ])],
169
+ database
170
+ }) : baseConfig
171
+ };
172
+ }
173
+ async function serializeProjectConfig(projectRoot, config, manifestPath) {
174
+ const loaded = await loadConfigDirectory(projectRoot, {
175
+ processEnv: process.env
176
+ }).catch(() => void 0);
177
+ const appConfig = loaded?.app ?? holoAppDefaults;
178
+ const contents = JSON.stringify({
179
+ name: appConfig.name,
180
+ key: appConfig.key,
181
+ url: appConfig.url,
182
+ debug: appConfig.debug,
183
+ env: appConfig.env,
184
+ paths: config.paths
185
+ }, null, 2);
186
+ const extension = extname(manifestPath);
187
+ const isCommonJs = extension === ".js" && !await isModulePackage(projectRoot);
188
+ if (isCommonJs) {
189
+ return [
190
+ "const { defineAppConfig } = require('@holo-js/config')",
191
+ "",
192
+ "module.exports = defineAppConfig(",
193
+ contents,
194
+ ")",
195
+ ""
196
+ ].join("\n");
197
+ }
198
+ return [
199
+ "import { defineAppConfig } from '@holo-js/config'",
200
+ "",
201
+ "export default defineAppConfig(",
202
+ contents,
203
+ ")",
204
+ ""
205
+ ].join("\n");
206
+ }
207
+ async function serializeDatabaseConfig(projectRoot, _targetPath) {
208
+ const loaded = await loadConfigDirectory(projectRoot, {
209
+ processEnv: process.env
210
+ }).catch(() => void 0);
211
+ const databaseConfig = loaded?.database ?? holoDatabaseDefaults;
212
+ const contents = JSON.stringify({
213
+ defaultConnection: databaseConfig.defaultConnection,
214
+ connections: databaseConfig.connections
215
+ }, null, 2);
216
+ return [
217
+ "import { defineDatabaseConfig } from '@holo-js/config'",
218
+ "",
219
+ "export default defineDatabaseConfig(",
220
+ contents,
221
+ ")",
222
+ ""
223
+ ].join("\n");
224
+ }
225
+ async function writeProjectConfig(projectRoot, config, manifestPath) {
226
+ const targetPath = manifestPath ?? join(projectRoot, "config/app.ts");
227
+ await mkdir(dirname(targetPath), { recursive: true });
228
+ await writeFile(targetPath, await serializeProjectConfig(projectRoot, config, targetPath), "utf8");
229
+ return targetPath;
230
+ }
231
+ function resolveGeneratedSchemaPath(projectRoot, config) {
232
+ return resolve(projectRoot, config.paths.generatedSchema);
233
+ }
234
+ async function ensureGeneratedSchemaPlaceholder(projectRoot, config) {
235
+ const filePath = resolveGeneratedSchemaPath(projectRoot, config);
236
+ if (await pathExists(filePath)) {
237
+ return filePath;
238
+ }
239
+ await mkdir(dirname(filePath), { recursive: true });
240
+ await writeFile(filePath, renderGeneratedSchemaPlaceholder(), "utf8");
241
+ return filePath;
242
+ }
243
+ async function ensureProjectConfig(projectRoot) {
244
+ const loaded = await loadProjectConfig(projectRoot);
245
+ if (loaded.manifestPath) {
246
+ await ensureDatabaseConfig(projectRoot);
247
+ return loaded;
248
+ }
249
+ const manifestPath = await writeProjectConfig(projectRoot, normalizeHoloProjectConfig());
250
+ await ensureDatabaseConfig(projectRoot);
251
+ return {
252
+ manifestPath,
253
+ config: normalizeHoloProjectConfig()
254
+ };
255
+ }
256
+ async function ensureDatabaseConfig(projectRoot) {
257
+ const existingPath = await resolveFirstExistingPath(projectRoot, DATABASE_CONFIG_FILE_NAMES);
258
+ if (existingPath) {
259
+ return existingPath;
260
+ }
261
+ const targetPath = join(projectRoot, "config/database.ts");
262
+ await mkdir(dirname(targetPath), { recursive: true });
263
+ await writeFile(targetPath, await serializeDatabaseConfig(projectRoot, targetPath), "utf8");
264
+ return targetPath;
265
+ }
266
+ function defaultProjectConfig() {
267
+ return normalizeHoloProjectConfig({
268
+ paths: DEFAULT_HOLO_PROJECT_PATHS,
269
+ models: [],
270
+ migrations: [],
271
+ seeders: []
272
+ });
273
+ }
274
+
275
+ export {
276
+ loadProjectConfig,
277
+ serializeProjectConfig,
278
+ serializeDatabaseConfig,
279
+ writeProjectConfig,
280
+ resolveGeneratedSchemaPath,
281
+ ensureGeneratedSchemaPlaceholder,
282
+ ensureProjectConfig,
283
+ defaultProjectConfig
284
+ };
@@ -2,10 +2,10 @@
2
2
  import { createInterface } from "readline/promises";
3
3
  var SUPPORTED_NEW_FRAMEWORKS = ["nuxt", "next", "sveltekit"];
4
4
  var SUPPORTED_NEW_DATABASE_DRIVERS = ["sqlite", "mysql", "postgres"];
5
- var SUPPORTED_NEW_PACKAGE_MANAGERS = ["bun", "npm", "pnpm", "yarn"];
5
+ var SUPPORTED_NEW_PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun"];
6
6
  var SUPPORTED_NEW_STORAGE_DISKS = ["local", "public"];
7
7
  var SUPPORTED_NEW_OPTIONAL_PACKAGES = ["storage", "events", "queue", "validation", "forms", "auth", "authorization", "notifications", "mail", "broadcast", "security", "cache"];
8
- var SUPPORTED_INSTALL_TARGETS = ["queue", "events", "auth", "authorization", "notifications", "mail", "broadcast", "security", "cache"];
8
+ var SUPPORTED_INSTALL_TARGETS = ["queue", "events", "auth", "authorization", "notifications", "mail", "broadcast", "security", "cache", "media"];
9
9
  var SUPPORTED_QUEUE_INSTALL_DRIVERS = ["sync", "redis", "database"];
10
10
  var SUPPORTED_CACHE_INSTALL_DRIVERS = ["file", "redis", "database"];
11
11
  function parseTokens(tokens) {
@@ -161,7 +161,7 @@ async function resolveNewProjectInput(io, input, prompts = {
161
161
  }
162
162
  const framework = resolveStringFlag(input.flags, "framework") ? normalizeChoice(resolveStringFlag(input.flags, "framework"), SUPPORTED_NEW_FRAMEWORKS, "framework") : interactive ? await prompts.choose("Framework", SUPPORTED_NEW_FRAMEWORKS, "nuxt") : "nuxt";
163
163
  const databaseDriver = resolveStringFlag(input.flags, "database") ? normalizeChoice(resolveStringFlag(input.flags, "database"), SUPPORTED_NEW_DATABASE_DRIVERS, "database driver") : interactive ? await prompts.choose("Database driver", SUPPORTED_NEW_DATABASE_DRIVERS, "sqlite") : "sqlite";
164
- const packageManager = resolveStringFlag(input.flags, "package-manager") ? normalizeChoice(resolveStringFlag(input.flags, "package-manager"), SUPPORTED_NEW_PACKAGE_MANAGERS, "package manager") : interactive ? await prompts.choose("Package manager", SUPPORTED_NEW_PACKAGE_MANAGERS, "bun") : "bun";
164
+ const packageManager = resolveStringFlag(input.flags, "package-manager") ? normalizeChoice(resolveStringFlag(input.flags, "package-manager"), SUPPORTED_NEW_PACKAGE_MANAGERS, "package manager") : interactive ? await prompts.choose("Package manager", SUPPORTED_NEW_PACKAGE_MANAGERS, "npm") : "npm";
165
165
  const requestedOptionalPackages = collectMultiStringFlag(input.flags, "package");
166
166
  let optionalPackages;
167
167
  if (requestedOptionalPackages) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  fileExists
3
- } from "./chunk-EUIVXVJL.mjs";
3
+ } from "./chunk-57SJ566R.mjs";
4
4
 
5
5
  // src/migrations.ts
6
6
  import { join } from "path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readTextFile
3
- } from "./chunk-G5ADO27Q.mjs";
3
+ } from "./chunk-R6BWRY3E.mjs";
4
4
 
5
5
  // src/package-json.ts
6
6
  import { join } from "path";