@holo-js/cli 0.1.4 → 0.1.6
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/bin/holo.mjs +192 -35
- package/dist/{broadcast-CSSARTSA.mjs → broadcast-2AZIC5ZP.mjs} +5 -5
- package/dist/{cache-4G6QGIZO.mjs → cache-5OROX4GL.mjs} +5 -5
- package/dist/{cache-migrations-NATT5WPQ.mjs → cache-migrations-7XFVLTOC.mjs} +15 -16
- package/dist/{chunk-EUIVXVJL.mjs → chunk-57SJ566R.mjs} +1 -1
- package/dist/chunk-5BLEC66P.mjs +284 -0
- package/dist/{chunk-JX2ZH6XY.mjs → chunk-5EU32E7X.mjs} +3 -3
- package/dist/{chunk-Q5F6C2D4.mjs → chunk-BAFQ2GOA.mjs} +1 -1
- package/dist/{chunk-CUL4RJTG.mjs → chunk-F4MT6GBK.mjs} +1 -1
- package/dist/{chunk-3OTCSFDG.mjs → chunk-MXKNQACM.mjs} +544 -82
- package/dist/{chunk-ZLRO7HXY.mjs → chunk-ODJA3TFG.mjs} +156 -15
- package/dist/{chunk-QYLSMF7V.mjs → chunk-OZUDZEAW.mjs} +142 -28
- package/dist/{chunk-66FHW725.mjs → chunk-R6BWRY3E.mjs} +28 -2
- package/dist/{chunk-MZXN2YMI.mjs → chunk-USACXIIB.mjs} +3544 -2522
- package/dist/{chunk-VT5IDQG6.mjs → chunk-UZTDQKIY.mjs} +61 -44
- package/dist/{config-LS5USBRB.mjs → config-5JSC6KJG.mjs} +3 -3
- package/dist/{dev-LZ3O2E3U.mjs → dev-F6QUWNCR.mjs} +7 -7
- package/dist/{discovery-GBLAUTXS.mjs → discovery-JLT2EOGH.mjs} +3 -3
- package/dist/{generators-DSN4GWJI.mjs → generators-WVKJLAYB.mjs} +134 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +189 -32
- package/dist/media-migrations-DU7WEKAY.mjs +117 -0
- package/dist/{queue-FV35LLPR.mjs → queue-NOLVWPCH.mjs} +14 -14
- package/dist/{queue-migrations-SSIYKK5S.mjs → queue-migrations-HXNTZMGL.mjs} +24 -20
- package/dist/{runtime-EFZ5H5IL.mjs → runtime-462O2BDR.mjs} +9 -7
- package/dist/{runtime-OOSJ5JBY.mjs → runtime-ZKD6URAV.mjs} +1 -1
- package/dist/{scaffold-7OTDH4UR.mjs → scaffold-WOJV2ZZI.mjs} +18 -5
- package/dist/{security-ATKDC26E.mjs → security-5VGM467J.mjs} +10 -7
- package/package.json +13 -12
- package/dist/broadcast-YSIJCL3R.mjs +0 -85
- package/dist/cache-OWQY4E7W.mjs +0 -67
- package/dist/cache-migrations-RVEA6CEU.mjs +0 -155
- package/dist/chunk-BWW5TDFI.mjs +0 -4
- package/dist/chunk-D4GG556Y.mjs +0 -23
- package/dist/chunk-DMH2B4UQ.mjs +0 -343
- package/dist/chunk-ET7UXHHQ.mjs +0 -166
- package/dist/chunk-G5ADO27Q.mjs +0 -463
- package/dist/chunk-GSQ3HTRO.mjs +0 -165
- package/dist/chunk-H7TJ4FB3.mjs +0 -848
- package/dist/chunk-ICJR7TS4.mjs +0 -66
- package/dist/chunk-M7J3YTHR.mjs +0 -26
- package/dist/chunk-QFUSWV3J.mjs +0 -3237
- package/dist/chunk-S7P7EBM3.mjs +0 -787
- package/dist/chunk-SRWJU3A5.mjs +0 -11
- package/dist/chunk-URK7C3VQ.mjs +0 -538
- package/dist/chunk-XUYKPU5Q.mjs +0 -272
- package/dist/config-DMWBMMGD.mjs +0 -26
- package/dist/dev-KQFT7RHR.mjs +0 -43
- package/dist/discovery-R733D2PO.mjs +0 -29
- package/dist/generators-WX45BI4U.mjs +0 -426
- package/dist/queue-6OG7VJ34.mjs +0 -626
- package/dist/queue-migrations-NK2EYX3J.mjs +0 -163
- package/dist/runtime-4BV3JODY.mjs +0 -56
- package/dist/runtime-ANBO7VQM.mjs +0 -33
- package/dist/scaffold-DRKBGS2K.mjs +0 -120
- package/dist/security-R7VH6W5H.mjs +0 -69
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
hasRegisteredCreateTableMigration,
|
|
4
|
-
hasRegisteredMigrationSlug,
|
|
5
|
-
nextMigrationTemplate
|
|
6
|
-
} from "./chunk-ICJR7TS4.mjs";
|
|
7
|
-
import {
|
|
8
|
-
resolveStringFlag
|
|
9
|
-
} from "./chunk-XUYKPU5Q.mjs";
|
|
10
|
-
import {
|
|
11
|
-
writeLine
|
|
12
|
-
} from "./chunk-SRWJU3A5.mjs";
|
|
13
|
-
import {
|
|
14
|
-
ensureAbsent,
|
|
15
|
-
fileExists
|
|
16
|
-
} from "./chunk-M7J3YTHR.mjs";
|
|
17
|
-
import {
|
|
18
|
-
runProjectPrepare
|
|
19
|
-
} from "./chunk-DMH2B4UQ.mjs";
|
|
20
|
-
import "./chunk-D4GG556Y.mjs";
|
|
21
|
-
import "./chunk-BWW5TDFI.mjs";
|
|
22
|
-
import {
|
|
23
|
-
prepareProjectDiscovery
|
|
24
|
-
} from "./chunk-VT5IDQG6.mjs";
|
|
25
|
-
import "./chunk-QFUSWV3J.mjs";
|
|
26
|
-
import {
|
|
27
|
-
ensureGeneratedSchemaPlaceholder,
|
|
28
|
-
ensureProjectConfig
|
|
29
|
-
} from "./chunk-ET7UXHHQ.mjs";
|
|
30
|
-
import {
|
|
31
|
-
ensureSuffix,
|
|
32
|
-
loadGeneratedProjectRegistry,
|
|
33
|
-
relativeImportPath,
|
|
34
|
-
renderBroadcastTemplate,
|
|
35
|
-
renderChannelTemplate,
|
|
36
|
-
renderEventTemplate,
|
|
37
|
-
renderFactoryTemplate,
|
|
38
|
-
renderJobTemplate,
|
|
39
|
-
renderListenerTemplate,
|
|
40
|
-
renderMarkdownMailTemplate,
|
|
41
|
-
renderModelTemplate,
|
|
42
|
-
renderMultiListenerTemplate,
|
|
43
|
-
renderObserverTemplate,
|
|
44
|
-
renderSeederTemplate,
|
|
45
|
-
resolveArtifactPath,
|
|
46
|
-
resolveNameInfo,
|
|
47
|
-
splitRequestedName,
|
|
48
|
-
toKebabCase,
|
|
49
|
-
toPascalCase,
|
|
50
|
-
toSnakeCase
|
|
51
|
-
} from "./chunk-3OTCSFDG.mjs";
|
|
52
|
-
import {
|
|
53
|
-
makeProjectRelativePath,
|
|
54
|
-
resolveDefaultArtifactPath,
|
|
55
|
-
writeTextFile
|
|
56
|
-
} from "./chunk-66FHW725.mjs";
|
|
57
|
-
|
|
58
|
-
// src/generators.ts
|
|
59
|
-
import { createHash } from "crypto";
|
|
60
|
-
import { readFile } from "fs/promises";
|
|
61
|
-
import { resolve } from "path";
|
|
62
|
-
import { normalizeMigrationSlug } from "@holo-js/db";
|
|
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.';
|
|
64
|
-
function hasRegisteredModelName(registry, modelName) {
|
|
65
|
-
return Boolean(registry?.models.some((entry) => entry.name === modelName));
|
|
66
|
-
}
|
|
67
|
-
function hasRegisteredJobName(registry, jobName) {
|
|
68
|
-
return Boolean(registry?.jobs.some((entry) => entry.name === jobName));
|
|
69
|
-
}
|
|
70
|
-
function hasRegisteredEventName(registry, eventName) {
|
|
71
|
-
return Boolean(registry?.events.some((entry) => entry.name === eventName));
|
|
72
|
-
}
|
|
73
|
-
function hasRegisteredListenerId(registry, listenerId) {
|
|
74
|
-
return Boolean(registry?.listeners.some((entry) => entry.id === listenerId));
|
|
75
|
-
}
|
|
76
|
-
function toChannelTemplateFileStem(pattern) {
|
|
77
|
-
const rawSegments = pattern.trim().replace(/\\/g, "/").replace(/^\.+/, "").split(/[/.]/).map((segment) => segment.trim()).filter(Boolean);
|
|
78
|
-
const hasOnlyWildcardSegments = rawSegments.length > 0 && rawSegments.every((segment) => /^\{[^}]+\}$/.test(segment));
|
|
79
|
-
const normalized = pattern.trim().replace(/\\/g, "/").replace(/^\.+/, "").replace(/\{([^}]+)\}/g, "$1").replace(/[^a-z0-9/]+/gi, "-").replace(/-+/g, "-").replace(/^[-/]+|[-/]+$/g, "");
|
|
80
|
-
const fileStem = normalized.split("/").filter(Boolean).map((segment) => toKebabCase(segment)).join("/") || "channel";
|
|
81
|
-
if (!hasOnlyWildcardSegments) {
|
|
82
|
-
return fileStem;
|
|
83
|
-
}
|
|
84
|
-
const suffix = createHash("sha1").update(pattern.trim()).digest("hex").slice(0, 8);
|
|
85
|
-
return `${fileStem}-${suffix}`;
|
|
86
|
-
}
|
|
87
|
-
function resolveChannelArtifactPath(projectRoot, channelsPath, pattern, registry) {
|
|
88
|
-
const fileStem = toChannelTemplateFileStem(pattern);
|
|
89
|
-
const filePath = resolveArtifactPath(projectRoot, channelsPath, "", `${fileStem}.ts`);
|
|
90
|
-
const relativePath = makeProjectRelativePath(projectRoot, filePath);
|
|
91
|
-
const collidesWithDifferentRegisteredPattern = registry.channels.some((entry) => {
|
|
92
|
-
return entry.sourcePath === relativePath && entry.pattern !== pattern;
|
|
93
|
-
});
|
|
94
|
-
if (!collidesWithDifferentRegisteredPattern) {
|
|
95
|
-
return filePath;
|
|
96
|
-
}
|
|
97
|
-
const suffix = createHash("sha1").update(pattern.trim()).digest("hex").slice(0, 8);
|
|
98
|
-
return resolveArtifactPath(projectRoot, channelsPath, "", `${fileStem}-${suffix}.ts`);
|
|
99
|
-
}
|
|
100
|
-
function resolveConfiguredBroadcastPath(project) {
|
|
101
|
-
const configuredPaths = project.config.paths;
|
|
102
|
-
return configuredPaths.broadcast ?? "server/broadcast";
|
|
103
|
-
}
|
|
104
|
-
function resolveConfiguredChannelsPath(project) {
|
|
105
|
-
const configuredPaths = project.config.paths;
|
|
106
|
-
return configuredPaths.channels ?? "server/channels";
|
|
107
|
-
}
|
|
108
|
-
async function resolveProjectMailViewFramework(projectRoot) {
|
|
109
|
-
try {
|
|
110
|
-
const packageJson = await readFile(resolve(projectRoot, "package.json"), "utf8");
|
|
111
|
-
const parsed = JSON.parse(packageJson);
|
|
112
|
-
const dependencies = {
|
|
113
|
-
...parsed.dependencies ?? {},
|
|
114
|
-
...parsed.devDependencies ?? {}
|
|
115
|
-
};
|
|
116
|
-
if (typeof dependencies.nuxt === "string") {
|
|
117
|
-
return "nuxt";
|
|
118
|
-
}
|
|
119
|
-
if (typeof dependencies.next === "string") {
|
|
120
|
-
return "next";
|
|
121
|
-
}
|
|
122
|
-
if (typeof dependencies["@sveltejs/kit"] === "string") {
|
|
123
|
-
return "sveltekit";
|
|
124
|
-
}
|
|
125
|
-
} catch {
|
|
126
|
-
return "generic";
|
|
127
|
-
}
|
|
128
|
-
return "generic";
|
|
129
|
-
}
|
|
130
|
-
async function runMakeModel(io, projectRoot, input) {
|
|
131
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
132
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
133
|
-
const requestedName = String(input.args[0] ?? "");
|
|
134
|
-
const options = {
|
|
135
|
-
migration: input.flags.migration === true,
|
|
136
|
-
observer: input.flags.observer === true,
|
|
137
|
-
seeder: input.flags.seeder === true,
|
|
138
|
-
factory: input.flags.factory === true
|
|
139
|
-
};
|
|
140
|
-
const nameInfo = resolveNameInfo(requestedName);
|
|
141
|
-
const explicitTableName = resolveStringFlag(input.flags, "table");
|
|
142
|
-
const tableName = explicitTableName ? toSnakeCase(explicitTableName) : nameInfo.tableName;
|
|
143
|
-
const modelFilePath = resolveArtifactPath(projectRoot, project.config.paths.models, nameInfo.directory, `${nameInfo.baseName}.ts`);
|
|
144
|
-
const observerInfo = resolveNameInfo(`${requestedName}Observer`, { suffix: "Observer" });
|
|
145
|
-
const observerFilePath = resolveArtifactPath(projectRoot, project.config.paths.observers, observerInfo.directory, `${observerInfo.baseName}.ts`);
|
|
146
|
-
const seederInfo = resolveNameInfo(`${requestedName}Seeder`, { suffix: "Seeder" });
|
|
147
|
-
const seederFilePath = resolveArtifactPath(projectRoot, project.config.paths.seeders, seederInfo.directory, `${seederInfo.baseName}.ts`);
|
|
148
|
-
const factoryInfo = resolveNameInfo(`${requestedName}Factory`, { suffix: "Factory" });
|
|
149
|
-
const factoryFilePath = resolveArtifactPath(projectRoot, project.config.paths.factories, factoryInfo.directory, `${factoryInfo.baseName}.ts`);
|
|
150
|
-
const generatedSchemaFilePath = await ensureGeneratedSchemaPlaceholder(projectRoot, project.config);
|
|
151
|
-
if (await fileExists(modelFilePath) || hasRegisteredModelName(registry, nameInfo.baseName)) {
|
|
152
|
-
throw new Error(`Model with the same name already exists: ${nameInfo.baseName}.`);
|
|
153
|
-
}
|
|
154
|
-
if (options.migration) {
|
|
155
|
-
const migrationName = normalizeMigrationSlug(`create_${tableName}_table`);
|
|
156
|
-
if (hasRegisteredMigrationSlug(registry, migrationName) || hasRegisteredCreateTableMigration(registry, tableName)) {
|
|
157
|
-
throw new Error(`A migration for table "${tableName}" already exists.`);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
await ensureAbsent(modelFilePath);
|
|
161
|
-
if (options.observer) {
|
|
162
|
-
await ensureAbsent(observerFilePath);
|
|
163
|
-
}
|
|
164
|
-
if (options.seeder) {
|
|
165
|
-
await ensureAbsent(seederFilePath);
|
|
166
|
-
}
|
|
167
|
-
if (options.factory) {
|
|
168
|
-
await ensureAbsent(factoryFilePath);
|
|
169
|
-
}
|
|
170
|
-
if (options.observer) {
|
|
171
|
-
await writeTextFile(observerFilePath, renderObserverTemplate(observerInfo.baseName));
|
|
172
|
-
}
|
|
173
|
-
await writeTextFile(modelFilePath, renderModelTemplate({
|
|
174
|
-
tableName,
|
|
175
|
-
generatedSchemaImportPath: relativeImportPath(modelFilePath, generatedSchemaFilePath),
|
|
176
|
-
...options.observer ? {
|
|
177
|
-
observerImportPath: relativeImportPath(modelFilePath, observerFilePath),
|
|
178
|
-
observerClassName: observerInfo.baseName
|
|
179
|
-
} : {}
|
|
180
|
-
}));
|
|
181
|
-
if (options.factory) {
|
|
182
|
-
await writeTextFile(factoryFilePath, renderFactoryTemplate(
|
|
183
|
-
relativeImportPath(factoryFilePath, modelFilePath),
|
|
184
|
-
nameInfo.baseName
|
|
185
|
-
));
|
|
186
|
-
}
|
|
187
|
-
if (options.seeder) {
|
|
188
|
-
await writeTextFile(seederFilePath, renderSeederTemplate(seederInfo.snakeStem));
|
|
189
|
-
}
|
|
190
|
-
if (options.migration) {
|
|
191
|
-
const migrationName = normalizeMigrationSlug(`create_${tableName}_table`);
|
|
192
|
-
const migrationTemplate = await nextMigrationTemplate(
|
|
193
|
-
migrationName,
|
|
194
|
-
resolve(projectRoot, project.config.paths.migrations)
|
|
195
|
-
);
|
|
196
|
-
const migrationFilePath = resolveDefaultArtifactPath(projectRoot, project.config.paths.migrations, migrationTemplate.fileName);
|
|
197
|
-
await writeTextFile(migrationFilePath, migrationTemplate.contents);
|
|
198
|
-
}
|
|
199
|
-
await runProjectPrepare(projectRoot);
|
|
200
|
-
writeLine(io.stdout, `Created model: ${makeProjectRelativePath(projectRoot, modelFilePath)}`);
|
|
201
|
-
if (options.migration) {
|
|
202
|
-
writeLine(io.stdout, `Registered migration for ${nameInfo.baseName}.`);
|
|
203
|
-
}
|
|
204
|
-
if (options.seeder) {
|
|
205
|
-
writeLine(io.stdout, `Registered seeder for ${nameInfo.baseName}.`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
async function runMakeMigration(io, projectRoot, input) {
|
|
209
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
210
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
211
|
-
const requestedName = String(input.args[0] ?? "");
|
|
212
|
-
const createTable = typeof input.flags.create === "string" ? normalizeMigrationSlug(input.flags.create) : void 0;
|
|
213
|
-
const alterTable = typeof input.flags.table === "string" ? normalizeMigrationSlug(input.flags.table) : void 0;
|
|
214
|
-
if (createTable && alterTable) {
|
|
215
|
-
throw new Error('Use either "--create" or "--table", not both.');
|
|
216
|
-
}
|
|
217
|
-
const requestedSlug = normalizeMigrationSlug(requestedName);
|
|
218
|
-
if (createTable) {
|
|
219
|
-
if (hasRegisteredCreateTableMigration(registry, createTable)) {
|
|
220
|
-
throw new Error(`A migration for table "${createTable}" already exists.`);
|
|
221
|
-
}
|
|
222
|
-
} else if (alterTable) {
|
|
223
|
-
if (hasRegisteredMigrationSlug(registry, requestedSlug)) {
|
|
224
|
-
throw new Error(`A migration named "${requestedSlug}" already exists.`);
|
|
225
|
-
}
|
|
226
|
-
} else if (hasRegisteredMigrationSlug(registry, requestedSlug)) {
|
|
227
|
-
throw new Error(`A migration named "${requestedSlug}" already exists.`);
|
|
228
|
-
}
|
|
229
|
-
const migrationTemplate = await nextMigrationTemplate(
|
|
230
|
-
requestedSlug,
|
|
231
|
-
resolve(projectRoot, project.config.paths.migrations),
|
|
232
|
-
{
|
|
233
|
-
...createTable ? { kind: "create_table", tableName: createTable } : {},
|
|
234
|
-
...alterTable ? { kind: "alter_table", tableName: alterTable } : {}
|
|
235
|
-
}
|
|
236
|
-
);
|
|
237
|
-
const migrationFilePath = resolveDefaultArtifactPath(projectRoot, project.config.paths.migrations, migrationTemplate.fileName);
|
|
238
|
-
await writeTextFile(migrationFilePath, migrationTemplate.contents);
|
|
239
|
-
await runProjectPrepare(projectRoot);
|
|
240
|
-
writeLine(io.stdout, `Created migration: ${makeProjectRelativePath(projectRoot, migrationFilePath)}`);
|
|
241
|
-
}
|
|
242
|
-
async function runMakeSeeder(io, projectRoot, input) {
|
|
243
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
244
|
-
const info = resolveNameInfo(String(input.args[0] ?? ""), { suffix: "Seeder" });
|
|
245
|
-
const filePath = resolveArtifactPath(projectRoot, project.config.paths.seeders, info.directory, `${info.baseName}.ts`);
|
|
246
|
-
await ensureAbsent(filePath);
|
|
247
|
-
await writeTextFile(filePath, renderSeederTemplate(info.snakeStem));
|
|
248
|
-
await runProjectPrepare(projectRoot);
|
|
249
|
-
writeLine(io.stdout, `Created seeder: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
250
|
-
}
|
|
251
|
-
async function runMakeJob(io, projectRoot, input) {
|
|
252
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
253
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
254
|
-
const requestedName = String(input.args[0] ?? "");
|
|
255
|
-
const nameParts = splitRequestedName(requestedName);
|
|
256
|
-
const directory = nameParts.directory.split("/").filter(Boolean).map((segment) => toKebabCase(segment)).join("/");
|
|
257
|
-
const fileStem = toKebabCase(nameParts.rawBaseName);
|
|
258
|
-
const filePath = resolveArtifactPath(projectRoot, project.config.paths.jobs, directory, `${fileStem}.ts`);
|
|
259
|
-
const jobName = [...directory ? directory.split("/") : [], fileStem].join(".");
|
|
260
|
-
if (await fileExists(filePath) || hasRegisteredJobName(registry, jobName)) {
|
|
261
|
-
throw new Error(`Job with the same name already exists: ${jobName}.`);
|
|
262
|
-
}
|
|
263
|
-
await ensureAbsent(filePath);
|
|
264
|
-
await writeTextFile(filePath, renderJobTemplate());
|
|
265
|
-
await runProjectPrepare(projectRoot);
|
|
266
|
-
writeLine(io.stdout, `Created job: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
267
|
-
}
|
|
268
|
-
async function runMakeEvent(io, projectRoot, input) {
|
|
269
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
270
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
271
|
-
const requestedName = String(input.args[0] ?? "");
|
|
272
|
-
const nameParts = splitRequestedName(requestedName);
|
|
273
|
-
const directory = nameParts.directory.split("/").filter(Boolean).map((segment) => toKebabCase(segment)).join("/");
|
|
274
|
-
const fileStem = toKebabCase(nameParts.rawBaseName);
|
|
275
|
-
const filePath = resolveArtifactPath(projectRoot, project.config.paths.events, directory, `${fileStem}.ts`);
|
|
276
|
-
const eventName = [...directory ? directory.split("/") : [], fileStem].join(".");
|
|
277
|
-
if (await fileExists(filePath) || hasRegisteredEventName(registry, eventName)) {
|
|
278
|
-
throw new Error(`Event with the same name already exists: ${eventName}.`);
|
|
279
|
-
}
|
|
280
|
-
await ensureAbsent(filePath);
|
|
281
|
-
await writeTextFile(filePath, renderEventTemplate(eventName));
|
|
282
|
-
await runProjectPrepare(projectRoot);
|
|
283
|
-
writeLine(io.stdout, `Created event: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
284
|
-
}
|
|
285
|
-
async function runMakeBroadcast(io, projectRoot, input) {
|
|
286
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
287
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
288
|
-
const requestedName = String(input.args[0] ?? "");
|
|
289
|
-
const nameParts = splitRequestedName(requestedName);
|
|
290
|
-
const directory = nameParts.directory.split("/").filter(Boolean).map((segment) => toKebabCase(segment)).join("/");
|
|
291
|
-
const fileStem = toKebabCase(nameParts.rawBaseName);
|
|
292
|
-
const broadcastPath = resolveConfiguredBroadcastPath(project);
|
|
293
|
-
const filePath = resolveArtifactPath(projectRoot, broadcastPath, directory, `${fileStem}.ts`);
|
|
294
|
-
const eventName = [...directory ? directory.split("/") : [], fileStem].join(".");
|
|
295
|
-
if (await fileExists(filePath) || registry.broadcast.some((entry) => entry.name === eventName)) {
|
|
296
|
-
throw new Error(`Broadcast with the same name already exists: ${eventName}.`);
|
|
297
|
-
}
|
|
298
|
-
await ensureAbsent(filePath);
|
|
299
|
-
await writeTextFile(filePath, renderBroadcastTemplate(eventName));
|
|
300
|
-
await runProjectPrepare(projectRoot);
|
|
301
|
-
writeLine(io.stdout, `Created broadcast: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
302
|
-
}
|
|
303
|
-
async function runMakeChannel(io, projectRoot, input) {
|
|
304
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
305
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
306
|
-
const pattern = String(input.args[0] ?? "").trim();
|
|
307
|
-
if (!pattern) {
|
|
308
|
-
throw new Error("A channel pattern is required.");
|
|
309
|
-
}
|
|
310
|
-
if (registry.channels.some((entry) => entry.pattern === pattern)) {
|
|
311
|
-
throw new Error(`Channel with the same pattern already exists: ${pattern}.`);
|
|
312
|
-
}
|
|
313
|
-
const channelsPath = resolveConfiguredChannelsPath(project);
|
|
314
|
-
const filePath = resolveChannelArtifactPath(projectRoot, channelsPath, pattern, registry);
|
|
315
|
-
await ensureAbsent(filePath);
|
|
316
|
-
await writeTextFile(filePath, renderChannelTemplate(pattern));
|
|
317
|
-
await runProjectPrepare(projectRoot);
|
|
318
|
-
writeLine(io.stdout, `Created channel: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
319
|
-
}
|
|
320
|
-
async function runMakeListener(io, projectRoot, input) {
|
|
321
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
322
|
-
const registry = await loadGeneratedProjectRegistry(projectRoot) ?? await prepareProjectDiscovery(projectRoot, project.config);
|
|
323
|
-
const requestedName = String(input.args[0] ?? "");
|
|
324
|
-
const requestedEvents = Array.isArray(input.flags.event) ? input.flags.event.map((value) => String(value).trim()).filter(Boolean) : [String(input.flags.event ?? "").trim()].filter(Boolean);
|
|
325
|
-
const eventNames = [...new Set(requestedEvents)];
|
|
326
|
-
const eventEntries = eventNames.map((eventName) => {
|
|
327
|
-
const entry = registry?.events.find((candidate) => candidate.name === eventName);
|
|
328
|
-
if (!entry) {
|
|
329
|
-
throw new Error(`Unknown event: ${eventName}.`);
|
|
330
|
-
}
|
|
331
|
-
return entry;
|
|
332
|
-
});
|
|
333
|
-
const nameParts = splitRequestedName(requestedName);
|
|
334
|
-
const directory = nameParts.directory.split("/").filter(Boolean).map((segment) => toKebabCase(segment)).join("/");
|
|
335
|
-
const fileStem = toKebabCase(nameParts.rawBaseName);
|
|
336
|
-
const filePath = resolveArtifactPath(projectRoot, project.config.paths.listeners, directory, `${fileStem}.ts`);
|
|
337
|
-
const listenerId = [...directory ? directory.split("/") : [], fileStem].join(".");
|
|
338
|
-
if (await fileExists(filePath) || hasRegisteredListenerId(registry, listenerId)) {
|
|
339
|
-
throw new Error(`Listener with the same id already exists: ${listenerId}.`);
|
|
340
|
-
}
|
|
341
|
-
const templateEvents = eventEntries.map((eventEntry, index) => {
|
|
342
|
-
const sourceEventBaseName = eventEntry.sourcePath.split("/").pop().replace(/\.[^.]+$/, "");
|
|
343
|
-
const importName = `${toPascalCase(sourceEventBaseName)}Event${index + 1}`;
|
|
344
|
-
const importPath = relativeImportPath(filePath, resolve(projectRoot, eventEntry.sourcePath));
|
|
345
|
-
return {
|
|
346
|
-
importName,
|
|
347
|
-
importStatement: eventEntry.exportName && eventEntry.exportName !== "default" ? `import { ${eventEntry.exportName} as ${importName} } from '${importPath}'` : `import ${importName} from '${importPath}'`
|
|
348
|
-
};
|
|
349
|
-
});
|
|
350
|
-
await ensureAbsent(filePath);
|
|
351
|
-
await writeTextFile(
|
|
352
|
-
filePath,
|
|
353
|
-
templateEvents.length === 1 ? renderListenerTemplate(templateEvents[0].importStatement, templateEvents[0].importName) : renderMultiListenerTemplate(templateEvents)
|
|
354
|
-
);
|
|
355
|
-
await runProjectPrepare(projectRoot);
|
|
356
|
-
writeLine(io.stdout, `Created listener: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
357
|
-
}
|
|
358
|
-
async function runMakeObserver(io, projectRoot, input) {
|
|
359
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
360
|
-
const info = resolveNameInfo(String(input.args[0] ?? ""), { suffix: "Observer" });
|
|
361
|
-
const filePath = resolveArtifactPath(projectRoot, project.config.paths.observers, info.directory, `${info.baseName}.ts`);
|
|
362
|
-
await ensureAbsent(filePath);
|
|
363
|
-
await writeTextFile(filePath, renderObserverTemplate(info.baseName));
|
|
364
|
-
await runProjectPrepare(projectRoot);
|
|
365
|
-
writeLine(io.stdout, `Created observer: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
366
|
-
}
|
|
367
|
-
async function runMakeFactory(io, projectRoot, input) {
|
|
368
|
-
const project = await ensureProjectConfig(projectRoot);
|
|
369
|
-
const info = resolveNameInfo(String(input.args[0] ?? ""), { suffix: "Factory" });
|
|
370
|
-
const filePath = resolveArtifactPath(projectRoot, project.config.paths.factories, info.directory, `${info.baseName}.ts`);
|
|
371
|
-
const baseName = info.baseStem;
|
|
372
|
-
const modelInfo = splitRequestedName(baseName);
|
|
373
|
-
const modelFilePath = resolveArtifactPath(
|
|
374
|
-
projectRoot,
|
|
375
|
-
project.config.paths.models,
|
|
376
|
-
info.directory,
|
|
377
|
-
`${toPascalCase(modelInfo.rawBaseName)}.ts`
|
|
378
|
-
);
|
|
379
|
-
await ensureAbsent(filePath);
|
|
380
|
-
await writeTextFile(filePath, renderFactoryTemplate(
|
|
381
|
-
relativeImportPath(filePath, modelFilePath),
|
|
382
|
-
toPascalCase(modelInfo.rawBaseName)
|
|
383
|
-
));
|
|
384
|
-
await runProjectPrepare(projectRoot);
|
|
385
|
-
writeLine(io.stdout, `Created factory: ${makeProjectRelativePath(projectRoot, filePath)}`);
|
|
386
|
-
}
|
|
387
|
-
async function runMakeMail(io, projectRoot, input) {
|
|
388
|
-
await ensureProjectConfig(projectRoot);
|
|
389
|
-
const requestedName = String(input.args[0] ?? "");
|
|
390
|
-
const templateType = input.flags.type === "view" ? "view" : "markdown";
|
|
391
|
-
if (templateType === "view") {
|
|
392
|
-
throw new Error(MAIL_VIEW_SCAFFOLDING_UNAVAILABLE_MESSAGE);
|
|
393
|
-
}
|
|
394
|
-
const nameParts = splitRequestedName(requestedName);
|
|
395
|
-
const directory = nameParts.directory.split("/").filter(Boolean).map((segment) => toKebabCase(segment)).join("/");
|
|
396
|
-
const fileStem = toKebabCase(nameParts.rawBaseName);
|
|
397
|
-
const mailName = ensureSuffix(toPascalCase(nameParts.rawBaseName), "Mail");
|
|
398
|
-
const inputTypeName = `${mailName}Input`;
|
|
399
|
-
const mailFilePath = resolveArtifactPath(projectRoot, "server/mail", directory, `${fileStem}.ts`);
|
|
400
|
-
await ensureAbsent(mailFilePath);
|
|
401
|
-
await writeTextFile(mailFilePath, renderMarkdownMailTemplate(mailName, inputTypeName));
|
|
402
|
-
await runProjectPrepare(projectRoot);
|
|
403
|
-
writeLine(io.stdout, `Created mail: ${makeProjectRelativePath(projectRoot, mailFilePath)}`);
|
|
404
|
-
}
|
|
405
|
-
var generatorInternals = {
|
|
406
|
-
resolveProjectMailViewFramework,
|
|
407
|
-
toChannelTemplateFileStem
|
|
408
|
-
};
|
|
409
|
-
export {
|
|
410
|
-
generatorInternals,
|
|
411
|
-
hasRegisteredEventName,
|
|
412
|
-
hasRegisteredJobName,
|
|
413
|
-
hasRegisteredListenerId,
|
|
414
|
-
hasRegisteredModelName,
|
|
415
|
-
runMakeBroadcast,
|
|
416
|
-
runMakeChannel,
|
|
417
|
-
runMakeEvent,
|
|
418
|
-
runMakeFactory,
|
|
419
|
-
runMakeJob,
|
|
420
|
-
runMakeListener,
|
|
421
|
-
runMakeMail,
|
|
422
|
-
runMakeMigration,
|
|
423
|
-
runMakeModel,
|
|
424
|
-
runMakeObserver,
|
|
425
|
-
runMakeSeeder
|
|
426
|
-
};
|