@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
@@ -7,11 +7,11 @@ import {
7
7
  serializeDatabaseConfig,
8
8
  serializeProjectConfig,
9
9
  writeProjectConfig
10
- } from "./chunk-GSQ3HTRO.mjs";
11
- import "./chunk-H7TJ4FB3.mjs";
10
+ } from "./chunk-5BLEC66P.mjs";
11
+ import "./chunk-MXKNQACM.mjs";
12
12
  import {
13
13
  readTextFile
14
- } from "./chunk-G5ADO27Q.mjs";
14
+ } from "./chunk-R6BWRY3E.mjs";
15
15
  export {
16
16
  defaultProjectConfig,
17
17
  ensureGeneratedSchemaPlaceholder,
@@ -13,16 +13,16 @@ import {
13
13
  runProjectLifecycleScript,
14
14
  runProjectPrepare,
15
15
  toPosixSlashes
16
- } from "./chunk-ICKN56JY.mjs";
16
+ } from "./chunk-SCCPDJGO.mjs";
17
17
  import {
18
18
  hasProjectDependency
19
- } from "./chunk-CUL4RJTG.mjs";
19
+ } from "./chunk-F4MT6GBK.mjs";
20
20
  import "./chunk-D7O4SU6N.mjs";
21
- import "./chunk-S7P7EBM3.mjs";
22
- import "./chunk-HE6FYNVN.mjs";
23
- import "./chunk-GSQ3HTRO.mjs";
24
- import "./chunk-H7TJ4FB3.mjs";
25
- import "./chunk-G5ADO27Q.mjs";
21
+ import "./chunk-UZTDQKIY.mjs";
22
+ import "./chunk-VCEO6N5T.mjs";
23
+ import "./chunk-5BLEC66P.mjs";
24
+ import "./chunk-MXKNQACM.mjs";
25
+ import "./chunk-R6BWRY3E.mjs";
26
26
  export {
27
27
  collectDirectoryTree,
28
28
  collectDiscoveryWatchRoots,
@@ -10,9 +10,9 @@ import {
10
10
  resolveListenerEventNamesFromSource,
11
11
  resolveNamedExport,
12
12
  resolveNamedExportEntry
13
- } from "./chunk-S7P7EBM3.mjs";
14
- import "./chunk-H7TJ4FB3.mjs";
15
- import "./chunk-G5ADO27Q.mjs";
13
+ } from "./chunk-UZTDQKIY.mjs";
14
+ import "./chunk-MXKNQACM.mjs";
15
+ import "./chunk-R6BWRY3E.mjs";
16
16
  export {
17
17
  collectImportedBindingsBySource,
18
18
  discoverAppCommands,
@@ -1,31 +1,32 @@
1
+ import {
2
+ resolveStringFlag
3
+ } from "./chunk-5EU32E7X.mjs";
4
+ import {
5
+ runProjectPrepare
6
+ } from "./chunk-SCCPDJGO.mjs";
7
+ import "./chunk-F4MT6GBK.mjs";
1
8
  import {
2
9
  hasRegisteredCreateTableMigration,
3
10
  hasRegisteredMigrationSlug,
4
11
  nextMigrationTemplate
5
- } from "./chunk-Q5F6C2D4.mjs";
6
- import {
7
- resolveStringFlag
8
- } from "./chunk-JX2ZH6XY.mjs";
12
+ } from "./chunk-BAFQ2GOA.mjs";
9
13
  import {
10
14
  writeLine
11
15
  } from "./chunk-ZXDU7RHU.mjs";
12
16
  import {
13
17
  ensureAbsent,
14
18
  fileExists
15
- } from "./chunk-EUIVXVJL.mjs";
16
- import {
17
- runProjectPrepare
18
- } from "./chunk-ICKN56JY.mjs";
19
- import "./chunk-CUL4RJTG.mjs";
19
+ } from "./chunk-57SJ566R.mjs";
20
20
  import "./chunk-D7O4SU6N.mjs";
