silgi 0.24.15 → 0.24.17

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.
Files changed (91) hide show
  1. package/dist/cli/build/prepare.mjs +43 -0
  2. package/dist/cli/{dev.mjs → commands/dev.mjs} +4 -43
  3. package/dist/cli/commands/env.mjs +40 -0
  4. package/dist/cli/{install.mjs → commands/install.mjs} +3 -37
  5. package/dist/cli/commands/prepare.mjs +66 -0
  6. package/dist/cli/{prepare.mjs → commands/run.mjs} +9 -82
  7. package/dist/cli/config/defaults.mjs +129 -0
  8. package/dist/cli/config/index.mjs +2 -16
  9. package/dist/cli/config/loader.mjs +97 -0
  10. package/dist/cli/config/resolvers/compatibility.mjs +90 -0
  11. package/dist/cli/config/resolvers/imports.mjs +96 -0
  12. package/dist/cli/config/resolvers/paths.mjs +167 -0
  13. package/dist/cli/config/resolvers/storage.mjs +25 -0
  14. package/dist/cli/config/resolvers/url.mjs +7 -0
  15. package/dist/cli/config/types.mjs +191 -0
  16. package/dist/cli/core/app.mjs +92 -0
  17. package/dist/cli/core/devServer.mjs +8 -0
  18. package/dist/cli/core/env.mjs +76 -0
  19. package/dist/cli/core/installPackage.mjs +31 -0
  20. package/dist/cli/core/prepare.mjs +7 -0
  21. package/dist/cli/core/runtimeConfig.mjs +14 -0
  22. package/dist/cli/core/scan.mjs +39 -0
  23. package/dist/cli/core/silgi.mjs +125 -0
  24. package/dist/cli/core/templates.mjs +31 -0
  25. package/dist/cli/framework/emptyFramework.mjs +9 -0
  26. package/dist/cli/framework/h3.mjs +89 -0
  27. package/dist/cli/framework/index.mjs +8 -0
  28. package/dist/cli/framework/nitro.mjs +106 -0
  29. package/dist/cli/framework/nuxt.mjs +9 -0
  30. package/dist/cli/index.mjs +6 -9
  31. package/dist/cli/module/exportScan.mjs +130 -0
  32. package/dist/cli/module/install.mjs +59 -0
  33. package/dist/cli/module/scan.mjs +227 -0
  34. package/dist/cli/scan/commands.mjs +47 -0
  35. package/dist/cli/scan/prepareConfigs.mjs +46 -0
  36. package/dist/cli/scan/prepareCoreFile.mjs +166 -0
  37. package/dist/cli/scan/prepareFramework.mjs +73 -0
  38. package/dist/cli/scan/prepareSchema.mjs +177 -0
  39. package/dist/cli/scan/prepareServerFiles.mjs +119 -0
  40. package/dist/cli/scan/scanExportFile.mjs +155 -0
  41. package/dist/cli/scan/writeCoreFile.mjs +34 -0
  42. package/dist/cli/scan/writeScanFiles.mjs +30 -0
  43. package/dist/cli/scan/writeTypesAndFiles.mjs +109 -0
  44. package/dist/cli/utils/build-uri-map.mjs +39 -0
  45. package/dist/cli/utils/common.mjs +13 -0
  46. package/dist/cli/{compatibility.mjs → utils/compatibility.mjs} +1 -1
  47. package/dist/cli/utils/generateRouterDTS.mjs +80 -0
  48. package/dist/cli/utils/ignore.mjs +46 -0
  49. package/dist/cli/utils/parser.mjs +168 -0
  50. package/dist/cli/utils/readScanFile.mjs +79 -0
  51. package/dist/cli/utils/storage.mjs +25 -0
  52. package/dist/core/createSilgi.mjs +76 -0
  53. package/dist/core/error.mjs +227 -0
  54. package/dist/core/index.mjs +8 -0
  55. package/dist/core/routeRules.mjs +288 -0
  56. package/dist/core/silgi.mjs +128 -0
  57. package/dist/core/silgiApp.mjs +25 -0
  58. package/dist/core/storage.mjs +15 -0
  59. package/dist/core/unctx.mjs +27 -0
  60. package/dist/core/uris/uri.mjs +33 -0
  61. package/dist/core/uris/utils.mjs +130 -0
  62. package/dist/core/utils/event.mjs +15 -0
  63. package/dist/core/utils/merge.mjs +29 -0
  64. package/dist/core/utils/runtime.mjs +22 -0
  65. package/dist/core/utils/schema.mjs +5 -0
  66. package/dist/core/utils/service.mjs +5 -0
  67. package/dist/core/utils/shared.mjs +5 -0
  68. package/dist/core/utils/storage.mjs +72 -0
  69. package/dist/index.mjs +20 -793
  70. package/dist/kit/errors.mjs +11 -0
  71. package/dist/kit/esm.mjs +14 -0
  72. package/dist/kit/fs.mjs +30 -0
  73. package/dist/kit/gen.mjs +44 -0
  74. package/dist/kit/hash.mjs +8 -0
  75. package/dist/kit/index.mjs +15 -528
  76. package/dist/kit/isFramework.mjs +25 -0
  77. package/dist/kit/logger.mjs +7 -0
  78. package/dist/kit/module.mjs +73 -0
  79. package/dist/kit/parseServices.mjs +57 -0
  80. package/dist/kit/path.mjs +34 -0
  81. package/dist/kit/preset.mjs +6 -0
  82. package/dist/kit/resolve.mjs +80 -0
  83. package/dist/kit/template.mjs +49 -0
  84. package/dist/kit/useRequest.mjs +91 -0
  85. package/dist/kit/utils.mjs +43 -0
  86. package/dist/package.json.mjs +5 -0
  87. package/dist/types/index.d.mts +1 -1
  88. package/package.json +1 -1
  89. package/dist/_chunks/silgiApp.mjs +0 -2682
  90. package/dist/cli/types.mjs +0 -772
  91. /package/dist/cli/{init.mjs → commands/init.mjs} +0 -0
