silgi 0.27.5 → 0.27.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/silgiApp.mjs +287 -1
- package/dist/build.d.mts +3 -16
- package/dist/build.mjs +8 -32
- package/dist/cli/build.mjs +861 -0
- package/dist/cli/config/index.mjs +2 -1
- package/dist/cli/dev.mjs +12 -12
- package/dist/cli/index.mjs +1 -1
- package/dist/cli/init.mjs +14 -14
- package/dist/cli/install.mjs +14 -14
- package/dist/cli/loader.mjs +598 -0
- package/dist/cli/prepare.mjs +1575 -18
- package/dist/cli/types.mjs +6 -597
- package/dist/core/index.mjs +2 -2
- package/dist/index.mjs +1 -2
- package/package.json +1 -1
- package/dist/_chunks/routeRules.mjs +0 -288
- package/dist/cli/writeTypesAndFiles.mjs +0 -2413
|
@@ -0,0 +1,861 @@
|
|
|
1
|
+
import { generateDTS } from 'apiful/openapi';
|
|
2
|
+
import { consola } from 'consola';
|
|
3
|
+
import { join, resolve, dirname, isAbsolute, relative } from 'pathe';
|
|
4
|
+
import { hasSilgiModule, addTemplate, normalizeTemplate, useLogger, genEnsureSafeVar, hash, relativeWithDot, writeFile, isDirectory } from 'silgi/kit';
|
|
5
|
+
import { mkdirSync, existsSync, writeFileSync, promises } from 'node:fs';
|
|
6
|
+
import 'node:fs/promises';
|
|
7
|
+
import { genObjectFromRawEntries, genObjectFromRaw, genObjectFromValues } from 'knitwork';
|
|
8
|
+
import { resolvePath, parseNodeModulePath, lookupNodeModuleSubpath } from 'mlly';
|
|
9
|
+
import { resolveAlias } from 'pathe/utils';
|
|
10
|
+
import { runtimeDir } from 'silgi/runtime/meta';
|
|
11
|
+
import { toExports } from 'unimport';
|
|
12
|
+
import { generateTypes, resolveSchema } from 'untyped';
|
|
13
|
+
import { s as silgiGenerateType } from './types.mjs';
|
|
14
|
+
|
|
15
|
+
async function generateApiFul(silgi) {
|
|
16
|
+
const config = silgi.options.apiFul;
|
|
17
|
+
if (!config.services || hasSilgiModule("openapi")) {
|
|
18
|
+
config.services ??= {};
|
|
19
|
+
config.services = {
|
|
20
|
+
silgi: {
|
|
21
|
+
schema: join(silgi.options.build.dir, "openapi.json")
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const resolvedOpenAPIServices = Object.fromEntries(
|
|
26
|
+
Object.entries(config?.services ?? {}).filter(([, service]) => Boolean(service.schema))
|
|
27
|
+
);
|
|
28
|
+
if (Object.keys(resolvedOpenAPIServices).length === 0) {
|
|
29
|
+
consola.info("No OpenAPI schemas found, skipping generation");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const service of Object.values(resolvedOpenAPIServices)) {
|
|
33
|
+
if (typeof service.schema === "string" && !service.schema.startsWith("http")) {
|
|
34
|
+
service.schema = resolve(silgi.options.rootDir, service.schema);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const types = await generateDTS(resolvedOpenAPIServices);
|
|
38
|
+
silgi.hook("prepare:types", (opts) => {
|
|
39
|
+
opts.references.push({ path: "./apiful.d.ts" });
|
|
40
|
+
});
|
|
41
|
+
addTemplate({
|
|
42
|
+
filename: "types/apiful.d.ts",
|
|
43
|
+
where: ".silgi",
|
|
44
|
+
write: true,
|
|
45
|
+
getContents: () => types
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const vueShim = {
|
|
50
|
+
filename: "delete/testtest.d.ts",
|
|
51
|
+
where: ".silgi",
|
|
52
|
+
getContents: ({ app }) => {
|
|
53
|
+
if (!app.options.typescript.shim) {
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
return [
|
|
57
|
+
"declare module '*.vue' {",
|
|
58
|
+
" import { DefineComponent } from 'vue'",
|
|
59
|
+
" const component: DefineComponent<{}, {}, any>",
|
|
60
|
+
" export default component",
|
|
61
|
+
"}"
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const pluginsDeclaration = {
|
|
66
|
+
filename: "delete/testtest1.d.ts",
|
|
67
|
+
where: ".silgi",
|
|
68
|
+
getContents: async () => {
|
|
69
|
+
return `
|
|
70
|
+
declare module 'nuxt' {
|
|
71
|
+
interface NuxtApp {
|
|
72
|
+
$myPlugin: any;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const defaultTemplates = {
|
|
80
|
+
__proto__: null,
|
|
81
|
+
pluginsDeclaration: pluginsDeclaration,
|
|
82
|
+
vueShim: vueShim
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const postTemplates = [
|
|
86
|
+
pluginsDeclaration.filename
|
|
87
|
+
];
|
|
88
|
+
const logger = useLogger("silgi");
|
|
89
|
+
async function generateApp(app, options = {}) {
|
|
90
|
+
app.templates = Object.values(defaultTemplates).concat(app.options.build.templates);
|
|
91
|
+
await app.callHook("app:templates", app);
|
|
92
|
+
app.templates = app.templates.map((tmpl) => {
|
|
93
|
+
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;
|
|
94
|
+
return normalizeTemplate(tmpl, dir);
|
|
95
|
+
});
|
|
96
|
+
const filteredTemplates = {
|
|
97
|
+
pre: [],
|
|
98
|
+
post: []
|
|
99
|
+
};
|
|
100
|
+
for (const template of app.templates) {
|
|
101
|
+
if (options.filter && !options.filter(template)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const key = template.filename && postTemplates.includes(template.filename) ? "post" : "pre";
|
|
105
|
+
filteredTemplates[key].push(template);
|
|
106
|
+
}
|
|
107
|
+
const templateContext = { app };
|
|
108
|
+
const writes = [];
|
|
109
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
110
|
+
const changedTemplates = [];
|
|
111
|
+
async function processTemplate(template) {
|
|
112
|
+
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;
|
|
113
|
+
const fullPath = template.dst || resolve(dir, template.filename);
|
|
114
|
+
const start = performance.now();
|
|
115
|
+
const contents = await compileTemplate(template, templateContext).catch((e) => {
|
|
116
|
+
logger.error(`Could not compile template \`${template.filename}\`.`);
|
|
117
|
+
logger.error(e);
|
|
118
|
+
throw e;
|
|
119
|
+
});
|
|
120
|
+
template.modified = true;
|
|
121
|
+
if (template.modified) {
|
|
122
|
+
changedTemplates.push(template);
|
|
123
|
+
}
|
|
124
|
+
const perf = performance.now() - start;
|
|
125
|
+
const setupTime = Math.round(perf * 100) / 100;
|
|
126
|
+
if (app.options.debug || setupTime > 500) {
|
|
127
|
+
logger.info(`Compiled \`${template.filename}\` in ${setupTime}ms`);
|
|
128
|
+
}
|
|
129
|
+
if (template.modified && template.write) {
|
|
130
|
+
dirs.add(dirname(fullPath));
|
|
131
|
+
if (template.skipIfExists && existsSync(fullPath)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
writes.push(() => writeFileSync(fullPath, contents, "utf8"));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
await Promise.allSettled(filteredTemplates.pre.map(processTemplate));
|
|
138
|
+
await Promise.allSettled(filteredTemplates.post.map(processTemplate));
|
|
139
|
+
for (const dir of dirs) {
|
|
140
|
+
mkdirSync(dir, { recursive: true });
|
|
141
|
+
}
|
|
142
|
+
for (const write of writes) {
|
|
143
|
+
if (!app.errors.length) {
|
|
144
|
+
write();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (changedTemplates.length) {
|
|
148
|
+
await app.callHook("app:templatesGenerated", app, changedTemplates, options);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async function compileTemplate(template, ctx) {
|
|
152
|
+
delete ctx.utils;
|
|
153
|
+
if (template.src) {
|
|
154
|
+
try {
|
|
155
|
+
return await promises.readFile(template.src, "utf-8");
|
|
156
|
+
} catch (err) {
|
|
157
|
+
logger.error(`[nuxt] Error reading template from \`${template.src}\``);
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (template.getContents) {
|
|
162
|
+
return template.getContents({
|
|
163
|
+
...ctx,
|
|
164
|
+
options: template.options
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
throw new Error(`[nuxt] Invalid template. Templates must have either \`src\` or \`getContents\`: ${JSON.stringify(template)}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function prepare(_silgi) {
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function prepareConfigs(silgi) {
|
|
174
|
+
const _data = {
|
|
175
|
+
runtimeConfig: {}
|
|
176
|
+
};
|
|
177
|
+
for (const module of silgi.scanModules) {
|
|
178
|
+
if (module.meta.cliToRuntimeOptionsKeys && module.meta.cliToRuntimeOptionsKeys?.length > 0) {
|
|
179
|
+
for (const key of module.meta.cliToRuntimeOptionsKeys) {
|
|
180
|
+
_data[module.meta.configKey] = {
|
|
181
|
+
..._data[module.meta.configKey],
|
|
182
|
+
[key]: module.options[key]
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
_data[module.meta.configKey] = {};
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
await silgi.callHook("prepare:configs.ts", _data);
|
|
190
|
+
const importData = [
|
|
191
|
+
"import type { SilgiRuntimeOptions, SilgiRuntimeConfig, SilgiOptions } from 'silgi/types'",
|
|
192
|
+
"import { useSilgiRuntimeConfig } from 'silgi/runtime'",
|
|
193
|
+
"",
|
|
194
|
+
`export const runtimeConfig: Partial<SilgiRuntimeConfig> = ${genObjectFromRawEntries(
|
|
195
|
+
Object.entries(_data.runtimeConfig).map(([key, value]) => [key, genEnsureSafeVar(value)]),
|
|
196
|
+
""
|
|
197
|
+
)}`,
|
|
198
|
+
"",
|
|
199
|
+
"const runtime = useSilgiRuntimeConfig(undefined, runtimeConfig)",
|
|
200
|
+
""
|
|
201
|
+
];
|
|
202
|
+
delete _data.runtimeConfig;
|
|
203
|
+
importData.push(`export const cliConfigs: Partial<SilgiRuntimeOptions & SilgiOptions> = ${genObjectFromRawEntries(
|
|
204
|
+
Object.entries(_data).map(
|
|
205
|
+
([key, value]) => [key, genEnsureSafeVar(value)]
|
|
206
|
+
).concat(
|
|
207
|
+
[
|
|
208
|
+
["runtimeConfig", "runtime"]
|
|
209
|
+
]
|
|
210
|
+
)
|
|
211
|
+
)}`);
|
|
212
|
+
return importData;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function prepareCoreFile(data, frameworkContext, silgi) {
|
|
216
|
+
let importItems = {
|
|
217
|
+
"silgi": {
|
|
218
|
+
import: [
|
|
219
|
+
{
|
|
220
|
+
name: "createSilgi",
|
|
221
|
+
key: "createSilgi"
|
|
222
|
+
}
|
|
223
|
+
],
|
|
224
|
+
from: "silgi"
|
|
225
|
+
},
|
|
226
|
+
"silgi/types": {
|
|
227
|
+
import: [
|
|
228
|
+
{
|
|
229
|
+
name: "SilgiRuntimeOptions",
|
|
230
|
+
type: true,
|
|
231
|
+
key: "SilgiRuntimeOptions"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: "FrameworkContext",
|
|
235
|
+
type: true,
|
|
236
|
+
key: "FrameworkContext"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
name: "SilgiOptions",
|
|
240
|
+
type: true,
|
|
241
|
+
key: "SilgiOptions"
|
|
242
|
+
}
|
|
243
|
+
],
|
|
244
|
+
from: "silgi/types"
|
|
245
|
+
},
|
|
246
|
+
"#silgi/vfs": {
|
|
247
|
+
import: [],
|
|
248
|
+
from: "./vfs"
|
|
249
|
+
},
|
|
250
|
+
"scan.ts": {
|
|
251
|
+
import: [
|
|
252
|
+
{
|
|
253
|
+
name: "uris",
|
|
254
|
+
type: false,
|
|
255
|
+
key: "uris"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: "services",
|
|
259
|
+
type: false,
|
|
260
|
+
key: "services"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: "shareds",
|
|
264
|
+
type: false,
|
|
265
|
+
key: "shareds"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "schemas",
|
|
269
|
+
type: false,
|
|
270
|
+
key: "schemas"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "modulesURIs",
|
|
274
|
+
type: false,
|
|
275
|
+
key: "modulesURIs"
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
from: "./scan.ts"
|
|
279
|
+
},
|
|
280
|
+
"configs.ts": {
|
|
281
|
+
import: [
|
|
282
|
+
{
|
|
283
|
+
name: "cliConfigs",
|
|
284
|
+
type: false,
|
|
285
|
+
key: "cliConfigs"
|
|
286
|
+
}
|
|
287
|
+
],
|
|
288
|
+
from: "./configs.ts"
|
|
289
|
+
},
|
|
290
|
+
"rules.ts": {
|
|
291
|
+
import: [
|
|
292
|
+
{
|
|
293
|
+
name: "routeRules",
|
|
294
|
+
key: "routeRules"
|
|
295
|
+
}
|
|
296
|
+
],
|
|
297
|
+
from: "./rules.ts"
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
importItems = { ...data._importItems, ...importItems };
|
|
301
|
+
const _data = {
|
|
302
|
+
customImports: data._customImports || [],
|
|
303
|
+
buildSilgiExtraContent: [],
|
|
304
|
+
beforeBuildSilgiExtraContent: [],
|
|
305
|
+
afterCliOptions: [],
|
|
306
|
+
_silgiConfigs: [],
|
|
307
|
+
customContent: [],
|
|
308
|
+
importItems
|
|
309
|
+
};
|
|
310
|
+
await silgi.callHook("prepare:core.ts", _data);
|
|
311
|
+
if (importItems["#silgi/vfs"].import.length === 0) {
|
|
312
|
+
delete importItems["#silgi/vfs"];
|
|
313
|
+
}
|
|
314
|
+
const plugins = [];
|
|
315
|
+
for (const plugin of silgi.options.plugins) {
|
|
316
|
+
const pluginImportName = `_${hash(plugin.packageImport)}`;
|
|
317
|
+
_data.customImports.push(`import ${pluginImportName} from '${plugin.packageImport}'`);
|
|
318
|
+
plugins.push(pluginImportName);
|
|
319
|
+
}
|
|
320
|
+
const importsContent = [
|
|
321
|
+
'import { mergeDeep } from "silgi/runtime"',
|
|
322
|
+
...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
|
|
323
|
+
if (silgi.options.typescript.removeFileExtension) {
|
|
324
|
+
from = from.replace(/\.(js|ts|mjs|cjs|jsx|tsx)$/, "");
|
|
325
|
+
}
|
|
326
|
+
return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${from}'`;
|
|
327
|
+
}),
|
|
328
|
+
"",
|
|
329
|
+
..._data.customImports,
|
|
330
|
+
""
|
|
331
|
+
];
|
|
332
|
+
const importData = [
|
|
333
|
+
"",
|
|
334
|
+
"export async function buildSilgi(framework: FrameworkContext, moduleOptions?: Partial<SilgiRuntimeOptions>,buildOptions?: Partial<SilgiOptions>) {",
|
|
335
|
+
"",
|
|
336
|
+
_data.beforeBuildSilgiExtraContent.length > 0 ? _data.beforeBuildSilgiExtraContent.map(({ value, type }) => {
|
|
337
|
+
return type === "function" ? value : `const ${value}`;
|
|
338
|
+
}) : "",
|
|
339
|
+
"",
|
|
340
|
+
" const silgi = await createSilgi({",
|
|
341
|
+
" framework,",
|
|
342
|
+
" shared: shareds as any,",
|
|
343
|
+
" services: services as any,",
|
|
344
|
+
" schemas: schemas as any,",
|
|
345
|
+
" uris,",
|
|
346
|
+
" modulesURIs,",
|
|
347
|
+
` plugins: [${plugins.join(", ")}],`,
|
|
348
|
+
_data._silgiConfigs.length > 0 ? ` ${_data._silgiConfigs.map((config) => typeof config === "string" ? config : typeof config === "object" ? Object.entries(config).map(([key, value]) => `${key}: ${value}`).join(",\n ") : "").join(",\n ")},` : "",
|
|
349
|
+
" options: mergeDeep(cliConfigs, {",
|
|
350
|
+
" runtimeConfig: {} as SilgiRuntimeOptions,",
|
|
351
|
+
" routeRules: routeRules as any,",
|
|
352
|
+
` present: '${silgi.options.preset}',`,
|
|
353
|
+
" ...moduleOptions,",
|
|
354
|
+
" ...buildOptions,",
|
|
355
|
+
" }) as any,",
|
|
356
|
+
" })",
|
|
357
|
+
"",
|
|
358
|
+
...frameworkContext,
|
|
359
|
+
"",
|
|
360
|
+
..._data.buildSilgiExtraContent,
|
|
361
|
+
"",
|
|
362
|
+
" return silgi",
|
|
363
|
+
"}",
|
|
364
|
+
""
|
|
365
|
+
];
|
|
366
|
+
await silgi.callHook("after:prepare:core.ts", importData);
|
|
367
|
+
importData.unshift(...importsContent);
|
|
368
|
+
return importData;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async function prepareFramework(silgi) {
|
|
372
|
+
const importItems = {
|
|
373
|
+
"silgi/types": {
|
|
374
|
+
import: [
|
|
375
|
+
{
|
|
376
|
+
name: "SilgiRuntimeContext",
|
|
377
|
+
type: true,
|
|
378
|
+
key: "SilgiRuntimeContext"
|
|
379
|
+
}
|
|
380
|
+
],
|
|
381
|
+
from: "silgi/types"
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
const customImports = [];
|
|
385
|
+
const functions = [];
|
|
386
|
+
await silgi.callHook("prepare:createCoreFramework", {
|
|
387
|
+
importItems,
|
|
388
|
+
customImports,
|
|
389
|
+
functions
|
|
390
|
+
});
|
|
391
|
+
const content = [
|
|
392
|
+
...functions.map((f) => f.params?.length ? ` await ${f.name}(framework, ${f.params.join(",")})` : ` await ${f.name}(framework)`)
|
|
393
|
+
];
|
|
394
|
+
return {
|
|
395
|
+
content,
|
|
396
|
+
importItems,
|
|
397
|
+
customImports
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
async function createDTSFramework(silgi) {
|
|
401
|
+
const importItems = {
|
|
402
|
+
"silgi/types": {
|
|
403
|
+
import: [
|
|
404
|
+
{
|
|
405
|
+
name: "SilgiRuntimeContext",
|
|
406
|
+
type: true,
|
|
407
|
+
key: "SilgiRuntimeContext"
|
|
408
|
+
}
|
|
409
|
+
],
|
|
410
|
+
from: "silgi/types"
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
const customImports = [];
|
|
414
|
+
const customContent = [];
|
|
415
|
+
await silgi.callHook("prepare:createDTSFramework", {
|
|
416
|
+
importItems,
|
|
417
|
+
customImports,
|
|
418
|
+
customContent
|
|
419
|
+
});
|
|
420
|
+
const content = [
|
|
421
|
+
...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
|
|
422
|
+
const path = isAbsolute(from) ? relativeWithDot(silgi.options.build.typesDir, from) : from;
|
|
423
|
+
if (silgi.options.typescript.removeFileExtension) {
|
|
424
|
+
from = from.replace(/\.(js|ts|mjs|cjs|jsx|tsx)$/, "");
|
|
425
|
+
}
|
|
426
|
+
return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${path}'`;
|
|
427
|
+
}),
|
|
428
|
+
"",
|
|
429
|
+
...customImports,
|
|
430
|
+
"",
|
|
431
|
+
...customContent,
|
|
432
|
+
""
|
|
433
|
+
];
|
|
434
|
+
return {
|
|
435
|
+
content,
|
|
436
|
+
importItems
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async function writeCoreFile(silgi) {
|
|
441
|
+
const data = await prepareFramework(silgi);
|
|
442
|
+
const coreContent = await prepareCoreFile({
|
|
443
|
+
_importItems: data?.importItems ?? {},
|
|
444
|
+
_customImports: data?.customImports ?? []
|
|
445
|
+
}, data?.content ?? [], silgi);
|
|
446
|
+
const configs = await prepareConfigs(silgi);
|
|
447
|
+
const silgiDir = resolve(silgi.options.silgi.serverDir);
|
|
448
|
+
const buildFiles = [];
|
|
449
|
+
buildFiles.push({
|
|
450
|
+
path: join(silgiDir, "core.ts"),
|
|
451
|
+
contents: coreContent.join("\n")
|
|
452
|
+
});
|
|
453
|
+
buildFiles.push({
|
|
454
|
+
path: join(silgiDir, "configs.ts"),
|
|
455
|
+
contents: configs.join("\n")
|
|
456
|
+
});
|
|
457
|
+
for await (const file of buildFiles) {
|
|
458
|
+
if (!silgi.errors.length) {
|
|
459
|
+
await writeFile(
|
|
460
|
+
resolve(silgi.options.build.dir, file.path),
|
|
461
|
+
file.contents
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
async function generateRouterDTS(silgi) {
|
|
468
|
+
const uris = silgi.uris;
|
|
469
|
+
const subPath = "srn";
|
|
470
|
+
const groupedPaths = /* @__PURE__ */ new Map();
|
|
471
|
+
Object.entries(uris || {}).forEach(([key, params]) => {
|
|
472
|
+
const [service, resource, method, action] = key.split("/");
|
|
473
|
+
const basePath = params ? `${subPath}/${service}/${resource}/${action}/${params}` : `${subPath}/${service}/${resource}/${action}`;
|
|
474
|
+
const fullPath = `${subPath}/${service}/${resource}/${action}`;
|
|
475
|
+
if (!groupedPaths.has(basePath)) {
|
|
476
|
+
groupedPaths.set(basePath, /* @__PURE__ */ new Map());
|
|
477
|
+
}
|
|
478
|
+
groupedPaths.get(basePath)?.set(method.toLowerCase(), fullPath);
|
|
479
|
+
});
|
|
480
|
+
const keys = [
|
|
481
|
+
" keys: {",
|
|
482
|
+
Array.from(groupedPaths.entries()).map(([basePath, methods]) => {
|
|
483
|
+
return ` '/${basePath}': {${Array.from(methods.entries()).map(([method, path]) => `
|
|
484
|
+
${method}: '/${path}'`).join(",")}
|
|
485
|
+
}`;
|
|
486
|
+
}).join(",\n"),
|
|
487
|
+
" }",
|
|
488
|
+
""
|
|
489
|
+
].join("\n");
|
|
490
|
+
const groupedRoutes = Object.entries(uris || {}).reduce((acc, [key, _params]) => {
|
|
491
|
+
const [service, resource, method, action] = key.split("/");
|
|
492
|
+
const routePath = `${subPath}/${service}/${resource}/${action}`;
|
|
493
|
+
if (!acc[routePath]) {
|
|
494
|
+
acc[routePath] = {};
|
|
495
|
+
}
|
|
496
|
+
acc[routePath][method] = {
|
|
497
|
+
input: `ExtractInputFromURI<'${key}'>`,
|
|
498
|
+
output: `ExtractOutputFromURI<'${key}'>`,
|
|
499
|
+
queryParams: `ExtractQueryParamsFromURI<'${key}'>`,
|
|
500
|
+
pathParams: `ExtractPathParamsFromURI<'${key}'>`
|
|
501
|
+
};
|
|
502
|
+
return acc;
|
|
503
|
+
}, {});
|
|
504
|
+
const routerTypes = Object.entries(groupedRoutes).map(([path, methods]) => {
|
|
505
|
+
const methodEntries = Object.entries(methods).map(([method, { input, output, queryParams, pathParams }]) => {
|
|
506
|
+
return ` '${method}': {
|
|
507
|
+
input: ${input},
|
|
508
|
+
output: ${output},
|
|
509
|
+
queryParams: ${queryParams},
|
|
510
|
+
pathParams: ${pathParams}
|
|
511
|
+
}`;
|
|
512
|
+
}).join(",\n");
|
|
513
|
+
return ` '/${path}': {
|
|
514
|
+
${methodEntries}
|
|
515
|
+
}`;
|
|
516
|
+
});
|
|
517
|
+
const nitro = [
|
|
518
|
+
"declare module 'nitropack/types' {",
|
|
519
|
+
" interface InternalApi extends RouterTypes {}",
|
|
520
|
+
"}"
|
|
521
|
+
];
|
|
522
|
+
const content = [
|
|
523
|
+
keys.slice(0, -1),
|
|
524
|
+
// son satırdaki boş satırı kaldır
|
|
525
|
+
...routerTypes
|
|
526
|
+
].join(",\n");
|
|
527
|
+
const context = [
|
|
528
|
+
"import type { ExtractInputFromURI, ExtractOutputFromURI, ExtractQueryParamsFromURI, ExtractPathParamsFromURI } from 'silgi/types'",
|
|
529
|
+
"",
|
|
530
|
+
"export interface RouterTypes {",
|
|
531
|
+
content,
|
|
532
|
+
"}",
|
|
533
|
+
"",
|
|
534
|
+
"declare module 'silgi/types' {",
|
|
535
|
+
" interface SilgiRouterTypes extends RouterTypes {",
|
|
536
|
+
" }",
|
|
537
|
+
"}",
|
|
538
|
+
"",
|
|
539
|
+
silgi.options.preset === "h3" || silgi.options.preset === "nitro" ? nitro.join("\n") : "",
|
|
540
|
+
"",
|
|
541
|
+
"export {}"
|
|
542
|
+
];
|
|
543
|
+
return context;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
async function prepareSchema(silgi) {
|
|
547
|
+
const importItems = {
|
|
548
|
+
"silgi/types": {
|
|
549
|
+
import: [
|
|
550
|
+
{
|
|
551
|
+
name: "URIsTypes",
|
|
552
|
+
type: true,
|
|
553
|
+
key: "URIsTypes"
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
name: "Namespaces",
|
|
557
|
+
type: true,
|
|
558
|
+
key: "Namespaces"
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
name: "SilgiRuntimeContext",
|
|
562
|
+
type: true,
|
|
563
|
+
key: "SilgiRuntimeContext"
|
|
564
|
+
}
|
|
565
|
+
],
|
|
566
|
+
from: "silgi/types"
|
|
567
|
+
},
|
|
568
|
+
"silgi/scan": {
|
|
569
|
+
import: [{
|
|
570
|
+
key: "modulesURIs",
|
|
571
|
+
name: "modulesURIs",
|
|
572
|
+
type: false
|
|
573
|
+
}],
|
|
574
|
+
from: relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/scan.ts`)
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
const data = {
|
|
578
|
+
importItems,
|
|
579
|
+
customImports: [],
|
|
580
|
+
options: [],
|
|
581
|
+
contexts: [],
|
|
582
|
+
actions: [],
|
|
583
|
+
shareds: [
|
|
584
|
+
{
|
|
585
|
+
key: "modulesURIs",
|
|
586
|
+
value: "{ modulesURIs: typeof modulesURIs }"
|
|
587
|
+
}
|
|
588
|
+
],
|
|
589
|
+
events: [],
|
|
590
|
+
hooks: [],
|
|
591
|
+
runtimeHooks: [],
|
|
592
|
+
runtimeOptions: [],
|
|
593
|
+
methods: [],
|
|
594
|
+
routeRules: [],
|
|
595
|
+
routeRulesConfig: []
|
|
596
|
+
};
|
|
597
|
+
await silgi.callHook("prepare:schema.ts", data);
|
|
598
|
+
relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/core.ts`);
|
|
599
|
+
const silgiScanTS = relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/scan.ts`);
|
|
600
|
+
let addSilgiContext = false;
|
|
601
|
+
const importsContent = [
|
|
602
|
+
...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
|
|
603
|
+
const path = isAbsolute(from) ? relativeWithDot(silgi.options.build.typesDir, from) : from;
|
|
604
|
+
if (silgi.options.typescript.removeFileExtension) {
|
|
605
|
+
from = from.replace(/\.(js|ts|mjs|cjs|jsx|tsx)$/, "");
|
|
606
|
+
}
|
|
607
|
+
return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${path}'`;
|
|
608
|
+
}),
|
|
609
|
+
"",
|
|
610
|
+
...data.customImports,
|
|
611
|
+
""
|
|
612
|
+
];
|
|
613
|
+
const importData = [
|
|
614
|
+
"interface InferredNamespaces {",
|
|
615
|
+
...(silgi.options.namespaces || []).map((key) => ` ${key}: string,`),
|
|
616
|
+
"}",
|
|
617
|
+
"",
|
|
618
|
+
`type SchemaExtends = Namespaces<typeof import('${silgiScanTS}')['schemas']>`,
|
|
619
|
+
"",
|
|
620
|
+
`type SilgiURIsMerge = URIsTypes<typeof import('${silgiScanTS}')['uris']>`,
|
|
621
|
+
"",
|
|
622
|
+
`type SilgiModuleContextExtends = ${data.contexts.length ? data.contexts.map(({ value }) => value).join(" & ") : "{}"}`,
|
|
623
|
+
"",
|
|
624
|
+
data.events.length ? `interface SilgiModuleEventsExtends extends ${data.events.map((item) => item.extends ? item.value : "").join(", ")} {
|
|
625
|
+
${data.events.map((item) => {
|
|
626
|
+
if (item.isSilgiContext) {
|
|
627
|
+
addSilgiContext = true;
|
|
628
|
+
}
|
|
629
|
+
return !item.extends && !addSilgiContext ? ` ${item.key}: ${item.value}` : item.isSilgiContext ? " context: SilgiRuntimeContext" : "";
|
|
630
|
+
}).join(",\n")}
|
|
631
|
+
}` : "interface SilgiModuleEventsExtends {}",
|
|
632
|
+
"",
|
|
633
|
+
`type RuntimeActionExtends = ${data.actions?.length ? data.actions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
634
|
+
"",
|
|
635
|
+
`type RuntimeMethodExtends = ${data.methods?.length ? data.methods.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
636
|
+
"",
|
|
637
|
+
`type RuntimeRouteRulesExtends = ${data.routeRules?.length ? data.routeRules.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
638
|
+
"",
|
|
639
|
+
`type RuntimeRouteRulesConfigExtends = ${data.routeRulesConfig?.length ? data.routeRulesConfig.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
640
|
+
"",
|
|
641
|
+
`type SilgiModuleSharedExtends = ${data.shareds.length ? data.shareds.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
642
|
+
"",
|
|
643
|
+
`type SilgiModuleOptionExtend = ${data.options?.length ? data.options.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
644
|
+
"",
|
|
645
|
+
`type SilgiRuntimeOptionExtends = ${data.runtimeOptions?.length ? data.runtimeOptions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
646
|
+
"",
|
|
647
|
+
silgi.options.typescript.generateRuntimeConfigTypes ? generateTypes(
|
|
648
|
+
await resolveSchema(
|
|
649
|
+
{
|
|
650
|
+
...Object.fromEntries(
|
|
651
|
+
Object.entries(silgi.options.runtimeConfig).filter(
|
|
652
|
+
([key]) => !["app", "nitro", "nuxt"].includes(key)
|
|
653
|
+
)
|
|
654
|
+
)
|
|
655
|
+
}
|
|
656
|
+
),
|
|
657
|
+
{
|
|
658
|
+
interfaceName: "SilgiRuntimeConfigExtends",
|
|
659
|
+
addExport: false,
|
|
660
|
+
addDefaults: false,
|
|
661
|
+
allowExtraKeys: false,
|
|
662
|
+
indentation: 0
|
|
663
|
+
}
|
|
664
|
+
) : "",
|
|
665
|
+
"",
|
|
666
|
+
generateTypes(
|
|
667
|
+
await resolveSchema(
|
|
668
|
+
{
|
|
669
|
+
...silgi.options.storages?.reduce((acc, key) => ({ ...acc, [key]: "" }), {}) || {},
|
|
670
|
+
// 'redis': {} -> 'redis': string
|
|
671
|
+
...Object.entries(silgi.options.storage).map(([key]) => ({
|
|
672
|
+
[key]: ""
|
|
673
|
+
})).reduce((acc, obj) => ({ ...acc, ...obj }), {})
|
|
674
|
+
}
|
|
675
|
+
),
|
|
676
|
+
{
|
|
677
|
+
interfaceName: "SilgiStorageBaseExtends",
|
|
678
|
+
addExport: false,
|
|
679
|
+
addDefaults: false,
|
|
680
|
+
allowExtraKeys: false,
|
|
681
|
+
indentation: 0
|
|
682
|
+
}
|
|
683
|
+
),
|
|
684
|
+
"",
|
|
685
|
+
`type ModuleHooksExtend = ${data.hooks?.length ? data.hooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
686
|
+
"",
|
|
687
|
+
`type SilgiRuntimeHooksExtends = ${data.runtimeHooks?.length ? data.runtimeHooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
|
|
688
|
+
"",
|
|
689
|
+
"declare module 'silgi/types' {",
|
|
690
|
+
" interface FrameworkContext extends FrameworkContextExtends {}",
|
|
691
|
+
" interface SilgiSchema extends SchemaExtends {}",
|
|
692
|
+
" interface SilgiNamespaces extends InferredNamespaces {}",
|
|
693
|
+
" interface SilgiStorageBase extends SilgiStorageBaseExtends {}",
|
|
694
|
+
" interface SilgiURIs extends SilgiURIsMerge {}",
|
|
695
|
+
" interface SilgiRuntimeContext extends SilgiModuleContextExtends {}",
|
|
696
|
+
" interface SilgiEvents extends SilgiModuleEventsExtends {}",
|
|
697
|
+
" interface SilgiRuntimeSharedsExtend extends SilgiModuleSharedExtends {}",
|
|
698
|
+
" interface SilgiRuntimeActions extends RuntimeActionExtends {}",
|
|
699
|
+
" interface SilgiModuleOptions extends SilgiModuleOptionExtend {}",
|
|
700
|
+
" interface SilgiRuntimeOptions extends SilgiRuntimeOptionExtends {}",
|
|
701
|
+
" interface SilgiRuntimeHooks extends SilgiRuntimeHooksExtends {}",
|
|
702
|
+
" interface SilgiRuntimeConfig extends SilgiRuntimeConfigExtends {}",
|
|
703
|
+
" interface SilgiHooks extends ModuleHooksExtend {}",
|
|
704
|
+
" interface SilgiRuntimeMethods extends RuntimeMethodExtends {}",
|
|
705
|
+
" interface SilgiRuntimeRouteRules extends RuntimeRouteRulesExtends {}",
|
|
706
|
+
" interface SilgiRuntimeRouteRulesConfig extends RuntimeRouteRulesConfigExtends {}",
|
|
707
|
+
" interface SilgiCommands extends SilgiCommandsExtended {}",
|
|
708
|
+
"",
|
|
709
|
+
"}",
|
|
710
|
+
"",
|
|
711
|
+
"export {}"
|
|
712
|
+
];
|
|
713
|
+
await silgi.callHook("after:prepare:schema.ts", importData);
|
|
714
|
+
importData.unshift(...importsContent);
|
|
715
|
+
return importData;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
async function writeTypesAndFiles(silgi) {
|
|
719
|
+
const routerDTS = await generateRouterDTS(silgi);
|
|
720
|
+
silgi.hook("prepare:types", (opts) => {
|
|
721
|
+
opts.references.push({ path: "./schema.d.ts" });
|
|
722
|
+
opts.references.push({ path: "./silgi-routes.d.ts" });
|
|
723
|
+
opts.references.push({ path: "./framework.d.ts" });
|
|
724
|
+
});
|
|
725
|
+
const schemaContent = await prepareSchema(silgi);
|
|
726
|
+
const frameworkDTS = await createDTSFramework(silgi);
|
|
727
|
+
const { declarations, tsConfig } = await silgiGenerateType(silgi);
|
|
728
|
+
const tsConfigPath = resolve(
|
|
729
|
+
silgi.options.rootDir,
|
|
730
|
+
silgi.options.typescript.tsconfigPath
|
|
731
|
+
);
|
|
732
|
+
const typesDir = resolve(silgi.options.build.typesDir);
|
|
733
|
+
let autoImportedTypes = [];
|
|
734
|
+
let autoImportExports = "";
|
|
735
|
+
if (silgi.unimport) {
|
|
736
|
+
await silgi.unimport.init();
|
|
737
|
+
const allImports = await silgi.unimport.getImports();
|
|
738
|
+
autoImportExports = toExports(allImports).replace(
|
|
739
|
+
/#internal\/nitro/g,
|
|
740
|
+
relative(typesDir, runtimeDir)
|
|
741
|
+
);
|
|
742
|
+
const resolvedImportPathMap = /* @__PURE__ */ new Map();
|
|
743
|
+
for (const i of allImports.filter((i2) => !i2.type)) {
|
|
744
|
+
if (resolvedImportPathMap.has(i.from)) {
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
let path = resolveAlias(i.from, silgi.options.alias);
|
|
748
|
+
if (isAbsolute(path)) {
|
|
749
|
+
const resolvedPath = await resolvePath(i.from, {
|
|
750
|
+
url: silgi.options.nodeModulesDirs
|
|
751
|
+
}).catch(() => null);
|
|
752
|
+
if (resolvedPath) {
|
|
753
|
+
const { dir, name } = parseNodeModulePath(resolvedPath);
|
|
754
|
+
if (!dir || !name) {
|
|
755
|
+
path = resolvedPath;
|
|
756
|
+
} else {
|
|
757
|
+
const subpath = await lookupNodeModuleSubpath(resolvedPath);
|
|
758
|
+
path = join(dir, name, subpath || "");
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (existsSync(path) && !await isDirectory(path)) {
|
|
763
|
+
path = path.replace(/\.[a-z]+$/, "");
|
|
764
|
+
}
|
|
765
|
+
if (isAbsolute(path)) {
|
|
766
|
+
path = relative(typesDir, path);
|
|
767
|
+
}
|
|
768
|
+
resolvedImportPathMap.set(i.from, path);
|
|
769
|
+
}
|
|
770
|
+
autoImportedTypes = [
|
|
771
|
+
silgi.options.imports && silgi.options.imports.autoImport !== false ? (await silgi.unimport.generateTypeDeclarations({
|
|
772
|
+
exportHelper: false,
|
|
773
|
+
resolvePath: (i) => resolvedImportPathMap.get(i.from) ?? i.from
|
|
774
|
+
})).trim() : ""
|
|
775
|
+
];
|
|
776
|
+
}
|
|
777
|
+
const buildFiles = [];
|
|
778
|
+
buildFiles.push({
|
|
779
|
+
path: join(typesDir, "silgi-routes.d.ts"),
|
|
780
|
+
contents: routerDTS.join("\n")
|
|
781
|
+
});
|
|
782
|
+
buildFiles.push({
|
|
783
|
+
path: join(typesDir, "silgi-imports.d.ts"),
|
|
784
|
+
contents: [...autoImportedTypes, autoImportExports || "export {}"].join(
|
|
785
|
+
"\n"
|
|
786
|
+
)
|
|
787
|
+
});
|
|
788
|
+
buildFiles.push({
|
|
789
|
+
path: join(typesDir, "schema.d.ts"),
|
|
790
|
+
contents: schemaContent.join("\n")
|
|
791
|
+
});
|
|
792
|
+
buildFiles.push({
|
|
793
|
+
path: join(typesDir, "silgi.d.ts"),
|
|
794
|
+
contents: declarations.join("\n")
|
|
795
|
+
});
|
|
796
|
+
buildFiles.push({
|
|
797
|
+
path: tsConfigPath,
|
|
798
|
+
contents: JSON.stringify(tsConfig, null, 2)
|
|
799
|
+
});
|
|
800
|
+
buildFiles.push({
|
|
801
|
+
path: join(typesDir, "framework.d.ts"),
|
|
802
|
+
contents: frameworkDTS.content.join("\n")
|
|
803
|
+
});
|
|
804
|
+
for await (const file of buildFiles) {
|
|
805
|
+
if (!silgi.errors.length) {
|
|
806
|
+
await writeFile(
|
|
807
|
+
resolve(silgi.options.build.dir, file.path),
|
|
808
|
+
file.contents
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
async function prepareBuild(silgi) {
|
|
815
|
+
try {
|
|
816
|
+
if (!silgi?.routeRules?.exportRules) {
|
|
817
|
+
throw new Error("Invalid silgi configuration: routeRules or exportRules is undefined");
|
|
818
|
+
}
|
|
819
|
+
const exportedRules = silgi.routeRules.exportRules();
|
|
820
|
+
if (!exportedRules || typeof exportedRules !== "object") {
|
|
821
|
+
throw new Error("No valid route rules to export");
|
|
822
|
+
}
|
|
823
|
+
const content = `/* eslint-disable */
|
|
824
|
+
// @ts-nocheck
|
|
825
|
+
// This file is auto-generated at build time by Silgi
|
|
826
|
+
// Contains route rules with preserved functions
|
|
827
|
+
// DO NOT MODIFY THIS FILE DIRECTLY
|
|
828
|
+
|
|
829
|
+
export const routeRules = ${genObjectFromRawEntries(
|
|
830
|
+
Object.entries(exportedRules).map(([key, value]) => {
|
|
831
|
+
if (typeof value === "function") {
|
|
832
|
+
return [key, genObjectFromRaw(value)];
|
|
833
|
+
}
|
|
834
|
+
return [key, genObjectFromValues(value)];
|
|
835
|
+
})
|
|
836
|
+
)}
|
|
837
|
+
`;
|
|
838
|
+
const serverDir = silgi.options.silgi.serverDir;
|
|
839
|
+
if (!serverDir) {
|
|
840
|
+
throw new Error("Server directory not defined in configuration");
|
|
841
|
+
}
|
|
842
|
+
const file = join(serverDir, "rules.ts");
|
|
843
|
+
if (!silgi.errors.length) {
|
|
844
|
+
await writeFile(file, content);
|
|
845
|
+
}
|
|
846
|
+
} catch (error) {
|
|
847
|
+
console.error("\u274C Failed to prepare build:", error instanceof Error ? error.message : String(error));
|
|
848
|
+
throw error;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
async function build(silgi) {
|
|
853
|
+
await prepare();
|
|
854
|
+
await generateApiFul(silgi);
|
|
855
|
+
await writeTypesAndFiles(silgi);
|
|
856
|
+
await writeCoreFile(silgi);
|
|
857
|
+
await prepareBuild(silgi);
|
|
858
|
+
await generateApp(silgi);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
export { build as b, generateApp as g };
|