silgi 0.9.34 → 0.10.0

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.
@@ -1,139 +1,150 @@
1
+ import { watch } from 'chokidar';
1
2
  import { defineCommand } from 'citty';
2
3
  import consola, { consola as consola$1 } from 'consola';
3
- import { resolve, isAbsolute, relative, join, dirname, basename, extname } from 'pathe';
4
+ import { resolve, relative, join, dirname, basename, extname, isAbsolute } from 'pathe';
4
5
  import { peerDependencies, version } from 'silgi/meta';
6
+ import { useSilgiCLI, silgiCLICtx } from 'silgi/core';
7
+ import { h as hasError, a as hasInstalledModule } from './compatibility.mjs';
8
+ import { writeFile, hash, relativeWithDot, resolveAlias, resolvePath, normalizeTemplate, useLogger, addTemplate, applyEnv, hasError as hasError$1, isDirectory } from 'silgi/kit';
5
9
  import { promises, existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
6
- import { readdir } from 'node:fs/promises';
7
- import { resolvePath, parseNodeModulePath, lookupNodeModuleSubpath, resolveModuleExportNames, resolve as resolve$1 } from 'mlly';
8
- import { resolveAlias } from 'pathe/utils';
9
- import { relativeWithDot, hash, isDirectory, writeFile, resolveAlias as resolveAlias$1, resolvePath as resolvePath$1, normalizeTemplate, useLogger, addTemplate, applyEnv } from 'silgi/kit';
10
- import { runtimeDir } from 'silgi/runtime/meta';
11
- import { toExports, scanExports, createUnimport } from 'unimport';
12
10
  import { createJiti } from 'dev-jiti';
13
- import { readPackageJSON } from 'pkg-types';
14
- import { s as silgiGenerateType } from './types.mjs';
15
- import { c as commonArgs } from './common.mjs';
11
+ import { createUnimport, scanExports, toExports } from 'unimport';
12
+ import { readdir, readFile } from 'node:fs/promises';
13
+ import { globby } from 'globby';
14
+ import { withTrailingSlash, isRelative } from 'ufo';
15
+ import ignore from 'ignore';
16
+ import { parseSync } from '@oxc-parser/wasm';
16
17
  import { createHooks, createDebugger } from 'hookable';
17
- import { useSilgiCLI, silgiCLICtx } from 'silgi/core';
18
+ import { runtimeDir } from 'silgi/runtime/meta';
18
19
  import { autoImportTypes } from 'silgi/types';
19
20
  import { p as prepareEnv } from './env.mjs';
21
+ import { resolveModuleExportNames, resolve as resolve$1, resolvePath as resolvePath$1, parseNodeModulePath, lookupNodeModuleSubpath } from 'mlly';
20
22
  import { pascalCase } from 'scule';
21
- import { h as hasInstalledModule } from './compatibility.mjs';
22
23
  import { pathToFileURL, fileURLToPath } from 'node:url';
23
24
  import defu from 'defu';
24
- import { isRelative, withTrailingSlash } from 'ufo';
25
- import { globby } from 'globby';
26
- import ignore from 'ignore';
27
- import { parseSync } from '@oxc-parser/wasm';
28
25
  import { klona } from 'klona';
29
26
  import { createStorage, builtinDrivers } from 'unstorage';
30
27
  import { l as loadOptions } from './loader.mjs';
28
+ import { resolveAlias as resolveAlias$1 } from 'pathe/utils';
29
+ import { s as silgiGenerateType } from './types.mjs';
30
+ import { c as commonArgs } from './common.mjs';
31
+ import 'semver/functions/satisfies.js';
31
32
  import '@clack/prompts';
32
33
  import 'dotenv';
33
- import 'semver/functions/satisfies.js';
34
34
  import 'c12';
35
35
  import 'compatx';
36
36
  import 'klona/full';
37
37
  import 'std-env';
38
38
  import 'consola/utils';
39
39
  import 'escape-string-regexp';
40
+ import 'pkg-types';
40
41
 
41
- async function prepare$1(_silgi) {
42
+ async function prepareServerFiles(silgi) {
43
+ const importItems = {
44
+ "silgi/core": {
45
+ import: [
46
+ { name: "createSilgi", key: "createSilgi" },
47
+ { name: "createShared", key: "createSilgi" }
48
+ ],
49
+ from: "silgi/core"
50
+ },
51
+ "silgi/types": {
52
+ import: [
53
+ { name: "SilgiRuntimeOptions", type: true, key: "SilgiRuntimeOptions" },
54
+ { name: "FrameworkContext", type: true, key: "FrameworkContext" },
55
+ { name: "BuildConfig", type: true, key: "BuildConfig" }
56
+ ],
57
+ from: "silgi/types"
58
+ },
59
+ "#silgi/vfs": {
60
+ import: [],
61
+ from: "./vfs"
62
+ }
63
+ };
64
+ const scanned = {
65
+ uris: [],
66
+ services: [],
67
+ shareds: [],
68
+ schemas: [],
69
+ modulesURIs: [],
70
+ customImports: [],
71
+ importItems
72
+ };
73
+ await silgi.callHook("prepare:scan.ts", scanned);
74
+ if (importItems["#silgi/vfs"].import.length === 0) {
75
+ delete importItems["#silgi/vfs"];
76
+ }
77
+ if (scanned.services.length > 0) {
78
+ importItems["silgi/core"].import.push({ name: "mergeServices", key: "mergeServices" });
79
+ }
80
+ if (scanned.shareds.length > 0) {
81
+ importItems["silgi/core"].import.push({ name: "mergeShared", key: "mergeShared" });
82
+ }
83
+ if (scanned.schemas.length > 0) {
84
+ importItems["silgi/core"].import.push({ name: "mergeSchemas", key: "mergeSchemas" });
85
+ }
86
+ for (const key in importItems) {
87
+ importItems[key].import = deduplicateImportsByKey(importItems[key].import);
88
+ }
89
+ scanned.services = deduplicateArray(scanned.services);
90
+ scanned.schemas = deduplicateArray(scanned.schemas);
91
+ scanned.shareds = deduplicateArray(scanned.shareds);
92
+ const importsContent = [
93
+ ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
94
+ return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${from}'`;
95
+ }),
96
+ "",
97
+ ...scanned.customImports,
98
+ ""
99
+ ];
100
+ const importData = [
101
+ "",
102
+ "export const uris = {}",
103
+ "",
104
+ "export const modulesURIs = {}",
105
+ "",
106
+ scanned.schemas.length > 0 ? "export const schemas = mergeSchemas([" : "export const schemas = {",
107
+ ...scanned.schemas.map((name) => {
108
+ return ` ${name},`;
109
+ }),
110
+ scanned.schemas.length > 0 ? "])" : "}",
111
+ "",
112
+ scanned.services.length > 0 ? "export const services = mergeServices([" : "export const services = {",
113
+ ...scanned.services.map((name) => {
114
+ return ` ${name},`;
115
+ }),
116
+ scanned.services.length > 0 ? "])" : "}",
117
+ "",
118
+ scanned.shareds.length > 0 ? "export const shareds = mergeShared([" : "export const shareds = {",
119
+ ...scanned.shareds.map((name) => {
120
+ return ` ${name},`;
121
+ }),
122
+ scanned.shareds.length > 0 ? "])" : "}",
123
+ ""
124
+ ];
125
+ await silgi.callHook("after:prepare:scan.ts", importData);
126
+ importData.unshift(...importsContent);
127
+ return importData;
42
128
  }