@@ -0,0 +1,80 @@
1
+ async function generateRouterDTS(silgi) {
2
+ const uris = silgi.uris;
3
+ const subPath = "srn";
4
+ const groupedPaths = /* @__PURE__ */ new Map();
5
+ Object.entries(uris || {}).forEach(([key, params]) => {
6
+ const [service, resource, method, action] = key.split("/");
7
+ const basePath = params ? `${subPath}/${service}/${resource}/${action}/${params}` : `${subPath}/${service}/${resource}/${action}`;
8
+ const fullPath = `${subPath}/${service}/${resource}/${action}`;
9
+ if (!groupedPaths.has(basePath)) {
10
+ groupedPaths.set(basePath, /* @__PURE__ */ new Map());
11
+ }
12
+ groupedPaths.get(basePath)?.set(method.toLowerCase(), fullPath);
13
+ });
14
+ const keys = [
15
+ " keys: {",
16
+ Array.from(groupedPaths.entries()).map(([basePath, methods]) => {
17
+ return ` '/${basePath}': {${Array.from(methods.entries()).map(([method, path]) => `
18
+ ${method}: '/${path}'`).join(",")}
19
+ }`;
20
+ }).join(",\n"),
21
+ " }",
22
+ ""
23
+ ].join("\n");
24
+ const groupedRoutes = Object.entries(uris || {}).reduce((acc, [key, _params]) => {
25
+ const [service, resource, method, action] = key.split("/");
26
+ const routePath = `${subPath}/${service}/${resource}/${action}`;
27
+ if (!acc[routePath]) {
28
+ acc[routePath] = {};
29
+ }
30
+ acc[routePath][method] = {
31
+ input: `ExtractInputFromURI<'${key}'>`,
32
+ output: `ExtractOutputFromURI<'${key}'>`,
33
+ queryParams: `ExtractQueryParamsFromURI<'${key}'>`,
34
+ pathParams: `ExtractPathParamsFromURI<'${key}'>`
35
+ };
36
+ return acc;
37
+ }, {});
38
+ const routerTypes = Object.entries(groupedRoutes).map(([path, methods]) => {
39
+ const methodEntries = Object.entries(methods).map(([method, { input, output, queryParams, pathParams }]) => {
40
+ return ` '${method}': {
41
+ input: ${input},
42
+ output: ${output},
43
+ queryParams: ${queryParams},
44
+ pathParams: ${pathParams}
45
+ }`;
46
+ }).join(",\n");
47
+ return ` '/${path}': {
48
+ ${methodEntries}
49
+ }`;
50
+ });
51
+ const nitro = [
52
+ "declare module 'nitropack/types' {",
53
+ " interface InternalApi extends RouterTypes {}",
54
+ "}"
55
+ ];
56
+ const content = [
57
+ keys.slice(0, -1),
58
+ // son satırdaki boş satırı kaldır
59
+ ...routerTypes
60
+ ].join(",\n");
61
+ const context = [
62
+ "import type { ExtractInputFromURI, ExtractOutputFromURI, ExtractQueryParamsFromURI, ExtractPathParamsFromURI } from 'silgi/types'",
63
+ "",
64
+ "export interface RouterTypes {",
65
+ content,
66
+ "}",
67
+ "",
68
+ "declare module 'silgi/types' {",
69
+ " interface SilgiRouterTypes extends RouterTypes {",
70
+ " }",
71
+ "}",
72
+ "",
73
+ silgi.options.preset === "h3" || silgi.options.preset === "nitro" ? nitro.join("\n") : "",
74
+ "",
75
+ "export {}"
76
+ ];
77
+ return context;
78
+ }
79
+
80
+ export { generateRouterDTS };
@@ -0,0 +1,46 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import ignore from 'ignore';
3
+ import { relative, join } from 'pathe';
4
+
5
+ function resolveIgnorePatterns(silgi, relativePath) {
6
+ if (!silgi) {
7
+ return [];
8
+ }
9
+ const ignorePatterns = silgi.options.ignore.flatMap((s) => resolveGroupSyntax(s));
10
+ const nuxtignoreFile = join(silgi.options.rootDir, ".nuxtignore");
11
+ if (existsSync(nuxtignoreFile)) {
12
+ const contents = readFileSync(nuxtignoreFile, "utf-8");
13
+ ignorePatterns.push(...contents.trim().split(/\r?\n/));
14
+ }
15
+ return ignorePatterns;
16
+ }
17
+ function isIgnored(pathname, silgi, _stats) {
18
+ if (!silgi) {
19
+ return false;
20
+ }
21
+ if (!silgi._ignore) {
22
+ silgi._ignore = ignore(silgi.options.ignoreOptions);
23
+ silgi._ignore.add(resolveIgnorePatterns(silgi));
24
+ }
25
+ const relativePath = relative(silgi.options.rootDir, pathname);
26
+ if (relativePath[0] === "." && relativePath[1] === ".") {
27
+ return false;
28
+ }
29
+ return !!(relativePath && silgi._ignore.ignores(relativePath));
30
+ }
31
+ function resolveGroupSyntax(group) {
32
+ let groups = [group];
33
+ while (groups.some((group2) => group2.includes("{"))) {
34
+ groups = groups.flatMap((group2) => {
35
+ const [head, ...tail] = group2.split("{");
36
+ if (tail.length) {
37
+ const [body = "", ...rest] = tail.join("{").split("}");
38
+ return body.split(",").map((part) => `${head}${part}${rest.join("")}`);
39
+ }
40
+ return group2;
41
+ });
42
+ }
43
+ return groups;
44
+ }
45
+
46
+ export { isIgnored, resolveGroupSyntax, resolveIgnorePatterns };
@@ -0,0 +1,168 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { parseSync } from '@oxc-parser/wasm';
3
+ import consola from 'consola';
4
+ import { useSilgiCLI } from 'silgi';
5
+
6
+ const safeFiles = [
7
+ "silgi/configs",
8
+ "silgi",
9
+ "silgi/rules",
10
+ "silgi/scan",
11
+ "silgi/vfs"
12
+ ];
13
+ class SchemaParser {
14
+ options = {
15
+ debug: false
16
+ };
17
+ /**
18
+ *
19
+ */
20
+ constructor(options) {
21
+ this.options = {
22
+ ...this.options,
23
+ ...options
24
+ };
25
+ }
26
+ parseExports(content, filePath) {
27
+ const ast = parseSync(content, { sourceType: "module", sourceFilename: filePath });
28
+ if (this.options.debug)
29
+ writeFileSync(`${filePath}.ast.json`, JSON.stringify(ast.program, null, 2));
30
+ return {
31
+ exportVariables: (search, path) => this.parseTypeDeclarations(ast, search, path),
32
+ parseInterfaceDeclarations: (search, path) => this.parseInterfaceDeclarations(ast, search, path)
33
+ // parsePlugin: (path: string) => this.parsePlugin(ast, path),
34
+ };
35
+ }
36
+ parseVariableDeclaration(ast, path) {
37
+ const silgi = useSilgiCLI();
38
+ if (ast.program.body.length === 0) {
39
+ if (safeFiles.find((i) => path.includes(i)))
40
+ return [];
41
+ silgi.errors.push({
42
+ type: "Parser",
43
+ path
44
+ });
45
+ consola.warn("This file has a problem:", path);
46
+ }
47
+ const variableDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "VariableDeclaration");
48
+ return variableDeclarations;
49
+ }
50
+ parseTSInterfaceDeclaration(ast, path = "") {
51
+ const silgi = useSilgiCLI();
52
+ if (ast.program.body.length === 0) {
53
+ if (safeFiles.find((i) => path.includes(i)))
54
+ return [];
55
+ silgi.errors.push({
56
+ type: "Parser",
57
+ path
58
+ });
59
+ consola.warn("This file has a problem:", path);
60
+ }
61
+ const interfaceDeclarations = ast.program.body.filter((i) => i.type === "ExportNamedDeclaration").filter((i) => i.declaration?.type === "TSInterfaceDeclaration");
62
+ return interfaceDeclarations;
63
+ }
64
+ parseTypeDeclarations(ast, find = "", path = "") {
65
+ const data = [];
66
+ const variableDeclarations = this.parseVariableDeclaration(ast, path);
67
+ for (const item of variableDeclarations) {
68
+ for (const declaration of item.declaration.declarations) {
69
+ if (declaration.init?.callee?.name === find) {
70
+ const options = {};
71
+ if (declaration.init.arguments) {
72
+ for (const argument of declaration.init.arguments) {
73
+ for (const propertie of argument.properties) {
74
+ if (propertie.key.name === "name")
75
+ options.pluginName = propertie.value.value;
76
+ }
77
+ }
78
+ }
79
+ for (const key in declaration.init.properties) {
80
+ const property = declaration.init.properties[key];
81
+ if (property.type === "ObjectProperty") {
82
+ if (property.key.name === "options") {
83
+ for (const key2 in property.value.properties) {
84
+ const option = property.value.properties[key2];
85
+ if (option.type === "ObjectProperty") {
86
+ options[option.key.name] = option.value.value;
87
+ }
88
+ }
89
+ }
90
+ }
91
+ }
92
+ options.type = false;
93
+ data.push({
94
+ exportName: declaration.id.name,
95
+ options,
96
+ // object: declaration.init,
97
+ path
98
+ });
99
+ }
100
+ }
101
+ }
102
+ return data;
103
+ }
104
+ parseInterfaceDeclarations(ast, find = "", path = "") {
105
+ const data = [];
106
+ for (const item of this.parseTSInterfaceDeclaration(ast, path)) {
107
+ if (!item?.declaration?.extends)
108
+ continue;
109
+ for (const declaration of item?.declaration?.extends) {
110
+ if (declaration.expression.name === find) {
111
+ const options = {};
112
+ options.type = true;
113
+ data.push({
114
+ exportName: item.declaration.id.name,
115
+ options,
116
+ // object: declaration.init,
117
+ path
118
+ });
119
+ }
120
+ }
121
+ }
122
+ return data;
123
+ }
124
+ // private parsePlugin(ast: any, path: string = '') {
125
+ // const data = {
126
+ // export: [],
127
+ // name: '',
128
+ // path: '',
129
+ // } as DataTypePlugin
130
+ // for (const item of this.parseVariableDeclaration(ast)) {
131
+ // for (const declaration of item.declaration.declarations) {
132
+ // if (declaration.init.callee?.name === 'defineSilgiModule') {
133
+ // if (declaration.init.arguments) {
134
+ // for (const argument of declaration.init.arguments) {
135
+ // for (const propertie of argument.properties) {
136
+ // if (propertie.key.name === 'name')
137
+ // data.name = propertie.value.value
138
+ // }
139
+ // }
140
+ // }
141
+ // data.export.push({
142
+ // name: data.name,
143
+ // as: camelCase(`${data.name}DefineSilgiModule`),
144
+ // type: false,
145
+ // })
146
+ // }
147
+ // }
148
+ // }
149
+ // for (const item of this.parseTSInterfaceDeclaration(ast)) {
150
+ // if (!item?.declaration?.extends)
151
+ // continue
152
+ // for (const declaration of item?.declaration?.extends) {
153
+ // if (declaration.expression.name === 'ModuleOptions') {
154
+ // data.export.push({
155
+ // name: item.declaration.id.name,
156
+ // as: camelCase(`${data.name}ModuleOptions`),
157
+ // type: true,
158
+ // })
159
+ // }
160
+ // // TODO add other plugins
161
+ // }
162
+ // }
163
+ // data.path = path
164
+ // return data
165
+ // }
166
+ }
167
+
168
+ export { SchemaParser };
@@ -0,0 +1,79 @@
1
+ import { promises } from 'node:fs';
2
+ import { consola } from 'consola';
3
+ import { defu } from 'defu';
4
+ import { createJiti } from 'dev-jiti';
5
+ import { resolve } from 'pathe';
6
+ import { createUnimport } from 'unimport';
7
+
8
+ async function readScanFile(silgi) {
9
+ const path = resolve(silgi.options.silgi.serverDir, "scan.ts");
10
+ const context = await promises.readFile(path, { encoding: "utf-8" });
11
+ silgi.unimport = createUnimport(silgi.options.imports || {});
12
+ await silgi.unimport.init();
13
+ const injectedResult = await silgi.unimport.injectImports(context, path);
14
+ if (!injectedResult) {
15
+ throw new Error("Failed to inject imports");
16
+ }
17
+ const jiti = createJiti(silgi.options.rootDir, {
18
+ fsCache: true,
19
+ moduleCache: false,
20
+ debug: silgi.options.debug,
21
+ alias: silgi.options.alias
22
+ });
23
+ try {
24
+ if (silgi.options.commandType === "prepare") {
25
+ globalThis.$silgiSharedRuntimeConfig = silgi.options.runtimeConfig;
26
+ injectedResult.code = `globalThis.$silgiSharedRuntimeConfig = ${JSON.stringify(silgi.options.runtimeConfig)};
27
+ ${injectedResult.code}`;
28
+ injectedResult.code = injectedResult.code.replace(/runtimeConfig: \{\}/, `runtimeConfig: ${JSON.stringify(silgi.options.runtimeConfig)}`);
29
+ }
30
+ const scanFile = await jiti.evalModule(
31
+ injectedResult.code,
32
+ {
33
+ filename: path,
34
+ async: true,
35
+ conditions: silgi.options.conditions
36
+ },
37
+ async (data, name) => {
38
+ return (await silgi.unimport.injectImports(data, name)).code;
39
+ }
40
+ );
41
+ silgi.uris = defu(silgi.uris, scanFile.uris) || {};
42
+ silgi.schemas = defu(scanFile.schemas, scanFile.uris) || {};
43
+ silgi.services = defu(scanFile.services, scanFile.uris) || {};
44
+ silgi.shareds = defu(scanFile.shareds, scanFile.shareds) || {};
45
+ silgi.modulesURIs = defu(scanFile.modulesURIs, scanFile.modulesURIs) || {};
46
+ return {
47
+ context,
48
+ object: {
49
+ schemas: scanFile.schemas,
50
+ uris: scanFile.uris,
51
+ services: scanFile.services,
52
+ shareds: scanFile.shareds,
53
+ modulesURIs: scanFile.modulesURIs
54
+ },
55
+ path
56
+ };
57
+ } catch (error) {
58
+ if (silgi.options.debug) {
59
+ console.error("Failed to read scan.ts file:", error);
60
+ } else {
61
+ if (error instanceof Error) {
62
+ consola.withTag("silgi").info(error.message);
63
+ }
64
+ }
65
+ return {
66
+ context,
67
+ object: {
68
+ schemas: {},
69
+ uris: {},
70
+ services: {},
71
+ shareds: {},
72
+ modulesURIs: {}
73
+ },
74
+ path
75
+ };
76
+ }
77
+ }
78
+
79
+ export { readScanFile };
@@ -0,0 +1,25 @@
1
+ import { klona } from 'klona';
2
+ import { replaceRuntimeValues } from 'silgi';
3
+ import { useSilgiRuntimeConfig } from 'silgi/runtime';
4
+ import { createStorage, builtinDrivers } from 'unstorage';
5
+
6
+ async function createStorageCLI(silgi) {
7
+ const storage = createStorage();
8
+ const runtime = useSilgiRuntimeConfig();
9
+ const mounts = klona({
10
+ ...silgi.options.storage,
11
+ ...silgi.options.devStorage
12
+ });
13
+ for (const [path, opts] of Object.entries(mounts)) {
14
+ if (opts.driver) {
15
+ const driver = await import(builtinDrivers[opts.driver] || opts.driver).then((r) => r.default || r);
16
+ const processedOpts = replaceRuntimeValues({ ...opts }, runtime);
17
+ storage.mount(path, driver(processedOpts));
18
+ } else {
19
+ silgi.logger.warn(`No \`driver\` set for storage mount point "${path}".`);
20
+ }
21
+ }
22
+ return storage;
23
+ }
24
+
25
+ export { createStorageCLI };
@@ -0,0 +1,76 @@
1
+ import { createConsola } from 'consola';
2
+ import defu from 'defu';
3
+ import { createHooks } from 'hookable';
4
+ import { createRouteRules } from './routeRules.mjs';
5
+ import { silgiCtx } from './unctx.mjs';
6
+ import { scanAction } from './uris/uri.mjs';
7
+ import { createStorage, useSilgiStorage } from './utils/storage.mjs';
8
+
9
+ async function runSilgiPlugins(silgi) {
10
+ for (const plugin of silgi.plugins) {
11
+ try {
12
+ await plugin(silgi);
13
+ } catch (error) {
14
+ silgi.captureError(error, { tags: ["plugin"] });
15
+ throw error;
16
+ }
17
+ }
18
+ }
19
+ async function createSilgi(config) {
20
+ const hooks = createHooks();
21
+ const silgi = {
22
+ schemas: config.schemas,
23
+ services: config.services ?? {},
24
+ shared: config.shared ?? void 0,
25
+ uris: config.uris ?? {},
26
+ modulesURIs: config.modulesURIs ?? {},
27
+ scannedHandlers: /* @__PURE__ */ new Map(),
28
+ plugins: config.plugins ?? [],
29
+ framework: config.framework ?? void 0,
30
+ storage: config.options.putStorage ?? void 0,
31
+ options: config.options ?? {},
32
+ hooks,
33
+ callHook: hooks.callHook,
34
+ addHooks: hooks.addHooks,
35
+ hook: hooks.hook,
36
+ ready: () => {
37
+ return hooks.callHook("ready", silgi);
38
+ },
39
+ envOptions: config.envOptions ?? {},
40
+ close: () => hooks.callHook("close", silgi),
41
+ logger: createConsola(defu(config.options?.consolaOptions ?? {}, {
42
+ tag: "silgi"
43
+ })).withTag("silgi"),
44
+ captureError: config.captureError ?? (() => {
45
+ }),
46
+ routeRules: void 0
47
+ };
48
+ const routeRules = createRouteRules();
49
+ routeRules.importRules(config.options.routeRules ?? {});
50
+ silgi.routeRules = routeRules;
51
+ silgi.hooks.addHooks(silgi.options.hooks);
52
+ await runSilgiPlugins(silgi);
53
+ await scanAction(silgi);
54
+ if (!silgi.storage) {
55
+ silgi.storage = await createStorage(silgi);
56
+ }
57
+ silgi.shared.storage = (...data) => {
58
+ return useSilgiStorage(...data);
59
+ };
60
+ silgi.shared.runtimeConfig = silgi.options.runtimeConfig;
61
+ if (silgiCtx.tryUse()) {
62
+ silgiCtx.unset();
63
+ silgiCtx.set(silgi);
64
+ } else {
65
+ silgiCtx.set(silgi);
66
+ silgi.hook("close", () => silgiCtx.unset());
67
+ }
68
+ silgi.logger.info("Silgi installed");
69
+ hooks.hookOnce("close", async () => {
70
+ hooks.removeAllHooks();
71
+ await silgi.storage.dispose();
72
+ });
73
+ return silgi;
74
+ }
75
+
76
+ export { createSilgi };