silgi 0.30.5 → 0.31.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.
package/dist/build.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { watch } from 'chokidar';
2
- import consola from 'consola';
3
- import { join, basename } from 'pathe';
4
- import { debounce } from 'perfect-debounce';
5
- import { u as useSilgiCLI, a as silgiCLIIClose } from './_chunks/silgiApp.mjs';
6
- import { r as reloadScan } from './cli/devServer.mjs';
7
- import { c as createSilgiCLI, b as build } from './cli/build.mjs';
1
+ export { p as prepareBuild, w as watchDev } from './cli/dev.mjs';
2
+ import 'chokidar';
3
+ import 'consola';
4
+ import 'pathe';
5
+ import 'perfect-debounce';
6
+ import './_chunks/silgiApp.mjs';
8
7
  import 'unctx';
9
8
  import 'silgi';
9
+ import './cli/build.mjs';
10
10
  import 'hookable';
11
11
  import 'silgi/kit';
12
12
  import 'silgi/runtime/meta';
@@ -27,7 +27,6 @@ import 'exsolve';
27
27
  import 'node:fs/promises';
28
28
  import 'globby';
29
29
  import 'ignore';
30
- import '@oxc-parser/wasm';
31
30
  import 'knitwork';
32
31
  import 'klona';
33
32
  import 'silgi/runtime';
@@ -44,73 +43,3 @@ import 'pkg-types';
44
43
  import 'apiful/openapi';
45
44
  import 'pathe/utils';
46
45
  import 'untyped';
47
-
48
- async function prepareBuild(config) {
49
- const silgi = await createSilgiCLI({
50
- commandType: config?.commandType || "prepare",
51
- ...config
52
- });
53
- await build(silgi);
54
- return silgi;
55
- }
56
-
57
- async function watchDev() {
58
- let watcher;
59
- async function load() {
60
- await prepareBuild({
61
- commandType: "prepare",
62
- activeEnvironment: ".env"
63
- });
64
- }
65
- const reload = debounce(load);
66
- const silgi = useSilgiCLI();
67
- silgi.options.watchOptions.ignored ??= [];
68
- silgi.options.watchOptions.ignoreInitial = true;
69
- if (Array.isArray(silgi.options.watchOptions.ignored)) {
70
- silgi.options.watchOptions.ignored.push(
71
- `!${join(silgi.options.silgi.serverDir, "config")}`
72
- );
73
- }
74
- silgi.options.devServer.watch.push(
75
- join(silgi.options.serverDir, "services"),
76
- join(silgi.options.serverDir, "schemas"),
77
- join(silgi.options.serverDir, "shared"),
78
- join(silgi.options.serverDir, "utils"),
79
- join(silgi.options.serverDir, "types"),
80
- join(silgi.options.silgi.serverDir, "config"),
81
- join(silgi.options.rootDir, "silgi.config.ts")
82
- );
83
- const watchReloadEvents = /* @__PURE__ */ new Set(["add", "addDir", "unlink", "unlinkDir", "change"]);
84
- if (silgi.options.devServer.watch.length > 0) {
85
- silgi.options.devServer.watch = [...new Set(silgi.options.devServer.watch)];
86
- watcher = watch(silgi.options.devServer.watch, silgi.options.watchOptions);
87
- watcher.on("all", async (event, path, stats) => {
88
- if (!watchReloadEvents.has(event)) {
89
- return;
90
- }
91
- const startTime = performance.now();
92
- silgi.errors = [];
93
- try {
94
- await reloadScan(path, stats);
95
- await reload();
96
- } catch (error) {
97
- consola.withTag("silgi").error(error);
98
- }
99
- silgi.errors = [];
100
- const endTime = performance.now();
101
- const elapsedTime = Math.round(endTime - startTime);
102
- silgi.logger.success(`${basename(path)} - ${elapsedTime}ms`);
103
- }).on("error", (error) => {
104
- consola.withTag("silgi").error(error);
105
- });
106
- }
107
- async function close() {
108
- await silgiCLIIClose();
109
- }
110
- return {
111
- watcher,
112
- close
113
- };
114
- }
115
-
116
- export { prepareBuild, watchDev };
@@ -1,13 +1,13 @@
1
- import consola, { consola as consola$1 } from 'consola';
1
+ import { consola } from 'consola';
2
2
  import { createHooks, createDebugger } from 'hookable';
3
- import { resolve, join, relative, dirname, basename, extname, isAbsolute } from 'pathe';
3
+ import { resolve, join, relative, extname, basename, dirname, isAbsolute } from 'pathe';
4
4
  import { useSilgiCLI, replaceRuntimeValues, silgiCLICtx, autoImportTypes } from 'silgi';
5
- import { isPresents, addTemplate, addCoreFile, relativeWithDot, hash, resolveAlias, directoryToURL, hasError, removeExtension, addImports, baseHeaderBannerComment, writeFile, parseServices, normalizeTemplate, useLogger, resolveSilgiPath, hasSilgiModule, genEnsureSafeVar, toArray, isDirectory } from 'silgi/kit';
5
+ import { isPresents, addTemplate, addCoreFile, relativeWithDot, hash, resolveAlias, directoryToURL, removeExtension, addImports, baseHeaderBannerComment, writeFile, parseServices, normalizeTemplate, useLogger, resolveSilgiPath, hasSilgiModule, genEnsureSafeVar, toArray, isDirectory } from 'silgi/kit';
6
6
  import { runtimeDir } from 'silgi/runtime/meta';