21
21
  import {
22
+ collectFiles,
22
23
  prepareProjectDiscovery
23
- } from "./chunk-S7P7EBM3.mjs";
24
- import "./chunk-HE6FYNVN.mjs";
24
+ } from "./chunk-UZTDQKIY.mjs";
25
+ import "./chunk-VCEO6N5T.mjs";
25
26
  import {
26
27
  ensureGeneratedSchemaPlaceholder,
27
28
  ensureProjectConfig
28
- } from "./chunk-GSQ3HTRO.mjs";
29
+ } from "./chunk-5BLEC66P.mjs";
29
30
  import {
30
31
  ensureSuffix,
31
32
  loadGeneratedProjectRegistry,
@@ -47,22 +48,127 @@ import {
47
48
  toKebabCase,
48
49
  toPascalCase,
49
50
  toSnakeCase
50
- } from "./chunk-H7TJ4FB3.mjs";
51
+ } from "./chunk-MXKNQACM.mjs";
51
52
  import {
52
53
  makeProjectRelativePath,
53
54
  resolveDefaultArtifactPath,
54
55
  writeTextFile
55
- } from "./chunk-G5ADO27Q.mjs";
56
+ } from "./chunk-R6BWRY3E.mjs";
56
57
 
57
58
  // src/generators.ts
58
59
  import { createHash } from "crypto";
59
60
  import { readFile } from "fs/promises";
60
- import { resolve } from "path";
61
+ import { basename, extname, resolve } from "path";
61
62
  import { normalizeMigrationSlug } from "@holo-js/db";
62
63
  var MAIL_VIEW_SCAFFOLDING_UNAVAILABLE_MESSAGE = 'View-backed mail scaffolding requires a renderView runtime binding, which the first-party app scaffolds do not configure yet. Use "--markdown" instead.';
63
64
  function hasRegisteredModelName(registry, modelName) {
64
65
  return Boolean(registry?.models.some((entry) => entry.name === modelName));
65
66
  }
67
+ function findRegisteredModelByTableName(registry, tableName) {
68
+ return registry?.models.find((entry) => entry.tableName === tableName);
69
+ }
70
+ async function findGeneratedModelSourceByTableName(projectRoot, modelsPath, tableName) {
71
+ const files = await collectFiles(resolve(projectRoot, modelsPath));
72
+ const generatedTableReference = tableName;
73
+ for (const filePath of files) {
74
+ const contents = await readFile(filePath, "utf8");
75
+ if (containsDefineModelTableReference(contents, generatedTableReference)) {
76
+ return basename(filePath, extname(filePath));
77
+ }
78
+ }
79
+ return void 0;
80
+ }
81
+ function containsDefineModelTableReference(contents, tableName) {
82
+ let index = 0;
83
+ while (index < contents.length) {
84
+ const nextReference = contents.indexOf("defineModel", index);
85
+ if (nextReference === -1) return false;
86
+ if (isInsideComment(contents, nextReference)) {
87
+ index = nextReference + "defineModel".length;
88
+ continue;
89
+ }
90
+ const before = contents[nextReference - 1];
91
+ const after = contents[nextReference + "defineModel".length];
92
+ const hasIdentifierBoundary = !isIdentifierCharacter(before) && !isIdentifierCharacter(after);
93
+ if (!hasIdentifierBoundary) {
94
+ index = nextReference + "defineModel".length;
95
+ continue;
96
+ }
97
+ const openParenIndex = skipWhitespace(contents, nextReference + "defineModel".length);
98
+ if (contents[openParenIndex] !== "(") {
99
+ index = nextReference + "defineModel".length;
100
+ continue;
101
+ }
102
+ const firstArgumentIndex = skipWhitespace(contents, openParenIndex + 1);
103
+ const quote = contents[firstArgumentIndex];
104
+ if (quote !== "'" && quote !== '"' && quote !== "`") {
105
+ index = firstArgumentIndex;
106
+ continue;
107
+ }
108
+ const literal = readStringLiteral(contents, firstArgumentIndex, quote);
109
+ if (literal?.value === tableName) return true;
110
+ index = literal?.endIndex ?? firstArgumentIndex + 1;
111
+ }
112
+ return false;
113
+ }
114
+ function isInsideComment(contents, position) {
115
+ let index = 0;
116
+ while (index < position) {
117
+ const current = contents[index];
118
+ const next = contents[index + 1];
119
+ if (current === "'" || current === '"' || current === "`") {
120
+ index = readStringLiteral(contents, index, current)?.endIndex ?? index + 1;
121
+ continue;
122
+ }
123
+ if (current === "/" && next === "/") {
124
+ const end = contents.indexOf("\n", index + 2);
125
+ if (end === -1 || end >= position) return true;
126
+ index = end + 1;
127
+ continue;
128
+ }
129
+ if (current === "/" && next === "*") {
130
+ const end = contents.indexOf("*/", index + 2);
131
+ if (end === -1 || end + 2 >= position) return true;
132
+ index = end + 2;
133
+ continue;
134
+ }
135
+ index += 1;
136
+ }
137
+ return false;
138
+ }
139
+ function isIdentifierCharacter(value) {
140
+ return typeof value === "string" && /[$\w]/.test(value);
141
+ }
142
+ function skipWhitespace(contents, startIndex) {
143
+ let index = startIndex;
144
+ while (/\s/.test(contents[index] ?? "")) {
145
+ index += 1;
146
+ }
147
+ return index;
148
+ }
149
+ function readStringLiteral(contents, startIndex, quote) {
150
+ let value = "";
151
+ let index = startIndex + 1;
152
+ while (index < contents.length) {
153
+ const current = contents[index];
154
+ if (current === "\\") {
155
+ const escaped = contents[index + 1];
156
+ if (typeof escaped === "string") {
157
+ value += escaped;
158
+ index += 2;
159
+ continue;
160
+ }
161
+ }
162
+ if (current === quote) {
163
+ return { value, endIndex: index + 1 };
164
+ }
165
+ if (typeof current === "string") {
166
+ value += current;
167
+ }
168
+ index += 1;
169
+ }
170
+ return void 0;
171
+ }
66
172
  function hasRegisteredJobName(registry, jobName) {
67
173
  return Boolean(registry?.jobs.some((entry) => entry.name === jobName));
68
174
  }
