silgi 0.30.0 → 0.30.2
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/build.d.mts +1 -6
- package/dist/build.mjs +1 -43
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/init.mjs +0 -1
- package/dist/cli/install.mjs +0 -1
- package/dist/cli/prepare.mjs +2372 -8
- package/dist/cli/watch.mjs +0 -1
- package/package.json +1 -1
- package/dist/cli/silgi.mjs +0 -2374
package/dist/cli/prepare.mjs
CHANGED
|
@@ -1,15 +1,2379 @@
|
|
|
1
1
|
import { defineCommand, runCommand } from 'citty';
|
|
2
|
-
import { resolve } from 'pathe';
|
|
2
|
+
import { join, resolve, dirname, relative, isAbsolute, basename, extname } from 'pathe';
|
|
3
3
|
import { version } from 'silgi/meta';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { generateDTS } from 'apiful/openapi';
|
|
5
|
+
import consola$1, { consola } from 'consola';
|
|
6
|
+
import { hasSilgiModule, addTemplate, normalizeTemplate, useLogger, writeFile, genEnsureSafeVar, baseHeaderBannerComment, addImports, hash, toArray, relativeWithDot, isDirectory, isPresents, addCoreFile, resolveAlias as resolveAlias$1, directoryToURL, hasError, removeExtension, parseServices, resolveSilgiPath } from 'silgi/kit';
|
|
7
|
+
import { mkdirSync, existsSync, writeFileSync, promises, readFileSync } from 'node:fs';
|
|
8
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
9
|
+
import { genObjectFromRawEntries, genObjectFromRaw, genObjectFromValues, genAugmentation, genImport, genTypeImport } from 'knitwork';
|
|
10
|
+
import { u as useSilgiCLI, a as silgiCLIIClose } from '../_chunks/silgiApp.mjs';
|
|
11
|
+
import { resolvePath, parseNodeModulePath, lookupNodeModuleSubpath, findTypeExports, findExports } from 'mlly';
|
|
12
|
+
import { resolveAlias } from 'pathe/utils';
|
|
13
|
+
import { runtimeDir } from 'silgi/runtime/meta';
|
|
14
|
+
import { toExports, scanExports, createUnimport } from 'unimport';
|
|
15
|
+
import { generateTypes, resolveSchema } from 'untyped';
|
|
16
|
+
import { s as silgiGenerateType, l as loadOptions } from './types.mjs';
|
|
17
|
+
import { createHooks, createDebugger } from 'hookable';
|
|
18
|
+
import { useSilgiCLI as useSilgiCLI$1, replaceRuntimeValues, silgiCLICtx, autoImportTypes } from 'silgi';
|
|
19
|
+
import { c as createRouteRules } from '../_chunks/routeRules.mjs';
|
|
6
20
|
import * as p from '@clack/prompts';
|
|
7
21
|
import { isCancel, cancel } from '@clack/prompts';
|
|
8
|
-
import
|
|
22
|
+
import * as dotenv from 'dotenv';
|
|
9
23
|
import { createJiti } from 'dev-jiti';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
24
|
+
import { h as hasInstalledModule } from './compatibility.mjs';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import { defu } from 'defu';
|
|
27
|
+
import { resolveModuleURL } from 'exsolve';
|
|
28
|
+
import { isRelative, withTrailingSlash } from 'ufo';
|
|
29
|
+
import { globby } from 'globby';
|
|
30
|
+
import ignore from 'ignore';
|
|
31
|
+
import { parseSync } from '@oxc-parser/wasm';
|
|
32
|
+
import { klona } from 'klona';
|
|
33
|
+
import { useSilgiRuntimeConfig, initRuntimeConfig } from 'silgi/runtime';
|
|
34
|
+
import { createStorage, builtinDrivers } from 'unstorage';
|
|
35
|
+
import { snakeCase } from 'scule';
|
|
36
|
+
import { execSync } from 'node:child_process';
|
|
37
|
+
|
|
38
|
+
async function generateApiFul(silgi) {
|
|
39
|
+
const config = silgi.options.apiFul;
|
|
40
|
+
if (!hasSilgiModule("openapi")) {
|
|
41
|
+
silgi.logger.info("Silgi OpenAPI module not found, if you want to use it, please install it @silgi/openapi");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (!config.services || hasSilgiModule("openapi")) {
|
|
45
|
+
config.services ??= {};
|
|
46
|
+
config.services = {
|
|
47
|
+
silgi: {
|
|
48
|
+
schema: join(silgi.options.build.dir, "openapi.json")
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const resolvedOpenAPIServices = Object.fromEntries(
|
|
53
|
+
Object.entries(config?.services ?? {}).filter(([, service]) => Boolean(service.schema))
|
|
54
|
+
);
|
|
55
|
+
if (Object.keys(resolvedOpenAPIServices).length === 0) {
|
|
56
|
+
consola.info("No OpenAPI schemas found, skipping generation");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
for (const service of Object.values(resolvedOpenAPIServices)) {
|
|
60
|
+
if (typeof service.schema === "string" && !service.schema.startsWith("http")) {
|
|
61
|
+
service.schema = resolve(silgi.options.rootDir, service.schema);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const types = await generateDTS(resolvedOpenAPIServices);
|
|
65
|
+
silgi.hook("prepare:types", (opts) => {
|
|
66
|
+
opts.references.push({ path: "./apiful.d.ts" });
|
|
67
|
+
});
|
|
68
|
+
addTemplate({
|
|
69
|
+
filename: "types/apiful.d.ts",
|
|
70
|
+
where: ".silgi",
|
|
71
|
+
write: true,
|
|
72
|
+
getContents: () => types
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const vueShim = {
|
|
77
|
+
filename: "delete/testtest.d.ts",
|
|
78
|
+
where: ".silgi",
|
|
79
|
+
getContents: ({ app }) => {
|
|
80
|
+
if (!app.options.typescript.shim) {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
return [
|
|
84
|
+
"declare module '*.vue' {",
|
|
85
|
+
" import { DefineComponent } from 'vue'",
|
|
86
|
+
" const component: DefineComponent<{}, {}, any>",
|
|
87
|
+
" export default component",
|
|
88
|
+
"}"
|
|
89
|
+
].join("\n");
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const pluginsDeclaration = {
|
|
93
|
+
filename: "delete/testtest1.d.ts",
|
|
94
|
+
where: ".silgi",
|
|
95
|
+
getContents: async () => {
|
|
96
|
+
return `
|
|
97
|
+
declare module 'nuxt' {
|
|
98
|
+
interface NuxtApp {
|
|
99
|
+
$myPlugin: any;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const defaultTemplates = {
|
|
107
|
+
__proto__: null,
|
|
108
|
+
pluginsDeclaration: pluginsDeclaration,
|
|
109
|
+
vueShim: vueShim
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const postTemplates = [
|
|
113
|
+
pluginsDeclaration.filename
|
|
114
|
+
];
|
|
115
|
+
const logger = useLogger("silgi");
|
|
116
|
+
async function generateApp(app, options = {}) {
|
|
117
|
+
app.templates = Object.values(defaultTemplates).concat(app.options.build.templates);
|
|
118
|
+
await app.callHook("app:templates", app);
|
|
119
|
+
app.templates = app.templates.map((tmpl) => {
|
|
120
|
+
const dir = tmpl.where === ".silgi" ? app.options.build.dir : tmpl.where === "server" ? app.options.silgi.serverDir : tmpl.where === "client" ? app.options.silgi.clientDir : app.options.silgi.vfsDir;
|
|
121
|
+
return normalizeTemplate(tmpl, dir);
|
|
122
|
+
});
|
|
123
|
+
const filteredTemplates = {
|
|
124
|
+
pre: [],
|
|
125
|
+
post: []
|
|
126
|
+
};
|
|
127
|
+
for (const template of app.templates) {
|
|
128
|
+
if (options.filter && !options.filter(template)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const key = template.filename && postTemplates.includes(template.filename) ? "post" : "pre";
|
|
132
|
+
filteredTemplates[key].push(template);
|
|
133
|
+
}
|
|
134
|
+
const templateContext = { app };
|
|
135
|
+
const writes = [];
|
|
136
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
137
|
+
const changedTemplates = [];
|
|
138
|
+
async function processTemplate(template) {
|
|
139
|
+
const dir = template.where === ".silgi" ? app.options.build.dir : template.where === "server" ? app.options.silgi.serverDir : template.where === "client" ? app.options.silgi.clientDir : app.options.silgi.vfsDir;
|
|
140
|
+
const fullPath = template.dst || resolve(dir, template.filename);
|
|
141
|
+
const start = performance.now();
|
|
142
|
+
const contents = await compileTemplate(template, templateContext).catch((e) => {
|
|
143
|
+
logger.error(`Could not compile template \`${template.filename}\`.`);
|
|
144
|
+
logger.error(e);
|
|
145
|
+
throw e;
|
|
146
|
+
});
|
|
147
|
+
template.modified = true;
|
|
148
|
+
if (template.modified) {
|
|
149
|
+
changedTemplates.push(template);
|
|
150
|
+
}
|
|
151
|
+
const perf = performance.now() - start;
|
|
152
|
+
const setupTime = Math.round(perf * 100) / 100;
|
|
153
|
+
if (app.options.debug || setupTime > 500) {
|
|
154
|
+
logger.info(`Compiled \`${template.filename}\` in ${setupTime}ms`);
|
|
155
|
+
}
|
|
156
|
+
if (template.modified && template.write) {
|
|
157
|
+
dirs.add(dirname(fullPath));
|
|
158
|
+
if (template.skipIfExists && existsSync(fullPath)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
writes.push(() => writeFileSync(fullPath, contents, "utf8"));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
await Promise.allSettled(filteredTemplates.pre.map(processTemplate));
|
|
165
|
+
await Promise.allSettled(filteredTemplates.post.map(processTemplate));
|
|
166
|
+
for (const dir of dirs) {
|
|
167
|
+
mkdirSync(dir, { recursive: true });
|
|
168
|
+
}
|
|
169
|
+
for (const write of writes) {
|
|
170
|
+
if (!app.errors.length) {
|
|
171
|
+
write();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (changedTemplates.length) {
|
|
175
|
+
await app.callHook("app:templatesGenerated", app, changedTemplates, options);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async function compileTemplate(template, ctx) {
|
|
179
|
+
delete ctx.utils;
|
|
180
|
+
if (template.src) {
|
|
181
|
+
try {
|
|
182
|
+
return await promises.readFile(template.src, "utf-8");
|
|
183
|
+
} catch (err) {
|
|
184
|
+
logger.error(`[nuxt] Error reading template from \`${template.src}\``);
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (template.getContents) {
|
|
189
|
+
return template.getContents({
|
|
190
|
+
...ctx,
|
|
191
|
+
options: template.options
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
throw new Error(`[nuxt] Invalid template. Templates must have either \`src\` or \`getContents\`: ${JSON.stringify(template)}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function prepare$1(_silgi) {
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function exportRules(silgi) {
|
|
201
|
+
try {
|
|
202
|
+
if (!silgi?.routeRules?.exportRules) {
|
|
203
|
+
throw new Error("Invalid silgi configuration: routeRules or exportRules is undefined");
|
|
204
|
+
}
|
|
205
|
+
const exportedRules = silgi.routeRules.exportRules();
|
|
206
|
+
if (!exportedRules || typeof exportedRules !== "object") {
|
|
207
|
+
throw new Error("No valid route rules to export");
|
|
208
|
+
}
|
|
209
|
+
const content = `/* eslint-disable */
|
|
210
|
+
// @ts-nocheck
|
|
211
|
+
// This file is auto-generated at build time by Silgi
|
|
212
|
+
// Contains route rules with preserved functions
|
|
213
|
+
// DO NOT MODIFY THIS FILE DIRECTLY
|
|
214
|
+
|
|
215
|
+
export const routeRules = ${genObjectFromRawEntries(
|
|
216
|
+
Object.entries(exportedRules).map(([key, value]) => {
|
|
217
|
+
if (typeof value === "function") {
|
|
218
|
+
return [key, genObjectFromRaw(value)];
|
|
219
|
+
}
|
|
220
|
+
return [key, genObjectFromValues(value)];
|
|
221
|
+
})
|
|
222
|
+
)}
|
|
223
|
+
`;
|
|
224
|
+
const serverDir = silgi.options.silgi.serverDir;
|
|
225
|
+
if (!serverDir) {
|
|
226
|
+
throw new Error("Server directory not defined in configuration");
|
|
227
|
+
}
|
|
228
|
+
const file = join(serverDir, "rules.ts");
|
|
229
|
+
if (!silgi.errors.length) {
|
|
230
|
+
await writeFile(file, content);
|
|
231
|
+
}
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.error("\u274C Failed to prepare build:", error instanceof Error ? error.message : String(error));
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function debugMode(name) {
|
|
239
|
+
const silgi = useSilgiCLI();
|
|
240
|
+
if (silgi.options.debug === true || typeof silgi.options.debug === "object" && silgi.options.debug[name]) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function prepareCommands(silgi = useSilgiCLI()) {
|
|
247
|
+
const commands = [];
|
|
248
|
+
await silgi.callHook("prepare:commands", commands);
|
|
249
|
+
if (debugMode("command")) {
|
|
250
|
+
addTemplate({
|
|
251
|
+
filename: "cli.json",
|
|
252
|
+
where: ".silgi",
|
|
253
|
+
write: true,
|
|
254
|
+
getContents: () => JSON.stringify(commands, null, 2)
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
silgi.hook("prepare:types", async ({ references }) => {
|
|
258
|
+
const allTags = commands.reduce((acc, commandGroup) => {
|
|
259
|
+
Object.values(commandGroup).forEach((command) => {
|
|
260
|
+
if (command.tags) {
|
|
261
|
+
command.tags.forEach((tag) => acc.add(tag));
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
return acc;
|
|
265
|
+
}, /* @__PURE__ */ new Set());
|
|
266
|
+
const data = [
|
|
267
|
+
genAugmentation("silgi/types", {
|
|
268
|
+
SilgiCommands: {
|
|
269
|
+
...Object.fromEntries(Array.from(allTags.values()).map((tag) => [tag, "string"]))
|
|
270
|
+
}
|
|
271
|
+
}),
|
|
272
|
+
"",
|
|
273
|
+
"export {}"
|
|
274
|
+
];
|
|
275
|
+
addTemplate({
|
|
276
|
+
filename: "types/commands.d.ts",
|
|
277
|
+
write: true,
|
|
278
|
+
where: ".silgi",
|
|
279
|
+
getContents: () => data.join("\n")
|
|
280
|
+
});
|
|
281
|
+
references.push({
|
|
282
|
+
path: "./commands.d.ts"
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
silgi.options.commands = commands;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async function prepareConfigs(silgi) {
|
|
289
|
+
const _data = {
|
|
290
|
+
runtimeConfig: {}
|
|
291
|
+
};
|
|
292
|
+
for (const module of silgi.scanModules) {
|
|
293
|
+
if (module.meta.cliToRuntimeOptionsKeys && module.meta.cliToRuntimeOptionsKeys?.length > 0) {
|
|
294
|
+
for (const key of module.meta.cliToRuntimeOptionsKeys) {
|
|
295
|
+
_data[module.meta.configKey] = {
|
|
296
|
+
..._data[module.meta.configKey],
|
|
297
|
+
[key]: module.options[key]
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
_data[module.meta.configKey] = {};
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
await silgi.callHook("prepare:configs.ts", _data);
|
|
305
|
+
const importData = [
|
|
306
|
+
"import type { SilgiRuntimeOptions, SilgiRuntimeConfig, SilgiOptions } from 'silgi/types'",
|
|
307
|
+
"import { useSilgiRuntimeConfig } from 'silgi/runtime'",
|
|
308
|
+
"",
|
|
309
|
+
`export const runtimeConfig: Partial<SilgiRuntimeConfig> = ${genObjectFromRawEntries(
|
|
310
|
+
Object.entries(_data.runtimeConfig).map(([key, value]) => [key, genEnsureSafeVar(value)]),
|
|
311
|
+
""
|
|
312
|
+
)}`,
|
|
313
|
+
"",
|
|
314
|
+
"const runtime = useSilgiRuntimeConfig(undefined, runtimeConfig)",
|
|
315
|
+
""
|
|
316
|
+
];
|
|
317
|
+
delete _data.runtimeConfig;
|
|
318
|
+
importData.push(`export const cliConfigs: Partial<SilgiRuntimeOptions & SilgiOptions> = ${genObjectFromRawEntries(
|
|
319
|
+
Object.entries(_data).map(
|
|
320
|
+
([key, value]) => [key, genEnsureSafeVar(value)]
|
|
321
|
+
).concat(
|
|
322
|
+
[
|
|
323
|
+
["runtimeConfig", "runtime"]
|
|
324
|
+
]
|
|
325
|
+
)
|
|
326
|
+
)}`);
|
|
327
|
+
importData.unshift(...baseHeaderBannerComment);
|
|
328
|
+
return importData;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async function prepareCoreFile(silgi) {
|
|
332
|
+
const { genImports, genTypeImports, addImportItem, addImportItemType } = addImports({
|
|
333
|
+
imports: [
|
|
334
|
+
{
|
|
335
|
+
specifier: "silgi/runtime",
|
|
336
|
+
imports: [
|
|
337
|
+
{
|
|
338
|
+
name: "mergeDeep"
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
specifier: "silgi",
|
|
344
|
+
imports: [
|
|
345
|
+
{
|
|
346
|
+
name: "createSilgi"
|
|
347
|
+
}
|
|
348
|
+
]
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
specifier: "./scan",
|
|
352
|
+
imports: [
|
|
353
|
+
{
|
|
354
|
+
name: "uris"
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
name: "services"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "shareds"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
name: "schemas"
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
name: "modulesURIs"
|
|
367
|
+
}
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
specifier: "./configs",
|
|
372
|
+
imports: [
|
|
373
|
+
{
|
|
374
|
+
name: "cliConfigs"
|
|
375
|
+
}
|
|
376
|
+
]
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
specifier: "./rules",
|
|
380
|
+
imports: [
|
|
381
|
+
{
|
|
382
|
+
name: "routeRules"
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
],
|
|
387
|
+
typeImports: [
|
|
388
|
+
{
|
|
389
|
+
specifier: "silgi/types",
|
|
390
|
+
imports: [
|
|
391
|
+
{
|
|
392
|
+
name: "SilgiRuntimeOptions"
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: "BuildSilgi"
|
|
396
|
+
}
|
|
397
|
+
]
|
|
398
|
+
}
|
|
399
|
+
]
|
|
400
|
+
});
|
|
401
|
+
const before = [];
|
|
402
|
+
const after = [];
|
|
403
|
+
const _data = {
|
|
404
|
+
silgiConfigs: [],
|
|
405
|
+
addImportItem,
|
|
406
|
+
addImportItemType,
|
|
407
|
+
addBuildFunction: (data) => {
|
|
408
|
+
for (const item of toArray(data)) {
|
|
409
|
+
if (item.where === "after") {
|
|
410
|
+
if (item.custom) {
|
|
411
|
+
after.push(item.custom);
|
|
412
|
+
} else {
|
|
413
|
+
after.push(item.params?.length ? ` await ${item.name}(option, ${item.params.join(",")})` : ` await ${item.name}(option)`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (item.where === "before") {
|
|
417
|
+
if (item.custom) {
|
|
418
|
+
before.push(item.custom);
|
|
419
|
+
} else {
|
|
420
|
+
before.push(item.params?.length ? ` await ${item.name}(option, ${item.params.join(",")})` : ` await ${item.name}(option)`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
await silgi.callHook("before:core.ts", _data);
|
|
427
|
+
const plugins = [];
|
|
428
|
+
for (const plugin of silgi.options.plugins) {
|
|
429
|
+
const pluginImportName = hash(plugin.packageImport);
|
|
430
|
+
addImportItem({
|
|
431
|
+
specifier: plugin.packageImport,
|
|
432
|
+
imports: pluginImportName
|
|
433
|
+
});
|
|
434
|
+
plugins.push(pluginImportName);
|
|
435
|
+
}
|
|
436
|
+
const importsContent = [
|
|
437
|
+
...genImports.map(({ specifier, imports, options }) => {
|
|
438
|
+
return genImport(specifier, imports, options);
|
|
439
|
+
}),
|
|
440
|
+
...genTypeImports.map(({ specifier, imports }) => {
|
|
441
|
+
return genTypeImport(specifier, Array.isArray(imports) ? imports : [imports]);
|
|
442
|
+
}),
|
|
443
|
+
""
|
|
444
|
+
];
|
|
445
|
+
const importData = [
|
|
446
|
+
"",
|
|
447
|
+
"export async function buildSilgi(option: BuildSilgi) {",
|
|
448
|
+
"",
|
|
449
|
+
"// buildSilgiBefore",
|
|
450
|
+
...before,
|
|
451
|
+
"",
|
|
452
|
+
"const silgi = await createSilgi({",
|
|
453
|
+
" framework: option.framework,",
|
|
454
|
+
" shared: shareds,",
|
|
455
|
+
" services: services,",
|
|
456
|
+
" schemas: schemas,",
|
|
457
|
+
" uris,",
|
|
458
|
+
" modulesURIs,",
|
|
459
|
+
` plugins: [${plugins.join(", ")}],`,
|
|
460
|
+
"",
|
|
461
|
+
_data.silgiConfigs.length > 0 ? _data.silgiConfigs.map((item) => {
|
|
462
|
+
const code = genObjectFromRawEntries(Object.entries(item));
|
|
463
|
+
return ` ${code.slice(1, -1).trim()},`;
|
|
464
|
+
}).filter(Boolean).join("\n") : "",
|
|
465
|
+
"",
|
|
466
|
+
" options: mergeDeep(cliConfigs, {",
|
|
467
|
+
" runtimeConfig: {} as SilgiRuntimeOptions,",
|
|
468
|
+
" routeRules: routeRules as any,",
|
|
469
|
+
` present: '${silgi.options.preset}',`,
|
|
470
|
+
" ...option.modules,",
|
|
471
|
+
" ...option.options,",
|
|
472
|
+
" }) as any,",
|
|
473
|
+
" })",
|
|
474
|
+
"",
|
|
475
|
+
"// buildSilgiAfter",
|
|
476
|
+
...after,
|
|
477
|
+
"",
|
|
478
|
+
" return silgi",
|
|
479
|
+
"}",
|
|
480
|
+
""
|
|
481
|
+
];
|
|
482
|
+
await silgi.callHook("after:core.ts", importData);
|
|
483
|
+
importData.unshift(...importsContent);
|
|
484
|
+
importData.unshift(...baseHeaderBannerComment);
|
|
485
|
+
return importData;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
async function writeCoreFile(silgi) {
|
|
489
|
+
const coreContent = await prepareCoreFile(silgi);
|
|
490
|
+
const configs = await prepareConfigs(silgi);
|
|
491
|
+
const silgiDir = resolve(silgi.options.silgi.serverDir);
|
|
492
|
+
const buildFiles = [];
|
|
493
|
+
buildFiles.push({
|
|
494
|
+
path: join(silgiDir, "core.ts"),
|
|
495
|
+
contents: coreContent.join("\n")
|
|
496
|
+
});
|
|
497
|
+
buildFiles.push({
|
|
498
|
+
path: join(silgiDir, "configs.ts"),
|
|
499
|
+
contents: configs.join("\n")
|
|
500
|
+
});
|
|
501
|
+
for await (const file of buildFiles) {
|
|
502
|
+
if (!silgi.errors.length) {
|
|
503
|
+
await writeFile(
|
|
504
|
+
resolve(silgi.options.build.dir, file.path),
|
|
505
|
+
file.contents
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
async function generateRouterDTS(silgi) {
|
|
512
|
+
const uris = silgi.uris;
|
|
513
|
+
const subPath = "srn";
|
|
514
|
+
const groupedPaths = /* @__PURE__ */ new Map();
|
|
515
|
+
Object.entries(uris || {}).forEach(([key, params]) => {
|
|
516
|
+
const [service, resource, method, action] = key.split("/");
|
|
517
|
+
const basePath = params ? `${subPath}/${service}/${resource}/${action}/${params}` : `${subPath}/${service}/${resource}/${action}`;
|
|
518
|
+
const fullPath = `${subPath}/${service}/${resource}/${action}`;
|
|
519
|
+
if (!groupedPaths.has(basePath)) {
|
|
520
|
+
groupedPaths.set(basePath, /* @__PURE__ */ new Map());
|
|
521
|
+
}
|
|
522
|
+
groupedPaths.get(basePath)?.set(method.toLowerCase(), fullPath);
|
|
523
|
+
});
|
|
524
|
+
const keys = [
|
|
525
|
+
" keys: {",
|
|
526
|
+
Array.from(groupedPaths.entries()).map(([basePath, methods]) => {
|
|
527
|
+
return ` '/${basePath}': {${Array.from(methods.entries()).map(([method, path]) => `
|
|
528
|
+
${method}: '/${path}'`).join(",")}
|
|
529
|
+
}`;
|
|
530
|
+
}).join(",\n"),
|
|
531
|
+
" }",
|
|
532
|
+
""
|
|
533
|
+
].join("\n");
|
|
534
|
+
const groupedRoutes = Object.entries(uris || {}).reduce((acc, [key, _params]) => {
|
|
535
|
+
const [service, resource, method, action] = key.split("/");
|
|
536
|
+
const routePath = `${subPath}/${service}/${resource}/${action}`;
|
|
537
|
+
if (!acc[routePath]) {
|
|
538
|
+
acc[routePath] = {};
|
|
539
|
+
}
|
|
540
|
+
acc[routePath][method] = {
|
|
541
|
+
input: `ExtractInputFromURI<'${key}'>`,
|
|
542
|
+
output: `ExtractOutputFromURI<'${key}'>`,
|
|
543
|
+
queryParams: `ExtractQueryParamsFromURI<'${key}'>`,
|
|
544
|
+
pathParams: `ExtractPathParamsFromURI<'${key}'>`
|
|
545
|
+
};
|
|
546
|
+
return acc;
|
|
547
|
+
}, {});
|
|
548
|
+
const routerTypes = Object.entries(groupedRoutes).map(([path, methods]) => {
|
|
549
|
+
const methodEntries = Object.entries(methods).map(([method, { input, output, queryParams, pathParams }]) => {
|
|
550
|
+
return ` '${method}': {
|
|
551
|
+
input: ${input},
|
|
552
|
+
output: ${output},
|
|
553
|
+
queryParams: ${queryParams},
|
|
554
|
+
pathParams: ${pathParams}
|
|
555
|
+
}`;
|
|
556
|
+
}).join(",\n");
|
|
557
|
+
return ` '/${path}': {
|
|
558
|
+
${methodEntries}
|
|
559
|
+
}`;
|
|
560
|
+
});
|
|
561
|
+
const nitro = [
|
|
562
|
+
"declare module 'nitropack/types' {",
|
|
563
|
+
" interface InternalApi extends RouterTypes {}",
|
|
564
|
+
"}"
|
|
565
|
+
];
|
|
566
|
+
const content = [
|
|
567
|
+
keys.slice(0, -1),
|
|
568
|
+
// son satırdaki boş satırı kaldır
|
|
569
|
+
...routerTypes
|
|
570
|
+
].join(",\n");
|
|
571
|
+
const context = [
|
|
572
|
+
"import type { ExtractInputFromURI, ExtractOutputFromURI, ExtractQueryParamsFromURI, ExtractPathParamsFromURI } from 'silgi/types'",
|
|
573
|
+
"",
|
|
574
|
+
"export interface RouterTypes {",
|
|
575
|
+
content,
|
|
576
|
+
"}",
|
|
577
|
+
"",
|
|
578
|
+
"declare module 'silgi/types' {",
|
|
579
|
+
" interface SilgiRouterTypes extends RouterTypes {",
|
|
580
|
+
" }",
|
|
581
|
+
"}",
|
|
582
|
+
"",
|
|
583
|
+
silgi.options.preset === "h3" || silgi.options.preset === "nitro" ? nitro.join("\n") : "",
|
|
584
|
+
"",
|
|
585
|
+
"export {}"
|
|
586
|
+
];
|
|
587
|
+
return context;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
async function prepareSchema(silgi) {
|
|
591
|
+
const { genImports, genTypeImports, addImportItem, addImportItemType } = addImports({
|
|
592
|
+
imports: [
|
|
593
|
+
{
|
|
594
|
+
specifier: relativeWithDot(
|
|
595
|
+
silgi.options.build.typesDir,
|
|
596
|
+
`${silgi.options.silgi.serverDir}/scan`
|
|
597
|
+
),
|
|
598
|
+
imports: [
|
|
599
|
+
{
|
|
600
|
+
name: "modulesURIs"
|
|
601
|
+
}
|
|
602
|
+
]
|
|
603
|
+
}
|
|
604
|
+
],
|
|
605
|
+
typeImports: [
|
|
606
|
+
{
|
|
607
|
+
specifier: "silgi/types",
|
|
608
|
+
imports: [
|
|
609
|
+
{
|
|
610
|
+
name: "URIsTypes"
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
name: "Namespaces"
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
name: "SilgiRuntimeContext"
|
|
617
|
+
}
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
});
|
|
622
|
+
const data = {
|
|
623
|
+
addImportItem,
|
|
624
|
+
addImportItemType,
|
|
625
|
+
options: [],
|
|
626
|
+
contexts: [],
|
|
627
|
+
actions: [],
|
|
628
|
+
shareds: [
|
|
629
|
+
{
|
|
630
|
+
key: "modulesURIs",
|
|
631
|
+
value: "{ modulesURIs: typeof modulesURIs }"
|
|
632
|
+
}
|
|
633
|
+
],
|
|
634
|
+
events: [],
|
|
635
|
+
hooks: [],
|
|
636
|
+
runtimeHooks: [],
|
|
637
|
+
runtimeOptions: [],
|
|
638
|
+
methods: [],
|
|
639
|
+
routeRules: [],
|
|
640
|
+
routeRulesConfig: []
|
|
641
|
+
};
|
|
642
|
+
await silgi.callHook("before:schema.ts", data);
|
|
643
|
+
const silgiScanTS = relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/scan`);
|
|
644
|
+
let addSilgiContext = false;
|
|
645
|
+
const importsContent = [
|
|
646
|
+
...genImports.map(({ specifier, imports, options }) => {
|
|
647
|
+
return genImport(specifier, imports, options);
|
|
648
|
+
}),
|
|
649
|
+
...genTypeImports.map(({ specifier, imports }) => {
|
|
650
|
+
return genTypeImport(specifier, Array.isArray(imports) ? imports : [imports]);
|
|
651
|
+
}),
|
|
652
|
+
""
|
|
653
|
+
];
|
|
654
|
+
const importData = [
|
|
655
|
+
generateTypes(
|
|
656
|
+
await resolveSchema(
|
|
657
|
+
{
|
|
658
|
+
...silgi.options.namespaces?.reduce((acc, key) => ({ ...acc, [key]: "" }), {}) || {}
|
|
659
|
+
}
|
|
660
|
+
),
|
|
661
|
+
{
|
|
662
|
+
interfaceName: "InferredNamespaces",
|
|
663
|
+
addExport: false,
|
|
664
|
+
addDefaults: false,
|
|
665
|
+
allowExtraKeys: false,
|
|
666
|
+
indentation: 0
|
|
667
|
+
}
|
|
668
|
+
),
|
|
669
|
+
"",
|
|
670
|
+
`type SchemaExtends = Namespaces<typeof import('${silgiScanTS}')['schemas']>`,
|
|
671
|
+
"",
|
|
672
|
+
`type SilgiURIsMerge = URIsTypes<typeof import('${silgiScanTS}')['uris']>`,
|
|
673
|
+
"",
|
|
674
|
+
`type SilgiModuleContextExtends = ${data.contexts.length ? data.contexts.map(({ value }) => value).join(" & ") : "{}"}`,
|
|
675
|
+
"",
|
|
676
|
+
data.events.length ? `interface SilgiModuleEventsExtends extends ${data.events.map((item) => item.extends ? item.value : "").join(", ")} {
|
|
677
|
+
${data.events.map((item) => {
|
|
678
|
+
if (item.isSilgiContext) {
|
|
679
|
+
addSilgiContext = true;
|
|
680
|
+
}
|
|
681
|
+
return !item.extends && !addSilgiContext ? ` ${item.key}: ${item.value}` : item.isSilgiContext ? " context: SilgiRuntimeContext" : "";
|
|
682
|
+
}).join(",\n")}
|
|
683
|
+
}` : "interface SilgiModuleEventsExtends {}",
|
|
684
|
+
"",
|
|
685
|
+
`type RuntimeActionExtends = ${data.actions?.length ? data.actions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
686
|
+
"",
|
|
687
|
+
`type RuntimeMethodExtends = ${data.methods?.length ? data.methods.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
688
|
+
"",
|
|
689
|
+
`type RuntimeRouteRulesExtends = ${data.routeRules?.length ? data.routeRules.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
690
|
+
"",
|
|
691
|
+
`type RuntimeRouteRulesConfigExtends = ${data.routeRulesConfig?.length ? data.routeRulesConfig.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
692
|
+
"",
|
|
693
|
+
`type SilgiModuleSharedExtends = ${data.shareds.length ? data.shareds.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
694
|
+
"",
|
|
695
|
+
`type SilgiModuleOptionExtend = ${data.options?.length ? data.options.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
696
|
+
"",
|
|
697
|
+
`type SilgiRuntimeOptionExtends = ${data.runtimeOptions?.length ? data.runtimeOptions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
698
|
+
"",
|
|
699
|
+
silgi.options.typescript.generateRuntimeConfigTypes ? generateTypes(
|
|
700
|
+
await resolveSchema(
|
|
701
|
+
{
|
|
702
|
+
...Object.fromEntries(
|
|
703
|
+
Object.entries(silgi.options.runtimeConfig).filter(
|
|
704
|
+
([key]) => !["app", "nitro", "nuxt"].includes(key)
|
|
705
|
+
)
|
|
706
|
+
)
|
|
707
|
+
}
|
|
708
|
+
),
|
|
709
|
+
{
|
|
710
|
+
interfaceName: "SilgiRuntimeConfigExtends",
|
|
711
|
+
addExport: false,
|
|
712
|
+
addDefaults: false,
|
|
713
|
+
allowExtraKeys: false,
|
|
714
|
+
indentation: 0
|
|
715
|
+
}
|
|
716
|
+
) : "",
|
|
717
|
+
"",
|
|
718
|
+
generateTypes(
|
|
719
|
+
await resolveSchema(
|
|
720
|
+
{
|
|
721
|
+
...silgi.options.storages?.reduce((acc, key) => ({ ...acc, [key]: "" }), {}) || {},
|
|
722
|
+
// 'redis': {} -> 'redis': string
|
|
723
|
+
...Object.entries(silgi.options.storage).map(([key]) => ({
|
|
724
|
+
[key]: ""
|
|
725
|
+
})).reduce((acc, obj) => ({ ...acc, ...obj }), {})
|
|
726
|
+
}
|
|
727
|
+
),
|
|
728
|
+
{
|
|
729
|
+
interfaceName: "SilgiStorageBaseExtends",
|
|
730
|
+
addExport: false,
|
|
731
|
+
addDefaults: false,
|
|
732
|
+
allowExtraKeys: false,
|
|
733
|
+
indentation: 0
|
|
734
|
+
}
|
|
735
|
+
),
|
|
736
|
+
"",
|
|
737
|
+
`type ModuleHooksExtend = ${data.hooks?.length ? data.hooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
738
|
+
"",
|
|
739
|
+
`type SilgiRuntimeHooksExtends = ${data.runtimeHooks?.length ? data.runtimeHooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
740
|
+
"",
|
|
741
|
+
genAugmentation("silgi/types", {
|
|
742
|
+
FrameworkContext: [{}, { extends: ["FrameworkContextExtends"] }],
|
|
743
|
+
SilgiSchema: [{}, { extends: ["SchemaExtends"] }],
|
|
744
|
+
SilgiNamespaces: [{}, { extends: ["InferredNamespaces"] }],
|
|
745
|
+
SilgiStorageBase: [{}, { extends: ["SilgiStorageBaseExtends"] }],
|
|
746
|
+
SilgiURIs: [{}, { extends: ["SilgiURIsMerge"] }],
|
|
747
|
+
SilgiRuntimeContext: [{}, { extends: ["SilgiModuleContextExtends"] }],
|
|
748
|
+
SilgiEvents: [{}, { extends: ["SilgiModuleEventsExtends"] }],
|
|
749
|
+
SilgiRuntimeSharedsExtend: [{}, { extends: ["SilgiModuleSharedExtends"] }],
|
|
750
|
+
SilgiRuntimeActions: [{}, { extends: ["RuntimeActionExtends"] }],
|
|
751
|
+
SilgiRuntimeOptions: [{}, { extends: ["SilgiRuntimeOptionExtends"] }],
|
|
752
|
+
SilgiRuntimeHooks: [{}, { extends: ["SilgiRuntimeHooksExtends"] }],
|
|
753
|
+
SilgiRuntimeConfig: [{}, { extends: ["SilgiRuntimeConfigExtends"] }],
|
|
754
|
+
SilgiHooks: [{}, { extends: ["ModuleHooksExtend"] }],
|
|
755
|
+
SilgiRuntimeMethods: [{}, { extends: ["RuntimeMethodExtends"] }],
|
|
756
|
+
SilgiRuntimeRouteRules: [{}, { extends: ["RuntimeRouteRulesExtends"] }],
|
|
757
|
+
SilgiRuntimeRouteRulesConfig: [{}, { extends: ["RuntimeRouteRulesConfigExtends"] }],
|
|
758
|
+
SilgiModuleOptions: [{}, { extends: ["SilgiModuleOptionExtend"] }]
|
|
759
|
+
}).replace(/,\s*/g, "\n"),
|
|
760
|
+
"",
|
|
761
|
+
"export {}"
|
|
762
|
+
];
|
|
763
|
+
await silgi.callHook("after:schema.ts", importData);
|
|
764
|
+
importData.unshift(...importsContent);
|
|
765
|
+
return importData;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
async function writeTypesAndFiles(silgi) {
|
|
769
|
+
const routerDTS = await generateRouterDTS(silgi);
|
|
770
|
+
silgi.hook("prepare:types", (opts) => {
|
|
771
|
+
opts.references.push({ path: "./schema.d.ts" });
|
|
772
|
+
opts.references.push({ path: "./silgi-routes.d.ts" });
|
|
773
|
+
});
|
|
774
|
+
const schemaContent = await prepareSchema(silgi);
|
|
775
|
+
const { declarations, tsConfig } = await silgiGenerateType(silgi);
|
|
776
|
+
const tsConfigPath = resolve(
|
|
777
|
+
silgi.options.rootDir,
|
|
778
|
+
silgi.options.typescript.tsconfigPath
|
|
779
|
+
);
|
|
780
|
+
const typesDir = resolve(silgi.options.build.typesDir);
|
|
781
|
+
let autoImportedTypes = [];
|
|
782
|
+
let autoImportExports = "";
|
|
783
|
+
if (silgi.unimport) {
|
|
784
|
+
await silgi.unimport.init();
|
|
785
|
+
const allImports = await silgi.unimport.getImports();
|
|
786
|
+
autoImportExports = toExports(allImports).replace(
|
|
787
|
+
/#internal\/nitro/g,
|
|
788
|
+
relative(typesDir, runtimeDir)
|
|
789
|
+
);
|
|
790
|
+
const resolvedImportPathMap = /* @__PURE__ */ new Map();
|
|
791
|
+
for (const i of allImports.filter((i2) => !i2.type)) {
|
|
792
|
+
if (resolvedImportPathMap.has(i.from)) {
|
|
793
|
+
continue;
|
|
794
|
+
}
|
|
795
|
+
let path = resolveAlias(i.from, silgi.options.alias);
|
|
796
|
+
if (isAbsolute(path)) {
|
|
797
|
+
const resolvedPath = await resolvePath(i.from, {
|
|
798
|
+
url: silgi.options.nodeModulesDirs
|
|
799
|
+
}).catch(() => null);
|
|
800
|
+
if (resolvedPath) {
|
|
801
|
+
const { dir, name } = parseNodeModulePath(resolvedPath);
|
|
802
|
+
if (!dir || !name) {
|
|
803
|
+
path = resolvedPath;
|
|
804
|
+
} else {
|
|
805
|
+
const subpath = await lookupNodeModuleSubpath(resolvedPath);
|
|
806
|
+
path = join(dir, name, subpath || "");
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
if (existsSync(path) && !await isDirectory(path)) {
|
|
811
|
+
path = path.replace(/\.[a-z]+$/, "");
|
|
812
|
+
}
|
|
813
|
+
if (isAbsolute(path)) {
|
|
814
|
+
path = relative(typesDir, path);
|
|
815
|
+
}
|
|
816
|
+
resolvedImportPathMap.set(i.from, path);
|
|
817
|
+
}
|
|
818
|
+
autoImportedTypes = [
|
|
819
|
+
silgi.options.imports && silgi.options.imports.autoImport !== false ? (await silgi.unimport.generateTypeDeclarations({
|
|
820
|
+
exportHelper: false,
|
|
821
|
+
resolvePath: (i) => resolvedImportPathMap.get(i.from) ?? i.from
|
|
822
|
+
})).trim() : ""
|
|
823
|
+
];
|
|
824
|
+
}
|
|
825
|
+
const buildFiles = [];
|
|
826
|
+
buildFiles.push({
|
|
827
|
+
path: join(typesDir, "silgi-routes.d.ts"),
|
|
828
|
+
contents: routerDTS.join("\n")
|
|
829
|
+
});
|
|
830
|
+
buildFiles.push({
|
|
831
|
+
path: join(typesDir, "silgi-imports.d.ts"),
|
|
832
|
+
contents: [...autoImportedTypes, autoImportExports || "export {}"].join(
|
|
833
|
+
"\n"
|
|
834
|
+
)
|
|
835
|
+
});
|
|
836
|
+
buildFiles.push({
|
|
837
|
+
path: join(typesDir, "schema.d.ts"),
|
|
838
|
+
contents: schemaContent.join("\n")
|
|
839
|
+
});
|
|
840
|
+
buildFiles.push({
|
|
841
|
+
path: join(typesDir, "silgi.d.ts"),
|
|
842
|
+
contents: declarations.join("\n")
|
|
843
|
+
});
|
|
844
|
+
buildFiles.push({
|
|
845
|
+
path: tsConfigPath,
|
|
846
|
+
contents: JSON.stringify(tsConfig, null, 2)
|
|
847
|
+
});
|
|
848
|
+
for await (const file of buildFiles) {
|
|
849
|
+
if (!silgi.errors.length) {
|
|
850
|
+
await writeFile(
|
|
851
|
+
resolve(silgi.options.build.dir, file.path),
|
|
852
|
+
file.contents
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
async function build(silgi) {
|
|
859
|
+
await prepare$1();
|
|
860
|
+
await generateApiFul(silgi);
|
|
861
|
+
await prepareCommands(silgi);
|
|
862
|
+
await writeCoreFile(silgi);
|
|
863
|
+
await exportRules(silgi);
|
|
864
|
+
await writeTypesAndFiles(silgi);
|
|
865
|
+
await generateApp(silgi);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
async function setupDotenv(options) {
|
|
869
|
+
const targetEnvironment = options.env ?? process.env;
|
|
870
|
+
const environment = await loadDotenv({
|
|
871
|
+
cwd: options.cwd,
|
|
872
|
+
fileName: options.fileName ?? ".env",
|
|
873
|
+
env: targetEnvironment,
|
|
874
|
+
interpolate: options.interpolate ?? true
|
|
875
|
+
});
|
|
876
|
+
for (const key in environment) {
|
|
877
|
+
if (!key.startsWith("_") && targetEnvironment[key] === void 0) {
|
|
878
|
+
targetEnvironment[key] = environment[key];
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
return environment;
|
|
882
|
+
}
|
|
883
|
+
async function loadDotenv(options) {
|
|
884
|
+
const environment = /* @__PURE__ */ Object.create(null);
|
|
885
|
+
const dotenvFile = resolve(options.cwd, options.fileName);
|
|
886
|
+
if (existsSync(dotenvFile)) {
|
|
887
|
+
const parsed = dotenv.parse(await promises.readFile(dotenvFile, "utf8"));
|
|
888
|
+
Object.assign(environment, parsed);
|
|
889
|
+
}
|
|
890
|
+
if (!options.env?._applied) {
|
|
891
|
+
Object.assign(environment, options.env);
|
|
892
|
+
environment._applied = true;
|
|
893
|
+
}
|
|
894
|
+
if (options.interpolate) {
|
|
895
|
+
interpolate(environment);
|
|
896
|
+
}
|
|
897
|
+
return environment;
|
|
898
|
+
}
|
|
899
|
+
function interpolate(target, source = {}, parse = (v) => v) {
|
|
900
|
+
function getValue(key) {
|
|
901
|
+
return source[key] === void 0 ? target[key] : source[key];
|
|
902
|
+
}
|
|
903
|
+
function interpolate2(value, parents = []) {
|
|
904
|
+
if (typeof value !== "string") {
|
|
905
|
+
return value;
|
|
906
|
+
}
|
|
907
|
+
const matches = value.match(/(.?\$\{?[\w:]*\}?)/g) || [];
|
|
908
|
+
return parse(
|
|
909
|
+
matches.reduce((newValue, match) => {
|
|
910
|
+
const parts = /(.?)\$\{?([\w:]+)?\}?/.exec(match) || [];
|
|
911
|
+
const prefix = parts[1];
|
|
912
|
+
let value2, replacePart;
|
|
913
|
+
if (prefix === "\\") {
|
|
914
|
+
replacePart = parts[0] || "";
|
|
915
|
+
value2 = replacePart.replace(String.raw`\$`, "$");
|
|
916
|
+
} else {
|
|
917
|
+
const key = parts[2];
|
|
918
|
+
replacePart = (parts[0] || "").slice(prefix.length);
|
|
919
|
+
if (parents.includes(key)) {
|
|
920
|
+
console.warn(
|
|
921
|
+
`Please avoid recursive environment variables ( loop: ${parents.join(
|
|
922
|
+
" > "
|
|
923
|
+
)} > ${key} )`
|
|
924
|
+
);
|
|
925
|
+
return "";
|
|
926
|
+
}
|
|
927
|
+
value2 = getValue(key);
|
|
928
|
+
value2 = interpolate2(value2, [...parents, key]);
|
|
929
|
+
}
|
|
930
|
+
return value2 === void 0 ? newValue : newValue.replace(replacePart, value2);
|
|
931
|
+
}, value)
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
for (const key in target) {
|
|
935
|
+
target[key] = interpolate2(getValue(key));
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
let initialized = false;
|
|
940
|
+
async function prepareEnv(silgiConfig) {
|
|
941
|
+
if (initialized)
|
|
942
|
+
return;
|
|
943
|
+
initialized = true;
|
|
944
|
+
const customEnvironments = silgiConfig.environments;
|
|
945
|
+
const environment = silgiConfig.activeEnvironment ? silgiConfig.activeEnvironment : await p.select({
|
|
946
|
+
message: "Select an environment",
|
|
947
|
+
options: customEnvironments?.length > 0 ? customEnvironments.map((env) => ({
|
|
948
|
+
label: env.fileName,
|
|
949
|
+
value: env.fileName
|
|
950
|
+
})) : [
|
|
951
|
+
{ label: "Development (.env)", value: ".env" },
|
|
952
|
+
{ label: "Docker (.env.docker)", value: "docker" },
|
|
953
|
+
{ label: "Staging (.env.staging)", value: "staging" },
|
|
954
|
+
{ label: "Testing (.env.testing)", value: "testing" },
|
|
955
|
+
{ label: "Production (.env.prod)", value: "prod" }
|
|
956
|
+
]
|
|
957
|
+
});
|
|
958
|
+
const findEnv = customEnvironments?.find((env) => env.fileName === environment);
|
|
959
|
+
if (findEnv) {
|
|
960
|
+
await setupDotenv({
|
|
961
|
+
cwd: findEnv.cwd || silgiConfig.rootDir,
|
|
962
|
+
interpolate: findEnv.interpolate,
|
|
963
|
+
fileName: findEnv.fileName,
|
|
964
|
+
env: findEnv.env
|
|
965
|
+
});
|
|
966
|
+
} else {
|
|
967
|
+
await setupDotenv({
|
|
968
|
+
cwd: silgiConfig.rootDir,
|
|
969
|
+
interpolate: true,
|
|
970
|
+
fileName: environment === ".env" ? ".env" : `.env.${environment}`
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
async function emptyFramework(silgi) {
|
|
976
|
+
if (silgi.options.preset === "npm-package" || !silgi.options.preset) {
|
|
977
|
+
silgi.hook("after:schema.ts", (data) => {
|
|
978
|
+
data.unshift("type FrameworkContextExtends = {}");
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
async function h3Framework(silgi, skip = false) {
|
|
984
|
+
if (!isPresents(["h3"]) && skip === false)
|
|
985
|
+
return;
|
|
986
|
+
if (isPresents(["h3"])) {
|
|
987
|
+
silgi.hook("after:schema.ts", (data) => {
|
|
988
|
+
data.unshift("type FrameworkContextExtends = NitroApp");
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
silgi.hook("before:schema.ts", (data) => {
|
|
992
|
+
data.addImportItemType([
|
|
993
|
+
{
|
|
994
|
+
imports: [
|
|
995
|
+
{
|
|
996
|
+
name: "H3Event"
|
|
997
|
+
}
|
|
998
|
+
],
|
|
999
|
+
specifier: "h3"
|
|
1000
|
+
},
|
|
1001
|
+
{
|
|
1002
|
+
imports: [
|
|
1003
|
+
{
|
|
1004
|
+
name: "NitroApp"
|
|
1005
|
+
}
|
|
1006
|
+
],
|
|
1007
|
+
specifier: "nitropack/types"
|
|
1008
|
+
}
|
|
1009
|
+
]);
|
|
1010
|
+
data.events.push({
|
|
1011
|
+
key: "H3Event",
|
|
1012
|
+
value: "H3Event",
|
|
1013
|
+
extends: true,
|
|
1014
|
+
isSilgiContext: false
|
|
1015
|
+
});
|
|
1016
|
+
});
|
|
1017
|
+
silgi.hook("prepare:types", (opts) => {
|
|
1018
|
+
addTemplate({
|
|
1019
|
+
filename: "types/h3.d.ts",
|
|
1020
|
+
where: ".silgi",
|
|
1021
|
+
getContents: () => {
|
|
1022
|
+
return [
|
|
1023
|
+
"import type { SilgiRuntimeContext } from 'silgi/types'",
|
|
1024
|
+
"",
|
|
1025
|
+
'declare module "h3" {',
|
|
1026
|
+
" interface H3EventContext extends SilgiRuntimeContext {}",
|
|
1027
|
+
"}",
|
|
1028
|
+
""
|
|
1029
|
+
].join("\n");
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
opts.references.push({ path: "./h3.d.ts" });
|
|
1033
|
+
});
|
|
1034
|
+
addCoreFile({
|
|
1035
|
+
before: ({ silgiConfigs }) => {
|
|
1036
|
+
silgiConfigs.push({
|
|
1037
|
+
captureError: `(silgi, error, context = {}) => {
|
|
1038
|
+
const promise = silgi.hooks
|
|
1039
|
+
.callHookParallel('error', silgi, error, context)
|
|
1040
|
+
.catch((error_) => {
|
|
1041
|
+
console.error('Error while capturing another error', error_)
|
|
1042
|
+
})
|
|
1043
|
+
|
|
1044
|
+
if (context.event && isEvent(context.event)) {
|
|
1045
|
+
const errors = context.event.context.nitro?.errors
|
|
1046
|
+
if (errors) {
|
|
1047
|
+
errors.push({ error, context })
|
|
1048
|
+
}
|
|
1049
|
+
if (context.event.waitUntil) {
|
|
1050
|
+
context.event.waitUntil(promise)
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
}`
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
if (silgi.options.imports !== false) {
|
|
1058
|
+
silgi.options.imports.presets ??= [];
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
async function nitroFramework(silgi, skip = false) {
|
|
1063
|
+
if (!isPresents(["nitro"]) && skip === false)
|
|
1064
|
+
return;
|
|
1065
|
+
silgi.hook("before:schema.ts", (data) => {
|
|
1066
|
+
data.addImportItemType({
|
|
1067
|
+
imports: [
|
|
1068
|
+
{
|
|
1069
|
+
name: "NitroApp"
|
|
1070
|
+
}
|
|
1071
|
+
],
|
|
1072
|
+
specifier: "nitropack/types"
|
|
1073
|
+
});
|
|
1074
|
+
});
|
|
1075
|
+
silgi.hook("after:schema.ts", (data) => {
|
|
1076
|
+
data.unshift("type FrameworkContextExtends = NitroApp");
|
|
1077
|
+
});
|
|
1078
|
+
silgi.options.plugins.push({
|
|
1079
|
+
packageImport: "silgi/runtime/internal/nitro",
|
|
1080
|
+
path: join(runtimeDir, "internal/nitro")
|
|
1081
|
+
});
|
|
1082
|
+
silgi.hook("prepare:types", (opts) => {
|
|
1083
|
+
addTemplate({
|
|
1084
|
+
filename: "types/nitro.d.ts",
|
|
1085
|
+
where: ".silgi",
|
|
1086
|
+
getContents: () => {
|
|
1087
|
+
return [
|
|
1088
|
+
"import type { NitroRuntimeConfig } from 'nitropack/types'",
|
|
1089
|
+
"",
|
|
1090
|
+
'declare module "silgi/types" {',
|
|
1091
|
+
" interface SilgiRuntimeConfig extends NitroRuntimeConfig {}",
|
|
1092
|
+
"}",
|
|
1093
|
+
""
|
|
1094
|
+
].join("\n");
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
opts.references.push({ path: "./nitro.d.ts" });
|
|
1098
|
+
});
|
|
1099
|
+
if (silgi.options.imports !== false) {
|
|
1100
|
+
silgi.options.imports.presets ??= [];
|
|
1101
|
+
}
|
|
1102
|
+
await h3Framework(silgi, true);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
async function nuxtFramework(silgi, skip = false) {
|
|
1106
|
+
if (silgi.options.preset !== "nuxt" && skip === false)
|
|
1107
|
+
return;
|
|
1108
|
+
await nitroFramework(silgi, true);
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
const frameworkSetup = [
|
|
1112
|
+
emptyFramework,
|
|
1113
|
+
h3Framework,
|
|
1114
|
+
nitroFramework,
|
|
1115
|
+
nuxtFramework
|
|
1116
|
+
];
|
|
1117
|
+
|
|
1118
|
+
async function registerModuleExportScan(silgi) {
|
|
1119
|
+
silgi.hook("before:schema.ts", async (options) => {
|
|
1120
|
+
for (const module of silgi.scanModules) {
|
|
1121
|
+
const moduleReExports = [];
|
|
1122
|
+
if (!module.entryPath) {
|
|
1123
|
+
continue;
|
|
1124
|
+
}
|
|
1125
|
+
const moduleTypes = await promises.readFile(module.entryPath.replace(/\.mjs$/, "Types.d.ts"), "utf8").catch(() => "");
|
|
1126
|
+
const normalisedModuleTypes = moduleTypes.replace(/export\s*\{.*?\}/gs, (match) => match.replace(/\b(type|interface)\b/g, ""));
|
|
1127
|
+
for (const e of findTypeExports(normalisedModuleTypes)) {
|
|
1128
|
+
moduleReExports.push(e);
|
|
1129
|
+
}
|
|
1130
|
+
for (const e of findExports(normalisedModuleTypes)) {
|
|
1131
|
+
moduleReExports.push(e);
|
|
1132
|
+
}
|
|
1133
|
+
const hasTypeExport = (name) => moduleReExports.find((exp) => exp.names?.includes(name));
|
|
1134
|
+
const configKey = module.meta.configKey;
|
|
1135
|
+
const moduleName = module.meta.name || module.meta._packageName;
|
|
1136
|
+
const specifier = module.meta._packageName ? moduleName : relativeWithDot(silgi.options.build.typesDir, module.entryPath);
|
|
1137
|
+
if (hasTypeExport("ModuleOptions")) {
|
|
1138
|
+
const importName = hash(`${configKey}ModuleOptions`);
|
|
1139
|
+
options.addImportItemType({
|
|
1140
|
+
imports: [
|
|
1141
|
+
{
|
|
1142
|
+
as: importName,
|
|
1143
|
+
name: "ModuleOptions"
|
|
1144
|
+
}
|
|
1145
|
+
],
|
|
1146
|
+
specifier
|
|
1147
|
+
});
|
|
1148
|
+
options.options.push({ key: configKey, value: importName });
|
|
1149
|
+
}
|
|
1150
|
+
if (hasTypeExport("ModuleRuntimeOptions")) {
|
|
1151
|
+
const importName = hash(`${configKey}ModuleRuntimeOptions`);
|
|
1152
|
+
options.addImportItemType({
|
|
1153
|
+
imports: [
|
|
1154
|
+
{
|
|
1155
|
+
as: importName,
|
|
1156
|
+
name: "ModuleRuntimeOptions"
|
|
1157
|
+
}
|
|
1158
|
+
],
|
|
1159
|
+
specifier
|
|
1160
|
+
});
|
|
1161
|
+
options.runtimeOptions.push({ key: configKey, value: importName });
|
|
1162
|
+
}
|
|
1163
|
+
if (hasTypeExport("ModuleRuntimeShareds")) {
|
|
1164
|
+
const importName = hash(`${configKey}ModuleRuntimeShareds`);
|
|
1165
|
+
options.addImportItemType({
|
|
1166
|
+
imports: [
|
|
1167
|
+
{
|
|
1168
|
+
as: importName,
|
|
1169
|
+
name: "ModuleRuntimeShareds"
|
|
1170
|
+
}
|
|
1171
|
+
],
|
|
1172
|
+
specifier
|
|
1173
|
+
});
|
|
1174
|
+
options.shareds.push({ key: configKey, value: importName });
|
|
1175
|
+
}
|
|
1176
|
+
if (hasTypeExport("ModuleEvents")) {
|
|
1177
|
+
const importName = hash(`${configKey}ModuleEvents`);
|
|
1178
|
+
options.addImportItemType({
|
|
1179
|
+
imports: [
|
|
1180
|
+
{
|
|
1181
|
+
as: importName,
|
|
1182
|
+
name: "ModuleEvents"
|
|
1183
|
+
}
|
|
1184
|
+
],
|
|
1185
|
+
specifier
|
|
1186
|
+
});
|
|
1187
|
+
options.events.push({ key: configKey, value: importName });
|
|
1188
|
+
}
|
|
1189
|
+
if (hasTypeExport("ModuleRuntimeContexts")) {
|
|
1190
|
+
const importName = hash(`${configKey}ModuleRuntimeContexts`);
|
|
1191
|
+
options.addImportItemType({
|
|
1192
|
+
imports: [
|
|
1193
|
+
{
|
|
1194
|
+
as: importName,
|
|
1195
|
+
name: "ModuleRuntimeContexts"
|
|
1196
|
+
}
|
|
1197
|
+
],
|
|
1198
|
+
specifier
|
|
1199
|
+
});
|
|
1200
|
+
options.contexts.push({ key: configKey, value: importName });
|
|
1201
|
+
}
|
|
1202
|
+
if (hasTypeExport("ModuleHooks")) {
|
|
1203
|
+
const importName = hash(`${configKey}ModuleHooks`);
|
|
1204
|
+
options.addImportItemType({
|
|
1205
|
+
imports: [
|
|
1206
|
+
{
|
|
1207
|
+
as: importName,
|
|
1208
|
+
name: "ModuleHooks"
|
|
1209
|
+
}
|
|
1210
|
+
],
|
|
1211
|
+
specifier
|
|
1212
|
+
});
|
|
1213
|
+
options.hooks.push({ key: configKey, value: importName });
|
|
1214
|
+
}
|
|
1215
|
+
if (hasTypeExport("ModuleRuntimeHooks")) {
|
|
1216
|
+
const importName = hash(`${configKey}RuntimeHooks`);
|
|
1217
|
+
options.addImportItemType({
|
|
1218
|
+
imports: [
|
|
1219
|
+
{
|
|
1220
|
+
as: importName,
|
|
1221
|
+
name: "ModuleRuntimeHooks"
|
|
1222
|
+
}
|
|
1223
|
+
],
|
|
1224
|
+
specifier
|
|
1225
|
+
});
|
|
1226
|
+
options.runtimeHooks.push({ key: configKey, value: importName });
|
|
1227
|
+
}
|
|
1228
|
+
if (hasTypeExport("ModuleRuntimeActions")) {
|
|
1229
|
+
const importName = hash(`${configKey}ModuleRuntimeActions`);
|
|
1230
|
+
options.addImportItemType({
|
|
1231
|
+
imports: [
|
|
1232
|
+
{
|
|
1233
|
+
as: importName,
|
|
1234
|
+
name: "ModuleRuntimeActions"
|
|
1235
|
+
}
|
|
1236
|
+
],
|
|
1237
|
+
specifier
|
|
1238
|
+
});
|
|
1239
|
+
options.actions.push({ key: configKey, value: importName });
|
|
1240
|
+
}
|
|
1241
|
+
if (hasTypeExport("ModuleRuntimeMethods")) {
|
|
1242
|
+
const importName = hash(`${configKey}ModuleRuntimeMethods`);
|
|
1243
|
+
options.addImportItemType({
|
|
1244
|
+
imports: [
|
|
1245
|
+
{
|
|
1246
|
+
as: importName,
|
|
1247
|
+
name: "ModuleRuntimeMethods"
|
|
1248
|
+
}
|
|
1249
|
+
],
|
|
1250
|
+
specifier
|
|
1251
|
+
});
|
|
1252
|
+
options.methods.push({ key: configKey, value: importName });
|
|
1253
|
+
}
|
|
1254
|
+
if (hasTypeExport("ModuleRuntimeRouteRules")) {
|
|
1255
|
+
const importName = hash(`${configKey}ModuleRuntimeRouteRules`);
|
|
1256
|
+
options.addImportItemType({
|
|
1257
|
+
imports: [
|
|
1258
|
+
{
|
|
1259
|
+
as: importName,
|
|
1260
|
+
name: "ModuleRuntimeRouteRules"
|
|
1261
|
+
}
|
|
1262
|
+
],
|
|
1263
|
+
specifier
|
|
1264
|
+
});
|
|
1265
|
+
options.routeRules.push({ key: configKey, value: importName });
|
|
1266
|
+
}
|
|
1267
|
+
if (hasTypeExport("ModuleRuntimeRouteRulesConfig")) {
|
|
1268
|
+
const importName = hash(`${configKey}ModuleRuntimeRouteRulesConfig`);
|
|
1269
|
+
options.addImportItemType({
|
|
1270
|
+
imports: [
|
|
1271
|
+
{
|
|
1272
|
+
as: importName,
|
|
1273
|
+
name: "ModuleRuntimeRouteRulesConfig"
|
|
1274
|
+
}
|
|
1275
|
+
],
|
|
1276
|
+
specifier
|
|
1277
|
+
});
|
|
1278
|
+
options.routeRulesConfig.push({ key: configKey, value: importName });
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
async function loadSilgiModuleInstance(silgiModule) {
|
|
1285
|
+
if (typeof silgiModule === "string") {
|
|
1286
|
+
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
1287
|
+
}
|
|
1288
|
+
if (typeof silgiModule !== "function") {
|
|
1289
|
+
throw new TypeError(`Nuxt module should be a function: ${silgiModule}`);
|
|
1290
|
+
}
|
|
1291
|
+
return { silgiModule };
|
|
1292
|
+
}
|
|
1293
|
+
async function installModules(silgi, prepare = false) {
|
|
1294
|
+
silgi.options.isPreparingModules = prepare;
|
|
1295
|
+
const jiti = createJiti(silgi.options.rootDir, {
|
|
1296
|
+
alias: silgi.options.alias,
|
|
1297
|
+
fsCache: true,
|
|
1298
|
+
moduleCache: true
|
|
1299
|
+
});
|
|
1300
|
+
for (const module of silgi.scanModules) {
|
|
1301
|
+
if (hasInstalledModule(module.meta.configKey) && !silgi.options.dev) {
|
|
1302
|
+
silgi.logger.info(`Module ${module.meta.configKey} installed`);
|
|
1303
|
+
}
|
|
1304
|
+
try {
|
|
1305
|
+
const silgiModule = module.entryPath !== void 0 ? await jiti.import(module.entryPath, {
|
|
1306
|
+
default: true,
|
|
1307
|
+
conditions: silgi.options.conditions
|
|
1308
|
+
}) : module.module;
|
|
1309
|
+
if (silgiModule.name !== "silgiNormalizedModule") {
|
|
1310
|
+
silgi.scanModules = silgi.scanModules.filter((m) => m.entryPath !== module.entryPath);
|
|
1311
|
+
continue;
|
|
1312
|
+
}
|
|
1313
|
+
await installModule(silgiModule, silgi, prepare);
|
|
1314
|
+
} catch (err) {
|
|
1315
|
+
silgi.logger.error(err);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
silgi.options.isPreparingModules = false;
|
|
1319
|
+
}
|
|
1320
|
+
async function installModule(moduleToInstall, silgi = useSilgiCLI$1(), inlineOptions, prepare = false) {
|
|
1321
|
+
const { silgiModule } = await loadSilgiModuleInstance(moduleToInstall);
|
|
1322
|
+
const res = await silgiModule(inlineOptions || {}, silgi) ?? {};
|
|
1323
|
+
if (res === false) {
|
|
1324
|
+
return false;
|
|
1325
|
+
}
|
|
1326
|
+
const metaData = await silgiModule.getMeta?.();
|
|
1327
|
+
if (prepare) {
|
|
1328
|
+
return metaData;
|
|
1329
|
+
}
|
|
1330
|
+
const installedModule = silgi.scanModules.find((m) => m.meta.configKey === metaData?.configKey);
|
|
1331
|
+
if (installedModule) {
|
|
1332
|
+
installedModule.installed = true;
|
|
1333
|
+
} else {
|
|
1334
|
+
throw new Error(`Module ${metaData?.name} not found`);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
const MissingModuleMatcher = /Cannot find module\s+['"]?([^'")\s]+)['"]?/i;
|
|
1339
|
+
async function _resolveSilgiModule(silgiModule, silgi) {
|
|
1340
|
+
let resolvedModulePath;
|
|
1341
|
+
let buildTimeModuleMeta = {};
|
|
1342
|
+
const jiti = createJiti(silgi.options.rootDir, {
|
|
1343
|
+
alias: silgi.options.alias,
|
|
1344
|
+
fsCache: true,
|
|
1345
|
+
moduleCache: true
|
|
1346
|
+
});
|
|
1347
|
+
if (typeof silgiModule === "string") {
|
|
1348
|
+
silgiModule = resolveAlias$1(silgiModule, silgi.options.alias);
|
|
1349
|
+
if (isRelative(silgiModule)) {
|
|
1350
|
+
silgiModule = resolve(silgi.options.rootDir, silgiModule);
|
|
1351
|
+
}
|
|
1352
|
+
try {
|
|
1353
|
+
const src = resolveModuleURL(silgiModule, {
|
|
1354
|
+
from: silgi.options.modulesDir.map((m) => directoryToURL(m.replace(/\/node_modules\/?$/, "/"))),
|
|
1355
|
+
suffixes: ["silgi", "silgi/index", "module", "module/index", "", "index"],
|
|
1356
|
+
extensions: [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"]
|
|
1357
|
+
// Maybe add https://github.com/unjs/exsolve/blob/dfff3e9bbc4a3a173a2d56b9b9ff731ab15598be/src/resolve.ts#L7
|
|
1358
|
+
// conditions: silgi.options.conditions,
|
|
1359
|
+
});
|
|
1360
|
+
resolvedModulePath = fileURLToPath(src);
|
|
1361
|
+
const resolvedSilgiModule = await jiti.import(src, { default: true });
|
|
1362
|
+
if (typeof resolvedSilgiModule !== "function") {
|
|
1363
|
+
throw new TypeError(`Nuxt module should be a function: ${silgiModule}.`);
|
|
1364
|
+
}
|
|
1365
|
+
silgiModule = await jiti.import(src, {
|
|
1366
|
+
default: true,
|
|
1367
|
+
conditions: silgi.options.conditions
|
|
1368
|
+
});
|
|
1369
|
+
const moduleMetadataPath = new URL("module.json", src);
|
|
1370
|
+
if (existsSync(moduleMetadataPath)) {
|
|
1371
|
+
buildTimeModuleMeta = JSON.parse(await promises.readFile(moduleMetadataPath, "utf-8"));
|
|
1372
|
+
} else {
|
|
1373
|
+
if (typeof silgiModule === "function") {
|
|
1374
|
+
const meta = await silgiModule.getMeta?.();
|
|
1375
|
+
const _exports = await scanExports(resolvedModulePath, true);
|
|
1376
|
+
buildTimeModuleMeta = {
|
|
1377
|
+
...meta,
|
|
1378
|
+
exports: _exports.map(({ from, ...rest }) => rest)
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
const code = error.code;
|
|
1384
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNSUPPORTED_DIR_IMPORT" || code === "ENOTDIR") {
|
|
1385
|
+
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
1386
|
+
}
|
|
1387
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
1388
|
+
const module = MissingModuleMatcher.exec(error.message)?.[1];
|
|
1389
|
+
if (module && !module.includes(silgiModule)) {
|
|
1390
|
+
throw new TypeError(`Error while importing module \`${silgiModule}\`: ${error}`);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
if (!buildTimeModuleMeta) {
|
|
1396
|
+
throw new Error(`Module ${silgiModule} is not a valid Silgi module`);
|
|
1397
|
+
}
|
|
1398
|
+
if (typeof silgiModule === "function") {
|
|
1399
|
+
if (!buildTimeModuleMeta.configKey) {
|
|
1400
|
+
const meta = await silgiModule.getMeta?.();
|
|
1401
|
+
buildTimeModuleMeta = {
|
|
1402
|
+
...meta,
|
|
1403
|
+
exports: []
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
if (silgi.scanModules.some((m) => m.meta?.configKey === buildTimeModuleMeta.configKey)) {
|
|
1407
|
+
throw new Error(`Module with key \`${buildTimeModuleMeta.configKey}\` already exists`);
|
|
1408
|
+
}
|
|
1409
|
+
const options = await silgiModule.getOptions?.() || {};
|
|
1410
|
+
if (options) {
|
|
1411
|
+
silgi.options._c12.config[buildTimeModuleMeta.configKey] = defu(
|
|
1412
|
+
silgi.options._c12.config[buildTimeModuleMeta.configKey] || {},
|
|
1413
|
+
options || {}
|
|
1414
|
+
);
|
|
1415
|
+
} else {
|
|
1416
|
+
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
1417
|
+
}
|
|
1418
|
+
silgi.scanModules.push({
|
|
1419
|
+
meta: buildTimeModuleMeta,
|
|
1420
|
+
entryPath: resolvedModulePath || void 0,
|
|
1421
|
+
installed: false,
|
|
1422
|
+
options,
|
|
1423
|
+
module: silgiModule
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
async function scanModules$1(silgi) {
|
|
1428
|
+
const _modules = [
|
|
1429
|
+
...silgi.options._modules,
|
|
1430
|
+
...silgi.options.modules
|
|
1431
|
+
];
|
|
1432
|
+
for await (const mod of _modules) {
|
|
1433
|
+
await _resolveSilgiModule(mod, silgi);
|
|
1434
|
+
}
|
|
1435
|
+
const moduleMap = new Map(
|
|
1436
|
+
silgi.scanModules.map((m) => [m.meta?.configKey, m])
|
|
1437
|
+
);
|
|
1438
|
+
const graphData = createDependencyGraph(silgi.scanModules);
|
|
1439
|
+
const sortedKeys = topologicalSort(graphData);
|
|
1440
|
+
const modules = sortedKeys.map((key) => moduleMap.get(key)).filter((module) => Boolean(module));
|
|
1441
|
+
silgi.scanModules = modules;
|
|
1442
|
+
}
|
|
1443
|
+
function createDependencyGraph(modules) {
|
|
1444
|
+
const graph = /* @__PURE__ */ new Map();
|
|
1445
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
1446
|
+
modules.forEach((module) => {
|
|
1447
|
+
const key = module.meta?.configKey;
|
|
1448
|
+
if (key) {
|
|
1449
|
+
graph.set(key, /* @__PURE__ */ new Set());
|
|
1450
|
+
inDegree.set(key, 0);
|
|
1451
|
+
}
|
|
1452
|
+
});
|
|
1453
|
+
modules.forEach((module) => {
|
|
1454
|
+
const key = module.meta?.configKey;
|
|
1455
|
+
if (!key) {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
const requiredDeps = module.meta?.requiredDependencies || [];
|
|
1459
|
+
const beforeDeps = module.meta?.beforeDependencies || [];
|
|
1460
|
+
const afterDeps = module.meta?.afterDependencies || [];
|
|
1461
|
+
const processedDeps = /* @__PURE__ */ new Set();
|
|
1462
|
+
requiredDeps.forEach((dep) => {
|
|
1463
|
+
if (!graph.has(dep)) {
|
|
1464
|
+
throw new Error(`Required dependency "${dep}" for module "${key}" is missing`);
|
|
1465
|
+
}
|
|
1466
|
+
graph.get(dep)?.add(key);
|
|
1467
|
+
inDegree.set(key, (inDegree.get(key) || 0) + 1);
|
|
1468
|
+
processedDeps.add(dep);
|
|
1469
|
+
});
|
|
1470
|
+
beforeDeps.forEach((dep) => {
|
|
1471
|
+
if (!graph.has(dep)) {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
graph.get(key)?.add(dep);
|
|
1475
|
+
inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
|
|
1476
|
+
});
|
|
1477
|
+
afterDeps.forEach((dep) => {
|
|
1478
|
+
if (processedDeps.has(dep)) {
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
if (!graph.has(dep)) {
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
graph.get(dep)?.add(key);
|
|
1485
|
+
inDegree.set(key, (inDegree.get(key) || 0) + 1);
|
|
1486
|
+
});
|
|
1487
|
+
});
|
|
1488
|
+
return { graph, inDegree };
|
|
1489
|
+
}
|
|
1490
|
+
function findCyclicDependencies(graph) {
|
|
1491
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1492
|
+
const recursionStack = /* @__PURE__ */ new Set();
|
|
1493
|
+
const cycles = [];
|
|
1494
|
+
function dfs(node, path = []) {
|
|
1495
|
+
visited.add(node);
|
|
1496
|
+
recursionStack.add(node);
|
|
1497
|
+
path.push(node);
|
|
1498
|
+
for (const neighbor of graph.get(node) || []) {
|
|
1499
|
+
if (recursionStack.has(neighbor)) {
|
|
1500
|
+
const cycleStart = path.indexOf(neighbor);
|
|
1501
|
+
if (cycleStart !== -1) {
|
|
1502
|
+
cycles.push([...path.slice(cycleStart), neighbor]);
|
|
1503
|
+
}
|
|
1504
|
+
} else if (!visited.has(neighbor)) {
|
|
1505
|
+
dfs(neighbor, [...path]);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
recursionStack.delete(node);
|
|
1509
|
+
path.pop();
|
|
1510
|
+
}
|
|
1511
|
+
for (const node of graph.keys()) {
|
|
1512
|
+
if (!visited.has(node)) {
|
|
1513
|
+
dfs(node, []);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return cycles;
|
|
1517
|
+
}
|
|
1518
|
+
function topologicalSort(graphData) {
|
|
1519
|
+
const { graph, inDegree } = graphData;
|
|
1520
|
+
const order = [];
|
|
1521
|
+
const queue = [];
|
|
1522
|
+
for (const [node, degree] of inDegree.entries()) {
|
|
1523
|
+
if (degree === 0) {
|
|
1524
|
+
queue.push(node);
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
while (queue.length > 0) {
|
|
1528
|
+
const node = queue.shift();
|
|
1529
|
+
order.push(node);
|
|
1530
|
+
const neighbors = Array.from(graph.get(node) || []);
|
|
1531
|
+
for (const neighbor of neighbors) {
|
|
1532
|
+
const newDegree = (inDegree.get(neighbor) || 0) - 1;
|
|
1533
|
+
inDegree.set(neighbor, newDegree);
|
|
1534
|
+
if (newDegree === 0) {
|
|
1535
|
+
queue.push(neighbor);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
if (order.length !== graph.size) {
|
|
1540
|
+
const cycles = findCyclicDependencies(graph);
|
|
1541
|
+
if (cycles.length > 0) {
|
|
1542
|
+
const cycleStr = cycles.map((cycle) => ` ${cycle.join(" -> ")}`).join("\n");
|
|
1543
|
+
throw new Error(`Circular dependencies detected:
|
|
1544
|
+
${cycleStr}`);
|
|
1545
|
+
} else {
|
|
1546
|
+
const unresolvedModules = Array.from(graph.keys()).filter((key) => !order.includes(key));
|
|
1547
|
+
throw new Error(`Unable to resolve dependencies for modules: ${unresolvedModules.join(", ")}`);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
return order;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
function resolveIgnorePatterns(silgi, relativePath) {
|
|
1554
|
+
if (!silgi) {
|
|
1555
|
+
return [];
|
|
1556
|
+
}
|
|
1557
|
+
const ignorePatterns = silgi.options.ignore.flatMap((s) => resolveGroupSyntax(s));
|
|
1558
|
+
const nuxtignoreFile = join(silgi.options.rootDir, ".nuxtignore");
|
|
1559
|
+
if (existsSync(nuxtignoreFile)) {
|
|
1560
|
+
const contents = readFileSync(nuxtignoreFile, "utf-8");
|
|
1561
|
+
ignorePatterns.push(...contents.trim().split(/\r?\n/));
|
|
1562
|
+
}
|
|
1563
|
+
return ignorePatterns;
|
|
1564
|
+
}
|
|
1565
|
+
function isIgnored(pathname, silgi, _stats) {
|
|
1566
|
+
if (!silgi) {
|
|
1567
|
+
return false;
|
|
1568
|
+
}
|
|
1569
|
+
if (!silgi._ignore) {
|
|
1570
|
+
silgi._ignore = ignore(silgi.options.ignoreOptions);
|
|
1571
|
+
silgi._ignore.add(resolveIgnorePatterns(silgi));
|
|
1572
|
+
}
|
|
1573
|
+
const relativePath = relative(silgi.options.rootDir, pathname);
|
|
1574
|
+
if (relativePath[0] === "." && relativePath[1] === ".") {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
return !!(relativePath && silgi._ignore.ignores(relativePath));
|
|
1578
|
+
}
|
|
1579
|
+
function resolveGroupSyntax(group) {
|
|
1580
|
+
let groups = [group];
|
|
1581
|
+
while (groups.some((group2) => group2.includes("{"))) {
|
|
1582
|
+
groups = groups.flatMap((group2) => {
|
|
1583
|
+
const [head, ...tail] = group2.split("{");
|
|
1584
|
+
if (tail.length) {
|
|
1585
|
+
const [body = "", ...rest] = tail.join("{").split("}");
|
|
1586
|
+
return body.split(",").map((part) => `${head}${part}${rest.join("")}`);
|
|
1587
|
+
}
|
|
1588
|
+
return group2;
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
return groups;
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
const safeFiles = [
|
|
1595
|
+
"silgi/configs",
|
|
1596
|
+
"silgi",
|
|
1597
|
+
"silgi/rules",
|
|
1598
|
+
"silgi/scan",
|
|
1599
|
+
"silgi/vfs"
|
|
1600
|
+
];
|
|
1601
|
+
class SchemaParser {
|
|
1602
|
+
options = {
|
|
1603
|
+
debug: false
|
|
1604
|
+
};
|
|
1605
|
+
/**
|
|
1606
|
+
*
|
|
1607
|
+
*/
|
|
1608
|
+
constructor(options) {
|
|
1609
|
+
this.options = {
|
|
1610
|
+
...this.options,
|
|
1611
|
+
...options
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
parseExports(content, filePath) {
|
|
1615
|
+
const ast = parseSync(content, { sourceType: "module", sourceFilename: filePath });
|
|
1616
|
+
if (this.options.debug)
|
|
1617
|
+
writeFileSync(`${filePath}.ast.json`, JSON.stringify(ast.program, null, 2));
|
|
1618
|
+
return {
|
|
1619
|
+
exportVariables: (search, path) => this.parseTypeDeclarations(ast, search, path),
|
|
1620
|
+
parseInterfaceDeclarations: (search, path) => this.parseInterfaceDeclarations(ast, search, path)
|
|
1621
|
+
// parsePlugin: (path: string) => this.parsePlugin(ast, path),
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
parseVariableDeclaration(ast, path) {
|
|
1625
|
+
const silgi = useSilgiCLI$1();
|
|
1626
|
+
if (ast.program.body.length === 0) {
|
|
1627
|
+
if (safeFiles.find((i) => path.includes(i)))
|
|
1628
|
+
return [];
|
|
1629
|
+
silgi.errors.push({
|
|
1630
|
+
type: "Parser",
|
|
1631
|
+
path
|
|
1632
|
+
});
|
|
1633
|
+
consola$1.warn("This file has a problem:", path);
|
|
1634
|
+
}
|
|
1635
|
+
const variableDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "VariableDeclaration");
|
|
1636
|
+
return variableDeclarations;
|
|
1637
|
+
}
|
|
1638
|
+
parseTSInterfaceDeclaration(ast, path = "") {
|
|
1639
|
+
const silgi = useSilgiCLI$1();
|
|
1640
|
+
if (ast.program.body.length === 0) {
|
|
1641
|
+
if (safeFiles.find((i) => path.includes(i)))
|
|
1642
|
+
return [];
|
|
1643
|
+
silgi.errors.push({
|
|
1644
|
+
type: "Parser",
|
|
1645
|
+
path
|
|
1646
|
+
});
|
|
1647
|
+
consola$1.warn("This file has a problem:", path);
|
|
1648
|
+
}
|
|
1649
|
+
const interfaceDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "TSInterfaceDeclaration");
|
|
1650
|
+
return interfaceDeclarations;
|
|
1651
|
+
}
|
|
1652
|
+
parseTypeDeclarations(ast, find = "", path = "") {
|
|
1653
|
+
const data = [];
|
|
1654
|
+
const variableDeclarations = this.parseVariableDeclaration(ast, path);
|
|
1655
|
+
for (const item of variableDeclarations) {
|
|
1656
|
+
for (const declaration of item.declaration.declarations) {
|
|
1657
|
+
if (declaration.init?.callee?.name === find) {
|
|
1658
|
+
const options = {};
|
|
1659
|
+
if (declaration.init.arguments) {
|
|
1660
|
+
for (const argument of declaration.init.arguments) {
|
|
1661
|
+
for (const propertie of argument.properties) {
|
|
1662
|
+
if (propertie.key.name === "name")
|
|
1663
|
+
options.pluginName = propertie.value.value;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
for (const key in declaration.init.properties) {
|
|
1668
|
+
const property = declaration.init.properties[key];
|
|
1669
|
+
if (property.type === "ObjectProperty") {
|
|
1670
|
+
if (property.key.name === "options") {
|
|
1671
|
+
for (const key2 in property.value.properties) {
|
|
1672
|
+
const option = property.value.properties[key2];
|
|
1673
|
+
if (option.type === "ObjectProperty") {
|
|
1674
|
+
options[option.key.name] = option.value.value;
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
options.type = false;
|
|
1681
|
+
data.push({
|
|
1682
|
+
exportName: declaration.id.name,
|
|
1683
|
+
options,
|
|
1684
|
+
// object: declaration.init,
|
|
1685
|
+
path
|
|
1686
|
+
});
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
return data;
|
|
1691
|
+
}
|
|
1692
|
+
parseInterfaceDeclarations(ast, find = "", path = "") {
|
|
1693
|
+
const data = [];
|
|
1694
|
+
for (const item of this.parseTSInterfaceDeclaration(ast, path)) {
|
|
1695
|
+
if (!item?.declaration?.extends)
|
|
1696
|
+
continue;
|
|
1697
|
+
for (const declaration of item?.declaration?.extends) {
|
|
1698
|
+
if (declaration.expression.name === find) {
|
|
1699
|
+
const options = {};
|
|
1700
|
+
options.type = true;
|
|
1701
|
+
data.push({
|
|
1702
|
+
exportName: item.declaration.id.name,
|
|
1703
|
+
options,
|
|
1704
|
+
// object: declaration.init,
|
|
1705
|
+
path
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
return data;
|
|
1711
|
+
}
|
|
1712
|
+
// private parsePlugin(ast: any, path: string = '') {
|
|
1713
|
+
// const data = {
|
|
1714
|
+
// export: [],
|
|
1715
|
+
// name: '',
|
|
1716
|
+
// path: '',
|
|
1717
|
+
// } as DataTypePlugin
|
|
1718
|
+
// for (const item of this.parseVariableDeclaration(ast)) {
|
|
1719
|
+
// for (const declaration of item.declaration.declarations) {
|
|
1720
|
+
// if (declaration.init.callee?.name === 'defineSilgiModule') {
|
|
1721
|
+
// if (declaration.init.arguments) {
|
|
1722
|
+
// for (const argument of declaration.init.arguments) {
|
|
1723
|
+
// for (const propertie of argument.properties) {
|
|
1724
|
+
// if (propertie.key.name === 'name')
|
|
1725
|
+
// data.name = propertie.value.value
|
|
1726
|
+
// }
|
|
1727
|
+
// }
|
|
1728
|
+
// }
|
|
1729
|
+
// data.export.push({
|
|
1730
|
+
// name: data.name,
|
|
1731
|
+
// as: camelCase(`${data.name}DefineSilgiModule`),
|
|
1732
|
+
// type: false,
|
|
1733
|
+
// })
|
|
1734
|
+
// }
|
|
1735
|
+
// }
|
|
1736
|
+
// }
|
|
1737
|
+
// for (const item of this.parseTSInterfaceDeclaration(ast)) {
|
|
1738
|
+
// if (!item?.declaration?.extends)
|
|
1739
|
+
// continue
|
|
1740
|
+
// for (const declaration of item?.declaration?.extends) {
|
|
1741
|
+
// if (declaration.expression.name === 'ModuleOptions') {
|
|
1742
|
+
// data.export.push({
|
|
1743
|
+
// name: item.declaration.id.name,
|
|
1744
|
+
// as: camelCase(`${data.name}ModuleOptions`),
|
|
1745
|
+
// type: true,
|
|
1746
|
+
// })
|
|
1747
|
+
// }
|
|
1748
|
+
// // TODO add other plugins
|
|
1749
|
+
// }
|
|
1750
|
+
// }
|
|
1751
|
+
// data.path = path
|
|
1752
|
+
// return data
|
|
1753
|
+
// }
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
async function scanExportFile(silgi) {
|
|
1757
|
+
const filePaths = /* @__PURE__ */ new Set();
|
|
1758
|
+
const scannedPaths = [];
|
|
1759
|
+
const dir = silgi.options.serverDir;
|
|
1760
|
+
const files = (await globby(dir, { cwd: silgi.options.rootDir, ignore: silgi.options.ignore })).sort();
|
|
1761
|
+
if (files.length) {
|
|
1762
|
+
const siblings = await readdir(dirname(dir)).catch(() => []);
|
|
1763
|
+
const directory = basename(dir);
|
|
1764
|
+
if (!siblings.includes(directory)) {
|
|
1765
|
+
const directoryLowerCase = directory.toLowerCase();
|
|
1766
|
+
const caseCorrected = siblings.find((sibling) => sibling.toLowerCase() === directoryLowerCase);
|
|
1767
|
+
if (caseCorrected) {
|
|
1768
|
+
const original = relative(silgi.options.serverDir, dir);
|
|
1769
|
+
const corrected = relative(silgi.options.serverDir, join(dirname(dir), caseCorrected));
|
|
1770
|
+
consola.warn(`Components not scanned from \`~/${corrected}\`. Did you mean to name the directory \`~/${original}\` instead?`);
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
for (const _file of files) {
|
|
1775
|
+
const filePath = resolve(dir, _file);
|
|
1776
|
+
if (scannedPaths.find((d) => filePath.startsWith(withTrailingSlash(d))) || isIgnored(filePath, silgi)) {
|
|
1777
|
+
continue;
|
|
1778
|
+
}
|
|
1779
|
+
if (filePaths.has(filePath)) {
|
|
1780
|
+
continue;
|
|
1781
|
+
}
|
|
1782
|
+
filePaths.add(filePath);
|
|
1783
|
+
if (silgi.options.extensions.includes(extname(filePath))) {
|
|
1784
|
+
const parser = new SchemaParser({
|
|
1785
|
+
debug: false
|
|
1786
|
+
});
|
|
1787
|
+
const readfile = await readFile(filePath, "utf-8");
|
|
1788
|
+
const { exportVariables, parseInterfaceDeclarations } = parser.parseExports(readfile, filePath);
|
|
1789
|
+
const createServices = exportVariables("createService", filePath);
|
|
1790
|
+
if (hasError("Parser", silgi)) {
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
const scanTS = [];
|
|
1794
|
+
const schemaTS = [];
|
|
1795
|
+
if (createServices.length > 0) {
|
|
1796
|
+
scanTS.push(...createServices.map(({ exportName, path }) => {
|
|
1797
|
+
const randomString = hash(basename(path) + exportName);
|
|
1798
|
+
const _name = `_v${randomString}`;
|
|
1799
|
+
return { exportName, path, _name, type: "service" };
|
|
1800
|
+
}));
|
|
1801
|
+
}
|
|
1802
|
+
const createSchemas = exportVariables("createSchema", filePath);
|
|
1803
|
+
if (hasError("Parser", silgi)) {
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
if (createSchemas.length > 0) {
|
|
1807
|
+
scanTS.push(...createSchemas.map(({ exportName, path }) => {
|
|
1808
|
+
const randomString = hash(basename(path) + exportName);
|
|
1809
|
+
const _name = `_v${randomString}`;
|
|
1810
|
+
return { exportName, path, _name, type: "schema" };
|
|
1811
|
+
}));
|
|
1812
|
+
}
|
|
1813
|
+
const createShareds = exportVariables("createShared", filePath);
|
|
1814
|
+
if (hasError("Parser", silgi)) {
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
if (createShareds.length > 0) {
|
|
1818
|
+
scanTS.push(...createShareds.map(({ exportName, path }) => {
|
|
1819
|
+
const randomString = hash(basename(path) + exportName);
|
|
1820
|
+
const _name = `_v${randomString}`;
|
|
1821
|
+
return { exportName, path, _name, type: "shared" };
|
|
1822
|
+
}));
|
|
1823
|
+
}
|
|
1824
|
+
const sharedsTypes = parseInterfaceDeclarations("ExtendShared", filePath);
|
|
1825
|
+
if (hasError("Parser", silgi)) {
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
if (sharedsTypes.length > 0) {
|
|
1829
|
+
schemaTS.push(...sharedsTypes.map(({ exportName, path }) => {
|
|
1830
|
+
const randomString = hash(basename(path) + exportName);
|
|
1831
|
+
const _name = `_v${randomString}`;
|
|
1832
|
+
return { exportName, path, _name, type: "shared" };
|
|
1833
|
+
}));
|
|
1834
|
+
}
|
|
1835
|
+
const contextTypes = parseInterfaceDeclarations("ExtendContext", filePath);
|
|
1836
|
+
if (hasError("Parser", silgi)) {
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
if (contextTypes.length > 0) {
|
|
1840
|
+
schemaTS.push(...contextTypes.map(({ exportName, path }) => {
|
|
1841
|
+
const randomString = hash(basename(path) + exportName);
|
|
1842
|
+
const _name = `_v${randomString}`;
|
|
1843
|
+
return { exportName, path, _name, type: "context" };
|
|
1844
|
+
}));
|
|
1845
|
+
}
|
|
1846
|
+
silgi.hook("before:scan.ts", (options) => {
|
|
1847
|
+
for (const { exportName, path, _name, type } of scanTS) {
|
|
1848
|
+
if (!path.includes("vfs")) {
|
|
1849
|
+
silgi.options.devServer.watch.push(path);
|
|
1850
|
+
}
|
|
1851
|
+
if (type === "service") {
|
|
1852
|
+
options.services.push(_name);
|
|
1853
|
+
}
|
|
1854
|
+
if (type === "shared") {
|
|
1855
|
+
options.shareds.push(_name);
|
|
1856
|
+
}
|
|
1857
|
+
if (type === "schema") {
|
|
1858
|
+
options.schemas.push(_name);
|
|
1859
|
+
}
|
|
1860
|
+
options.addImportItem({
|
|
1861
|
+
specifier: removeExtension(relativeWithDot(silgi.options.silgi.serverDir, path)),
|
|
1862
|
+
imports: [
|
|
1863
|
+
{
|
|
1864
|
+
name: exportName,
|
|
1865
|
+
as: _name
|
|
1866
|
+
}
|
|
1867
|
+
]
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
});
|
|
1871
|
+
silgi.hook("before:schema.ts", (options) => {
|
|
1872
|
+
for (const { exportName, path, _name, type } of schemaTS) {
|
|
1873
|
+
if (!path.includes("vfs")) {
|
|
1874
|
+
silgi.options.devServer.watch.push(path);
|
|
1875
|
+
}
|
|
1876
|
+
if (type === "shared") {
|
|
1877
|
+
options.shareds.push({
|
|
1878
|
+
key: _name,
|
|
1879
|
+
value: _name
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
if (type === "context") {
|
|
1883
|
+
options.contexts.push({
|
|
1884
|
+
key: _name,
|
|
1885
|
+
value: _name
|
|
1886
|
+
});
|
|
1887
|
+
}
|
|
1888
|
+
options.addImportItem({
|
|
1889
|
+
imports: [
|
|
1890
|
+
{
|
|
1891
|
+
name: exportName,
|
|
1892
|
+
as: _name
|
|
1893
|
+
}
|
|
1894
|
+
],
|
|
1895
|
+
specifier: removeExtension(relativeWithDot(silgi.options.build.typesDir, path))
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
function buildUriMap(silgi, currentPath = []) {
|
|
1904
|
+
const uriMap = /* @__PURE__ */ new Map();
|
|
1905
|
+
function traverse(node, path = []) {
|
|
1906
|
+
if (!node || typeof node !== "object")
|
|
1907
|
+
return;
|
|
1908
|
+
if (path.length === 4) {
|
|
1909
|
+
const basePath = path.join("/");
|
|
1910
|
+
let pathString = "";
|
|
1911
|
+
if (node.pathParams) {
|
|
1912
|
+
let paths = null;
|
|
1913
|
+
if (node.pathParams?._def?.typeName !== void 0) {
|
|
1914
|
+
try {
|
|
1915
|
+
const shape = node.pathParams?.shape;
|
|
1916
|
+
paths = shape ? Object.keys(shape) : null;
|
|
1917
|
+
} catch {
|
|
1918
|
+
paths = null;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
if (paths?.length) {
|
|
1922
|
+
pathString = paths.map((p) => `:${p}`).join("/");
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
uriMap.set(basePath, pathString);
|
|
1926
|
+
return;
|
|
1927
|
+
}
|
|
1928
|
+
for (const key in node) {
|
|
1929
|
+
if (!["_type", "fields"].includes(key)) {
|
|
1930
|
+
traverse(node[key], [...path, key]);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
traverse(silgi.schemas, currentPath);
|
|
1935
|
+
silgi.uris = defu(silgi.uris, Object.fromEntries(uriMap));
|
|
1936
|
+
return uriMap;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
async function readScanFile(silgi) {
|
|
1940
|
+
const path = resolve(silgi.options.silgi.serverDir, "scan.ts");
|
|
1941
|
+
const context = await promises.readFile(path, { encoding: "utf-8" });
|
|
1942
|
+
silgi.unimport = createUnimport(silgi.options.imports || {});
|
|
1943
|
+
await silgi.unimport.init();
|
|
1944
|
+
const injectedResult = await silgi.unimport.injectImports(context, path);
|
|
1945
|
+
if (!injectedResult) {
|
|
1946
|
+
throw new Error("Failed to inject imports");
|
|
1947
|
+
}
|
|
1948
|
+
const jiti = createJiti(silgi.options.rootDir, {
|
|
1949
|
+
fsCache: true,
|
|
1950
|
+
moduleCache: false,
|
|
1951
|
+
debug: silgi.options.debug === true,
|
|
1952
|
+
alias: silgi.options.alias
|
|
1953
|
+
});
|
|
1954
|
+
try {
|
|
1955
|
+
globalThis._silgi_runtime = silgi.options.runtimeConfig;
|
|
1956
|
+
injectedResult.code = `globalThis._silgi_runtime = ${JSON.stringify(silgi.options.runtimeConfig)};
|
|
1957
|
+
${injectedResult.code}`;
|
|
1958
|
+
injectedResult.code = injectedResult.code.replace(/runtimeConfig: \{\}/, `runtimeConfig: ${JSON.stringify(silgi.options.runtimeConfig)}`);
|
|
1959
|
+
const scanFile = await jiti.evalModule(
|
|
1960
|
+
injectedResult.code,
|
|
1961
|
+
{
|
|
1962
|
+
filename: path,
|
|
1963
|
+
async: true,
|
|
1964
|
+
conditions: silgi.options.conditions
|
|
1965
|
+
},
|
|
1966
|
+
async (data, name) => {
|
|
1967
|
+
return (await silgi.unimport.injectImports(data, name)).code;
|
|
1968
|
+
}
|
|
1969
|
+
);
|
|
1970
|
+
silgi.uris = defu(silgi.uris, scanFile.uris) || {};
|
|
1971
|
+
silgi.schemas = defu(scanFile.schemas, scanFile.uris) || {};
|
|
1972
|
+
silgi.services = defu(scanFile.services, scanFile.uris) || {};
|
|
1973
|
+
silgi.shareds = defu(scanFile.shareds, scanFile.shareds) || {};
|
|
1974
|
+
silgi.modulesURIs = defu(scanFile.modulesURIs, scanFile.modulesURIs) || {};
|
|
1975
|
+
return {
|
|
1976
|
+
context,
|
|
1977
|
+
object: {
|
|
1978
|
+
schemas: scanFile.schemas,
|
|
1979
|
+
uris: scanFile.uris,
|
|
1980
|
+
services: scanFile.services,
|
|
1981
|
+
shareds: scanFile.shareds,
|
|
1982
|
+
modulesURIs: scanFile.modulesURIs
|
|
1983
|
+
},
|
|
1984
|
+
path
|
|
1985
|
+
};
|
|
1986
|
+
} catch (error) {
|
|
1987
|
+
if (silgi.options.debug) {
|
|
1988
|
+
console.error("Failed to read scan.ts file:", error);
|
|
1989
|
+
} else {
|
|
1990
|
+
consola.withTag("silgi").error(error);
|
|
1991
|
+
}
|
|
1992
|
+
return {
|
|
1993
|
+
context,
|
|
1994
|
+
object: {
|
|
1995
|
+
schemas: {},
|
|
1996
|
+
uris: {},
|
|
1997
|
+
services: {},
|
|
1998
|
+
shareds: {},
|
|
1999
|
+
modulesURIs: {}
|
|
2000
|
+
},
|
|
2001
|
+
path
|
|
2002
|
+
};
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
async function prepareScanFile(silgi) {
|
|
2007
|
+
const { genImports, genTypeImports, addImportItem, addImportItemType } = addImports({
|
|
2008
|
+
imports: [
|
|
2009
|
+
{
|
|
2010
|
+
specifier: "silgi",
|
|
2011
|
+
imports: [
|
|
2012
|
+
{
|
|
2013
|
+
name: "createSilgi"
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
name: "createShared"
|
|
2017
|
+
}
|
|
2018
|
+
]
|
|
2019
|
+
},
|
|
2020
|
+
{
|
|
2021
|
+
specifier: "./configs",
|
|
2022
|
+
imports: [
|
|
2023
|
+
{
|
|
2024
|
+
name: "cliConfigs"
|
|
2025
|
+
}
|
|
2026
|
+
]
|
|
2027
|
+
}
|
|
2028
|
+
],
|
|
2029
|
+
typeImports: [
|
|
2030
|
+
{
|
|
2031
|
+
specifier: "silgi/types",
|
|
2032
|
+
imports: [
|
|
2033
|
+
{
|
|
2034
|
+
name: "SilgiRuntimeOptions"
|
|
2035
|
+
},
|
|
2036
|
+
{
|
|
2037
|
+
name: "FrameworkContext"
|
|
2038
|
+
}
|
|
2039
|
+
]
|
|
2040
|
+
}
|
|
2041
|
+
]
|
|
2042
|
+
});
|
|
2043
|
+
const scanned = {
|
|
2044
|
+
uris: {},
|
|
2045
|
+
services: [],
|
|
2046
|
+
shareds: [],
|
|
2047
|
+
schemas: [],
|
|
2048
|
+
modulesURIs: {},
|
|
2049
|
+
addImportItem,
|
|
2050
|
+
addImportItemType
|
|
2051
|
+
};
|
|
2052
|
+
if (silgi.uris) {
|
|
2053
|
+
defu(scanned.uris, silgi.uris);
|
|
2054
|
+
}
|
|
2055
|
+
if (silgi.modulesURIs) {
|
|
2056
|
+
scanned.shareds.push(
|
|
2057
|
+
`createShared({
|
|
2058
|
+
modulesURIs,
|
|
2059
|
+
})`
|
|
2060
|
+
);
|
|
2061
|
+
defu(scanned.modulesURIs, silgi.modulesURIs);
|
|
2062
|
+
}
|
|
2063
|
+
await silgi.callHook("before:scan.ts", scanned);
|
|
2064
|
+
if (scanned.services.length > 0) {
|
|
2065
|
+
addImportItem({
|
|
2066
|
+
specifier: "silgi",
|
|
2067
|
+
imports: {
|
|
2068
|
+
name: "mergeServices"
|
|
2069
|
+
}
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
if (scanned.shareds.length > 0) {
|
|
2073
|
+
addImportItem({
|
|
2074
|
+
specifier: "silgi",
|
|
2075
|
+
imports: {
|
|
2076
|
+
name: "mergeShared"
|
|
2077
|
+
}
|
|
2078
|
+
});
|
|
2079
|
+
}
|
|
2080
|
+
if (scanned.schemas.length > 0) {
|
|
2081
|
+
addImportItem({
|
|
2082
|
+
specifier: "silgi",
|
|
2083
|
+
imports: {
|
|
2084
|
+
name: "mergeSchemas"
|
|
2085
|
+
}
|
|
2086
|
+
});
|
|
2087
|
+
}
|
|
2088
|
+
const importsContent = [
|
|
2089
|
+
...genImports.map(({ specifier, imports, options }) => {
|
|
2090
|
+
return genImport(specifier, imports, options);
|
|
2091
|
+
}),
|
|
2092
|
+
...genTypeImports.map(({ specifier, imports }) => {
|
|
2093
|
+
return genTypeImport(specifier, Array.isArray(imports) ? imports : [imports]);
|
|
2094
|
+
}),
|
|
2095
|
+
""
|
|
2096
|
+
];
|
|
2097
|
+
const importData = [
|
|
2098
|
+
`export const uris = ${JSON.stringify(scanned.uris, null, 2)}`,
|
|
2099
|
+
"",
|
|
2100
|
+
`export const modulesURIs = ${JSON.stringify(scanned.modulesURIs, null, 2)}`,
|
|
2101
|
+
"",
|
|
2102
|
+
scanned.schemas.length > 0 ? "export const schemas = mergeSchemas([" : "export const schemas = {",
|
|
2103
|
+
...scanned.schemas.map((name) => {
|
|
2104
|
+
return ` ${name},`;
|
|
2105
|
+
}),
|
|
2106
|
+
scanned.schemas.length > 0 ? "])" : "}",
|
|
2107
|
+
"",
|
|
2108
|
+
scanned.services.length > 0 ? "export const services = mergeServices([" : "export const services = {",
|
|
2109
|
+
...scanned.services.map((name) => {
|
|
2110
|
+
return ` ${name},`;
|
|
2111
|
+
}),
|
|
2112
|
+
scanned.services.length > 0 ? "])" : "}",
|
|
2113
|
+
"",
|
|
2114
|
+
scanned.shareds.length > 0 ? "export const shareds = mergeShared([" : "export const shareds = {",
|
|
2115
|
+
...scanned.shareds.map((name) => {
|
|
2116
|
+
return ` ${name},`;
|
|
2117
|
+
}),
|
|
2118
|
+
scanned.shareds.length > 0 ? "])" : "}",
|
|
2119
|
+
""
|
|
2120
|
+
];
|
|
2121
|
+
await silgi.callHook("after:scan.ts", importData);
|
|
2122
|
+
importData.unshift(...importsContent);
|
|
2123
|
+
importData.unshift(...baseHeaderBannerComment);
|
|
2124
|
+
return importData;
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
async function writeScanFiles(silgi) {
|
|
2128
|
+
const data = await prepareScanFile(silgi);
|
|
2129
|
+
if (!silgi.errors.length) {
|
|
2130
|
+
await writeFile(
|
|
2131
|
+
resolve(silgi.options.silgi.serverDir, "scan.ts"),
|
|
2132
|
+
data.join("\n")
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
await readScanFile(silgi);
|
|
2136
|
+
buildUriMap(silgi);
|
|
2137
|
+
parseServices(silgi);
|
|
2138
|
+
silgi.hook("before:scan.ts", (file) => {
|
|
2139
|
+
file.uris = {
|
|
2140
|
+
...file.uris,
|
|
2141
|
+
...silgi.uris
|
|
2142
|
+
};
|
|
2143
|
+
file.modulesURIs = {
|
|
2144
|
+
...file.modulesURIs,
|
|
2145
|
+
...silgi.modulesURIs
|
|
2146
|
+
};
|
|
2147
|
+
});
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
async function createStorageCLI(silgi) {
|
|
2151
|
+
const storage = createStorage();
|
|
2152
|
+
const runtime = useSilgiRuntimeConfig();
|
|
2153
|
+
const mounts = klona({
|
|
2154
|
+
...silgi.options.storage,
|
|
2155
|
+
...silgi.options.devStorage
|
|
2156
|
+
});
|
|
2157
|
+
for (const [path, opts] of Object.entries(mounts)) {
|
|
2158
|
+
if (opts.driver) {
|
|
2159
|
+
const driver = await import(builtinDrivers[opts.driver] || opts.driver).then((r) => r.default || r);
|
|
2160
|
+
const processedOpts = replaceRuntimeValues({ ...opts }, runtime);
|
|
2161
|
+
storage.mount(path, driver(processedOpts));
|
|
2162
|
+
} else {
|
|
2163
|
+
silgi.logger.warn(`No \`driver\` set for storage mount point "${path}".`);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return storage;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
function useCLIRuntimeConfig(silgi) {
|
|
2170
|
+
const safeRuntimeConfig = JSON.parse(JSON.stringify(silgi.options.runtimeConfig));
|
|
2171
|
+
silgi.hook("prepare:configs.ts", (data) => {
|
|
2172
|
+
data.runtimeConfig = safeRuntimeConfig;
|
|
2173
|
+
silgi.options.envOptions = silgi.options.envOptions;
|
|
2174
|
+
});
|
|
2175
|
+
addTemplate({
|
|
2176
|
+
filename: "env.example",
|
|
2177
|
+
write: true,
|
|
2178
|
+
where: ".silgi",
|
|
2179
|
+
getContents() {
|
|
2180
|
+
const flattenedConfig = flattenObject(safeRuntimeConfig);
|
|
2181
|
+
const groupedVars = {};
|
|
2182
|
+
Object.entries(flattenedConfig).forEach(([key, { value, originalPath }]) => {
|
|
2183
|
+
const shouldExclude = silgi.options.codegen.env.safeList.some((safePath) => {
|
|
2184
|
+
if (safePath.length !== originalPath.length)
|
|
2185
|
+
return false;
|
|
2186
|
+
return safePath.every((segment, index) => segment.toLowerCase() === originalPath[index].toLowerCase());
|
|
2187
|
+
});
|
|
2188
|
+
if (shouldExclude)
|
|
2189
|
+
return;
|
|
2190
|
+
if (originalPath.length > 0) {
|
|
2191
|
+
const firstKey = originalPath[0];
|
|
2192
|
+
const categoryName = extractCategoryFromCamel(firstKey);
|
|
2193
|
+
if (!groupedVars[categoryName]) {
|
|
2194
|
+
groupedVars[categoryName] = {};
|
|
2195
|
+
}
|
|
2196
|
+
groupedVars[categoryName][key] = value;
|
|
2197
|
+
} else {
|
|
2198
|
+
if (!groupedVars.OTHER) {
|
|
2199
|
+
groupedVars.OTHER = {};
|
|
2200
|
+
}
|
|
2201
|
+
groupedVars.OTHER[key] = value;
|
|
2202
|
+
}
|
|
2203
|
+
});
|
|
2204
|
+
return Object.entries(groupedVars).map(([category, vars]) => {
|
|
2205
|
+
const varsContent = Object.entries(vars).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
2206
|
+
return `# ${category}
|
|
2207
|
+
${varsContent}`;
|
|
2208
|
+
}).join("\n\n");
|
|
2209
|
+
}
|
|
2210
|
+
});
|
|
2211
|
+
const _sharedRuntimeConfig = initRuntimeConfig(silgi.options.envOptions, silgi.options.runtimeConfig);
|
|
2212
|
+
silgi.options.runtimeConfig = safeRuntimeConfig;
|
|
2213
|
+
return _sharedRuntimeConfig;
|
|
2214
|
+
}
|
|
2215
|
+
function extractCategoryFromCamel(str) {
|
|
2216
|
+
if (/^[a-z]+[A-Z]/.test(str)) {
|
|
2217
|
+
const matches = str.match(/^([a-z]+)([A-Z][a-z0-9]*)?/);
|
|
2218
|
+
if (matches && matches[2]) {
|
|
2219
|
+
return `${matches[1].toUpperCase()}_${matches[2].toUpperCase()}`;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
return str.toUpperCase();
|
|
2223
|
+
}
|
|
2224
|
+
function flattenObject(obj, prefix = "SILGI", originalPath = []) {
|
|
2225
|
+
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
2226
|
+
const formattedKey = snakeCase(key).toUpperCase();
|
|
2227
|
+
const newKey = `${prefix}_${formattedKey}`;
|
|
2228
|
+
const newPath = [...originalPath, key];
|
|
2229
|
+
if (typeof value === "object" && value !== null) {
|
|
2230
|
+
Object.assign(acc, flattenObject(value, newKey, newPath));
|
|
2231
|
+
} else {
|
|
2232
|
+
acc[newKey] = { value, originalPath: newPath };
|
|
2233
|
+
}
|
|
2234
|
+
return acc;
|
|
2235
|
+
}, {});
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
const GLOB_SCAN_PATTERN = "**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}";
|
|
2239
|
+
async function scanAndSyncOptions(silgi) {
|
|
2240
|
+
const scannedModules = await scanModules(silgi);
|
|
2241
|
+
silgi.options.modules = silgi.options.modules || [];
|
|
2242
|
+
for (const modPath of scannedModules) {
|
|
2243
|
+
if (!silgi.options.modules.includes(modPath)) {
|
|
2244
|
+
silgi.options.modules.push(modPath);
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
async function scanModules(silgi) {
|
|
2249
|
+
const files = await scanFiles(silgi, "silgi/modules");
|
|
2250
|
+
return files.map((f) => f.fullPath);
|
|
2251
|
+
}
|
|
2252
|
+
async function scanFiles(silgi, name) {
|
|
2253
|
+
const files = await Promise.all(
|
|
2254
|
+
silgi.options.scanDirs.map((dir) => scanDir(silgi, dir, name))
|
|
2255
|
+
).then((r) => r.flat());
|
|
2256
|
+
return files;
|
|
2257
|
+
}
|
|
2258
|
+
async function scanDir(silgi, dir, name) {
|
|
2259
|
+
const fileNames = await globby(join(name, GLOB_SCAN_PATTERN), {
|
|
2260
|
+
cwd: dir,
|
|
2261
|
+
dot: true,
|
|
2262
|
+
ignore: silgi.options.ignore,
|
|
2263
|
+
absolute: true
|
|
2264
|
+
});
|
|
2265
|
+
return fileNames.map((fullPath) => {
|
|
2266
|
+
return {
|
|
2267
|
+
fullPath,
|
|
2268
|
+
path: relative(join(dir, name), fullPath)
|
|
2269
|
+
};
|
|
2270
|
+
}).sort((a, b) => a.path.localeCompare(b.path));
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
async function createSilgiCLI(config = {}, opts = {}) {
|
|
2274
|
+
const options = await loadOptions(config, opts);
|
|
2275
|
+
const hooks = createHooks();
|
|
2276
|
+
const silgi = {
|
|
2277
|
+
modulesURIs: {},
|
|
2278
|
+
scannedURIs: /* @__PURE__ */ new Map(),
|
|
2279
|
+
services: {},
|
|
2280
|
+
uris: {},
|
|
2281
|
+
shareds: {},
|
|
2282
|
+
schemas: {},
|
|
2283
|
+
unimport: void 0,
|
|
2284
|
+
options,
|
|
2285
|
+
hooks,
|
|
2286
|
+
errors: [],
|
|
2287
|
+
_requiredModules: {},
|
|
2288
|
+
logger: opts.consola || consola.withTag("silgi"),
|
|
2289
|
+
close: () => silgi.hooks.callHook("close", silgi),
|
|
2290
|
+
storage: void 0,
|
|
2291
|
+
scanModules: [],
|
|
2292
|
+
templates: [],
|
|
2293
|
+
callHook: hooks.callHook,
|
|
2294
|
+
addHooks: hooks.addHooks,
|
|
2295
|
+
hook: hooks.hook,
|
|
2296
|
+
async updateConfig(_config) {
|
|
2297
|
+
},
|
|
2298
|
+
routeRules: void 0,
|
|
2299
|
+
adapters: {}
|
|
2300
|
+
};
|
|
2301
|
+
if (silgi.options.adapters && Object.keys(silgi.options.adapters)?.length > 0) {
|
|
2302
|
+
for (const [key, value] of Object.entries(silgi.options.adapters)) {
|
|
2303
|
+
silgi.adapters[key] = value;
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
await prepareEnv(options);
|
|
2307
|
+
const routeRules = createRouteRules();
|
|
2308
|
+
routeRules.importRules(options.routeRules ?? {});
|
|
2309
|
+
silgi.routeRules = routeRules;
|
|
2310
|
+
if (silgiCLICtx.tryUse()) {
|
|
2311
|
+
silgiCLICtx.unset();
|
|
2312
|
+
silgiCLICtx.set(silgi);
|
|
2313
|
+
} else {
|
|
2314
|
+
silgiCLICtx.set(silgi);
|
|
2315
|
+
silgi.hook("close", () => silgiCLICtx.unset());
|
|
2316
|
+
}
|
|
2317
|
+
await silgi.hooks.callHook("ready", silgi);
|
|
2318
|
+
if (silgi.options.debug) {
|
|
2319
|
+
createDebugger(silgi.hooks, { tag: "silgi" });
|
|
2320
|
+
silgi.options.plugins.push({
|
|
2321
|
+
path: join(runtimeDir, "internal/debug"),
|
|
2322
|
+
packageImport: "silgi/runtime/internal/debug"
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
2325
|
+
for (const framework of frameworkSetup) {
|
|
2326
|
+
await framework(silgi);
|
|
2327
|
+
}
|
|
2328
|
+
await scanAndSyncOptions(silgi);
|
|
2329
|
+
await scanModules$1(silgi);
|
|
2330
|
+
await scanExportFile(silgi);
|
|
2331
|
+
await installModules(silgi, true);
|
|
2332
|
+
useCLIRuntimeConfig(silgi);
|
|
2333
|
+
await writeScanFiles(silgi);
|
|
2334
|
+
silgi.storage = await createStorageCLI(silgi);
|
|
2335
|
+
silgi.hooks.hook("close", async () => {
|
|
2336
|
+
await silgi.storage.dispose();
|
|
2337
|
+
});
|
|
2338
|
+
if (silgi.options.logLevel !== void 0) {
|
|
2339
|
+
silgi.logger.level = silgi.options.logLevel;
|
|
2340
|
+
}
|
|
2341
|
+
silgi.hooks.addHooks(silgi.options.hooks);
|
|
2342
|
+
await installModules(silgi);
|
|
2343
|
+
await silgi.hooks.callHook("scanFiles:done", silgi);
|
|
2344
|
+
await generateApp(silgi);
|
|
2345
|
+
if (silgi.options.imports) {
|
|
2346
|
+
silgi.options.imports.dirs ??= [];
|
|
2347
|
+
silgi.options.imports.dirs = silgi.options.imports.dirs.map((dir) => {
|
|
2348
|
+
if (typeof dir === "string") {
|
|
2349
|
+
if (dir.startsWith("!")) {
|
|
2350
|
+
return `!${resolveSilgiPath(dir.slice(1), options, silgi.options.rootDir)}`;
|
|
2351
|
+
}
|
|
2352
|
+
return resolveSilgiPath(dir, options, silgi.options.rootDir);
|
|
2353
|
+
}
|
|
2354
|
+
return dir;
|
|
2355
|
+
});
|
|
2356
|
+
silgi.options.imports.presets.push({
|
|
2357
|
+
from: "silgi/types",
|
|
2358
|
+
imports: autoImportTypes.map((type) => type),
|
|
2359
|
+
type: true
|
|
2360
|
+
});
|
|
2361
|
+
silgi.options.imports.presets.push({
|
|
2362
|
+
from: "silgi/types",
|
|
2363
|
+
imports: autoImportTypes.map((type) => type),
|
|
2364
|
+
type: true
|
|
2365
|
+
});
|
|
2366
|
+
silgi.options.imports.presets.push({
|
|
2367
|
+
from: "silgi/runtime/internal/ofetch",
|
|
2368
|
+
imports: ["createSilgiFetch", "silgi$fetch"]
|
|
2369
|
+
});
|
|
2370
|
+
silgi.unimport = createUnimport(silgi.options.imports);
|
|
2371
|
+
await silgi.unimport.init();
|
|
2372
|
+
}
|
|
2373
|
+
await registerModuleExportScan(silgi);
|
|
2374
|
+
await writeScanFiles(silgi);
|
|
2375
|
+
return silgi;
|
|
2376
|
+
}
|
|
13
2377
|
|
|
14
2378
|
const commonArgs = {
|
|
15
2379
|
dir: {
|
|
@@ -65,7 +2429,7 @@ const command$1 = defineCommand({
|
|
|
65
2429
|
rawArgs: ["--commandType", "run"]
|
|
66
2430
|
});
|
|
67
2431
|
}
|
|
68
|
-
const silgi = useSilgiCLI();
|
|
2432
|
+
const silgi = useSilgiCLI$1();
|
|
69
2433
|
if (!silgi) {
|
|
70
2434
|
throw new Error("Silgi is not initialized");
|
|
71
2435
|
}
|