7
7
  import { scanExports, createUnimport, toExports } from 'unimport';
8
8
  import { c as createRouteRules } from '../_chunks/routeRules.mjs';
9
9
  import * as p from '@clack/prompts';
10
- import { existsSync, promises, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
10
+ import { existsSync, promises, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
11
11
  import * as dotenv from 'dotenv';
12
12
  import { findTypeExports, findExports, resolvePath, parseNodeModulePath, lookupNodeModuleSubpath } from 'mlly';
13
13
  import { createJiti } from 'dev-jiti';
@@ -16,10 +16,9 @@ import { fileURLToPath } from 'node:url';
16
16
  import { defu } from 'defu';
17
17
  import { resolveModuleURL } from 'exsolve';
18
18
  import { isRelative, withTrailingSlash } from 'ufo';
19
- import { readdir, readFile } from 'node:fs/promises';
19
+ import { readFile, readdir } from 'node:fs/promises';
20
20
  import { globby } from 'globby';
21
21
  import ignore from 'ignore';
22
- import { parseSync } from '@oxc-parser/wasm';
23
22
  import { genImport, genTypeImport, genObjectFromRawEntries, genObjectFromRaw, genObjectFromValues, genAugmentation } from 'knitwork';
24
23
  import { klona } from 'klona';
25
24
  import { useSilgiRuntimeConfig, initRuntimeConfig } from 'silgi/runtime';
@@ -757,312 +756,193 @@ function resolveGroupSyntax(group) {
757
756
  return groups;
758
757
  }
759
758
 
760
- const safeFiles = [
761
- "silgi/configs",
762
- "silgi",
763
- "silgi/rules",
764
- "silgi/scan",
765
- "silgi/vfs"
766
- ];
767
- class SchemaParser {
768
- options = {
769
- debug: false
759
+ const TYPE_DECLARATION_EXPORT_REGEX = /\bexport\s+(?<declaration>(interface|type|declare (async function|function|let|const enum|const|enum|var|class)))\s+(?<name>[\w$]+)(?:\s+extends\s+(?<extends>[\w$, \t\n\r]+))?/g;
760
+ const FUNCTION_VARIABLE_EXPORT_REGEX = /\bexport\s+(?:const|let|var)\s+(?<name>[\w$]+)\s*=\s*(?<funcName>\w+)\s*\(/g;
761
+ function extractExportMatches(regex, fileContent, additionalMetadata = {}) {
762
+ const matchedExports = [];
763
+ for (const match of fileContent.matchAll(regex)) {
764
+ const name = match.groups?.name || "";
765
+ const declaration = match.groups?.declaration || "";
766
+ const funcName = match.groups?.funcName || "";
767
+ const extendsClause = match.groups?.extends || "";
768
+ const codeSnippet = funcName ? `export const ${name} = ${funcName}(` : `export ${declaration} ${name}`;
769
+ const extendedTypes = extendsClause ? extendsClause.split(",").map((typeName) => typeName.trim()) : [];
770
+ matchedExports.push({
771
+ ...additionalMetadata,
772
+ name,
773
+ declaration,
774
+ funcName,
775
+ code: codeSnippet,
776
+ start: match.index,
777
+ end: (match.index || 0) + match[0].length,
778
+ extends: extendedTypes
779
+ });
780
+ }
781
+ return matchedExports;
782
+ }
783
+ function generateUniqueIdentifier(filePath, exportName) {
784
+ const fileBaseName = basename(filePath);
785
+ const uniqueString = `${fileBaseName}${exportName}`;
786
+ return hash(uniqueString);
787
+ }
788
+ function categorizeExports(exportedEntities, filePath) {
789
+ const runtimeExports = [];
790
+ const typeExports = [];
791
+ const functionExportCategories = {
792
+ createService: "service",
793
+ createSchema: "schema",
794
+ createShared: "shared"
770
795
  };
771
- /**
772
- *
773
- */
774
- constructor(options) {
775
- this.options = {
776
- ...this.options,
777
- ...options
778
- };
796
+ for (const [functionName, category] of Object.entries(functionExportCategories)) {
797
+ const matchingExports = exportedEntities.filter((entity) => entity.funcName === functionName);
798
+ for (const exportEntity of matchingExports) {
799
+ if (!exportEntity.name)
800
+ continue;
801
+ runtimeExports.push({
802
+ exportName: exportEntity.name,
803
+ path: filePath,
804
+ uniqueId: generateUniqueIdentifier(filePath, exportEntity.name),
805
+ category
806
+ });
807
+ }
779
808
  }
780
- parseExports(content, filePath) {
781
- const ast = parseSync(content, { sourceType: "module", sourceFilename: filePath });
782
- if (this.options.debug)
783
- writeFileSync(`${filePath}.ast.json`, JSON.stringify(ast.program, null, 2));
784
- return {
785
- exportVariables: (search, path) => this.parseTypeDeclarations(ast, search, path),
786
- parseInterfaceDeclarations: (search, path) => this.parseInterfaceDeclarations(ast, search, path)
787
- // parsePlugin: (path: string) => this.parsePlugin(ast, path),
788
- };
809
+ const interfaceExportCategories = {
810
+ ExtendShared: "shared",
811
+ ExtendContext: "context"
812
+ };
813
+ for (const [extensionName, category] of Object.entries(interfaceExportCategories)) {
814
+ const matchingExports = exportedEntities.filter(
815
+ (entity) => entity.declaration === "interface" && entity.extends?.includes(extensionName)
816
+ );
817
+ for (const exportEntity of matchingExports) {
818
+ if (!exportEntity.name)
819
+ continue;
820
+ typeExports.push({
821
+ exportName: exportEntity.name,
822
+ path: filePath,
823
+ uniqueId: generateUniqueIdentifier(filePath, exportEntity.name),
824
+ category
825
+ });
826
+ }
789
827
  }
790
- parseVariableDeclaration(ast, path) {
791
- const silgi = useSilgiCLI();
792
- if (ast.program.body.length === 0) {
793
- if (safeFiles.find((i) => path.includes(i)))
794
- return [];
795
- silgi.errors.push({
796
- type: "Parser",
797
- path
828
+ return { runtimeExports, typeExports };
829
+ }
830
+ function registerExportsWithHooks(silgiInstance, runtimeExports, typeExports) {
831
+ silgiInstance.hook("before:scan.ts", (options) => {
832
+ for (const { exportName, path, uniqueId, category } of runtimeExports) {
833
+ if (!path.includes("vfs")) {
834
+ silgiInstance.options.devServer.watch.push(path);
835
+ }
836
+ switch (category) {
837
+ case "service":
838
+ options.services.push(uniqueId);
839
+ break;
840
+ case "shared":
841
+ options.shareds.push(uniqueId);
842
+ break;
843
+ case "schema":
844
+ options.schemas.push(uniqueId);
845
+ break;
846
+ }
847
+ options.addImportItem({
848
+ specifier: removeExtension(relativeWithDot(silgiInstance.options.silgi.serverDir, path)),
849
+ imports: [{ name: exportName, as: uniqueId }]
798
850
  });
799
- consola.warn("This file has a problem:", path);
800
851
  }
801
- const variableDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "VariableDeclaration");
802
- return variableDeclarations;
803
- }
804
- parseTSInterfaceDeclaration(ast, path = "") {
805
- const silgi = useSilgiCLI();
806
- if (ast.program.body.length === 0) {
807
- if (safeFiles.find((i) => path.includes(i)))
808
- return [];
809
- silgi.errors.push({
810
- type: "Parser",
811
- path
852
+ });
853
+ silgiInstance.hook("before:schema.ts", (options) => {
854
+ for (const { exportName, path, uniqueId, category } of typeExports) {
855
+ if (!path.includes("vfs")) {
856
+ silgiInstance.options.devServer.watch.push(path);
857
+ }
858
+ if (category === "shared" || category === "context") {
859
+ const targetCollection = category === "shared" ? options.shareds : options.contexts;
860
+ targetCollection.push({ key: uniqueId, value: uniqueId });
861
+ }
862
+ options.addImportItem({
863
+ imports: [{ name: exportName, as: uniqueId }],
864
+ specifier: removeExtension(relativeWithDot(silgiInstance.options.build.typesDir, path))
812
865
  });
813
- consola.warn("This file has a problem:", path);
814
866
  }
815
- const interfaceDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "TSInterfaceDeclaration");
816
- return interfaceDeclarations;
817
- }
818
- parseTypeDeclarations(ast, find = "", path = "") {
819
- const data = [];
820
- const variableDeclarations = this.parseVariableDeclaration(ast, path);
821
- for (const item of variableDeclarations) {
822
- for (const declaration of item.declaration.declarations) {
823
- if (declaration.init?.callee?.name === find) {
824
- const options = {};
825
- if (declaration.init.arguments) {
826
- for (const argument of declaration.init.arguments) {
827
- for (const propertie of argument.properties) {
828
- if (propertie.key.name === "name")
829
- options.pluginName = propertie.value.value;
830
- }
831
- }
832
- }
833
- for (const key in declaration.init.properties) {
834
- const property = declaration.init.properties[key];
835
- if (property.type === "ObjectProperty") {
836
- if (property.key.name === "options") {
837
- for (const key2 in property.value.properties) {
838
- const option = property.value.properties[key2];
839
- if (option.type === "ObjectProperty") {
840
- options[option.key.name] = option.value.value;
841
- }
842
- }
843
- }
844
- }
845
- }
846
- options.type = false;
847
- data.push({
848
- exportName: declaration.id.name,
849
- options,
850
- // object: declaration.init,
851
- path
852
- });
853
- }
867
+ });
868
+ }
869
+ async function verifyDirectoryCaseSensitivity(directoryPath, rootDirectory) {
870
+ const directoryName = basename(directoryPath);
871
+ const parentDirectory = dirname(directoryPath);
872
+ try {
873
+ const siblingEntries = await readdir(parentDirectory);
874
+ if (!siblingEntries.includes(directoryName)) {
875
+ const directoryNameLowerCase = directoryName.toLowerCase();
876
+ const caseInsensitiveMatch = siblingEntries.find(
877
+ (sibling) => sibling.toLowerCase() === directoryNameLowerCase
878
+ );
879
+ if (caseInsensitiveMatch) {
880
+ const originalRelative = relative(rootDirectory, directoryPath);
881
+ const correctedRelative = relative(
882
+ rootDirectory,
883
+ join(parentDirectory, caseInsensitiveMatch)
884
+ );
885
+ consola.warn(
886
+ `Components not scanned from \`~/${correctedRelative}\`. Did you mean to name the directory \`~/${originalRelative}\` instead?`
887
+ );
854
888
  }
855
889
  }
856
- return data;
890
+ } catch {
857
891
  }
858
- parseInterfaceDeclarations(ast, find = "", path = "") {
859
- const data = [];
860
- for (const item of this.parseTSInterfaceDeclaration(ast, path)) {
861
- if (!item?.declaration?.extends)
862
- continue;
863
- for (const declaration of item?.declaration?.extends) {
864
- if (declaration.expression.name === find) {
865
- const options = {};
866
- options.type = true;
867
- data.push({
868
- exportName: item.declaration.id.name,
869
- options,
870
- // object: declaration.init,
871
- path
872
- });
873
- }
874
- }
875
- }
876
- return data;
877
- }
878
- // private parsePlugin(ast: any, path: string = '') {
879
- // const data = {
880
- // export: [],
881
- // name: '',
882
- // path: '',
883
- // } as DataTypePlugin
884
- // for (const item of this.parseVariableDeclaration(ast)) {
885
- // for (const declaration of item.declaration.declarations) {
886
- // if (declaration.init.callee?.name === 'defineSilgiModule') {
887
- // if (declaration.init.arguments) {
888
- // for (const argument of declaration.init.arguments) {
889
- // for (const propertie of argument.properties) {
890
- // if (propertie.key.name === 'name')
891
- // data.name = propertie.value.value
892
- // }
893
- // }
894
- // }
895
- // data.export.push({
896
- // name: data.name,
897
- // as: camelCase(`${data.name}DefineSilgiModule`),
898
- // type: false,
899
- // })
900
- // }
901
- // }
902
- // }
903
- // for (const item of this.parseTSInterfaceDeclaration(ast)) {
904
- // if (!item?.declaration?.extends)
905
- // continue
906
- // for (const declaration of item?.declaration?.extends) {
907
- // if (declaration.expression.name === 'ModuleOptions') {
908
- // data.export.push({
909
- // name: item.declaration.id.name,
910
- // as: camelCase(`${data.name}ModuleOptions`),
911
- // type: true,
912
- // })
913
- // }
914
- // // TODO add other plugins
915
- // }
916
- // }
917
- // data.path = path
918
- // return data
919
- // }
920
892
  }
921
-
922
- async function scanExportFile(silgi) {
923
- const filePaths = /* @__PURE__ */ new Set();
924
- const scannedPaths = [];
925
- const dir = silgi.options.serverDir;
926
- const files = (await globby(dir, { cwd: silgi.options.rootDir, ignore: silgi.options.ignore })).sort();
927
- if (files.length) {
928
- const siblings = await readdir(dirname(dir)).catch(() => []);
929
- const directory = basename(dir);
930
- if (!siblings.includes(directory)) {
931
- const directoryLowerCase = directory.toLowerCase();
932
- const caseCorrected = siblings.find((sibling) => sibling.toLowerCase() === directoryLowerCase);
933
- if (caseCorrected) {
934
- const original = relative(silgi.options.serverDir, dir);
935
- const corrected = relative(silgi.options.serverDir, join(dirname(dir), caseCorrected));
936
- consola$1.warn(`Components not scanned from \`~/${corrected}\`. Did you mean to name the directory \`~/${original}\` instead?`);
937
- }
938
- }
893
+ async function scanExportFile(silgiInstance) {
894
+ const processedFilePaths = /* @__PURE__ */ new Set();
895
+ const alreadyScannedPaths = [];
896
+ const serverDirectory = silgiInstance.options.serverDir;
897
+ if (!serverDirectory) {
898
+ consola.warn("No server directory specified for scanning");
899
+ return;
939
900
  }
940
- for (const _file of files) {
941
- const filePath = resolve(dir, _file);
942
- if (scannedPaths.find((d) => filePath.startsWith(withTrailingSlash(d))) || isIgnored(filePath, silgi)) {
943
- continue;
944
- }
945
- if (filePaths.has(filePath)) {
946
- continue;
901
+ try {
902
+ const matchedFiles = await globby(serverDirectory, {
903
+ cwd: silgiInstance.options.rootDir,
904
+ ignore: silgiInstance.options.ignore
905
+ });
906
+ if (matchedFiles.length) {
907
+ await verifyDirectoryCaseSensitivity(
908
+ serverDirectory,
909
+ silgiInstance.options.rootDir
910
+ );
947
911
  }
948
- filePaths.add(filePath);
949
- if (silgi.options.extensions.includes(extname(filePath))) {
950
- const parser = new SchemaParser({
951
- debug: false
952
- });
953
- const readfile = await readFile(filePath, "utf-8");
954
- const { exportVariables, parseInterfaceDeclarations } = parser.parseExports(readfile, filePath);
955
- const createServices = exportVariables("createService", filePath);
956
- if (hasError("Parser", silgi)) {
957
- return;
958
- }
959
- const scanTS = [];
960
- const schemaTS = [];
961
- if (createServices.length > 0) {
962
- scanTS.push(...createServices.map(({ exportName, path }) => {
963
- const randomString = hash(basename(path) + exportName);
964
- const _name = `_v${randomString}`;
965
- return { exportName, path, _name, type: "service" };
966
- }));
967
- }
968
- const createSchemas = exportVariables("createSchema", filePath);
969
- if (hasError("Parser", silgi)) {
970
- return;
971
- }
972
- if (createSchemas.length > 0) {
973
- scanTS.push(...createSchemas.map(({ exportName, path }) => {
974
- const randomString = hash(basename(path) + exportName);
975
- const _name = `_v${randomString}`;
976
- return { exportName, path, _name, type: "schema" };
977
- }));
978
- }
979
- const createShareds = exportVariables("createShared", filePath);
980
- if (hasError("Parser", silgi)) {
981
- return;
982
- }
983
- if (createShareds.length > 0) {
984
- scanTS.push(...createShareds.map(({ exportName, path }) => {
985
- const randomString = hash(basename(path) + exportName);
986
- const _name = `_v${randomString}`;
987
- return { exportName, path, _name, type: "shared" };
988
- }));
989
- }
990
- const sharedsTypes = parseInterfaceDeclarations("ExtendShared", filePath);
991
- if (hasError("Parser", silgi)) {
992
- return;
912
+ for (const relativeFilePath of matchedFiles.sort()) {
913
+ const absoluteFilePath = resolve(silgiInstance.options.rootDir, relativeFilePath);
914
+ if (alreadyScannedPaths.find((path) => absoluteFilePath.startsWith(withTrailingSlash(path))) || isIgnored(absoluteFilePath, silgiInstance) || processedFilePaths.has(absoluteFilePath)) {
915
+ continue;
993
916
  }
994
- if (sharedsTypes.length > 0) {
995
- schemaTS.push(...sharedsTypes.map(({ exportName, path }) => {
996
- const randomString = hash(basename(path) + exportName);
997
- const _name = `_v${randomString}`;
998
- return { exportName, path, _name, type: "shared" };
999
- }));
917
+ processedFilePaths.add(absoluteFilePath);
918
+ const fileExtension = extname(absoluteFilePath);
919
+ if (!silgiInstance.options.extensions?.includes(fileExtension)) {
920
+ continue;
1000
921
  }
1001
- const contextTypes = parseInterfaceDeclarations("ExtendContext", filePath);
1002
- if (hasError("Parser", silgi)) {
1003
- return;
922
+ try {
923
+ const fileContent = await readFile(absoluteFilePath, "utf-8");
924
+ const typeDeclarationExports = extractExportMatches(
925
+ TYPE_DECLARATION_EXPORT_REGEX,
926
+ fileContent,
927
+ { type: "declaration" }
928
+ );
929
+ const functionVariableExports = extractExportMatches(
930
+ FUNCTION_VARIABLE_EXPORT_REGEX,
931
+ fileContent,
932
+ { type: "variable" }
933
+ );
934
+ const allExportedEntities = [...typeDeclarationExports, ...functionVariableExports];
935
+ const { runtimeExports, typeExports } = categorizeExports(
936
+ allExportedEntities,
937
+ absoluteFilePath
938
+ );
939
+ registerExportsWithHooks(silgiInstance, runtimeExports, typeExports);
940
+ } catch (error) {
941
+ consola.error(`Error processing file ${absoluteFilePath}:`, error);
1004
942
  }
1005
- if (contextTypes.length > 0) {
1006
- schemaTS.push(...contextTypes.map(({ exportName, path }) => {
1007
- const randomString = hash(basename(path) + exportName);
1008
- const _name = `_v${randomString}`;
1009
- return { exportName, path, _name, type: "context" };
1010
- }));
1011
- }
1012
- silgi.hook("before:scan.ts", (options) => {
1013
- for (const { exportName, path, _name, type } of scanTS) {
1014
- if (!path.includes("vfs")) {
1015
- silgi.options.devServer.watch.push(path);
1016
- }
1017
- if (type === "service") {
1018
- options.services.push(_name);
1019
- }
1020
- if (type === "shared") {
1021
- options.shareds.push(_name);
1022
- }
1023
- if (type === "schema") {
1024
- options.schemas.push(_name);
1025
- }
1026
- options.addImportItem({
1027
- specifier: removeExtension(relativeWithDot(silgi.options.silgi.serverDir, path)),
1028
- imports: [
1029
- {
1030
- name: exportName,
1031
- as: _name
1032
- }
1033
- ]
1034
- });
1035
- }
1036
- });
1037
- silgi.hook("before:schema.ts", (options) => {
1038
- for (const { exportName, path, _name, type } of schemaTS) {
1039
- if (!path.includes("vfs")) {
1040
- silgi.options.devServer.watch.push(path);
1041
- }
1042
- if (type === "shared") {
1043
- options.shareds.push({
1044
- key: _name,
1045
- value: _name
1046
- });
1047
- }
1048
- if (type === "context") {
1049
- options.contexts.push({
1050
- key: _name,
1051
- value: _name
1052
- });
1053
- }
1054
- options.addImportItem({
1055
- imports: [
1056
- {
1057
- name: exportName,
1058
- as: _name
1059
- }
1060
- ],
1061
- specifier: removeExtension(relativeWithDot(silgi.options.build.typesDir, path))
1062
- });
1063
- }
1064
- });
1065
943
  }
944
+ } catch (error) {
945
+ consola.error("Error scanning export files:", error);
1066
946
  }
1067
947
  }
1068
948
 
@@ -1153,7 +1033,7 @@ ${injectedResult.code}`;
1153
1033
  if (silgi.options.debug) {
1154
1034
  console.error("Failed to read scan.ts file:", error);
1155
1035
  } else {
1156
- consola$1.withTag("silgi").error(error);
1036
+ consola.withTag("silgi").error(error);
1157
1037
  }
1158
1038
  return {
1159
1039
  context,
@@ -1572,7 +1452,7 @@ async function createSilgiCLI(config = {}, opts = {}) {
1572
1452
  hooks,
1573
1453
  errors: [],
1574
1454
  _requiredModules: {},
1575
- logger: opts.consola || consola$1.withTag("silgi"),
1455
+ logger: opts.consola || consola.withTag("silgi"),
1576
1456
  close: () => silgi.hooks.callHook("close", silgi),
1577
1457
  storage: void 0,
1578
1458
  scanModules: [],
@@ -1680,7 +1560,7 @@ async function generateApiFul(silgi) {
1680
1560
  Object.entries(config?.services ?? {}).filter(([, service]) => Boolean(service.schema))
1681
1561
  );
1682
1562
  if (Object.keys(resolvedOpenAPIServices).length === 0) {
1683
- consola$1.info("No OpenAPI schemas found, skipping generation");
1563
+ consola.info("No OpenAPI schemas found, skipping generation");
1684
1564
  return;
1685
1565
  }
1686
1566
  for (const service of Object.values(resolvedOpenAPIServices)) {
@@ -0,0 +1,83 @@
1
+ import { watch } from 'chokidar';
2
+ import consola from 'consola';
3
+ import { join, basename } from 'pathe';
4
+ import { debounce } from 'perfect-debounce';
5
+ import { u as useSilgiCLI$1, a as silgiCLIIClose } from '../_chunks/silgiApp.mjs';
6
+ import { useSilgiCLI } from 'silgi';
7
+ import { c as createSilgiCLI, b as build } from './build.mjs';
8
+
9
+ async function reloadScan(path, _stats) {
10
+ const silgi = useSilgiCLI();
11
+ await silgi.callHook("reload:scan", path, _stats);
12
+ }
13
+
14
+ async function prepareBuild(config) {
15
+ const silgi = await createSilgiCLI({
16
+ commandType: config?.commandType || "prepare",
17
+ ...config
18
+ });
19
+ await build(silgi);
20
+ return silgi;
21
+ }
22
+
23
+ async function watchDev() {
24
+ let watcher;
25
+ async function load() {
26
+ await prepareBuild({
27
+ commandType: "prepare",
28
+ activeEnvironment: ".env"
29
+ });
30
+ }
31
+ const reload = debounce(load);
32
+ const silgi = useSilgiCLI$1();
33
+ silgi.options.watchOptions.ignored ??= [];
34
+ silgi.options.watchOptions.ignoreInitial = true;
35
+ if (Array.isArray(silgi.options.watchOptions.ignored)) {
36
+ silgi.options.watchOptions.ignored.push(
37
+ `!${join(silgi.options.silgi.serverDir, "config")}`
38
+ );
39
+ }
40
+ silgi.options.devServer.watch.push(
41
+ join(silgi.options.serverDir, "services"),
42
+ join(silgi.options.serverDir, "schemas"),
43
+ join(silgi.options.serverDir, "shared"),
44
+ join(silgi.options.serverDir, "utils"),
45
+ join(silgi.options.serverDir, "types"),
46
+ join(silgi.options.silgi.serverDir, "config"),
47
+ join(silgi.options.silgi.serverDir, "modules"),
48
+ join(silgi.options.rootDir, "silgi.config.ts")
49
+ );
50
+ const watchReloadEvents = /* @__PURE__ */ new Set(["add", "addDir", "unlink", "unlinkDir", "change"]);
51
+ if (silgi.options.devServer.watch.length > 0) {
52
+ silgi.options.devServer.watch = [...new Set(silgi.options.devServer.watch)];
53
+ watcher = watch(silgi.options.devServer.watch, silgi.options.watchOptions);
54
+ watcher.on("all", async (event, path, stats) => {
55
+ if (!watchReloadEvents.has(event)) {
56
+ return;
57
+ }
58
+ const startTime = performance.now();
59
+ silgi.errors = [];
60
+ try {
61
+ await reloadScan(path, stats);
62
+ await reload();
63
+ } catch (error) {
64
+ consola.withTag("silgi").error(error);
65
+ }
66
+ silgi.errors = [];
67
+ const endTime = performance.now();
68
+ const elapsedTime = Math.round(endTime - startTime);
69
+ silgi.logger.success(`${basename(path)} - ${elapsedTime}ms`);
70
+ }).on("error", (error) => {
71
+ consola.withTag("silgi").error(error);
72
+ });
73
+ }
74
+ async function close() {
75
+ await silgiCLIIClose();
76
+ }
77
+ return {
78
+ watcher,
79
+ close
80
+ };
81
+ }
82
+
83
+ export { prepareBuild as p, watchDev as w };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { defineCommand, runMain } from 'citty';
3
3
 
4
- const version = "0.30.5";
4
+ const version = "0.31.0";
5
5
  const packageJson = {
6
6
  version: version};
7
7
 
package/dist/cli/init.mjs CHANGED
@@ -24,7 +24,6 @@ import 'defu';
24
24
  import 'exsolve';
25
25
  import 'globby';
26
26
  import 'ignore';
27
- import '@oxc-parser/wasm';
28
27
  import 'knitwork';
29
28
  import 'klona';
30
29
  import 'silgi/runtime';
@@ -27,7 +27,6 @@ import 'exsolve';
27
27
  import 'node:fs/promises';
28
28
  import 'globby';
29
29
  import 'ignore';
30
- import '@oxc-parser/wasm';
31
30
  import 'knitwork';
32
31
  import 'klona';
33
32
  import 'silgi/runtime';
@@ -1,14 +1,14 @@
1
- import { basename } from 'node:path';
2
- import { watch } from 'chokidar';
3
1
  import { defineCommand, runCommand } from 'citty';
4
2
  import consola from 'consola';
5
- import { join } from 'pathe';
6
- import { useSilgiCLI } from 'silgi';
7
3
  import { version } from 'silgi/meta';
8
- import { a as silgiCLIIClose } from '../_chunks/silgiApp.mjs';
9
- import { r as reloadScan } from './devServer.mjs';
4
+ import { w as watchDev } from './dev.mjs';
10
5
  import { b as commonArgs, a as command$1 } from './prepare.mjs';
6
+ import 'chokidar';
7
+ import 'pathe';
8
+ import 'perfect-debounce';
9
+ import '../_chunks/silgiApp.mjs';
11
10
  import 'unctx';
11
+ import 'silgi';
12
12
  import './build.mjs';
13
13
  import 'hookable';
14
14
  import 'silgi/kit';
@@ -29,7 +29,6 @@ import 'exsolve';
29
29
  import 'node:fs/promises';
30
30
  import 'globby';
31
31
  import 'ignore';
32
- import '@oxc-parser/wasm';
33
32
  import 'knitwork';
34
33
  import 'klona';
35
34
  import 'silgi/runtime';
@@ -69,56 +68,13 @@ const command = defineCommand({
69
68
  await runCommand(command$1, {
70
69
  rawArgs: ["--commandType", "dev", "--dev", "true"]
71
70
  });
72
- const silgi = useSilgiCLI();
73
- silgi.options.watchOptions.ignored ??= [];
74
- silgi.options.watchOptions.ignoreInitial = true;
75
- if (Array.isArray(silgi.options.watchOptions.ignored)) {
76
- silgi.options.watchOptions.ignored.push(
77
- `!${join(silgi.options.silgi.serverDir, "config")}`
78
- );
79
- }
80
- silgi.options.devServer.watch.push(
81
- join(silgi.options.serverDir, "services"),
82
- join(silgi.options.serverDir, "schemas"),
83
- join(silgi.options.serverDir, "shared"),
84
- join(silgi.options.serverDir, "utils"),
85
- join(silgi.options.serverDir, "types"),
86
- join(silgi.options.silgi.serverDir, "config"),
87
- join(silgi.options.rootDir, "silgi.config.ts")
88
- );
89
- const watchReloadEvents = /* @__PURE__ */ new Set(["add", "addDir", "unlink", "unlinkDir", "change"]);
90
- let watcher;
91
- if (silgi.options.devServer.watch.length > 0) {
92
- silgi.options.devServer.watch = [...new Set(silgi.options.devServer.watch)];
93
- watcher = watch(silgi.options.devServer.watch, silgi.options.watchOptions);
94
- watcher.on("all", async (event, path, stats) => {
95
- if (!watchReloadEvents.has(event)) {
96
- return;
97
- }
98
- const startTime = performance.now();
99
- silgi.errors = [];
100
- try {
101
- await reloadScan(path, stats);
102
- await runCommand(command$1, {
103
- rawArgs: ["--commands", "run", "--dev", "true"]
104
- });
105
- } catch (error) {
106
- consola.withTag("silgi").error(error);
107
- }
108
- silgi.errors = [];
109
- const endTime = performance.now();
110
- const elapsedTime = Math.round(endTime - startTime);
111
- silgi.logger.success(`${basename(path)} - ${elapsedTime}ms`);
112
- }).on("error", (error) => {
113
- consola.withTag("silgi").error(error);
114
- });
115
- }
71
+ const watch = await watchDev();
116
72
  process.on("SIGINT", async () => {
117
73
  consola.withTag("silgi").info("Shutting down...");
118
- if (watcher) {
119
- watcher.close();
74
+ if (watch) {
75
+ watch.close();
120
76
  }
121
- await silgiCLIIClose();
77
+ await watch.close();
122
78
  process.exit(0);
123
79
  });
124
80
  consola.withTag("silgi").success("Prepare completed");
@@ -10,8 +10,10 @@ import { PresetName, PresetOptions, PresetNameInput } from 'silgi/presets';
10
10
  import { ResolvedServiceType as ResolvedServiceType$1, SilgiRuntimeShareds as SilgiRuntimeShareds$1, SilgiRuntimeOptions as SilgiRuntimeOptions$1, RouteRules as RouteRules$1, ModuleMeta as ModuleMeta$1, SilgiModule as SilgiModule$1, BuildSilgi as BuildSilgi$1, Commands as Commands$1, SilgiRouteRules as SilgiRouteRules$1, DotenvOptions as DotenvOptions$1, EnvOptions as EnvOptions$1, SilgiRuntimeConfig as SilgiRuntimeConfig$1, ServiceParseModule as ServiceParseModule$1, SilgiCLIHooks as SilgiCLIHooks$1, StorageMounts as StorageMounts$1, SilgiTemplate as SilgiTemplate$1, SilgiFrameworkInfo as SilgiFrameworkInfo$1 } from 'silgi/types';
11
11
  import { Adapter, TablesSchema, InferModelTypes } from 'unadapter/types';
12
12
  import { UnimportPluginOptions } from 'unimport/unplugin';
13
- import { Router, H3Event } from 'h3';
14
- import { NitroApp, NitroRuntimeConfig } from 'nitropack/types';
13
+ import * as h3 from 'h3';
14
+ import { H3Event } from 'h3';
15
+ import * as nitropack_types from 'nitropack/types';
16
+ import { NitroRuntimeConfig } from 'nitropack/types';
15
17
  import { Defu } from 'defu';
16
18
  import { Stats } from 'node:fs';
17
19
  import { ESMImport, ESMCodeGenOptions } from 'knitwork';
@@ -153,7 +155,7 @@ interface GenImport {
153
155
  imports: ESMImport | ESMImport[];
154
156
  options?: ESMCodeGenOptions;
155
157
  }
156
- type Framework<T extends PresetName> = T extends 'nitro' ? NitroApp : T extends 'nuxt' ? NitroApp : T extends 'h3' ? Router : never;
158
+ type Framework<T extends PresetName> = T extends 'nitro' ? nitropack_types.NitroApp : T extends 'nuxt' ? nitropack_types.NitroApp : T extends 'h3' ? h3.Router : never;
157
159
  interface DefineFrameworkOptions<T extends PresetName> extends Omit<BuildSilgi$1, 'framework'> {
158
160
  framework: Framework<T>;
159
161
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "silgi",
3
3
  "type": "module",
4
- "version": "0.30.5",
4
+ "version": "0.31.0",
5
5
  "private": false,
6
6
  "sideEffects": false,
7
7
  "exports": {
@@ -81,7 +81,6 @@
81
81
  "dependencies": {
82
82
  "@clack/prompts": "^0.10.1",
83
83
  "@fastify/deepmerge": "^3.1.0",
84
- "@oxc-parser/wasm": "^0.60.0",
85
84
  "@standard-schema/spec": "^1.0.0",
86
85
  "apiful": "^2.1.0",
87
86
  "c12": "^3.0.3",
@@ -124,7 +123,7 @@
124
123
  "@antfu/eslint-config": "^4.12.0",
125
124
  "@nuxt/kit": "^3.16.2",
126
125
  "@nuxt/schema": "^3.16.2",
127
- "@silgi/ecosystem": "^0.6.0",
126
+ "@silgi/ecosystem": "^0.6.2",
128
127
  "@types/node": "^22.15.2",
129
128
  "@types/semver": "^7.7.0",
130
129
  "@vitest/coverage-v8": "3.0.5",
@@ -1,8 +0,0 @@
1
- import { useSilgiCLI } from 'silgi';
2
-
3
- async function reloadScan(path, _stats) {
4
- const silgi = useSilgiCLI();
5
- await silgi.callHook("reload:scan", path, _stats);
6
- }
7
-
8
- export { reloadScan as r };