@@ -128,6 +234,7 @@ async function resolveProjectMailViewFramework(projectRoot) {
128
234
  }
129
235
  async function runMakeModel(io, projectRoot, input) {
130
236
  const project = await ensureProjectConfig(projectRoot);
237
+ const generatedSchemaFilePath = await ensureGeneratedSchemaPlaceholder(projectRoot, project.config);
131
238
  const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
132
239
  const requestedName = String(input.args[0] ?? "");
133
240
  const options = {
@@ -146,7 +253,6 @@ async function runMakeModel(io, projectRoot, input) {
146
253
  const seederFilePath = resolveArtifactPath(projectRoot, project.config.paths.seeders, seederInfo.directory, `${seederInfo.baseName}.ts`);
147
254
  const factoryInfo = resolveNameInfo(`${requestedName}Factory`, { suffix: "Factory" });
148
255
  const factoryFilePath = resolveArtifactPath(projectRoot, project.config.paths.factories, factoryInfo.directory, `${factoryInfo.baseName}.ts`);
149
- const generatedSchemaFilePath = await ensureGeneratedSchemaPlaceholder(projectRoot, project.config);
150
256
  if (await fileExists(modelFilePath) || hasRegisteredModelName(registry, nameInfo.baseName)) {
151
257
  throw new Error(`Model with the same name already exists: ${nameInfo.baseName}.`);
152
258
  }
@@ -156,6 +262,18 @@ async function runMakeModel(io, projectRoot, input) {
156
262
  throw new Error(`A migration for table "${tableName}" already exists.`);
157
263
  }
158
264
  }
265
+ const existingTableModel = findRegisteredModelByTableName(registry, tableName);
266
+ if (existingTableModel) {
267
+ throw new Error(`Discovered duplicate model "${existingTableModel.name}" for table "${tableName}".`);
268
+ }
269
+ const existingGeneratedModelName = await findGeneratedModelSourceByTableName(
270
+ projectRoot,
271
+ project.config.paths.models,
272
+ tableName
273
+ );
274
+ if (existingGeneratedModelName) {
275
+ throw new Error(`Discovered duplicate model "${existingGeneratedModelName}" for table "${tableName}".`);
276
+ }
159
277
  await ensureAbsent(modelFilePath);
160
278
  if (options.observer) {
161
279
  await ensureAbsent(observerFilePath);
package/dist/index.d.ts CHANGED
@@ -19,7 +19,7 @@ interface HoloAppCommand {
19
19
  readonly usage?: string;
20
20
  run(context: CommandExecutionContext): unknown | Promise<unknown>;
21
21
  }
22
- declare function defineCommand<TCommand extends HoloAppCommand>(command: TCommand): TCommand;
22
+ declare function defineCommand(command: HoloAppCommand): Readonly<HoloAppCommand>;
23
23
 
24
24
  type IoStreams = {
25
25
  readonly cwd: string;