43
-
44
- async function generateSilgiStorageBaseType(silgi) {
45
- silgi.hook("prepare:schema.ts", async (options) => {
46
- if (silgi.options.storage) {
47
- for (const [key, _value] of Object.entries(silgi.options.storage)) {
48
- options.storeBase.push(key);
49
- }
129
+ function deduplicateImportsByKey(imports) {
130
+ const seenKeys = /* @__PURE__ */ new Map();
131
+ return imports.filter((item) => {
132
+ if (seenKeys.has(item.key)) {
133
+ return false;
50
134
  }
135
+ seenKeys.set(item.key, true);
136
+ return true;
51
137
  });
52
138
  }
53
-
54
- async function generateRouterDTS(silgi) {
55
- silgi.hook("finish:types", async (data) => {
56
- const uris = data.object.uris;
57
- const subPath = "srn";
58
- const groupedPaths = /* @__PURE__ */ new Map();
59
- Object.entries(uris || {}).forEach(([key, params]) => {
60
- const [service, resource, method, action] = key.split("/");
61
- const basePath = params ? `${subPath}/${service}/${resource}/${action}/${params}` : `${subPath}/${service}/${resource}/${action}`;
62
- const fullPath = `${subPath}/${service}/${resource}/${action}`;
63
- if (!groupedPaths.has(basePath)) {
64
- groupedPaths.set(basePath, /* @__PURE__ */ new Map());
65
- }
66
- groupedPaths.get(basePath)?.set(method.toLowerCase(), fullPath);
67
- });
68
- const keys = [
69
- " keys: {",
70
- Array.from(groupedPaths.entries()).map(([basePath, methods]) => {
71
- return ` '/${basePath}': {${Array.from(methods.entries()).map(([method, path]) => `
72
- ${method}: '/${path}'`).join(",")}
73
- }`;
74
- }).join(",\n"),
75
- " }",
76
- ""
77
- ].join("\n");
78
- const groupedRoutes = Object.entries(uris || {}).reduce((acc, [key, _params]) => {
79
- const [service, resource, method, action] = key.split("/");
80
- const routePath = `${subPath}/${service}/${resource}/${action}`;
81
- if (!acc[routePath]) {
82
- acc[routePath] = {};
83
- }
84
- acc[routePath][method] = {
85
- input: `ExtractInputFromURI<'${key}'>`,
86
- output: `ExtractOutputFromURI<'${key}'>`,
87
- params: `ExtractRouterParamsFromURI<'${key}'>['params']`
88
- };
89
- return acc;
90
- }, {});
91
- const routerTypes = Object.entries(groupedRoutes).map(([path, methods]) => {
92
- const methodEntries = Object.entries(methods).map(([method, { input, output, params }]) => {
93
- return ` '${method}': {
94
- input: ${input},
95
- output: ${output}
96
- params: ${params}
97
- }`;
98
- }).join(",\n");
99
- return ` '/${path}': {
100
- ${methodEntries}
101
- }`;
102
- });
103
- const nitro = [
104
- "declare module 'nitropack/types' {",
105
- " interface InternalApi extends RouterTypes {}",
106
- "}"
107
- ];
108
- const content = [
109
- keys.slice(0, -1),
110
- // son satırdaki boş satırı kaldır
111
- ...routerTypes
112
- ].join(",\n");
113
- const context = [
114
- "import type { ExtractInputFromURI, ExtractOutputFromURI, ExtractRouterParamsFromURI } from 'silgi/types'",
115
- "",
116
- "export interface RouterTypes {",
117
- content,
118
- "}",
119
- "",
120
- "declare module 'silgi/types' {",
121
- " interface SilgiRouterTypes extends RouterTypes {",
122
- " }",
123
- "}",
124
- "",
125
- silgi.options.preset === "h3" || silgi.options.preset === "nitro" ? nitro.join("\n") : "",
126
- "",
127
- "export {}"
128
- ].join("\n");
129
- const outputPath = resolve(silgi.options.build.typesDir, "silgi-routes.d.ts");
130
- await promises.writeFile(outputPath, context);
131
- });
139
+ function deduplicateArray(array) {
140
+ return [...new Set(array)];
132
141
  }
133
142
 
134
- async function readCoreFile(silgi) {
135
- const path = resolve(silgi.options.silgi.serverDir, "core.ts");
143
+ async function readScanFile(silgi) {
144
+ const path = resolve(silgi.options.silgi.serverDir, "scan.ts");
136
145
  const context = await promises.readFile(path, { encoding: "utf-8" });
146
+ silgi.unimport = createUnimport(silgi.options.imports || {});
147
+ await silgi.unimport.init();
137
148
  const injectedResult = await silgi.unimport.injectImports(context, path);
138
149
  if (!injectedResult) {
139
150
  throw new Error("Failed to inject imports");
@@ -151,7 +162,7 @@ async function readCoreFile(silgi) {
151
162
  ${injectedResult.code}`;
152
163
  injectedResult.code = injectedResult.code.replace(/runtimeConfig: \{\}/, `runtimeConfig: ${JSON.stringify(silgi.options.runtimeConfig)}`);
153
164
  }
154
- const coreFile = await jiti.evalModule(
165
+ const scanFile = await jiti.evalModule(
155
166
  injectedResult.code,
156
167
  {
157
168
  filename: path,
@@ -162,25 +173,25 @@ ${injectedResult.code}`;
162
173
  return (await silgi.unimport.injectImports(data, name)).code;
163
174
  }
164
175
  );
165
- silgi.uris = coreFile.uris;
166
- silgi.schemas = coreFile.schemas;
167
- silgi.services = coreFile.services;
168
- silgi.shareds = coreFile.shareds;
169
- silgi.modulesURIs = coreFile.modulesURIs;
176
+ silgi.uris = scanFile.uris || {};
177
+ silgi.schemas = scanFile.schemas || {};
178
+ silgi.services = scanFile.services || {};
179
+ silgi.shareds = scanFile.shareds || {};
180
+ silgi.modulesURIs = scanFile.modulesURIs || {};
170
181
  return {
171
182
  context,
172
183
  object: {
173
- schemas: coreFile.schemas,
174
- uris: coreFile.uris,
175
- services: coreFile.services,
176
- shareds: coreFile.shareds,
177
- modulesURIs: coreFile.modulesURIs
184
+ schemas: scanFile.schemas,
185
+ uris: scanFile.uris,
186
+ services: scanFile.services,
187
+ shareds: scanFile.shareds,
188
+ modulesURIs: scanFile.modulesURIs
178
189
  },
179
190
  path
180
191
  };
181
192
  } catch (error) {
182
193
  if (silgi.options.debug) {
183
- console.error("Failed to read core.ts file:", error);
194
+ console.error("Failed to read scan.ts file:", error);
184
195
  } else {
185
196
  if (error instanceof Error) {
186
197
  consola.withTag("silgi").error(error.message);
@@ -271,7 +282,7 @@ function scanActionModulesUris(silgi, obj, currentPath = []) {
271
282
  }
272
283
 
273
284
  async function scanUris(silgi) {
274
- const { context, object, path } = await readCoreFile(silgi);
285
+ const { context, object, path } = await readScanFile(silgi);
275
286
  const uriMap = traverseObject(silgi, object.schemas, []);
276
287
  const modulesURIs = scanActionModulesUris(silgi, object.services, []);
277
288
  const uriContent = Array.from(uriMap.entries()).map(([uri, params]) => ` '${uri}': '${params}',`).join("\n");
@@ -290,479 +301,404 @@ ${uriContent}
290
301
  newContext = context;
291
302
  }
292
303
  await promises.writeFile(path, newContext);
304
+ await readScanFile(silgi);
293
305
  }
294
306
 
295
- async function createCoreFramework(silgi) {
296
- const relativeRootDir = relativeWithDot(silgi.options.rootDir, silgi.options.serverDir);
297
- const importItems = {
298
- "silgi/types": {
299
- import: [
300
- { name: "SilgiRuntimeContext", type: true }
301
- ],
302
- from: "silgi/types"
303
- }
304
- };
305
- await Promise.all([...silgi.options.modules, ...silgi.options._modules].map(async (id) => {
306
- if (typeof id !== "string") {
307
- return;
308
- }
309
- const pkg = await readPackageJSON(id, { url: silgi.options.modulesDir }).catch(() => null);
310
- if (!pkg?.name) {
311
- return;
312
- }
313
- if (importItems[pkg.name]) {
314
- importItems[pkg.name].from = isAbsolute(id) ? relativeWithDot(relativeRootDir, id) : id;
315
- }
316
- }));
317
- const customImports = [];
318
- const functions = [];
319
- await silgi.callHook("prepare:createCoreFramework", {
320
- importItems,
321
- customImports,
322
- functions
323
- });
324
- const content = [
325
- ...functions.map((f) => f.params?.length ? ` await ${f.name}(framework, ${f.params.join(",")})` : ` await ${f.name}(framework)`)
326
- ];
327
- return {
328
- content,
329
- importItems,
330
- customImports
331
- };
307
+ async function writeScanFiles(silgi) {
308
+ const data = await prepareServerFiles(silgi);
309
+ await writeFile(
310
+ resolve(silgi.options.silgi.serverDir, "scan.ts"),
311
+ data.join("\n")
312
+ );
313
+ await scanUris(silgi);
332
314
  }
333
- async function createDTSFramework(silgi) {
334
- const relativeRootDir = relativeWithDot(silgi.options.rootDir, silgi.options.serverDir);
335
- const importItems = {
336
- "silgi/types": {
337
- import: [
338
- { name: "SilgiRuntimeContext", type: true }
339
- ],
340
- from: "silgi/types"
341
- }
342
- };
343
- await Promise.all([...silgi.options.modules, ...silgi.options._modules].map(async (id) => {
344
- if (typeof id !== "string") {
345
- return;
346
- }
347
- const pkg = await readPackageJSON(id, { url: silgi.options.modulesDir }).catch(() => null);
348
- if (!pkg?.name) {
349
- return;
350
- }
351
- if (importItems[pkg.name]) {
352
- importItems[pkg.name].from = isAbsolute(id) ? relativeWithDot(relativeRootDir, id) : id;
353
- }
354
- }));
355
- const customImports = [];
356
- const customContent = [];
357
- await silgi.callHook("prepare:createDTSFramework", {
358
- importItems,
359
- customImports,
360
- customContent
361
- });
362
- const content = [
363
- ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
364
- const path = isAbsolute(from) ? relativeWithDot(silgi.options.build.typesDir, from) : from;
365
- return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${path}'`;
366
- }),
367
- "",
368
- ...customImports,
369
- "",
370
- ...customContent,
371
- ""
372
- ];
373
- return {
374
- content,
375
- importItems
376
- };
315
+
316
+ function resolveIgnorePatterns(silgi, relativePath) {
317
+ if (!silgi) {
318
+ return [];
319
+ }
320
+ const ignorePatterns = silgi.options.ignore.flatMap((s) => resolveGroupSyntax(s));
321
+ const nuxtignoreFile = join(silgi.options.rootDir, ".nuxtignore");
322
+ if (existsSync(nuxtignoreFile)) {
323
+ const contents = readFileSync(nuxtignoreFile, "utf-8");
324
+ ignorePatterns.push(...contents.trim().split(/\r?\n/));
325
+ }
326
+ return ignorePatterns;
327
+ }
328
+ function isIgnored(pathname, silgi, _stats) {
329
+ if (!silgi) {
330
+ return false;
331
+ }
332
+ if (!silgi._ignore) {
333
+ silgi._ignore = ignore(silgi.options.ignoreOptions);
334
+ silgi._ignore.add(resolveIgnorePatterns(silgi));
335
+ }
336
+ const relativePath = relative(silgi.options.rootDir, pathname);
337
+ if (relativePath[0] === "." && relativePath[1] === ".") {
338
+ return false;
339
+ }
340
+ return !!(relativePath && silgi._ignore.ignores(relativePath));
341
+ }
342
+ function resolveGroupSyntax(group) {
343
+ let groups = [group];
344
+ while (groups.some((group2) => group2.includes("{"))) {
345
+ groups = groups.flatMap((group2) => {
346
+ const [head, ...tail] = group2.split("{");
347
+ if (tail.length) {
348
+ const [body = "", ...rest] = tail.join("{").split("}");
349
+ return body.split(",").map((part) => `${head}${part}${rest.join("")}`);
350
+ }
351
+ return group2;
352
+ });
353
+ }
354
+ return groups;
377
355
  }
378
356
 
379
- async function schemaTemplate(silgi) {
380
- const relativeRootDir = relativeWithDot(silgi.options.rootDir, silgi.options.serverDir);
381
- const importItems = {
382
- "silgi/types": {
383
- import: [
384
- { name: "URIsTypes", type: true },
385
- { name: "Namespaces", type: true },
386
- { name: "SilgiRuntimeContext", type: true }
387
- ],
388
- from: "silgi/types"
389
- }
357
+ class SchemaParser {
358
+ options = {
359
+ debug: false
390
360
  };
391
- await Promise.all([...silgi.options.modules, ...silgi.options._modules].map(async (id) => {
392
- if (typeof id !== "string") {
393
- return;
394
- }
395
- const pkg = await readPackageJSON(id, { url: silgi.options.modulesDir }).catch(() => null);
396
- if (!pkg?.name) {
397
- return;
361
+ /**
362
+ *
363
+ */
364
+ constructor(options) {
365
+ this.options = {
366
+ ...this.options,
367
+ ...options
368
+ };
369
+ }
370
+ parseExports(content, filePath) {
371
+ const ast = parseSync(content, { sourceType: "module", sourceFilename: filePath });
372
+ if (this.options.debug)
373
+ writeFileSync(`${filePath}.ast.json`, JSON.stringify(ast.program, null, 2));
374
+ return {
375
+ exportVariables: (search, path) => this.parseTypeDeclarations(ast, search, path),
376
+ parseInterfaceDeclarations: (search, path) => this.parseInterfaceDeclarations(ast, search, path)
377
+ // parsePlugin: (path: string) => this.parsePlugin(ast, path),
378
+ };
379
+ }
380
+ parseVariableDeclaration(ast, path) {
381
+ const silgi = useSilgiCLI();
382
+ if (ast.program.body.length === 0) {
383
+ silgi.errors.push({
384
+ type: "Parser",
385
+ path
386
+ });
387
+ consola.warn("This file has a problem:", path);
398
388
  }
399
- if (importItems[pkg.name]) {
400
- importItems[pkg.name].from = isAbsolute(id) ? relativeWithDot(relativeRootDir, id) : id;
389
+ const variableDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "VariableDeclaration");
390
+ return variableDeclarations;
391
+ }
392
+ parseTSInterfaceDeclaration(ast, path = "") {
393
+ const silgi = useSilgiCLI();
394
+ if (ast.program.body.length === 0) {
395
+ silgi.errors.push({
396
+ type: "Parser",
397
+ path
398
+ });
399
+ consola.warn("This file has a problem:", path);
401
400
  }
402
- }));
403
- const data = {
404
- importItems,
405
- customImports: [],
406
- options: [],
407
- contexts: [],
408
- actions: [],
409
- shareds: [],
410
- events: [],
411
- storeBase: [],
412
- hooks: [],
413
- runtimeHooks: [],
414
- runtimeOptions: [],
415
- methods: []
416
- };
417
- const storeBase = [];
418
- await silgi.callHook("prepare:schema.ts", data);
419
- const silgiExport = relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/core.ts`);
420
- let addSilgiContext = false;
421
- const importsContent = [
422
- ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
423
- const path = isAbsolute(from) ? relativeWithDot(silgi.options.build.typesDir, from) : from;
424
- return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${path}'`;
425
- }),
426
- "",
427
- ...data.customImports,
428
- ""
429
- ];
430
- const importData = [
431
- "interface InferredNamespaces {",
432
- ...(silgi.options.namespaces || []).map((key) => ` ${key}: string,`),
433
- "}",
434
- "",
435
- `type SchemaExtends = Namespaces<typeof import('${silgiExport}')['schemas']>`,
436
- "",
437
- `type SilgiURIsMerge = URIsTypes<typeof import('${silgiExport}')['uris']>`,
438
- "",
439
- `type SilgiModuleContextExtends = ${data.contexts.length ? data.contexts.map(({ value }) => value).join(" & ") : "{}"}`,
440
- "",
441
- data.events.length ? `interface SilgiModuleEventsExtends extends ${data.events.map((item) => item.extends ? item.value : "").join(", ")} {
442
- ${data.events.map((item) => {
443
- if (item.isSilgiContext) {
444
- addSilgiContext = true;
445
- }
446
- return !item.extends && !addSilgiContext ? ` ${item.key}: ${item.value}` : item.isSilgiContext ? " context: SilgiRuntimeContext" : "";
447
- }).join(",\n")}
448
- }` : "interface SilgiModuleEventsExtends {}",
449
- "",
450
- `type RuntimeActionExtends = ${data.actions?.length ? data.actions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
451
- "",
452
- `type RuntimeMethodExtends = ${data.methods?.length ? data.methods.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
453
- "",
454
- `type SilgiModuleSharedExtends = ${data.shareds.length ? data.shareds.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
455
- "",
456
- `type SilgiModuleOptionExtend = ${data.options?.length ? data.options.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
457
- "",
458
- `type SilgiRuntimeOptionExtends = ${data.runtimeOptions?.length ? data.runtimeOptions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
459
- "",
460
- "interface SilgiStorageBaseExtends {",
461
- ...(storeBase || []).map((value) => ` ${value}: ''`),
462
- "}",
463
- "",
464
- `type ModuleHooksExtend = ${data.hooks?.length ? data.hooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
465
- "",
466
- `type SilgiRuntimeHooksExtends = ${data.runtimeHooks?.length ? data.runtimeHooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
467
- "",
468
- "declare module 'silgi/types' {",
469
- " interface FrameworkContext extends FrameworkContextExtends {}",
470
- " interface SilgiSchema extends SchemaExtends {}",
471
- " interface SilgiNamespaces extends InferredNamespaces {}",
472
- " interface SilgiStorageBase extends SilgiStorageBaseExtends {}",
473
- " interface SilgiURIs extends SilgiURIsMerge {}",
474
- " interface SilgiRuntimeContext extends SilgiModuleContextExtends {}",
475
- " interface SilgiEvents extends SilgiModuleEventsExtends {}",
476
- " interface SilgiRuntimeShareds extends SilgiModuleSharedExtends {}",
477
- " interface SilgiRuntimeActions extends RuntimeActionExtends {}",
478
- " interface SilgiModuleOptions extends SilgiModuleOptionExtend {}",
479
- " interface SilgiRuntimeOptions extends SilgiRuntimeOptionExtends {}",
480
- " interface SilgiRuntimeHooks extends SilgiRuntimeHooksExtends {}",
481
- " interface SilgiHooks extends ModuleHooksExtend {}",
482
- " interface SilgiRuntimeMethods extends RuntimeMethodExtends {}",
483
- "}",
484
- "",
485
- "export {}"
486
- ];
487
- await silgi.callHook("after:prepare:schema.ts", importData);
488
- importData.unshift(...importsContent);
489
- return importData;
490
- }
491
-
492
- async function silgiCoreFile(data, frameworkContext, silgi) {
493
- const relativeRootDir = relativeWithDot(silgi.options.rootDir, silgi.options.serverDir);
494
- let importItems = {
495
- "silgi/core": {
496
- import: [
497
- { name: "createSilgi" },
498
- { name: "createShared" }
499
- ],
500
- from: "silgi/core"
501
- },
502
- "silgi/types": {
503
- import: [
504
- { name: "SilgiRuntimeOptions", type: true },
505
- { name: "FrameworkContext", type: true },
506
- { name: "BuildConfig", type: true }
507
- ],
508
- from: "silgi/types"
509
- },
510
- "#silgi/vfs": {
511
- import: [],
512
- from: "./vfs"
513
- },
514
- "silgi/runtime/internal/defu": {
515
- import: [
516
- {
517
- name: "mergeDeep"
401
+ const interfaceDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "TSInterfaceDeclaration");
402
+ return interfaceDeclarations;
403
+ }
404
+ parseTypeDeclarations(ast, find = "", path = "") {
405
+ const data = [];
406
+ const variableDeclarations = this.parseVariableDeclaration(ast, path);
407
+ for (const item of variableDeclarations) {
408
+ for (const declaration of item.declaration.declarations) {
409
+ if (declaration.init?.callee?.name === find) {
410
+ const options = {};
411
+ if (declaration.init.arguments) {
412
+ for (const argument of declaration.init.arguments) {
413
+ for (const propertie of argument.properties) {
414
+ if (propertie.key.name === "name")
415
+ options.pluginName = propertie.value.value;
416
+ }
417
+ }
418
+ }
419
+ for (const key in declaration.init.properties) {
420
+ const property = declaration.init.properties[key];
421
+ if (property.type === "ObjectProperty") {
422
+ if (property.key.name === "options") {
423
+ for (const key2 in property.value.properties) {
424
+ const option = property.value.properties[key2];
425
+ if (option.type === "ObjectProperty") {
426
+ options[option.key.name] = option.value.value;
427
+ }
428
+ }
429
+ }
430
+ }
431
+ }
432
+ options.type = false;
433
+ data.push({
434
+ exportName: declaration.id.name,
435
+ options,
436
+ // object: declaration.init,
437
+ path
438
+ });
518
439
  }
519
- ],
520
- from: "silgi/runtime/internal/defu"
521
- }
522
- };
523
- importItems = { ...data._importItems, ...importItems };
524
- await Promise.all([...silgi.options.modules, ...silgi.options._modules].map(async (id) => {
525
- if (typeof id !== "string") {
526
- return;
527
- }
528
- const pkg = await readPackageJSON(id, { url: silgi.options.modulesDir }).catch(() => null);
529
- if (!pkg?.name) {
530
- return;
531
- }
532
- if (importItems[pkg.name]) {
533
- importItems[pkg.name].from = isAbsolute(id) ? relativeWithDot(relativeRootDir, id) : id;
534
- }
535
- }));
536
- const _data = {
537
- customImports: data._customImports || [],
538
- uris: [],
539
- services: [],
540
- shareds: [],
541
- schemas: [],
542
- buildSilgiExtraContent: [],
543
- beforeBuildSilgiExtraContent: [],
544
- cliOptions: {},
545
- afterCliOptions: [],
546
- _silgiConfigs: [],
547
- customContent: [],
548
- importItems
549
- };
550
- for (const module of silgi.scanModules) {
551
- if (module.meta.cliToRuntimeOptionsKeys && module.meta.cliToRuntimeOptionsKeys?.length > 0) {
552
- for (const key of module.meta.cliToRuntimeOptionsKeys) {
553
- _data.cliOptions[module.meta.configKey] = {
554
- ..._data.cliOptions[module.meta.configKey],
555
- [key]: module.options[key]
556
- };
557
440
  }
558
- } else {
559
- _data.cliOptions[module.meta.configKey] = {};
560
441
  }
442
+ return data;
561
443
  }
562
- await silgi.callHook("prepare:core.ts", _data);
563
- if (importItems["#silgi/vfs"].import.length === 0) {
564
- delete importItems["#silgi/vfs"];
565
- }
566
- if (_data.services.length > 0) {
567
- importItems["silgi/core"].import.push({ name: "mergeServices" });
568
- }
569
- if (_data.shareds.length > 0) {
570
- importItems["silgi/core"].import.push({ name: "mergeShared" });
571
- }
572
- if (_data.schemas.length > 0) {
573
- importItems["silgi/core"].import.push({ name: "mergeSchemas" });
574
- }
575
- const plugins = [];
576
- for (const plugin of silgi.options.plugins) {
577
- const pluginImportName = `_${hash(plugin.packageImport)}`;
578
- _data.customImports.push(`import ${pluginImportName} from '${plugin.packageImport}'`);
579
- plugins.push(pluginImportName);
444
+ parseInterfaceDeclarations(ast, find = "", path = "") {
445
+ const data = [];
446
+ for (const item of this.parseTSInterfaceDeclaration(ast, path)) {
447
+ if (!item?.declaration?.extends)
448
+ continue;
449
+ for (const declaration of item?.declaration?.extends) {
450
+ if (declaration.expression.name === find) {
451
+ const options = {};
452
+ options.type = true;
453
+ data.push({
454
+ exportName: item.declaration.id.name,
455
+ options,
456
+ // object: declaration.init,
457
+ path
458
+ });
459
+ }
460
+ }
461
+ }
462
+ return data;
580
463
  }
581
- const importsContent = [
582
- ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
583
- return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${from}'`;
584
- }),
585
- "",
586
- ..._data.customImports,
587
- ""
588
- ];
589
- const importData = [
590
- `export const cliOptions: SilgiRuntimeOptions = ${JSON.stringify(_data.cliOptions, null, 2)}`,
591
- "",
592
- ..._data.afterCliOptions,
593
- "",
594
- "export const uris = {}",
595
- "",
596
- "export const modulesURIs = {}",
597
- "",
598
- _data.schemas.length > 0 ? "export const schemas = mergeSchemas([" : "export const schemas = {",
599
- ..._data.schemas.map((name) => {
600
- return ` ${name},`;
601
- }),
602
- _data.schemas.length > 0 ? "])" : "}",
603
- "",
604
- _data.services.length > 0 ? "export const services = mergeServices([" : "export const services = {",
605
- ..._data.services.map((name) => {
606
- return ` ${name},`;
607
- }),
608
- _data.services.length > 0 ? "])" : "}",
609
- "",
610
- _data.shareds.length > 0 ? "export const shareds = mergeShared([" : "export const shareds = {",
611
- ..._data.shareds.map((name) => {
612
- return ` ${name},`;
613
- }),
614
- _data.shareds.length > 0 ? "])" : "}",
615
- "",
616
- "export async function buildSilgi(framework: FrameworkContext, moduleOptions?: Partial<SilgiRuntimeOptions>,buildOptions?: Partial<BuildConfig>) {",
617
- "",
618
- _data.beforeBuildSilgiExtraContent.length > 0 ? _data.beforeBuildSilgiExtraContent.map(({ value, type }) => {
619
- return type === "function" ? value : `const ${value}`;
620
- }) : "",
621
- "",
622
- " const silgi = await createSilgi({",
623
- " framework,",
624
- " shared: shareds as any,",
625
- " services: services as any,",
626
- " schemas: schemas as any,",
627
- " uris,",
628
- " modulesURIs,",
629
- ` plugins: [${plugins.join(", ")}],`,
630
- _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 ")},` : "",
631
- " runtimeConfig: {},",
632
- " ...buildOptions,",
633
- " options: mergeDeep(",
634
- " moduleOptions || {},",
635
- " {",
636
- ` present: '${silgi.options.preset}',`,
637
- " ...cliOptions,",
638
- " },",
639
- " ) as any,",
640
- " })",
641
- "",
642
- ...frameworkContext,
643
- "",
644
- ..._data.buildSilgiExtraContent,
645
- "",
646
- " return silgi",
647
- "}",
648
- ""
649
- ];
650
- await silgi.callHook("after:prepare:core.ts", importData);
651
- importData.unshift(...importsContent);
652
- return importData;
464
+ // private parsePlugin(ast: any, path: string = '') {
465
+ // const data = {
466
+ // export: [],
467
+ // name: '',
468
+ // path: '',
469
+ // } as DataTypePlugin
470
+ // for (const item of this.parseVariableDeclaration(ast)) {
471
+ // for (const declaration of item.declaration.declarations) {
472
+ // if (declaration.init.callee?.name === 'defineSilgiModule') {
473
+ // if (declaration.init.arguments) {
474
+ // for (const argument of declaration.init.arguments) {
475
+ // for (const propertie of argument.properties) {
476
+ // if (propertie.key.name === 'name')
477
+ // data.name = propertie.value.value
478
+ // }
479
+ // }
480
+ // }
481
+ // data.export.push({
482
+ // name: data.name,
483
+ // as: camelCase(`${data.name}DefineSilgiModule`),
484
+ // type: false,
485
+ // })
486
+ // }
487
+ // }
488
+ // }
489
+ // for (const item of this.parseTSInterfaceDeclaration(ast)) {
490
+ // if (!item?.declaration?.extends)
491
+ // continue
492
+ // for (const declaration of item?.declaration?.extends) {
493
+ // if (declaration.expression.name === 'ModuleOptions') {
494
+ // data.export.push({
495
+ // name: item.declaration.id.name,
496
+ // as: camelCase(`${data.name}ModuleOptions`),
497
+ // type: true,
498
+ // })
499
+ // }
500
+ // // TODO add other plugins
501
+ // }
502
+ // }
503
+ // data.path = path
504
+ // return data
505
+ // }
653
506
  }
654
507
 
655
- async function writeTypesAndFiles(silgi) {
656
- const data = await createCoreFramework(silgi);
657
- await generateSilgiStorageBaseType(silgi);
658
- await generateRouterDTS(silgi);
659
- silgi.hook("prepare:types", (opts) => {
660
- opts.references.push({ path: "./schema.d.ts" });
661
- opts.references.push({ path: "./silgi-routes.d.ts" });
662
- opts.references.push({ path: "./framework.d.ts" });
663
- });
664
- const schemaContent = await schemaTemplate(silgi);
665
- const coreContent = await silgiCoreFile({
666
- _importItems: data?.importItems ?? {},
667
- _customImports: data?.customImports ?? []
668
- }, data?.content ?? [], silgi);
669
- const frameworkDTS = await createDTSFramework(silgi);
670
- const { declarations, tsConfig } = await silgiGenerateType(silgi);
671
- const tsConfigPath = resolve(
672
- silgi.options.rootDir,
673
- silgi.options.typescript.tsconfigPath
674
- );
675
- const typesDir = resolve(silgi.options.build.typesDir);
676
- const silgiDir = resolve(silgi.options.silgi.serverDir);
677
- let autoImportedTypes = [];
678
- let autoImportExports = "";
679
- if (silgi.unimport) {
680
- await silgi.unimport.init();
681
- const allImports = await silgi.unimport.getImports();
682
- autoImportExports = toExports(allImports).replace(
683
- /#internal\/nitro/g,
684
- relative(typesDir, runtimeDir)
685
- );
686
- const resolvedImportPathMap = /* @__PURE__ */ new Map();
687
- for (const i of allImports.filter((i2) => !i2.type)) {
688
- if (resolvedImportPathMap.has(i.from)) {
689
- continue;
508
+ async function scanFiles$1(silgi, watchFiles) {
509
+ const isWatch = watchFiles && watchFiles.length > 0;
510
+ const filePaths = /* @__PURE__ */ new Set();
511
+ const scannedPaths = [];
512
+ const dir = silgi.options.serverDir;
513
+ const files = isWatch ? watchFiles : (await globby(dir, { cwd: silgi.options.rootDir, ignore: silgi.options.ignore })).sort();
514
+ if (files.length) {
515
+ const siblings = await readdir(dirname(dir)).catch(() => []);
516
+ const directory = basename(dir);
517
+ if (!siblings.includes(directory)) {
518
+ const directoryLowerCase = directory.toLowerCase();
519
+ const caseCorrected = siblings.find((sibling) => sibling.toLowerCase() === directoryLowerCase);
520
+ if (caseCorrected) {
521
+ const original = relative(silgi.options.serverDir, dir);
522
+ const corrected = relative(silgi.options.serverDir, join(dirname(dir), caseCorrected));
523
+ consola$1.warn(`Components not scanned from \`~/${corrected}\`. Did you mean to name the directory \`~/${original}\` instead?`);
690
524
  }
691
- let path = resolveAlias(i.from, silgi.options.alias);
692
- if (isAbsolute(path)) {
693
- const resolvedPath = await resolvePath(i.from, {
694
- url: silgi.options.nodeModulesDirs
695
- }).catch(() => null);
696
- if (resolvedPath) {
697
- const { dir, name } = parseNodeModulePath(resolvedPath);
698
- if (!dir || !name) {
699
- path = resolvedPath;
700
- } else {
701
- const subpath = await lookupNodeModuleSubpath(resolvedPath);
702
- path = join(dir, name, subpath || "");
703
- }
525
+ }
526
+ }
527
+ for (const _file of files) {
528
+ const filePath = resolve(dir, _file);
529
+ if (scannedPaths.find((d) => filePath.startsWith(withTrailingSlash(d))) || isIgnored(filePath, silgi)) {
530
+ continue;
531
+ }
532
+ if (filePaths.has(filePath)) {
533
+ continue;
534
+ }
535
+ filePaths.add(filePath);
536
+ if (silgi.options.extensions.includes(extname(filePath))) {
537
+ const parser = new SchemaParser({
538
+ debug: false
539
+ });
540
+ const readfile = await readFile(filePath, "utf-8");
541
+ const { exportVariables, parseInterfaceDeclarations } = parser.parseExports(readfile, filePath);
542
+ const createServices = exportVariables("createService", filePath);
543
+ if (hasError("Parser", silgi)) {
544
+ return;
545
+ }
546
+ if (createServices.length > 0) {
547
+ for (const createService of createServices) {
548
+ const { exportName, path } = createService;
549
+ silgi.options.devServer.watch.push(path);
550
+ const randomString = hash(basename(path) + exportName);
551
+ const _name = `_v${randomString}`;
552
+ silgi.hook("prepare:scan.ts", (options) => {
553
+ options.services.push(_name);
554
+ });
555
+ silgi.hook("prepare:scan.ts", (options) => {
556
+ options.importItems[path] ??= {
557
+ import: [],
558
+ from: relativeWithDot(silgi.options.silgi.serverDir, path)
559
+ };
560
+ options.importItems[path].import.push({
561
+ name: `${exportName} as ${_name}`,
562
+ key: _name
563
+ });
564
+ });
704
565
  }
705
566
  }
706
- if (existsSync(path) && !await isDirectory(path)) {
707
- path = path.replace(/\.[a-z]+$/, "");
567
+ const createSchemas = exportVariables("createSchema", filePath);
568
+ if (hasError("Parser", silgi)) {
569
+ return;
708
570
  }
709
- if (isAbsolute(path)) {
710
- path = relative(typesDir, path);
571
+ if (createSchemas.length > 0) {
572
+ for (const createSchema of createSchemas) {
573
+ const { exportName, path } = createSchema;
574
+ silgi.options.devServer.watch.push(path);
575
+ const randomString = hash(basename(path) + exportName);
576
+ const _name = `_v${randomString}`;
577
+ silgi.hook("prepare:scan.ts", (options) => {
578
+ options.schemas.push(_name);
579
+ });
580
+ silgi.hook("prepare:scan.ts", (options) => {
581
+ options.importItems[path] ??= {
582
+ import: [],
583
+ from: relativeWithDot(silgi.options.silgi.serverDir, path)
584
+ };
585
+ options.importItems[path].import.push({
586
+ name: `${exportName} as ${_name}`,
587
+ key: _name
588
+ });
589
+ });
590
+ }
711
591
  }
712
- resolvedImportPathMap.set(i.from, path);
713
- }
714
- autoImportedTypes = [
715
- silgi.options.imports && silgi.options.imports.autoImport !== false ? (await silgi.unimport.generateTypeDeclarations({
716
- exportHelper: false,
717
- resolvePath: (i) => resolvedImportPathMap.get(i.from) ?? i.from
718
- })).trim() : ""
719
- ];
720
- }
721
- const buildFiles = [];
722
- buildFiles.push({
723
- path: join(typesDir, "silgi-routes.d.ts"),
724
- // contents: uris.join('\n'),
725
- contents: ""
726
- });
727
- buildFiles.push({
728
- path: join(silgiDir, "core.ts"),
729
- contents: coreContent.join("\n")
730
- });
731
- buildFiles.push({
732
- path: join(typesDir, "schema.d.ts"),
733
- contents: schemaContent.join("\n")
734
- });
735
- buildFiles.push({
736
- path: join(typesDir, "silgi-imports.d.ts"),
737
- contents: [...autoImportedTypes, autoImportExports || "export {}"].join(
738
- "\n"
739
- )
740
- });
741
- buildFiles.push({
742
- path: join(typesDir, "silgi.d.ts"),
743
- contents: declarations.join("\n")
744
- });
745
- buildFiles.push({
746
- path: tsConfigPath,
747
- contents: JSON.stringify(tsConfig, null, 2)
748
- });
749
- buildFiles.push({
750
- path: join(typesDir, "framework.d.ts"),
751
- contents: frameworkDTS.content.join("\n")
752
- });
753
- for await (const file of buildFiles) {
754
- await writeFile(
755
- resolve(silgi.options.build.dir, file.path),
756
- file.contents
757
- );
592
+ const createShareds = exportVariables("createShared", filePath);
593
+ if (hasError("Parser", silgi)) {
594
+ return;
595
+ }
596
+ if (createShareds.length > 0) {
597
+ for (const createShared of createShareds) {
598
+ const { exportName, path } = createShared;
599
+ silgi.options.devServer.watch.push(path);
600
+ const randomString = hash(basename(path) + exportName);
601
+ const _name = `_v${randomString}`;
602
+ silgi.hook("prepare:scan.ts", (options) => {
603
+ options.shareds.push(_name);
604
+ });
605
+ silgi.hook("prepare:scan.ts", (options) => {
606
+ options.importItems[path] ??= {
607
+ import: [],
608
+ // Relative path kaldirmamiz gerekiyor bunlar hooklarin bittigi yerde karar verilmeli.
609
+ from: relativeWithDot(silgi.options.silgi.serverDir, path)
610
+ };
611
+ options.importItems[path].import.push({
612
+ name: `${exportName} as ${_name}`,
613
+ key: _name
614
+ });
615
+ });
616
+ }
617
+ }
618
+ const sharedsTypes = parseInterfaceDeclarations("ExtendShared", filePath);
619
+ if (hasError("Parser", silgi)) {
620
+ return;
621
+ }
622
+ if (sharedsTypes.length > 0) {
623
+ for (const sharedType of sharedsTypes) {
624
+ const { exportName, path } = sharedType;
625
+ silgi.options.devServer.watch.push(path);
626
+ const randomString = hash(basename(path) + exportName);
627
+ const _name = `_v${randomString}`;
628
+ silgi.hook("prepare:schema.ts", (options) => {
629
+ options.shareds.push({
630
+ key: _name,
631
+ value: _name
632
+ });
633
+ });
634
+ silgi.hook("prepare:schema.ts", (options) => {
635
+ options.importItems[path] ??= {
636
+ import: [],
637
+ from: path
638
+ };
639
+ options.importItems[path].import.push({
640
+ name: `${exportName} as ${_name}`,
641
+ type: true,
642
+ key: _name
643
+ });
644
+ });
645
+ }
646
+ }
647
+ const contextTypes = parseInterfaceDeclarations("ExtendContext", filePath);
648
+ if (hasError("Parser", silgi)) {
649
+ return;
650
+ }
651
+ if (contextTypes.length > 0) {
652
+ for (const contextType of contextTypes) {
653
+ const { exportName, path } = contextType;
654
+ silgi.options.devServer.watch.push(path);
655
+ const randomString = hash(basename(path) + exportName);
656
+ const _name = `_v${randomString}`;
657
+ silgi.hook("prepare:schema.ts", (options) => {
658
+ options.contexts.push({
659
+ key: _name,
660
+ value: _name
661
+ });
662
+ });
663
+ silgi.hook("prepare:schema.ts", (options) => {
664
+ options.importItems[path] ??= {
665
+ import: [],
666
+ from: path
667
+ };
668
+ options.importItems[path].import.push({
669
+ name: `${exportName} as ${_name}`,
670
+ type: true,
671
+ key: _name
672
+ });
673
+ });
674
+ }
675
+ }
676
+ }
758
677
  }
759
- await scanUris(silgi);
760
- const readCore = await readCoreFile(silgi);
761
- silgi.uris = readCore.object.uris;
762
- silgi.modulesURIs = readCore.object.modulesURIs;
763
- silgi.schemas = readCore.object.schemas;
764
- silgi.shareds = readCore.object.shareds;
765
- await silgi.hooks.callHook("finish:types", readCore);
678
+ }
679
+
680
+ async function reloadScan(silgi, path, _stats) {
681
+ const startTime = performance.now();
682
+ silgi.errors = [];
683
+ if (silgiCLICtx.tryUse()) {
684
+ silgiCLICtx.unset();
685
+ silgiCLICtx.set(silgi);
686
+ } else {
687
+ silgiCLICtx.set(silgi);
688
+ silgi.hook("close", () => silgiCLICtx.unset());
689
+ }
690
+ silgi.hooks.removeAllHooks();
691
+ await scanFiles$1(silgi, silgi.options.devServer.watch);
692
+ if (!hasError("Parser", silgi)) {
693
+ await writeScanFiles(silgi);
694
+ }
695
+ silgi.errors = [];
696
+ const endTime = performance.now();
697
+ const elapsedTime = Math.round(endTime - startTime);
698
+ silgi.logger.success(`${basename(path)} - ${elapsedTime}ms`);
699
+ }
700
+
701
+ async function prepare$1(_silgi) {
766
702
  }
767
703
 
768
704
  async function emptyFramework(silgi) {
@@ -1013,592 +949,273 @@ async function registerModuleExportScan(silgi) {
1013
949
  options.hooks.push({ key: configKey, value: importName });
1014
950
  }
1015
951
  if (exportedTypes.includes("ModuleRuntimeHooks")) {
1016
- const importName = pascalCase(`${configKey}RuntimeHooks`);
1017
- options.importItems[configKey].import.push({
1018
- name: `ModuleRuntimeHooks as ${importName}`,
1019
- type: true
1020
- });
1021
- options.runtimeHooks.push({ key: configKey, value: importName });
1022
- }
1023
- if (exportedTypes.includes("ModuleRuntimeOptions")) {
1024
- const importName = pascalCase(`${configKey}RuntimeOptions`);
1025
- options.importItems[configKey].import.push({
1026
- name: `ModuleRuntimeOptions as ${importName}`,
1027
- type: true
1028
- });
1029
- options.runtimeOptions.push({ key: configKey, value: importName });
1030
- }
1031
- if (exportedTypes.includes("SilgiRuntimeMethods")) {
1032
- const importName = pascalCase(`${configKey}RuntimeMethods`);
1033
- options.importItems[configKey].import.push({
1034
- name: `SilgiRuntimeMethods as ${importName}`,
1035
- type: true
1036
- });
1037
- options.methods.push({ key: configKey, value: importName });
1038
- }
1039
- }
1040
- });
1041
- }
1042
-
1043
- async function loadSilgiModuleInstance(silgiModule) {
1044
- if (typeof silgiModule === "string") {
1045
- throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
1046
- }
1047
- if (typeof silgiModule !== "function") {
1048
- throw new TypeError(`Nuxt module should be a function: ${silgiModule}`);
1049
- }
1050
- return { silgiModule };
1051
- }
1052
- async function installModules(silgi) {
1053
- const jiti = createJiti(silgi.options.rootDir, {
1054
- alias: silgi.options.alias
1055
- });
1056
- for (const module of silgi.scanModules) {
1057
- if (hasInstalledModule(module.meta.configKey)) {
1058
- silgi.logger.info(`Module ${module.meta.configKey} installed`);
1059
- }
1060
- try {
1061
- const silgiModule = await jiti.import(module.entryPath, {
1062
- default: true,
1063
- conditions: silgi.options.conditions
1064
- });
1065
- if (silgiModule.name !== "silgiNormalizedModule") {
1066
- silgi.scanModules = silgi.scanModules.filter((m) => m.entryPath !== module.entryPath);
1067
- continue;
1068
- }
1069
- await installModule(silgiModule, silgi);
1070
- } catch (err) {
1071
- silgi.logger.error(err);
1072
- }
1073
- }
1074
- }
1075
- async function installModule(moduleToInstall, silgi = useSilgiCLI(), inlineOptions) {
1076
- const { silgiModule } = await loadSilgiModuleInstance(moduleToInstall);
1077
- const res = await silgiModule({}, silgi) ?? {};
1078
- if (res === false) {
1079
- return false;
1080
- }
1081
- const metaData = await silgiModule.getMeta?.();
1082
- const installedModule = silgi.scanModules.find((m) => m.meta.configKey === metaData?.configKey);
1083
- if (installedModule) {
1084
- installedModule.installed = true;
1085
- } else {
1086
- throw new Error(`Module ${metaData?.name} not found`);
1087
- }
1088
- }
1089
-
1090
- const logger$1 = consola$1;
1091
- async function _resolveSilgiModule(mod, silgi) {
1092
- let _url;
1093
- let buildTimeModuleMeta = {};
1094
- const jiti = createJiti(silgi.options.rootDir, {
1095
- alias: silgi.options.alias
1096
- });
1097
- if (typeof mod === "string") {
1098
- const paths = /* @__PURE__ */ new Set();
1099
- mod = resolveAlias$1(mod, silgi.options.alias);
1100
- if (isRelative(mod)) {
1101
- mod = resolve(silgi.options.rootDir, mod);
1102
- }
1103
- paths.add(join(mod, "module"));
1104
- paths.add(mod);
1105
- for (const path of paths) {
1106
- try {
1107
- const src = isAbsolute(path) ? pathToFileURL(await resolvePath$1(path, { fallbackToOriginal: false, extensions: silgi.options.extensions })).href : await resolve$1(path, { url: silgi.options.modulesDir.map((m) => pathToFileURL(m.replace(/\/node_modules\/?$/, ""))), extensions: silgi.options.extensions });
1108
- mod = await jiti.import(src, {
1109
- default: true,
1110
- conditions: silgi.options.conditions
1111
- });
1112
- _url = fileURLToPath(new URL(src));
1113
- const moduleMetadataPath = new URL("module.json", src);
1114
- if (existsSync(moduleMetadataPath)) {
1115
- buildTimeModuleMeta = JSON.parse(await promises.readFile(moduleMetadataPath, "utf-8"));
1116
- } else {
1117
- if (typeof mod === "function") {
1118
- const meta = await mod.getMeta?.();
1119
- const _exports = await scanExports(_url, true);
1120
- buildTimeModuleMeta = {
1121
- ...meta,
1122
- exports: _exports.map(({ from, ...rest }) => rest)
1123
- };
1124
- }
1125
- }
1126
- break;
1127
- } catch (error) {
1128
- const code = error.code;
1129
- if (code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNSUPPORTED_DIR_IMPORT" || code === "ENOTDIR") {
1130
- continue;
1131
- }
1132
- logger$1.error(`Error while importing module \`${mod}\`: ${error}`);
1133
- throw error;
1134
- }
1135
- }
1136
- }
1137
- if (!buildTimeModuleMeta) {
1138
- throw new Error(`Module ${mod} is not a valid Silgi module`);
1139
- }
1140
- if (typeof mod === "function") {
1141
- if (silgi.scanModules.some((m) => m.meta?.configKey === buildTimeModuleMeta.configKey)) {
1142
- throw new Error(`Module with key \`${buildTimeModuleMeta.configKey}\` already exists`);
1143
- }
1144
- const options = await mod.getOptions?.() || {};
1145
- if (options) {
1146
- silgi.options._c12.config[buildTimeModuleMeta.configKey] = defu(
1147
- silgi.options._c12.config[buildTimeModuleMeta.configKey] || {},
1148
- options || {}
1149
- );
1150
- }
1151
- silgi.scanModules.push({
1152
- meta: buildTimeModuleMeta,
1153
- entryPath: _url,
1154
- installed: false,
1155
- options
1156
- });
1157
- }
1158
- }
1159
- async function scanModules$1(silgi) {
1160
- const _modules = [
1161
- ...silgi.options._modules,
1162
- ...silgi.options.modules
1163
- ];
1164
- for await (const mod of _modules) {
1165
- await _resolveSilgiModule(mod, silgi);
1166
- }
1167
- const moduleMap = new Map(
1168
- silgi.scanModules.map((m) => [m.meta?.configKey, m])
1169
- );
1170
- const graphData = createDependencyGraph(silgi.scanModules);
1171
- const sortedKeys = topologicalSort(graphData);
1172
- const modules = sortedKeys.map((key) => moduleMap.get(key)).filter((module) => Boolean(module));
1173
- silgi.scanModules = modules;
1174
- }
1175
- function createDependencyGraph(modules) {
1176
- const graph = /* @__PURE__ */ new Map();
1177
- const inDegree = /* @__PURE__ */ new Map();
1178
- modules.forEach((module) => {
1179
- const key = module.meta?.configKey;
1180
- if (key) {
1181
- graph.set(key, /* @__PURE__ */ new Set());
1182
- inDegree.set(key, 0);
1183
- }
1184
- });
1185
- modules.forEach((module) => {
1186
- const key = module.meta?.configKey;
1187
- if (!key) {
1188
- return;
1189
- }
1190
- const requiredDeps = module.meta?.requiredDependencies || [];
1191
- const beforeDeps = module.meta?.beforeDependencies || [];
1192
- const afterDeps = module.meta?.afterDependencies || [];
1193
- const processedDeps = /* @__PURE__ */ new Set();
1194
- requiredDeps.forEach((dep) => {
1195
- if (!graph.has(dep)) {
1196
- throw new Error(`Required dependency "${dep}" for module "${key}" is missing`);
1197
- }
1198
- graph.get(dep)?.add(key);
1199
- inDegree.set(key, (inDegree.get(key) || 0) + 1);
1200
- processedDeps.add(dep);
1201
- });
1202
- beforeDeps.forEach((dep) => {
1203
- if (!graph.has(dep)) {
1204
- return;
1205
- }
1206
- graph.get(key)?.add(dep);
1207
- inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
1208
- });
1209
- afterDeps.forEach((dep) => {
1210
- if (processedDeps.has(dep)) {
1211
- return;
1212
- }
1213
- if (!graph.has(dep)) {
1214
- return;
1215
- }
1216
- graph.get(dep)?.add(key);
1217
- inDegree.set(key, (inDegree.get(key) || 0) + 1);
1218
- });
1219
- });
1220
- return { graph, inDegree };
1221
- }
1222
- function findCyclicDependencies(graph) {
1223
- const visited = /* @__PURE__ */ new Set();
1224
- const recursionStack = /* @__PURE__ */ new Set();
1225
- const cycles = [];
1226
- function dfs(node, path = []) {
1227
- visited.add(node);
1228
- recursionStack.add(node);
1229
- path.push(node);
1230
- for (const neighbor of graph.get(node) || []) {
1231
- if (recursionStack.has(neighbor)) {
1232
- const cycleStart = path.indexOf(neighbor);
1233
- if (cycleStart !== -1) {
1234
- cycles.push([...path.slice(cycleStart), neighbor]);
1235
- }
1236
- } else if (!visited.has(neighbor)) {
1237
- dfs(neighbor, [...path]);
952
+ const importName = pascalCase(`${configKey}RuntimeHooks`);
953
+ options.importItems[configKey].import.push({
954
+ name: `ModuleRuntimeHooks as ${importName}`,
955
+ type: true
956
+ });
957
+ options.runtimeHooks.push({ key: configKey, value: importName });
1238
958
  }
1239
- }
1240
- recursionStack.delete(node);
1241
- path.pop();
1242
- }
1243
- for (const node of graph.keys()) {
1244
- if (!visited.has(node)) {
1245
- dfs(node, []);
1246
- }
1247
- }
1248
- return cycles;
1249
- }
1250
- function topologicalSort(graphData) {
1251
- const { graph, inDegree } = graphData;
1252
- const order = [];
1253
- const queue = [];
1254
- for (const [node, degree] of inDegree.entries()) {
1255
- if (degree === 0) {
1256
- queue.push(node);
1257
- }
1258
- }
1259
- while (queue.length > 0) {
1260
- const node = queue.shift();
1261
- order.push(node);
1262
- const neighbors = Array.from(graph.get(node) || []);
1263
- for (const neighbor of neighbors) {
1264
- const newDegree = (inDegree.get(neighbor) || 0) - 1;
1265
- inDegree.set(neighbor, newDegree);
1266
- if (newDegree === 0) {
1267
- queue.push(neighbor);
959
+ if (exportedTypes.includes("ModuleRuntimeOptions")) {
960
+ const importName = pascalCase(`${configKey}RuntimeOptions`);
961
+ options.importItems[configKey].import.push({
962
+ name: `ModuleRuntimeOptions as ${importName}`,
963
+ type: true
964
+ });
965
+ options.runtimeOptions.push({ key: configKey, value: importName });
966
+ }
967
+ if (exportedTypes.includes("SilgiRuntimeMethods")) {
968
+ const importName = pascalCase(`${configKey}RuntimeMethods`);
969
+ options.importItems[configKey].import.push({
970
+ name: `SilgiRuntimeMethods as ${importName}`,
971
+ type: true
972
+ });
973
+ options.methods.push({ key: configKey, value: importName });
1268
974
  }
1269
975
  }
1270
- }
1271
- if (order.length !== graph.size) {
1272
- const cycles = findCyclicDependencies(graph);
1273
- if (cycles.length > 0) {
1274
- const cycleStr = cycles.map((cycle) => ` ${cycle.join(" -> ")}`).join("\n");
1275
- throw new Error(`Circular dependencies detected:
1276
- ${cycleStr}`);
1277
- } else {
1278
- const unresolvedModules = Array.from(graph.keys()).filter((key) => !order.includes(key));
1279
- throw new Error(`Unable to resolve dependencies for modules: ${unresolvedModules.join(", ")}`);
1280
- }
1281
- }
1282
- return order;
976
+ });
1283
977
  }
1284
978
 
1285
- function resolveIgnorePatterns(silgi, relativePath) {
1286
- if (!silgi) {
1287
- return [];
1288
- }
1289
- const ignorePatterns = silgi.options.ignore.flatMap((s) => resolveGroupSyntax(s));
1290
- const nuxtignoreFile = join(silgi.options.rootDir, ".nuxtignore");
1291
- if (existsSync(nuxtignoreFile)) {
1292
- const contents = readFileSync(nuxtignoreFile, "utf-8");
1293
- ignorePatterns.push(...contents.trim().split(/\r?\n/));
1294
- }
1295
- return ignorePatterns;
1296
- }
1297
- function isIgnored(pathname, silgi, _stats) {
1298
- if (!silgi) {
1299
- return false;
1300
- }
1301
- if (!silgi._ignore) {
1302
- silgi._ignore = ignore(silgi.options.ignoreOptions);
1303
- silgi._ignore.add(resolveIgnorePatterns(silgi));
1304
- }
1305
- const relativePath = relative(silgi.options.rootDir, pathname);
1306
- if (relativePath[0] === "." && relativePath[1] === ".") {
1307
- return false;
979
+ async function loadSilgiModuleInstance(silgiModule) {
980
+ if (typeof silgiModule === "string") {
981
+ throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
1308
982
  }
1309
- return !!(relativePath && silgi._ignore.ignores(relativePath));
1310
- }
1311
- function resolveGroupSyntax(group) {
1312
- let groups = [group];
1313
- while (groups.some((group2) => group2.includes("{"))) {
1314
- groups = groups.flatMap((group2) => {
1315
- const [head, ...tail] = group2.split("{");
1316
- if (tail.length) {
1317
- const [body = "", ...rest] = tail.join("{").split("}");
1318
- return body.split(",").map((part) => `${head}${part}${rest.join("")}`);
1319
- }
1320
- return group2;
1321
- });
983
+ if (typeof silgiModule !== "function") {
984
+ throw new TypeError(`Nuxt module should be a function: ${silgiModule}`);
1322
985
  }
1323
- return groups;
986
+ return { silgiModule };
1324
987
  }
1325
-
1326
- class SchemaParser {
1327
- options = {
1328
- debug: false
1329
- };
1330
- /**
1331
- *
1332
- */
1333
- constructor(options) {
1334
- this.options = {
1335
- ...this.options,
1336
- ...options
1337
- };
1338
- }
1339
- parseExports(content, filePath) {
1340
- const ast = parseSync(content, { sourceType: "module", sourceFilename: filePath });
1341
- if (this.options.debug)
1342
- writeFileSync(`${filePath}.ast.json`, JSON.stringify(ast.program, null, 2));
1343
- return {
1344
- exportVariables: (search, path) => this.parseTypeDeclarations(ast, search, path),
1345
- parseInterfaceDeclarations: (search, path) => this.parseInterfaceDeclarations(ast, search, path)
1346
- // parsePlugin: (path: string) => this.parsePlugin(ast, path),
1347
- };
1348
- }
1349
- parseVariableDeclaration(ast) {
1350
- return ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "VariableDeclaration");
1351
- }
1352
- parseTSInterfaceDeclaration(ast) {
1353
- return ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "TSInterfaceDeclaration");
1354
- }
1355
- parseTypeDeclarations(ast, find = "", path = "") {
1356
- const data = [];
1357
- for (const item of this.parseVariableDeclaration(ast)) {
1358
- for (const declaration of item.declaration.declarations) {
1359
- if (declaration.init?.callee?.name === find) {
1360
- const options = {};
1361
- if (declaration.init.arguments) {
1362
- for (const argument of declaration.init.arguments) {
1363
- for (const propertie of argument.properties) {
1364
- if (propertie.key.name === "name")
1365
- options.pluginName = propertie.value.value;
1366
- }
1367
- }
1368
- }
1369
- for (const key in declaration.init.properties) {
1370
- const property = declaration.init.properties[key];
1371
- if (property.type === "ObjectProperty") {
1372
- if (property.key.name === "options") {
1373
- for (const key2 in property.value.properties) {
1374
- const option = property.value.properties[key2];
1375
- if (option.type === "ObjectProperty") {
1376
- options[option.key.name] = option.value.value;
1377
- }
1378
- }
1379
- }
1380
- }
1381
- }
1382
- options.type = false;
1383
- data.push({
1384
- exportName: declaration.id.name,
1385
- options,
1386
- // object: declaration.init,
1387
- path
1388
- });
1389
- }
1390
- }
988
+ async function installModules(silgi) {
989
+ const jiti = createJiti(silgi.options.rootDir, {
990
+ alias: silgi.options.alias
991
+ });
992
+ for (const module of silgi.scanModules) {
993
+ if (hasInstalledModule(module.meta.configKey)) {
994
+ silgi.logger.info(`Module ${module.meta.configKey} installed`);
1391
995
  }
1392
- return data;
1393
- }
1394
- parseInterfaceDeclarations(ast, find = "", path = "") {
1395
- const data = [];
1396
- for (const item of this.parseTSInterfaceDeclaration(ast)) {
1397
- if (!item?.declaration?.extends)
996
+ try {
997
+ const silgiModule = await jiti.import(module.entryPath, {
998
+ default: true,
999
+ conditions: silgi.options.conditions
1000
+ });
1001
+ if (silgiModule.name !== "silgiNormalizedModule") {
1002
+ silgi.scanModules = silgi.scanModules.filter((m) => m.entryPath !== module.entryPath);
1398
1003
  continue;
1399
- for (const declaration of item?.declaration?.extends) {
1400
- if (declaration.expression.name === find) {
1401
- const options = {};
1402
- options.type = true;
1403
- data.push({
1404
- exportName: item.declaration.id.name,
1405
- options,
1406
- // object: declaration.init,
1407
- path
1408
- });
1409
- }
1410
1004
  }
1005
+ await installModule(silgiModule, silgi);
1006
+ } catch (err) {
1007
+ silgi.logger.error(err);
1411
1008
  }
1412
- return data;
1413
1009
  }
1414
- // private parsePlugin(ast: any, path: string = '') {
1415
- // const data = {
1416
- // export: [],
1417
- // name: '',
1418
- // path: '',
1419
- // } as DataTypePlugin
1420
- // for (const item of this.parseVariableDeclaration(ast)) {
1421
- // for (const declaration of item.declaration.declarations) {
1422
- // if (declaration.init.callee?.name === 'defineSilgiModule') {
1423
- // if (declaration.init.arguments) {
1424
- // for (const argument of declaration.init.arguments) {
1425
- // for (const propertie of argument.properties) {
1426
- // if (propertie.key.name === 'name')
1427
- // data.name = propertie.value.value
1428
- // }
1429
- // }
1430
- // }
1431
- // data.export.push({
1432
- // name: data.name,
1433
- // as: camelCase(`${data.name}DefineSilgiModule`),
1434
- // type: false,
1435
- // })
1436
- // }
1437
- // }
1438
- // }
1439
- // for (const item of this.parseTSInterfaceDeclaration(ast)) {
1440
- // if (!item?.declaration?.extends)
1441
- // continue
1442
- // for (const declaration of item?.declaration?.extends) {
1443
- // if (declaration.expression.name === 'ModuleOptions') {
1444
- // data.export.push({
1445
- // name: item.declaration.id.name,
1446
- // as: camelCase(`${data.name}ModuleOptions`),
1447
- // type: true,
1448
- // })
1449
- // }
1450
- // // TODO add other plugins
1451
- // }
1452
- // }
1453
- // data.path = path
1454
- // return data
1455
- // }
1010
+ }
1011
+ async function installModule(moduleToInstall, silgi = useSilgiCLI(), inlineOptions) {
1012
+ const { silgiModule } = await loadSilgiModuleInstance(moduleToInstall);
1013
+ const res = await silgiModule({}, silgi) ?? {};
1014
+ if (res === false) {
1015
+ return false;
1016
+ }
1017
+ const metaData = await silgiModule.getMeta?.();
1018
+ const installedModule = silgi.scanModules.find((m) => m.meta.configKey === metaData?.configKey);
1019
+ if (installedModule) {
1020
+ installedModule.installed = true;
1021
+ } else {
1022
+ throw new Error(`Module ${metaData?.name} not found`);
1023
+ }
1456
1024
  }
1457
1025
 
1458
- async function scanFiles$1(silgi) {
1459
- const filePaths = /* @__PURE__ */ new Set();
1460
- const scannedPaths = [];
1461
- const dir = silgi.options.serverDir;
1462
- const files = (await globby(dir, { cwd: silgi.options.rootDir, ignore: silgi.options.ignore })).sort();
1463
- if (files.length) {
1464
- const siblings = await readdir(dirname(dir)).catch(() => []);
1465
- const directory = basename(dir);
1466
- if (!siblings.includes(directory)) {
1467
- const directoryLowerCase = directory.toLowerCase();
1468
- const caseCorrected = siblings.find((sibling) => sibling.toLowerCase() === directoryLowerCase);
1469
- if (caseCorrected) {
1470
- const original = relative(silgi.options.serverDir, dir);
1471
- const corrected = relative(silgi.options.serverDir, join(dirname(dir), caseCorrected));
1472
- consola$1.warn(`Components not scanned from \`~/${corrected}\`. Did you mean to name the directory \`~/${original}\` instead?`);
1026
+ const logger$1 = consola$1;
1027
+ async function _resolveSilgiModule(mod, silgi) {
1028
+ let _url;
1029
+ let buildTimeModuleMeta = {};
1030
+ const jiti = createJiti(silgi.options.rootDir, {
1031
+ alias: silgi.options.alias
1032
+ });
1033
+ if (typeof mod === "string") {
1034
+ const paths = /* @__PURE__ */ new Set();
1035
+ mod = resolveAlias(mod, silgi.options.alias);
1036
+ if (isRelative(mod)) {
1037
+ mod = resolve(silgi.options.rootDir, mod);
1038
+ }
1039
+ paths.add(join(mod, "module"));
1040
+ paths.add(mod);
1041
+ for (const path of paths) {
1042
+ try {
1043
+ const src = isAbsolute(path) ? pathToFileURL(await resolvePath(path, { fallbackToOriginal: false, extensions: silgi.options.extensions })).href : await resolve$1(path, { url: silgi.options.modulesDir.map((m) => pathToFileURL(m.replace(/\/node_modules\/?$/, ""))), extensions: silgi.options.extensions });
1044
+ mod = await jiti.import(src, {
1045
+ default: true,
1046
+ conditions: silgi.options.conditions
1047
+ });
1048
+ _url = fileURLToPath(new URL(src));
1049
+ const moduleMetadataPath = new URL("module.json", src);
1050
+ if (existsSync(moduleMetadataPath)) {
1051
+ buildTimeModuleMeta = JSON.parse(await promises.readFile(moduleMetadataPath, "utf-8"));
1052
+ } else {
1053
+ if (typeof mod === "function") {
1054
+ const meta = await mod.getMeta?.();
1055
+ const _exports = await scanExports(_url, true);
1056
+ buildTimeModuleMeta = {
1057
+ ...meta,
1058
+ exports: _exports.map(({ from, ...rest }) => rest)
1059
+ };
1060
+ }
1061
+ }
1062
+ break;
1063
+ } catch (error) {
1064
+ const code = error.code;
1065
+ if (code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNSUPPORTED_DIR_IMPORT" || code === "ENOTDIR") {
1066
+ continue;
1067
+ }
1068
+ logger$1.error(`Error while importing module \`${mod}\`: ${error}`);
1069
+ throw error;
1473
1070
  }
1474
1071
  }
1475
1072
  }
1476
- for (const _file of files) {
1477
- const filePath = resolve(dir, _file);
1478
- if (scannedPaths.find((d) => filePath.startsWith(withTrailingSlash(d))) || isIgnored(filePath, silgi)) {
1479
- continue;
1073
+ if (!buildTimeModuleMeta) {
1074
+ throw new Error(`Module ${mod} is not a valid Silgi module`);
1075
+ }
1076
+ if (typeof mod === "function") {
1077
+ if (silgi.scanModules.some((m) => m.meta?.configKey === buildTimeModuleMeta.configKey)) {
1078
+ throw new Error(`Module with key \`${buildTimeModuleMeta.configKey}\` already exists`);
1480
1079
  }
1481
- if (filePaths.has(filePath)) {
1482
- continue;
1080
+ const options = await mod.getOptions?.() || {};
1081
+ if (options) {
1082
+ silgi.options._c12.config[buildTimeModuleMeta.configKey] = defu(
1083
+ silgi.options._c12.config[buildTimeModuleMeta.configKey] || {},
1084
+ options || {}
1085
+ );
1483
1086
  }
1484
- filePaths.add(filePath);
1485
- if (silgi.options.extensions.includes(extname(filePath))) {
1486
- const parser = new SchemaParser({
1487
- debug: false
1488
- });
1489
- const readfile = readFileSync(filePath, "utf-8");
1490
- const { exportVariables, parseInterfaceDeclarations } = parser.parseExports(readfile, filePath);
1491
- const createServices = exportVariables("createService", filePath);
1492
- if (createServices.length > 0) {
1493
- for (const createService of createServices) {
1494
- const { exportName, path } = createService;
1495
- const randomString = hash(basename(path) + exportName);
1496
- const _name = `_v${randomString}`;
1497
- silgi.hook("prepare:core.ts", (options) => {
1498
- options.services.push(_name);
1499
- });
1500
- silgi.hook("prepare:core.ts", (options) => {
1501
- options.importItems[path] ??= {
1502
- import: [],
1503
- from: relativeWithDot(silgi.options.silgi.serverDir, path)
1504
- };
1505
- options.importItems[path].import.push({
1506
- name: `${exportName} as ${_name}`
1507
- });
1508
- });
1509
- }
1087
+ silgi.scanModules.push({
1088
+ meta: buildTimeModuleMeta,
1089
+ entryPath: _url,
1090
+ installed: false,
1091
+ options
1092
+ });
1093
+ }
1094
+ }
1095
+ async function scanModules$1(silgi) {
1096
+ const _modules = [
1097
+ ...silgi.options._modules,
1098
+ ...silgi.options.modules
1099
+ ];
1100
+ for await (const mod of _modules) {
1101
+ await _resolveSilgiModule(mod, silgi);
1102
+ }
1103
+ const moduleMap = new Map(
1104
+ silgi.scanModules.map((m) => [m.meta?.configKey, m])
1105
+ );
1106
+ const graphData = createDependencyGraph(silgi.scanModules);
1107
+ const sortedKeys = topologicalSort(graphData);
1108
+ const modules = sortedKeys.map((key) => moduleMap.get(key)).filter((module) => Boolean(module));
1109
+ silgi.scanModules = modules;
1110
+ }
1111
+ function createDependencyGraph(modules) {
1112
+ const graph = /* @__PURE__ */ new Map();
1113
+ const inDegree = /* @__PURE__ */ new Map();
1114
+ modules.forEach((module) => {
1115
+ const key = module.meta?.configKey;
1116
+ if (key) {
1117
+ graph.set(key, /* @__PURE__ */ new Set());
1118
+ inDegree.set(key, 0);
1119
+ }
1120
+ });
1121
+ modules.forEach((module) => {
1122
+ const key = module.meta?.configKey;
1123
+ if (!key) {
1124
+ return;
1125
+ }
1126
+ const requiredDeps = module.meta?.requiredDependencies || [];
1127
+ const beforeDeps = module.meta?.beforeDependencies || [];
1128
+ const afterDeps = module.meta?.afterDependencies || [];
1129
+ const processedDeps = /* @__PURE__ */ new Set();
1130
+ requiredDeps.forEach((dep) => {
1131
+ if (!graph.has(dep)) {
1132
+ throw new Error(`Required dependency "${dep}" for module "${key}" is missing`);
1510
1133
  }
1511
- const createSchemas = exportVariables("createSchema", filePath);
1512
- if (createSchemas.length > 0) {
1513
- for (const createSchema of createSchemas) {
1514
- const { exportName, path } = createSchema;
1515
- const randomString = hash(basename(path) + exportName);
1516
- const _name = `_v${randomString}`;
1517
- silgi.hook("prepare:core.ts", (options) => {
1518
- options.schemas.push(_name);
1519
- });
1520
- silgi.hook("prepare:core.ts", (options) => {
1521
- options.importItems[path] ??= {
1522
- import: [],
1523
- from: relativeWithDot(silgi.options.silgi.serverDir, path)
1524
- };
1525
- options.importItems[path].import.push({
1526
- name: `${exportName} as ${_name}`
1527
- });
1528
- });
1529
- }
1134
+ graph.get(dep)?.add(key);
1135
+ inDegree.set(key, (inDegree.get(key) || 0) + 1);
1136
+ processedDeps.add(dep);
1137
+ });
1138
+ beforeDeps.forEach((dep) => {
1139
+ if (!graph.has(dep)) {
1140
+ return;
1530
1141
  }
1531
- const createShareds = exportVariables("createShared", filePath);
1532
- if (createShareds.length > 0) {
1533
- for (const createShared of createShareds) {
1534
- const { exportName, path } = createShared;
1535
- const randomString = hash(basename(path) + exportName);
1536
- const _name = `_v${randomString}`;
1537
- silgi.hook("prepare:core.ts", (options) => {
1538
- options.shareds.push(_name);
1539
- });
1540
- silgi.hook("prepare:core.ts", (options) => {
1541
- options.importItems[path] ??= {
1542
- import: [],
1543
- // Relative path kaldirmamiz gerekiyor bunlar hooklarin bittigi yerde karar verilmeli.
1544
- from: relativeWithDot(silgi.options.silgi.serverDir, path)
1545
- };
1546
- options.importItems[path].import.push({
1547
- name: `${exportName} as ${_name}`
1548
- });
1549
- });
1550
- }
1142
+ graph.get(key)?.add(dep);
1143
+ inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
1144
+ });
1145
+ afterDeps.forEach((dep) => {
1146
+ if (processedDeps.has(dep)) {
1147
+ return;
1551
1148
  }
1552
- const sharedsTypes = parseInterfaceDeclarations("ExtendShared", filePath);
1553
- if (sharedsTypes.length > 0) {
1554
- for (const sharedType of sharedsTypes) {
1555
- const { exportName, path } = sharedType;
1556
- const randomString = hash(basename(path) + exportName);
1557
- const _name = `_v${randomString}`;
1558
- silgi.hook("prepare:schema.ts", (options) => {
1559
- options.shareds.push({
1560
- key: _name,
1561
- value: _name
1562
- });
1563
- });
1564
- silgi.hook("prepare:schema.ts", (options) => {
1565
- options.importItems[path] ??= {
1566
- import: [],
1567
- from: path
1568
- };
1569
- options.importItems[path].import.push({
1570
- name: `${exportName} as ${_name}`,
1571
- type: true
1572
- });
1573
- });
1574
- }
1149
+ if (!graph.has(dep)) {
1150
+ return;
1575
1151
  }
1576
- const contextTypes = parseInterfaceDeclarations("ExtendContext", filePath);
1577
- if (contextTypes.length > 0) {
1578
- for (const contextType of contextTypes) {
1579
- const { exportName, path } = contextType;
1580
- const randomString = hash(basename(path) + exportName);
1581
- const _name = `_v${randomString}`;
1582
- silgi.hook("prepare:schema.ts", (options) => {
1583
- options.contexts.push({
1584
- key: _name,
1585
- value: _name
1586
- });
1587
- });
1588
- silgi.hook("prepare:schema.ts", (options) => {
1589
- options.importItems[path] ??= {
1590
- import: [],
1591
- from: path
1592
- };
1593
- options.importItems[path].import.push({
1594
- name: `${exportName} as ${_name}`,
1595
- type: true
1596
- });
1597
- });
1152
+ graph.get(dep)?.add(key);
1153
+ inDegree.set(key, (inDegree.get(key) || 0) + 1);
1154
+ });
1155
+ });
1156
+ return { graph, inDegree };
1157
+ }
1158
+ function findCyclicDependencies(graph) {
1159
+ const visited = /* @__PURE__ */ new Set();
1160
+ const recursionStack = /* @__PURE__ */ new Set();
1161
+ const cycles = [];
1162
+ function dfs(node, path = []) {
1163
+ visited.add(node);
1164
+ recursionStack.add(node);
1165
+ path.push(node);
1166
+ for (const neighbor of graph.get(node) || []) {
1167
+ if (recursionStack.has(neighbor)) {
1168
+ const cycleStart = path.indexOf(neighbor);
1169
+ if (cycleStart !== -1) {
1170
+ cycles.push([...path.slice(cycleStart), neighbor]);
1598
1171
  }
1172
+ } else if (!visited.has(neighbor)) {
1173
+ dfs(neighbor, [...path]);
1174
+ }
1175
+ }
1176
+ recursionStack.delete(node);
1177
+ path.pop();
1178
+ }
1179
+ for (const node of graph.keys()) {
1180
+ if (!visited.has(node)) {
1181
+ dfs(node, []);
1182
+ }
1183
+ }
1184
+ return cycles;
1185
+ }
1186
+ function topologicalSort(graphData) {
1187
+ const { graph, inDegree } = graphData;
1188
+ const order = [];
1189
+ const queue = [];
1190
+ for (const [node, degree] of inDegree.entries()) {
1191
+ if (degree === 0) {
1192
+ queue.push(node);
1193
+ }
1194
+ }
1195
+ while (queue.length > 0) {
1196
+ const node = queue.shift();
1197
+ order.push(node);
1198
+ const neighbors = Array.from(graph.get(node) || []);
1199
+ for (const neighbor of neighbors) {
1200
+ const newDegree = (inDegree.get(neighbor) || 0) - 1;
1201
+ inDegree.set(neighbor, newDegree);
1202
+ if (newDegree === 0) {
1203
+ queue.push(neighbor);
1599
1204
  }
1600
1205
  }
1601
1206
  }
1207
+ if (order.length !== graph.size) {
1208
+ const cycles = findCyclicDependencies(graph);
1209
+ if (cycles.length > 0) {
1210
+ const cycleStr = cycles.map((cycle) => ` ${cycle.join(" -> ")}`).join("\n");
1211
+ throw new Error(`Circular dependencies detected:
1212
+ ${cycleStr}`);
1213
+ } else {
1214
+ const unresolvedModules = Array.from(graph.keys()).filter((key) => !order.includes(key));
1215
+ throw new Error(`Unable to resolve dependencies for modules: ${unresolvedModules.join(", ")}`);
1216
+ }
1217
+ }
1218
+ return order;
1602
1219
  }
1603
1220
 
1604
1221
  async function createStorageCLI(silgi) {
@@ -1607,321 +1224,822 @@ async function createStorageCLI(silgi) {
1607
1224
  ...silgi.options.storage,
1608
1225
  ...silgi.options.devStorage
1609
1226
  });
1610
- for (const [path, opts] of Object.entries(mounts)) {
1611
- if (opts.driver) {
1612
- const driver = await import(builtinDrivers[opts.driver] || opts.driver).then((r) => r.default || r);
1613
- storage.mount(path, driver(opts));
1614
- } else {
1615
- silgi.logger.warn(`No \`driver\` set for storage mount point "${path}".`);
1616
- }
1617
- }
1618
- return storage;
1227
+ for (const [path, opts] of Object.entries(mounts)) {
1228
+ if (opts.driver) {
1229
+ const driver = await import(builtinDrivers[opts.driver] || opts.driver).then((r) => r.default || r);
1230
+ storage.mount(path, driver(opts));
1231
+ } else {
1232
+ silgi.logger.warn(`No \`driver\` set for storage mount point "${path}".`);
1233
+ }
1234
+ }
1235
+ return storage;
1236
+ }
1237
+
1238
+ const vueShim = {
1239
+ filename: "delete/testtest.d.ts",
1240
+ where: ".silgi",
1241
+ getContents: ({ app }) => {
1242
+ if (!app.options.typescript.shim) {
1243
+ return "";
1244
+ }
1245
+ return [
1246
+ "declare module '*.vue' {",
1247
+ " import { DefineComponent } from 'vue'",
1248
+ " const component: DefineComponent<{}, {}, any>",
1249
+ " export default component",
1250
+ "}"
1251
+ ].join("\n");
1252
+ }
1253
+ };
1254
+ const pluginsDeclaration = {
1255
+ filename: "delete/testtest1.d.ts",
1256
+ where: ".silgi",
1257
+ getContents: async () => {
1258
+ return `
1259
+ declare module 'nuxt' {
1260
+ interface NuxtApp {
1261
+ $myPlugin: any;
1262
+ }
1263
+ }
1264
+ `;
1265
+ }
1266
+ };
1267
+
1268
+ const defaultTemplates = {
1269
+ __proto__: null,
1270
+ pluginsDeclaration: pluginsDeclaration,
1271
+ vueShim: vueShim
1272
+ };
1273
+
1274
+ const postTemplates = [
1275
+ pluginsDeclaration.filename
1276
+ ];
1277
+ const logger = useLogger("silgi");
1278
+ async function generateApp(app, options = {}) {
1279
+ app.templates = Object.values(defaultTemplates).concat(app.options.build.templates);
1280
+ await app.callHook("app:templates", app);
1281
+ app.templates = app.templates.map((tmpl) => {
1282
+ 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;
1283
+ return normalizeTemplate(tmpl, dir);
1284
+ });
1285
+ const filteredTemplates = {
1286
+ pre: [],
1287
+ post: []
1288
+ };
1289
+ for (const template of app.templates) {
1290
+ if (options.filter && !options.filter(template)) {
1291
+ continue;
1292
+ }
1293
+ const key = template.filename && postTemplates.includes(template.filename) ? "post" : "pre";
1294
+ filteredTemplates[key].push(template);
1295
+ }
1296
+ const templateContext = { app };
1297
+ const writes = [];
1298
+ const dirs = /* @__PURE__ */ new Set();
1299
+ const changedTemplates = [];
1300
+ async function processTemplate(template) {
1301
+ 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;
1302
+ const fullPath = template.dst || resolve(dir, template.filename);
1303
+ const start = performance.now();
1304
+ const contents = await compileTemplate(template, templateContext).catch((e) => {
1305
+ logger.error(`Could not compile template \`${template.filename}\`.`);
1306
+ logger.error(e);
1307
+ throw e;
1308
+ });
1309
+ template.modified = true;
1310
+ if (template.modified) {
1311
+ changedTemplates.push(template);
1312
+ }
1313
+ const perf = performance.now() - start;
1314
+ const setupTime = Math.round(perf * 100) / 100;
1315
+ if (app.options.debug || setupTime > 500) {
1316
+ logger.info(`Compiled \`${template.filename}\` in ${setupTime}ms`);
1317
+ }
1318
+ if (template.modified && template.write) {
1319
+ dirs.add(dirname(fullPath));
1320
+ writes.push(() => writeFileSync(fullPath, contents, "utf8"));
1321
+ }
1322
+ }
1323
+ await Promise.allSettled(filteredTemplates.pre.map(processTemplate));
1324
+ await Promise.allSettled(filteredTemplates.post.map(processTemplate));
1325
+ for (const dir of dirs) {
1326
+ mkdirSync(dir, { recursive: true });
1327
+ }
1328
+ for (const write of writes) {
1329
+ write();
1330
+ }
1331
+ if (changedTemplates.length) {
1332
+ await app.callHook("app:templatesGenerated", app, changedTemplates, options);
1333
+ }
1334
+ }
1335
+ async function compileTemplate(template, ctx) {
1336
+ delete ctx.utils;
1337
+ if (template.src) {
1338
+ try {
1339
+ return await promises.readFile(template.src, "utf-8");
1340
+ } catch (err) {
1341
+ logger.error(`[nuxt] Error reading template from \`${template.src}\``);
1342
+ throw err;
1343
+ }
1344
+ }
1345
+ if (template.getContents) {
1346
+ return template.getContents({
1347
+ ...ctx,
1348
+ options: template.options
1349
+ });
1350
+ }
1351
+ throw new Error(`[nuxt] Invalid template. Templates must have either \`src\` or \`getContents\`: ${JSON.stringify(template)}`);
1352
+ }
1353
+
1354
+ async function commands(silgi) {
1355
+ const commands2 = {
1356
+ ...silgi.options.commands
1357
+ };
1358
+ await silgi.callHook("prepare:commands", commands2);
1359
+ addTemplate({
1360
+ filename: "cli.json",
1361
+ where: ".silgi",
1362
+ write: true,
1363
+ getContents: () => JSON.stringify(commands2, null, 2)
1364
+ });
1365
+ }
1366
+
1367
+ async function installPackages(silgi) {
1368
+ const packages = {
1369
+ dependencies: {
1370
+ "@fastify/deepmerge": peerDependencies["@fastify/deepmerge"],
1371
+ "@silgi/ecosystem": peerDependencies["@silgi/ecosystem"],
1372
+ ...silgi.options.installPackages?.dependencies
1373
+ },
1374
+ devDependencies: {
1375
+ ...silgi.options.installPackages?.devDependencies
1376
+ }
1377
+ };
1378
+ await silgi.callHook("prepare:installPackages", packages);
1379
+ if (silgi.options.preset === "npm-package") {
1380
+ packages.devDependencies = {
1381
+ ...packages.devDependencies,
1382
+ ...packages.dependencies
1383
+ };
1384
+ packages.dependencies = {};
1385
+ }
1386
+ addTemplate({
1387
+ filename: "install.json",
1388
+ where: ".silgi",
1389
+ write: true,
1390
+ getContents: () => JSON.stringify(packages, null, 2)
1391
+ });
1392
+ }
1393
+
1394
+ function _deepFreeze(object) {
1395
+ const propNames = Object.getOwnPropertyNames(object);
1396
+ for (const name of propNames) {
1397
+ const value = object[name];
1398
+ if (value && typeof value === "object") {
1399
+ _deepFreeze(value);
1400
+ }
1401
+ }
1402
+ return Object.freeze(object);
1403
+ }
1404
+ function useCLIRuntimeConfig(silgi) {
1405
+ const _inlineRuntimeConfig = silgi.options.runtimeConfig;
1406
+ const envOptions = {
1407
+ prefix: "NITRO_",
1408
+ altPrefix: process.env.NITRO_ENV_PREFIX ?? process.env.SILGI_ENV_PREFIX ?? "_",
1409
+ silgiPrefix: "SILGI_",
1410
+ envExpansion: process.env.NITRO_ENV_EXPANSION ?? process.env.SILGI_ENV_EXPANSION ?? false,
1411
+ ...silgi.options.envOptions
1412
+ };
1413
+ silgi.hook("prepare:core.ts", (data) => {
1414
+ data.cliOptions.envOptions = envOptions;
1415
+ });
1416
+ const _sharedRuntimeConfig = _deepFreeze(
1417
+ applyEnv(klona(_inlineRuntimeConfig), envOptions)
1418
+ );
1419
+ silgi.options.runtimeConfig = _sharedRuntimeConfig;
1420
+ return _sharedRuntimeConfig;
1421
+ }
1422
+
1423
+ const GLOB_SCAN_PATTERN = "**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}";
1424
+ async function scanAndSyncOptions(silgi) {
1425
+ const scannedModules = await scanModules(silgi);
1426
+ silgi.options.modules = silgi.options.modules || [];
1427
+ for (const modPath of scannedModules) {
1428
+ if (!silgi.options.modules.includes(modPath)) {
1429
+ silgi.options.modules.push(modPath);
1430
+ }
1431
+ }
1432
+ }
1433
+ async function scanModules(silgi) {
1434
+ const files = await scanFiles(silgi, "silgi/modules");
1435
+ return files.map((f) => f.fullPath);
1436
+ }
1437
+ async function scanFiles(silgi, name) {
1438
+ const files = await Promise.all(
1439
+ silgi.options.scanDirs.map((dir) => scanDir(silgi, dir, name))
1440
+ ).then((r) => r.flat());
1441
+ return files;
1442
+ }
1443
+ async function scanDir(silgi, dir, name) {
1444
+ const fileNames = await globby(join(name, GLOB_SCAN_PATTERN), {
1445
+ cwd: dir,
1446
+ dot: true,
1447
+ ignore: silgi.options.ignore,
1448
+ absolute: true
1449
+ });
1450
+ return fileNames.map((fullPath) => {
1451
+ return {
1452
+ fullPath,
1453
+ path: relative(join(dir, name), fullPath)
1454
+ };
1455
+ }).sort((a, b) => a.path.localeCompare(b.path));
1619
1456
  }
1620
1457
 
1621
- const vueShim = {
1622
- filename: "delete/testtest.d.ts",
1623
- where: ".silgi",
1624
- getContents: ({ app }) => {
1625
- if (!app.options.typescript.shim) {
1626
- return "";
1458
+ async function createSilgiCLI(config = {}, opts = {}) {
1459
+ const options = await loadOptions(config, opts);
1460
+ await prepareEnv(options);
1461
+ const hooks = createHooks();
1462
+ const silgi = {
1463
+ modulesURIs: {},
1464
+ scannedURIs: /* @__PURE__ */ new Map(),
1465
+ services: {},
1466
+ uris: {},
1467
+ shareds: {},
1468
+ schemas: {},
1469
+ unimport: void 0,
1470
+ options,
1471
+ hooks,
1472
+ errors: [],
1473
+ // vfs: {}
1474
+ _requiredModules: {},
1475
+ logger: consola$1.withTag("silgi"),
1476
+ close: () => silgi.hooks.callHook("close", silgi),
1477
+ storage: void 0,
1478
+ scanModules: [],
1479
+ templates: [],
1480
+ callHook: hooks.callHook,
1481
+ addHooks: hooks.addHooks,
1482
+ hook: hooks.hook,
1483
+ async updateConfig(_config) {
1627
1484
  }
1628
- return [
1629
- "declare module '*.vue' {",
1630
- " import { DefineComponent } from 'vue'",
1631
- " const component: DefineComponent<{}, {}, any>",
1632
- " export default component",
1633
- "}"
1634
- ].join("\n");
1635
- }
1636
- };
1637
- const pluginsDeclaration = {
1638
- filename: "delete/testtest1.d.ts",
1639
- where: ".silgi",
1640
- getContents: async () => {
1641
- return `
1642
- declare module 'nuxt' {
1643
- interface NuxtApp {
1644
- $myPlugin: any;
1645
- }
1646
- }
1647
- `;
1648
- }
1649
- };
1650
-
1651
- const defaultTemplates = {
1652
- __proto__: null,
1653
- pluginsDeclaration: pluginsDeclaration,
1654
- vueShim: vueShim
1655
- };
1656
-
1657
- const postTemplates = [
1658
- pluginsDeclaration.filename
1659
- ];
1660
- const logger = useLogger("silgi");
1661
- async function generateApp(app, options = {}) {
1662
- app.templates = Object.values(defaultTemplates).concat(app.options.build.templates);
1663
- await app.callHook("app:templates", app);
1664
- app.templates = app.templates.map((tmpl) => {
1665
- 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;
1666
- return normalizeTemplate(tmpl, dir);
1667
- });
1668
- const filteredTemplates = {
1669
- pre: [],
1670
- post: []
1671
1485
  };
1672
- for (const template of app.templates) {
1673
- if (options.filter && !options.filter(template)) {
1674
- continue;
1675
- }
1676
- const key = template.filename && postTemplates.includes(template.filename) ? "post" : "pre";
1677
- filteredTemplates[key].push(template);
1486
+ useCLIRuntimeConfig(silgi);
1487
+ if (silgiCLICtx.tryUse()) {
1488
+ silgiCLICtx.unset();
1489
+ silgiCLICtx.set(silgi);
1490
+ } else {
1491
+ silgiCLICtx.set(silgi);
1492
+ silgi.hook("close", () => silgiCLICtx.unset());
1678
1493
  }
1679
- const templateContext = { app };
1680
- const writes = [];
1681
- const dirs = /* @__PURE__ */ new Set();
1682
- const changedTemplates = [];
1683
- async function processTemplate(template) {
1684
- 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;
1685
- const fullPath = template.dst || resolve(dir, template.filename);
1686
- const start = performance.now();
1687
- const contents = await compileTemplate(template, templateContext).catch((e) => {
1688
- logger.error(`Could not compile template \`${template.filename}\`.`);
1689
- logger.error(e);
1690
- throw e;
1494
+ if (silgi.options.debug) {
1495
+ createDebugger(silgi.hooks, { tag: "silgi" });
1496
+ silgi.options.plugins.push({
1497
+ path: join(runtimeDir, "internal/debug"),
1498
+ packageImport: "silgi/runtime/internal/debug"
1691
1499
  });
1692
- template.modified = true;
1693
- if (template.modified) {
1694
- changedTemplates.push(template);
1695
- }
1696
- const perf = performance.now() - start;
1697
- const setupTime = Math.round(perf * 100) / 100;
1698
- if (app.options.debug || setupTime > 500) {
1699
- logger.info(`Compiled \`${template.filename}\` in ${setupTime}ms`);
1700
- }
1701
- if (template.modified && template.write) {
1702
- dirs.add(dirname(fullPath));
1703
- writes.push(() => writeFileSync(fullPath, contents, "utf8"));
1704
- }
1705
1500
  }
1706
- await Promise.allSettled(filteredTemplates.pre.map(processTemplate));
1707
- await Promise.allSettled(filteredTemplates.post.map(processTemplate));
1708
- for (const dir of dirs) {
1709
- mkdirSync(dir, { recursive: true });
1501
+ for (const framework of frameworkSetup) {
1502
+ await framework(silgi);
1710
1503
  }
1711
- for (const write of writes) {
1712
- write();
1504
+ await scanAndSyncOptions(silgi);
1505
+ await scanModules$1(silgi);
1506
+ await scanFiles$1(silgi);
1507
+ if (hasError$1("Parser", silgi)) {
1508
+ console.error("Please fix type errors before continuing");
1509
+ process.exit(1);
1713
1510
  }
1714
- if (changedTemplates.length) {
1715
- await app.callHook("app:templatesGenerated", app, changedTemplates, options);
1511
+ await writeScanFiles(silgi);
1512
+ silgi.storage = await createStorageCLI(silgi);
1513
+ silgi.hooks.hook("close", async () => {
1514
+ await silgi.storage.dispose();
1515
+ });
1516
+ if (silgi.options.logLevel !== void 0) {
1517
+ silgi.logger.level = silgi.options.logLevel;
1518
+ }
1519
+ silgi.hooks.addHooks(silgi.options.hooks);
1520
+ await installModules(silgi);
1521
+ await silgi.hooks.callHook("scanFiles:done", silgi);
1522
+ await commands(silgi);
1523
+ await installPackages(silgi);
1524
+ await generateApp(silgi);
1525
+ if (silgi.options.imports) {
1526
+ silgi.options.imports.dirs ??= [];
1527
+ silgi.options.imports.dirs.push(
1528
+ join(silgi.options.serverDir, "**/*")
1529
+ );
1530
+ silgi.options.imports.presets.push({
1531
+ from: "silgi/types",
1532
+ imports: autoImportTypes.map((type) => type),
1533
+ type: true
1534
+ });
1535
+ silgi.options.imports.presets.push({
1536
+ from: "silgi/types",
1537
+ imports: autoImportTypes.map((type) => type),
1538
+ type: true
1539
+ });
1540
+ silgi.options.imports.presets.push({
1541
+ from: "silgi/runtime/internal/ofetch",
1542
+ imports: ["createSilgiFetch", "silgi$fetch"]
1543
+ });
1544
+ silgi.unimport = createUnimport(silgi.options.imports);
1545
+ await silgi.unimport.init();
1716
1546
  }
1547
+ await registerModuleExportScan(silgi);
1548
+ return silgi;
1717
1549
  }
1718
- async function compileTemplate(template, ctx) {
1719
- delete ctx.utils;
1720
- if (template.src) {
1721
- try {
1722
- return await promises.readFile(template.src, "utf-8");
1723
- } catch (err) {
1724
- logger.error(`[nuxt] Error reading template from \`${template.src}\``);
1725
- throw err;
1550
+
1551
+ async function generateSilgiStorageBaseType(silgi) {
1552
+ silgi.hook("prepare:schema.ts", async (options) => {
1553
+ if (silgi.options.storage) {
1554
+ for (const [key, _value] of Object.entries(silgi.options.storage)) {
1555
+ options.storeBase.push(key);
1556
+ }
1557
+ }
1558
+ });
1559
+ }
1560
+
1561
+ async function prepareCoreFile(data, frameworkContext, silgi) {
1562
+ let importItems = {
1563
+ "silgi/core": {
1564
+ import: [
1565
+ { name: "createSilgi" }
1566
+ ],
1567
+ from: "silgi/core"
1568
+ },
1569
+ "silgi/types": {
1570
+ import: [
1571
+ { name: "SilgiRuntimeOptions", type: true },
1572
+ { name: "FrameworkContext", type: true },
1573
+ { name: "BuildConfig", type: true }
1574
+ ],
1575
+ from: "silgi/types"
1576
+ },
1577
+ "#silgi/vfs": {
1578
+ import: [],
1579
+ from: "./vfs"
1580
+ },
1581
+ "silgi/runtime/internal/defu": {
1582
+ import: [
1583
+ {
1584
+ name: "mergeDeep"
1585
+ }
1586
+ ],
1587
+ from: "silgi/runtime/internal/defu"
1588
+ },
1589
+ "scan.ts": {
1590
+ import: [{
1591
+ name: "uris",
1592
+ type: false
1593
+ }, {
1594
+ name: "services",
1595
+ type: false
1596
+ }, {
1597
+ name: "shareds",
1598
+ type: false
1599
+ }, {
1600
+ name: "schemas",
1601
+ type: false
1602
+ }, {
1603
+ name: "modulesURIs",
1604
+ type: false
1605
+ }],
1606
+ from: "./scan.ts"
1607
+ }
1608
+ };
1609
+ importItems = { ...data._importItems, ...importItems };
1610
+ const _data = {
1611
+ customImports: data._customImports || [],
1612
+ buildSilgiExtraContent: [],
1613
+ beforeBuildSilgiExtraContent: [],
1614
+ cliOptions: {},
1615
+ afterCliOptions: [],
1616
+ _silgiConfigs: [],
1617
+ customContent: [],
1618
+ importItems
1619
+ };
1620
+ for (const module of silgi.scanModules) {
1621
+ if (module.meta.cliToRuntimeOptionsKeys && module.meta.cliToRuntimeOptionsKeys?.length > 0) {
1622
+ for (const key of module.meta.cliToRuntimeOptionsKeys) {
1623
+ _data.cliOptions[module.meta.configKey] = {
1624
+ ..._data.cliOptions[module.meta.configKey],
1625
+ [key]: module.options[key]
1626
+ };
1627
+ }
1628
+ } else {
1629
+ _data.cliOptions[module.meta.configKey] = {};
1726
1630
  }
1727
1631
  }
1728
- if (template.getContents) {
1729
- return template.getContents({
1730
- ...ctx,
1731
- options: template.options
1732
- });
1632
+ await silgi.callHook("prepare:core.ts", _data);
1633
+ if (importItems["#silgi/vfs"].import.length === 0) {
1634
+ delete importItems["#silgi/vfs"];
1733
1635
  }
1734
- throw new Error(`[nuxt] Invalid template. Templates must have either \`src\` or \`getContents\`: ${JSON.stringify(template)}`);
1636
+ const plugins = [];
1637
+ for (const plugin of silgi.options.plugins) {
1638
+ const pluginImportName = `_${hash(plugin.packageImport)}`;
1639
+ _data.customImports.push(`import ${pluginImportName} from '${plugin.packageImport}'`);
1640
+ plugins.push(pluginImportName);
1641
+ }
1642
+ const importsContent = [
1643
+ ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
1644
+ return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${from}'`;
1645
+ }),
1646
+ "",
1647
+ ..._data.customImports,
1648
+ ""
1649
+ ];
1650
+ const importData = [
1651
+ `export const cliOptions: Partial<SilgiRuntimeOptions> = ${JSON.stringify(_data.cliOptions, null, 2)}`,
1652
+ "",
1653
+ ..._data.afterCliOptions,
1654
+ "",
1655
+ "export async function buildSilgi(framework: FrameworkContext, moduleOptions?: Partial<SilgiRuntimeOptions>,buildOptions?: Partial<BuildConfig>) {",
1656
+ "",
1657
+ _data.beforeBuildSilgiExtraContent.length > 0 ? _data.beforeBuildSilgiExtraContent.map(({ value, type }) => {
1658
+ return type === "function" ? value : `const ${value}`;
1659
+ }) : "",
1660
+ "",
1661
+ " const silgi = await createSilgi({",
1662
+ " framework,",
1663
+ " shared: shareds as any,",
1664
+ " services: services as any,",
1665
+ " schemas: schemas as any,",
1666
+ " uris,",
1667
+ " modulesURIs,",
1668
+ ` plugins: [${plugins.join(", ")}],`,
1669
+ _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 ")},` : "",
1670
+ " runtimeConfig: {} as SilgiRuntimeOptions,",
1671
+ " ...buildOptions,",
1672
+ " options: mergeDeep(",
1673
+ " moduleOptions || {},",
1674
+ " {",
1675
+ ` present: '${silgi.options.preset}',`,
1676
+ " ...cliOptions,",
1677
+ " },",
1678
+ " ) as any,",
1679
+ " })",
1680
+ "",
1681
+ ...frameworkContext,
1682
+ "",
1683
+ ..._data.buildSilgiExtraContent,
1684
+ "",
1685
+ " return silgi",
1686
+ "}",
1687
+ ""
1688
+ ];
1689
+ await silgi.callHook("after:prepare:core.ts", importData);
1690
+ importData.unshift(...importsContent);
1691
+ return importData;
1735
1692
  }
1736
1693
 
1737
- async function commands(silgi) {
1738
- const commands2 = {
1739
- ...silgi.options.commands
1694
+ async function prepareFramework(silgi) {
1695
+ const importItems = {
1696
+ "silgi/types": {
1697
+ import: [
1698
+ { name: "SilgiRuntimeContext", type: true }
1699
+ ],
1700
+ from: "silgi/types"
1701
+ }
1740
1702
  };
1741
- await silgi.callHook("prepare:commands", commands2);
1742
- addTemplate({
1743
- filename: "cli.json",
1744
- where: ".silgi",
1745
- write: true,
1746
- getContents: () => JSON.stringify(commands2, null, 2)
1703
+ const customImports = [];
1704
+ const functions = [];
1705
+ await silgi.callHook("prepare:createCoreFramework", {
1706
+ importItems,
1707
+ customImports,
1708
+ functions
1747
1709
  });
1710
+ const content = [
1711
+ ...functions.map((f) => f.params?.length ? ` await ${f.name}(framework, ${f.params.join(",")})` : ` await ${f.name}(framework)`)
1712
+ ];
1713
+ return {
1714
+ content,
1715
+ importItems,
1716
+ customImports
1717
+ };
1748
1718
  }
1749
-
1750
- async function installPackages(silgi) {
1751
- const packages = {
1752
- dependencies: {
1753
- "@fastify/deepmerge": peerDependencies["@fastify/deepmerge"],
1754
- ...silgi.options.installPackages?.dependencies
1755
- },
1756
- devDependencies: {
1757
- ...silgi.options.installPackages?.devDependencies
1719
+ async function createDTSFramework(silgi) {
1720
+ const importItems = {
1721
+ "silgi/types": {
1722
+ import: [
1723
+ { name: "SilgiRuntimeContext", type: true }
1724
+ ],
1725
+ from: "silgi/types"
1758
1726
  }
1759
1727
  };
1760
- await silgi.callHook("prepare:installPackages", packages);
1761
- if (silgi.options.preset === "npm-package") {
1762
- packages.devDependencies = {
1763
- ...packages.devDependencies,
1764
- ...packages.dependencies
1765
- };
1766
- packages.dependencies = {};
1728
+ const customImports = [];
1729
+ const customContent = [];
1730
+ await silgi.callHook("prepare:createDTSFramework", {
1731
+ importItems,
1732
+ customImports,
1733
+ customContent
1734
+ });
1735
+ const content = [
1736
+ ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
1737
+ const path = isAbsolute(from) ? relativeWithDot(silgi.options.build.typesDir, from) : from;
1738
+ return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${path}'`;
1739
+ }),
1740
+ "",
1741
+ ...customImports,
1742
+ "",
1743
+ ...customContent,
1744
+ ""
1745
+ ];
1746
+ return {
1747
+ content,
1748
+ importItems
1749
+ };
1750
+ }
1751
+
1752
+ async function writeCoreFile(silgi) {
1753
+ const data = await prepareFramework(silgi);
1754
+ await generateSilgiStorageBaseType(silgi);
1755
+ const coreContent = await prepareCoreFile({
1756
+ _importItems: data?.importItems ?? {},
1757
+ _customImports: data?.customImports ?? []
1758
+ }, data?.content ?? [], silgi);
1759
+ const silgiDir = resolve(silgi.options.silgi.serverDir);
1760
+ const buildFiles = [];
1761
+ buildFiles.push({
1762
+ path: join(silgiDir, "core.ts"),
1763
+ contents: coreContent.join("\n")
1764
+ });
1765
+ for await (const file of buildFiles) {
1766
+ await writeFile(
1767
+ resolve(silgi.options.build.dir, file.path),
1768
+ file.contents
1769
+ );
1767
1770
  }
1768
- addTemplate({
1769
- filename: "install.json",
1770
- where: ".silgi",
1771
- write: true,
1772
- getContents: () => JSON.stringify(packages, null, 2)
1771
+ }
1772
+
1773
+ async function generateRouterDTS(silgi) {
1774
+ const uris = silgi.uris;
1775
+ const subPath = "srn";
1776
+ const groupedPaths = /* @__PURE__ */ new Map();
1777
+ Object.entries(uris || {}).forEach(([key, params]) => {
1778
+ const [service, resource, method, action] = key.split("/");
1779
+ const basePath = params ? `${subPath}/${service}/${resource}/${action}/${params}` : `${subPath}/${service}/${resource}/${action}`;
1780
+ const fullPath = `${subPath}/${service}/${resource}/${action}`;
1781
+ if (!groupedPaths.has(basePath)) {
1782
+ groupedPaths.set(basePath, /* @__PURE__ */ new Map());
1783
+ }
1784
+ groupedPaths.get(basePath)?.set(method.toLowerCase(), fullPath);
1785
+ });
1786
+ const keys = [
1787
+ " keys: {",
1788
+ Array.from(groupedPaths.entries()).map(([basePath, methods]) => {
1789
+ return ` '/${basePath}': {${Array.from(methods.entries()).map(([method, path]) => `
1790
+ ${method}: '/${path}'`).join(",")}
1791
+ }`;
1792
+ }).join(",\n"),
1793
+ " }",
1794
+ ""
1795
+ ].join("\n");
1796
+ const groupedRoutes = Object.entries(uris || {}).reduce((acc, [key, _params]) => {
1797
+ const [service, resource, method, action] = key.split("/");
1798
+ const routePath = `${subPath}/${service}/${resource}/${action}`;
1799
+ if (!acc[routePath]) {
1800
+ acc[routePath] = {};
1801
+ }
1802
+ acc[routePath][method] = {
1803
+ input: `ExtractInputFromURI<'${key}'>`,
1804
+ output: `ExtractOutputFromURI<'${key}'>`,
1805
+ params: `ExtractRouterParamsFromURI<'${key}'>['params']`
1806
+ };
1807
+ return acc;
1808
+ }, {});
1809
+ const routerTypes = Object.entries(groupedRoutes).map(([path, methods]) => {
1810
+ const methodEntries = Object.entries(methods).map(([method, { input, output, params }]) => {
1811
+ return ` '${method}': {
1812
+ input: ${input},
1813
+ output: ${output}
1814
+ params: ${params}
1815
+ }`;
1816
+ }).join(",\n");
1817
+ return ` '/${path}': {
1818
+ ${methodEntries}
1819
+ }`;
1773
1820
  });
1821
+ const nitro = [
1822
+ "declare module 'nitropack/types' {",
1823
+ " interface InternalApi extends RouterTypes {}",
1824
+ "}"
1825
+ ];
1826
+ const content = [
1827
+ keys.slice(0, -1),
1828
+ // son satırdaki boş satırı kaldır
1829
+ ...routerTypes
1830
+ ].join(",\n");
1831
+ const context = [
1832
+ "import type { ExtractInputFromURI, ExtractOutputFromURI, ExtractRouterParamsFromURI } from 'silgi/types'",
1833
+ "",
1834
+ "export interface RouterTypes {",
1835
+ content,
1836
+ "}",
1837
+ "",
1838
+ "declare module 'silgi/types' {",
1839
+ " interface SilgiRouterTypes extends RouterTypes {",
1840
+ " }",
1841
+ "}",
1842
+ "",
1843
+ silgi.options.preset === "h3" || silgi.options.preset === "nitro" ? nitro.join("\n") : "",
1844
+ "",
1845
+ "export {}"
1846
+ ];
1847
+ return context;
1848
+ }
1849
+
1850
+ async function prepareSchema(silgi) {
1851
+ const importItems = {
1852
+ "silgi/types": {
1853
+ import: [
1854
+ { name: "URIsTypes", type: true },
1855
+ { name: "Namespaces", type: true },
1856
+ { name: "SilgiRuntimeContext", type: true }
1857
+ ],
1858
+ from: "silgi/types"
1859
+ }
1860
+ };
1861
+ const data = {
1862
+ importItems,
1863
+ customImports: [],
1864
+ options: [],
1865
+ contexts: [],
1866
+ actions: [],
1867
+ shareds: [],
1868
+ events: [],
1869
+ storeBase: [],
1870
+ hooks: [],
1871
+ runtimeHooks: [],
1872
+ runtimeOptions: [],
1873
+ methods: []
1874
+ };
1875
+ const storeBase = [];
1876
+ await silgi.callHook("prepare:schema.ts", data);
1877
+ relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/core.ts`);
1878
+ const silgiScanTS = relativeWithDot(silgi.options.build.typesDir, `${silgi.options.silgi.serverDir}/scan.ts`);
1879
+ let addSilgiContext = false;
1880
+ const importsContent = [
1881
+ ...Object.entries(importItems).map(([_name, { from, import: imports }]) => {
1882
+ const path = isAbsolute(from) ? relativeWithDot(silgi.options.build.typesDir, from) : from;
1883
+ return `import { ${imports.map(({ type, name }) => type ? `type ${name}` : name).join(", ")} } from '${path}'`;
1884
+ }),
1885
+ "",
1886
+ ...data.customImports,
1887
+ ""
1888
+ ];
1889
+ const importData = [
1890
+ "interface InferredNamespaces {",
1891
+ ...(silgi.options.namespaces || []).map((key) => ` ${key}: string,`),
1892
+ "}",
1893
+ "",
1894
+ `type SchemaExtends = Namespaces<typeof import('${silgiScanTS}')['schemas']>`,
1895
+ "",
1896
+ `type SilgiURIsMerge = URIsTypes<typeof import('${silgiScanTS}')['uris']>`,
1897
+ "",
1898
+ `type SilgiModuleContextExtends = ${data.contexts.length ? data.contexts.map(({ value }) => value).join(" & ") : "{}"}`,
1899
+ "",
1900
+ data.events.length ? `interface SilgiModuleEventsExtends extends ${data.events.map((item) => item.extends ? item.value : "").join(", ")} {
1901
+ ${data.events.map((item) => {
1902
+ if (item.isSilgiContext) {
1903
+ addSilgiContext = true;
1904
+ }
1905
+ return !item.extends && !addSilgiContext ? ` ${item.key}: ${item.value}` : item.isSilgiContext ? " context: SilgiRuntimeContext" : "";
1906
+ }).join(",\n")}
1907
+ }` : "interface SilgiModuleEventsExtends {}",
1908
+ "",
1909
+ `type RuntimeActionExtends = ${data.actions?.length ? data.actions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1910
+ "",
1911
+ `type RuntimeMethodExtends = ${data.methods?.length ? data.methods.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1912
+ "",
1913
+ `type SilgiModuleSharedExtends = ${data.shareds.length ? data.shareds.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1914
+ "",
1915
+ `type SilgiModuleOptionExtend = ${data.options?.length ? data.options.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1916
+ "",
1917
+ `type SilgiRuntimeOptionExtends = ${data.runtimeOptions?.length ? data.runtimeOptions.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1918
+ "",
1919
+ "interface SilgiStorageBaseExtends {",
1920
+ ...(storeBase || []).map((value) => ` ${value}: ''`),
1921
+ "}",
1922
+ "",
1923
+ `type ModuleHooksExtend = ${data.hooks?.length ? data.hooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1924
+ "",
1925
+ `type SilgiRuntimeHooksExtends = ${data.runtimeHooks?.length ? data.runtimeHooks.map(({ value }) => `${value}`).join(" & ") : "{}"}`,
1926
+ "",
1927
+ "declare module 'silgi/types' {",
1928
+ " interface FrameworkContext extends FrameworkContextExtends {}",
1929
+ " interface SilgiSchema extends SchemaExtends {}",
1930
+ " interface SilgiNamespaces extends InferredNamespaces {}",
1931
+ " interface SilgiStorageBase extends SilgiStorageBaseExtends {}",
1932
+ " interface SilgiURIs extends SilgiURIsMerge {}",
1933
+ " interface SilgiRuntimeContext extends SilgiModuleContextExtends {}",
1934
+ " interface SilgiEvents extends SilgiModuleEventsExtends {}",
1935
+ " interface SilgiRuntimeShareds extends SilgiModuleSharedExtends {}",
1936
+ " interface SilgiRuntimeActions extends RuntimeActionExtends {}",
1937
+ " interface SilgiModuleOptions extends SilgiModuleOptionExtend {}",
1938
+ " interface SilgiRuntimeOptions extends SilgiRuntimeOptionExtends {}",
1939
+ " interface SilgiRuntimeHooks extends SilgiRuntimeHooksExtends {}",
1940
+ " interface SilgiHooks extends ModuleHooksExtend {}",
1941
+ " interface SilgiRuntimeMethods extends RuntimeMethodExtends {}",
1942
+ "}",
1943
+ "",
1944
+ "export {}"
1945
+ ];
1946
+ await silgi.callHook("after:prepare:schema.ts", importData);
1947
+ importData.unshift(...importsContent);
1948
+ return importData;
1774
1949
  }
1775
1950
 
1776
- function _deepFreeze(object) {
1777
- const propNames = Object.getOwnPropertyNames(object);
1778
- for (const name of propNames) {
1779
- const value = object[name];
1780
- if (value && typeof value === "object") {
1781
- _deepFreeze(value);
1782
- }
1783
- }
1784
- return Object.freeze(object);
1785
- }
1786
- function useCLIRuntimeConfig(silgi) {
1787
- const _inlineRuntimeConfig = silgi.options.runtimeConfig;
1788
- const envOptions = {
1789
- prefix: "NITRO_",
1790
- altPrefix: process.env.NITRO_ENV_PREFIX ?? process.env.SILGI_ENV_PREFIX ?? "_",
1791
- silgiPrefix: "SILGI_",
1792
- envExpansion: process.env.NITRO_ENV_EXPANSION ?? process.env.SILGI_ENV_EXPANSION ?? false,
1793
- ...silgi.options.envOptions
1794
- };
1795
- silgi.hook("prepare:core.ts", (data) => {
1796
- data.cliOptions.envOptions = envOptions;
1951
+ async function writeTypesAndFiles(silgi) {
1952
+ const routerDTS = await generateRouterDTS(silgi);
1953
+ silgi.hook("prepare:types", (opts) => {
1954
+ opts.references.push({ path: "./schema.d.ts" });
1955
+ opts.references.push({ path: "./silgi-routes.d.ts" });
1956
+ opts.references.push({ path: "./framework.d.ts" });
1797
1957
  });
1798
- const _sharedRuntimeConfig = _deepFreeze(
1799
- applyEnv(klona(_inlineRuntimeConfig), envOptions)
1958
+ const schemaContent = await prepareSchema(silgi);
1959
+ const frameworkDTS = await createDTSFramework(silgi);
1960
+ const { declarations, tsConfig } = await silgiGenerateType(silgi);
1961
+ const tsConfigPath = resolve(
1962
+ silgi.options.rootDir,
1963
+ silgi.options.typescript.tsconfigPath
1800
1964
  );
1801
- silgi.options.runtimeConfig = _sharedRuntimeConfig;
1802
- return _sharedRuntimeConfig;
1803
- }
1804
-
1805
- const GLOB_SCAN_PATTERN = "**/*.{js,mjs,cjs,ts,mts,cts,tsx,jsx}";
1806
- async function scanAndSyncOptions(silgi) {
1807
- const scannedModules = await scanModules(silgi);
1808
- silgi.options.modules = silgi.options.modules || [];
1809
- for (const modPath of scannedModules) {
1810
- if (!silgi.options.modules.includes(modPath)) {
1811
- silgi.options.modules.push(modPath);
1965
+ const typesDir = resolve(silgi.options.build.typesDir);
1966
+ let autoImportedTypes = [];
1967
+ let autoImportExports = "";
1968
+ if (silgi.unimport) {
1969
+ await silgi.unimport.init();
1970
+ const allImports = await silgi.unimport.getImports();
1971
+ autoImportExports = toExports(allImports).replace(
1972
+ /#internal\/nitro/g,
1973
+ relative(typesDir, runtimeDir)
1974
+ );
1975
+ const resolvedImportPathMap = /* @__PURE__ */ new Map();
1976
+ for (const i of allImports.filter((i2) => !i2.type)) {
1977
+ if (resolvedImportPathMap.has(i.from)) {
1978
+ continue;
1979
+ }
1980
+ let path = resolveAlias$1(i.from, silgi.options.alias);
1981
+ if (isAbsolute(path)) {
1982
+ const resolvedPath = await resolvePath$1(i.from, {
1983
+ url: silgi.options.nodeModulesDirs
1984
+ }).catch(() => null);
1985
+ if (resolvedPath) {
1986
+ const { dir, name } = parseNodeModulePath(resolvedPath);
1987
+ if (!dir || !name) {
1988
+ path = resolvedPath;
1989
+ } else {
1990
+ const subpath = await lookupNodeModuleSubpath(resolvedPath);
1991
+ path = join(dir, name, subpath || "");
1992
+ }
1993
+ }
1994
+ }
1995
+ if (existsSync(path) && !await isDirectory(path)) {
1996
+ path = path.replace(/\.[a-z]+$/, "");
1997
+ }
1998
+ if (isAbsolute(path)) {
1999
+ path = relative(typesDir, path);
2000
+ }
2001
+ resolvedImportPathMap.set(i.from, path);
1812
2002
  }
2003
+ autoImportedTypes = [
2004
+ silgi.options.imports && silgi.options.imports.autoImport !== false ? (await silgi.unimport.generateTypeDeclarations({
2005
+ exportHelper: false,
2006
+ resolvePath: (i) => resolvedImportPathMap.get(i.from) ?? i.from
2007
+ })).trim() : ""
2008
+ ];
1813
2009
  }
1814
- }
1815
- async function scanModules(silgi) {
1816
- const files = await scanFiles(silgi, "silgi/modules");
1817
- return files.map((f) => f.fullPath);
1818
- }
1819
- async function scanFiles(silgi, name) {
1820
- const files = await Promise.all(
1821
- silgi.options.scanDirs.map((dir) => scanDir(silgi, dir, name))
1822
- ).then((r) => r.flat());
1823
- return files;
1824
- }
1825
- async function scanDir(silgi, dir, name) {
1826
- const fileNames = await globby(join(name, GLOB_SCAN_PATTERN), {
1827
- cwd: dir,
1828
- dot: true,
1829
- ignore: silgi.options.ignore,
1830
- absolute: true
2010
+ const buildFiles = [];
2011
+ buildFiles.push({
2012
+ path: join(typesDir, "silgi-routes.d.ts"),
2013
+ contents: routerDTS.join("\n")
1831
2014
  });
1832
- return fileNames.map((fullPath) => {
1833
- return {
1834
- fullPath,
1835
- path: relative(join(dir, name), fullPath)
1836
- };
1837
- }).sort((a, b) => a.path.localeCompare(b.path));
1838
- }
1839
-
1840
- async function createSilgiCLI(config = {}, opts = {}) {
1841
- const options = await loadOptions(config, opts);
1842
- await prepareEnv(options);
1843
- const hooks = createHooks();
1844
- const silgi = {
1845
- modulesURIs: {},
1846
- scannedURIs: /* @__PURE__ */ new Map(),
1847
- services: {},
1848
- uris: {},
1849
- shareds: {},
1850
- schemas: {},
1851
- unimport: void 0,
1852
- options,
1853
- hooks,
1854
- // vfs: {}
1855
- _requiredModules: {},
1856
- logger: consola$1.withTag("silgi"),
1857
- close: () => silgi.hooks.callHook("close", silgi),
1858
- storage: void 0,
1859
- scanModules: [],
1860
- templates: [],
1861
- callHook: hooks.callHook,
1862
- addHooks: hooks.addHooks,
1863
- hook: hooks.hook,
1864
- async updateConfig(_config) {
1865
- }
1866
- };
1867
- useCLIRuntimeConfig(silgi);
1868
- if (silgiCLICtx.tryUse()) {
1869
- silgiCLICtx.unset();
1870
- silgiCLICtx.set(silgi);
1871
- } else {
1872
- silgiCLICtx.set(silgi);
1873
- silgi.hook("close", () => silgiCLICtx.unset());
1874
- }
1875
- if (silgi.options.debug) {
1876
- createDebugger(silgi.hooks, { tag: "silgi" });
1877
- silgi.options.plugins.push({
1878
- path: join(runtimeDir, "internal/debug"),
1879
- packageImport: "silgi/runtime/internal/debug"
1880
- });
1881
- }
1882
- for (const framework of frameworkSetup) {
1883
- await framework(silgi);
1884
- }
1885
- await scanAndSyncOptions(silgi);
1886
- await scanModules$1(silgi);
1887
- await scanFiles$1(silgi);
1888
- silgi.storage = await createStorageCLI(silgi);
1889
- silgi.hooks.hook("close", async () => {
1890
- await silgi.storage.dispose();
2015
+ buildFiles.push({
2016
+ path: join(typesDir, "silgi-imports.d.ts"),
2017
+ contents: [...autoImportedTypes, autoImportExports || "export {}"].join(
2018
+ "\n"
2019
+ )
1891
2020
  });
1892
- if (silgi.options.logLevel !== void 0) {
1893
- silgi.logger.level = silgi.options.logLevel;
1894
- }
1895
- silgi.hooks.addHooks(silgi.options.hooks);
1896
- await installModules(silgi);
1897
- await silgi.hooks.callHook("scanFiles:done", silgi);
1898
- await commands(silgi);
1899
- await installPackages(silgi);
1900
- await generateApp(silgi);
1901
- if (silgi.options.imports) {
1902
- silgi.options.imports.dirs ??= [];
1903
- silgi.options.imports.dirs.push(
1904
- join(silgi.options.serverDir, "**/*")
2021
+ buildFiles.push({
2022
+ path: join(typesDir, "schema.d.ts"),
2023
+ contents: schemaContent.join("\n")
2024
+ });
2025
+ buildFiles.push({
2026
+ path: join(typesDir, "silgi.d.ts"),
2027
+ contents: declarations.join("\n")
2028
+ });
2029
+ buildFiles.push({
2030
+ path: tsConfigPath,
2031
+ contents: JSON.stringify(tsConfig, null, 2)
2032
+ });
2033
+ buildFiles.push({
2034
+ path: join(typesDir, "framework.d.ts"),
2035
+ contents: frameworkDTS.content.join("\n")
2036
+ });
2037
+ for await (const file of buildFiles) {
2038
+ await writeFile(
2039
+ resolve(silgi.options.build.dir, file.path),
2040
+ file.contents
1905
2041
  );
1906
- silgi.options.imports.presets.push({
1907
- from: "silgi/types",
1908
- imports: autoImportTypes.map((type) => type),
1909
- type: true
1910
- });
1911
- silgi.options.imports.presets.push({
1912
- from: "silgi/types",
1913
- imports: autoImportTypes.map((type) => type),
1914
- type: true
1915
- });
1916
- silgi.options.imports.presets.push({
1917
- from: "silgi/runtime/internal/ofetch",
1918
- imports: ["createSilgiFetch", "silgi$fetch"]
1919
- });
1920
- silgi.unimport = createUnimport(silgi.options.imports);
1921
- await silgi.unimport.init();
1922
2042
  }
1923
- await registerModuleExportScan(silgi);
1924
- return silgi;
1925
2043
  }
1926
2044
 
1927
2045
  const prepare = defineCommand({
@@ -1942,27 +2060,40 @@ const prepare = defineCommand({
1942
2060
  }
1943
2061
  },
1944
2062
  async run({ args }) {
1945
- async function generate() {
1946
- const rootDir = resolve(args.dir || args._dir || ".");
1947
- const silgi = await createSilgiCLI({
1948
- rootDir,
1949
- dev: args.stub,
1950
- stub: args.stub,
1951
- preset: args.preset,
1952
- commandType: "prepare"
1953
- });
1954
- await prepare$1();
1955
- await writeTypesAndFiles(silgi);
1956
- await silgi.callHook("read:core.ts", async () => {
1957
- const data = await readCoreFile(silgi);
1958
- return data;
1959
- });
1960
- await silgi.close();
2063
+ const rootDir = resolve(args.dir || args._dir || ".");
2064
+ const silgi = await createSilgiCLI({
2065
+ rootDir,
2066
+ dev: args.stub,
2067
+ stub: args.stub,
2068
+ preset: args.preset,
2069
+ commandType: "prepare"
2070
+ });
2071
+ await prepare$1();
2072
+ await writeTypesAndFiles(silgi);
2073
+ await writeCoreFile(silgi);
2074
+ let watcher;
2075
+ if (silgi.options.devServer.watch.length > 0) {
2076
+ watcher = watch(silgi.options.devServer.watch, silgi.options.watchOptions);
2077
+ watcher.on("add", (...data) => reloadScan(silgi, ...data)).on("change", (...data) => reloadScan(silgi, ...data));
1961
2078
  }
1962
- await generate();
1963
- await generate();
2079
+ const close = async () => {
2080
+ await silgi.close();
2081
+ if (watcher) {
2082
+ watcher.close();
2083
+ }
2084
+ await silgi.callHook("close", silgi);
2085
+ consola.withTag("silgi").success("Process terminated");
2086
+ };
2087
+ process.on("SIGINT", async () => {
2088
+ consola.withTag("silgi").info("Shutting down...");
2089
+ await close();
2090
+ process.exit(0);
2091
+ });
2092
+ await silgi.callHook("close", silgi);
1964
2093
  consola.withTag("silgi").success("Prepare completed");
1965
- process.exit(0);
2094
+ consola.withTag("silgi").info("Process is still running. Press Ctrl+C to exit.");
2095
+ setInterval(() => {
2096
+ }, 1e3);
1966
2097
  }
1967
2098
  });
1968
2099