silgi 0.36.18 → 0.37.1

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
@@ -26,6 +26,7 @@ import 'exsolve';
26
26
  import 'ufo';
27
27
  import 'node:fs/promises';
28
28
  import 'globby';
29
+ import 'oxc-parser';
29
30
  import 'ignore';
30
31
  import 'klona';
31
32
  import 'silgi/runtime';
@@ -16,8 +16,9 @@ import { fileURLToPath } from 'node:url';
16
16
  import { defu } from 'defu';
17
17
  import { resolveModuleURL } from 'exsolve';
18
18
  import { withTrailingSlash, isRelative } from 'ufo';
19
- import { readFile, readdir } from 'node:fs/promises';
19
+ import { readdir, readFile } from 'node:fs/promises';
20
20
  import { globby } from 'globby';
21
+ import { parseAsync } from 'oxc-parser';
21
22
  import ignore from 'ignore';
22
23
  import { klona } from 'klona';
23
24
  import { useSilgiRuntimeConfig, initRuntimeConfig } from 'silgi/runtime';
@@ -574,44 +575,22 @@ function resolveGroupSyntax(group) {
574
575
  return groups;
575
576
  }
576
577
 
577
- 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;
578
- const FUNCTION_VARIABLE_EXPORT_REGEX = /\bexport\s+(?:const|let|var)\s+(?<name>[\w$]+)\s*=\s*(?<funcName>\w+)\s*\(/g;
579
- function extractExportMatches(regex, fileContent, additionalMetadata = {}) {
580
- const matchedExports = [];
581
- for (const match of fileContent.matchAll(regex)) {
582
- const name = match.groups?.name || "";
583
- const declaration = match.groups?.declaration || "";
584
- const funcName = match.groups?.funcName || "";
585
- const extendsClause = match.groups?.extends || "";
586
- const codeSnippet = funcName ? `export const ${name} = ${funcName}(` : `export ${declaration} ${name}`;
587
- const extendedTypes = extendsClause ? extendsClause.split(",").map((typeName) => typeName.trim()) : [];
588
- matchedExports.push({
589
- ...additionalMetadata,
590
- name,
591
- declaration,
592
- funcName,
593
- code: codeSnippet,
594
- start: match.index,
595
- end: (match.index || 0) + match[0].length,
596
- extends: extendedTypes
597
- });
598
- }
599
- return matchedExports;
600
- }
601
578
  function generateUniqueIdentifier(filePath, exportName) {
602
579
  const fileBaseName = basename(filePath);
603
580
  const uniqueString = `${fileBaseName}${exportName}`;
604
581
  return hash(uniqueString);
605
582
  }
606
- function categorizeExports(exportedEntities, filePath) {
583
+ function categorizeExports(exportedEntities, filePath, functionExportCategories = {
584
+ createService: "service",
585
+ createSchema: "schema",
586
+ createShared: "shared",
587
+ createRoute: "route"
588
+ }, interfaceExportCategories = {
589
+ ExtendShared: "shared",
590
+ ExtendContext: "context"
591
+ }) {
607
592
  const runtimeExports = [];
608
593
  const typeExports = [];
609
- const functionExportCategories = {
610
- createService: "service",
611
- createSchema: "schema",
612
- createShared: "shared",
613
- createRoute: "route"
614
- };
615
594
  for (const [functionName, category] of Object.entries(functionExportCategories)) {
616
595
  const matchingExports = exportedEntities.filter((entity) => entity.funcName === functionName);
617
596
  for (const exportEntity of matchingExports) {
@@ -625,10 +604,6 @@ function categorizeExports(exportedEntities, filePath) {
625
604
  });
626
605
  }
627
606
  }
628
- const interfaceExportCategories = {
629
- ExtendShared: "shared",
630
- ExtendContext: "context"
631
- };
632
607
  for (const [extensionName, category] of Object.entries(interfaceExportCategories)) {
633
608
  const matchingExports = exportedEntities.filter(
634
609
  (entity) => entity.declaration === "interface" && entity.extends?.includes(extensionName)
@@ -725,13 +700,69 @@ async function verifyDirectoryCaseSensitivity(directoryPath, rootDirectory) {
725
700
  } catch {
726
701
  }
727
702
  }
728
- function stripCommentsAndStrings(code) {
729
- return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/"([^"\\]|\\.)*"/g, '""').replace(/'([^'\\]|\\.)*'/g, "''").replace(/`([^`\\]|\\.)*`/g, "``");
703
+ async function extractExportEntitiesFromFile(absoluteFilePath, functionExportNames = ["createSchema", "createService", "createRoute"], interfaceExtendsNames = ["ExtendShared", "ExtendContext"]) {
704
+ const exportEntities = [];
705
+ const fileContent = await readFile(absoluteFilePath, "utf-8");
706
+ const parsed = await parseAsync(absoluteFilePath, fileContent);
707
+ for (const node of parsed.program.body) {
708
+ if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "TSInterfaceDeclaration") {
709
+ const decl = node.declaration;
710
+ if (Array.isArray(decl.extends) && decl.extends.some(
711
+ (dec) => dec.type === "TSInterfaceHeritage" && dec.expression.type === "Identifier" && interfaceExtendsNames.includes(dec.expression.name)
712
+ )) {
713
+ exportEntities.push({
714
+ name: decl.id?.name,
715
+ type: "interface",
716
+ declaration: "interface",
717
+ extends: decl.extends.filter((e) => e.type === "TSInterfaceHeritage" && e.expression.type === "Identifier").map((e) => e.expression.type === "Identifier" ? e.expression.name : false).filter((name) => Boolean(name))
718
+ });
719
+ }
720
+ }
721
+ }
722
+ for (const node of parsed.program.body) {
723
+ if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") {
724
+ const decls = node.declaration.declarations;
725
+ if (Array.isArray(decls)) {
726
+ for (const decl of decls) {
727
+ if (decl.type === "VariableDeclarator" && decl.id.type === "Identifier" && decl.init && decl.init.type === "CallExpression" && decl.init.callee.type === "Identifier" && functionExportNames.includes(decl.init.callee.name)) {
728
+ exportEntities.push({
729
+ name: decl.id.name,
730
+ type: "function",
731
+ funcName: decl.init.callee.name
732
+ });
733
+ }
734
+ }
735
+ }
736
+ }
737
+ }
738
+ return exportEntities;
730
739
  }
731
- async function scanSilgiExports(path, packageName, silgiInstance = useSilgiCLI()) {
740
+ async function scanSilgiExports(path, packageName, silgiInstance = useSilgiCLI(), scanOptions = {}) {
732
741
  const processedFilePaths = /* @__PURE__ */ new Set();
733
742
  const alreadyScannedPaths = [];
734
743
  const serverDirectory = path || silgiInstance.options.serverDir;
744
+ const functionExportNames = scanOptions.functionExportNames ?? ["createSchema", "createService", "createRoute"];
745
+ const interfaceExtendsNames = scanOptions.interfaceExtendsNames ?? ["ExtendShared", "ExtendContext"];
746
+ const functionExportCategories = {};
747
+ functionExportNames.forEach((name) => {
748
+ if (name === "createService")
749
+ functionExportCategories[name] = "service";
750
+ else if (name === "createSchema")
751
+ functionExportCategories[name] = "schema";
752
+ else if (name === "createShared")
753
+ functionExportCategories[name] = "shared";
754
+ else if (name === "createRoute")
755
+ functionExportCategories[name] = "route";
756
+ else functionExportCategories[name] = name;
757
+ });
758
+ const interfaceExportCategories = {};
759
+ interfaceExtendsNames.forEach((name) => {
760
+ if (name === "ExtendShared")
761
+ interfaceExportCategories[name] = "shared";
762
+ else if (name === "ExtendContext")
763
+ interfaceExportCategories[name] = "context";
764
+ else interfaceExportCategories[name] = name;
765
+ });
735
766
  if (!serverDirectory) {
736
767
  consola.warn("No server directory specified for scanning");
737
768
  return;
@@ -758,22 +789,17 @@ async function scanSilgiExports(path, packageName, silgiInstance = useSilgiCLI()
758
789
  continue;
759
790
  }
760
791
  try {
761
- const fileContent = await readFile(absoluteFilePath, "utf-8");
762
- const cleanedContent = stripCommentsAndStrings(fileContent);
763
- const typeDeclarationExports = extractExportMatches(
764
- TYPE_DECLARATION_EXPORT_REGEX,
765
- cleanedContent,
766
- { type: "declaration" }
767
- );
768
- const functionVariableExports = extractExportMatches(
769
- FUNCTION_VARIABLE_EXPORT_REGEX,
770
- cleanedContent,
771
- { type: "variable" }
792
+ const exportEntities = await extractExportEntitiesFromFile(
793
+ absoluteFilePath,
794
+ functionExportNames,
795
+ interfaceExtendsNames
772
796
  );
773
- const allExportedEntities = [...typeDeclarationExports, ...functionVariableExports];
797
+ const allExportedEntities = exportEntities;
774
798
  const { runtimeExports, typeExports } = categorizeExports(
775
799
  allExportedEntities,
776
- absoluteFilePath
800
+ absoluteFilePath,
801
+ functionExportCategories,
802
+ interfaceExportCategories
777
803
  );
778
804
  registerExportsWithHooks(silgiInstance, runtimeExports, typeExports, packageName);
779
805
  } catch (error) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { defineCommand, runMain } from 'citty';
3
3
 
4
- const version = "0.36.18";
4
+ const version = "0.37.1";
5
5
  const packageJson = {
6
6
  version: version};
7
7
 
package/dist/cli/init.mjs CHANGED
@@ -23,6 +23,7 @@ import 'defu';
23
23
  import 'exsolve';
24
24
  import 'ufo';
25
25
  import 'globby';
26
+ import 'oxc-parser';
26
27
  import 'ignore';
27
28
  import 'klona';
28
29
  import 'silgi/runtime';
@@ -26,6 +26,7 @@ import 'exsolve';
26
26
  import 'ufo';
27
27
  import 'node:fs/promises';
28
28
  import 'globby';
29
+ import 'oxc-parser';
29
30
  import 'ignore';
30
31
  import 'klona';
31
32
  import 'silgi/runtime';
@@ -28,6 +28,7 @@ import 'exsolve';
28
28
  import 'ufo';
29
29
  import 'node:fs/promises';
30
30
  import 'globby';
31
+ import 'oxc-parser';
31
32
  import 'ignore';
32
33
  import 'klona';
33
34
  import 'silgi/runtime';
@@ -8,7 +8,6 @@ import { klona } from 'klona';
8
8
  import { useSilgiRuntimeConfig } from 'silgi/runtime';
9
9
  import { createStorage as createStorage$1, builtinDrivers, prefixStorage } from 'unstorage';
10
10
  import { FastURL, FastResponse } from 'srvx';
11
- import { isRuntimePresents } from 'silgi/kit';
12
11
  export { s as silgiCLICtx, t as tryUseSilgiCLI, u as useSilgiCLI } from '../_chunks/silgiApp.mjs';
13
12
 
14
13
  const silgiCtx = getContext("silgi");
@@ -532,56 +531,73 @@ function getUrlPrefix(path, method) {
532
531
  }
533
532
 
534
533
  async function orchestrate(route, event) {
535
- const input = await parseRequestInput(event.req);
536
534
  const silgiCtx = useSilgi();
537
535
  const silgiURL = getUrlPrefix(route.route, event.req.method);
536
+ const input = await parseRequestInput(event.req);
538
537
  try {
539
538
  const routerParams = getRouterParams(event);
540
539
  const queryParams = getQuery(event);
541
- let success = false;
542
- let cached = false;
543
- let result;
544
540
  const setup = route.setup;
545
- const cacheData = await cacheExecute(input, route, silgiURL, event);
541
+ const cachePromise = cacheExecute(input, route, silgiURL, event);
542
+ const beforeHookPromise = silgiCtx.callHook("fetch:before", {
543
+ url: silgiURL,
544
+ input,
545
+ event,
546
+ route
547
+ });
548
+ const cacheData = await cachePromise;
549
+ await beforeHookPromise;
546
550
  if (cacheData?.success) {
547
- result = cacheData.data;
548
- success = cacheData.success;
549
- cached = cacheData.cached;
550
- } else {
551
- silgiCtx.shared.$fetch = silgiFetch;
552
- silgiCtx.shared.silgi = silgiCtx;
553
- result = await setup?.handler(
554
- {
555
- args: input,
556
- parameters: {
557
- query: queryParams,
558
- path: routerParams
559
- }
560
- },
561
- silgiCtx.shared,
551
+ await silgiCtx.callHook("fetch:after", {
562
552
  event,
563
- event.context.source
564
- );
565
- success = true;
553
+ url: silgiURL,
554
+ input,
555
+ result: cacheData.data,
556
+ success: true,
557
+ // modules: setup.modules,
558
+ route
559
+ });
560
+ return cacheData.data;
566
561
  }
562
+ silgiCtx.shared.$fetch = silgiFetch;
563
+ silgiCtx.shared.silgi = silgiCtx;
564
+ const result = await setup?.handler(
565
+ {
566
+ args: input,
567
+ parameters: {
568
+ query: queryParams,
569
+ path: routerParams
570
+ }
571
+ },
572
+ silgiCtx.shared,
573
+ event,
574
+ event.context.source
575
+ );
567
576
  await silgiCtx.callHook("fetch:after", {
577
+ event,
568
578
  url: silgiURL,
569
579
  input,
570
580
  result,
571
- success,
572
- modules: setup.modules
581
+ success: true,
582
+ // modules: setup.modules,
583
+ route
573
584
  });
574
- if (!cached) {
575
- if (success && cacheData?.cachedKey && setup.storage) {
576
- await useSilgiStorage(setup.storage.base).setItem(cacheData.cachedKey, result, setup.storage.options);
577
- }
585
+ if (setup.storage && cacheData?.cachedKey) {
586
+ await useSilgiStorage(setup.storage.base).setItem(
587
+ cacheData.cachedKey,
588
+ result,
589
+ // Cast to StorageValue if needed
590
+ setup.storage.options
591
+ );
578
592
  }
579
593
  return result;
580
594
  } catch (err) {
581
595
  await silgiCtx.callHook("fetch:error", {
596
+ event,
582
597
  input,
583
598
  error: err instanceof Error ? err : new Error(String(err)),
584
- url: silgiURL
599
+ url: silgiURL,
600
+ route
585
601
  });
586
602
  silgiCtx.captureError(
587
603
  silgiCtx,
@@ -869,17 +885,11 @@ function getEvent(event) {
869
885
  if (event?.event) {
870
886
  return getEvent(event.event);
871
887
  }
872
- if (isRuntimePresents(["h3", "nitro", "nuxt"])) {
873
- return event;
874
- }
875
888
  return event;
876
889
  }
877
890
  function getEventContext(event) {
878
891
  const _event = getEvent(event);
879
- if (isRuntimePresents(["h3", "nitro", "nuxt"])) {
880
- return _event.context;
881
- }
882
- return _event;
892
+ return _event.context;
883
893
  }
884
894
 
885
895
  function createSchema(params) {
package/dist/index.mjs CHANGED
@@ -10,4 +10,3 @@ import 'klona';
10
10
  import 'silgi/runtime';
11
11
  import 'unstorage';
12
12
  import 'srvx';
13
- import 'silgi/kit';
@@ -1,10 +1,9 @@
1
- import { createError, getUrlPrefix, isError, silgiFetch, useSilgi } from "silgi";
1
+ import { createError, silgiFetch, useSilgi } from "silgi";
2
2
  export function toNextJsHandler(silgiContext = useSilgi()) {
3
3
  const handler = async (request) => {
4
4
  if (!silgiContext) {
5
5
  throw new Error("Silgi context is not defined");
6
6
  }
7
- const silgiURL = getUrlPrefix(request.url, request.method);
8
7
  try {
9
8
  const res = await silgiFetch(request);
10
9
  if (!res.ok) {
@@ -22,30 +21,6 @@ export function toNextJsHandler(silgiContext = useSilgi()) {
22
21
  }
23
22
  return res;
24
23
  } catch (err) {
25
- if (isError(err)) {
26
- throw createError({
27
- statusCode: 500,
28
- statusMessage: "Internal Server Error",
29
- cause: err
30
- });
31
- }
32
- await silgiContext.callHook("fetch:error", {
33
- error: err instanceof Error ? err : new Error(String(err)),
34
- url: silgiURL
35
- });
36
- silgiContext.captureError(
37
- silgiContext,
38
- createError({
39
- message: err instanceof Error ? err.message : String(err),
40
- statusCode: 500,
41
- statusMessage: "Internal Server Error",
42
- cause: err
43
- }),
44
- {
45
- url: silgiURL,
46
- tags: ["execute"]
47
- }
48
- );
49
24
  throw createError({
50
25
  statusCode: 500,
51
26
  message: "Internal Server Error",
@@ -1,13 +1,10 @@
1
1
  import {
2
- createError as createH3Error,
3
2
  defineEventHandler,
4
- getRequestWebStream,
5
- H3Error
3
+ getRequestWebStream
6
4
  } from "h3";
7
5
  import {
8
6
  createError,
9
7
  getUrlPrefix,
10
- isError,
11
8
  silgiFetch,
12
9
  useSilgi
13
10
  } from "silgi";
@@ -53,34 +50,6 @@ export async function addNitroApp(silgiContext = useSilgi()) {
53
50
  }
54
51
  return resolvedRoute;
55
52
  } catch (err) {
56
- if (err instanceof H3Error) {
57
- throw err;
58
- }
59
- if (isError(err)) {
60
- throw createH3Error({
61
- statusCode: 500,
62
- statusMessage: "Internal Server Error",
63
- cause: err
64
- });
65
- }
66
- await silgiContext.callHook("fetch:error", {
67
- error: err instanceof Error ? err : new Error(String(err)),
68
- url: silgiURL
69
- });
70
- silgiContext.captureError(
71
- silgiContext,
72
- createError({
73
- message: err instanceof Error ? err.message : String(err),
74
- statusCode: 500,
75
- statusMessage: "Internal Server Error",
76
- cause: err
77
- }),
78
- {
79
- event,
80
- url: silgiURL,
81
- tags: ["execute"]
82
- }
83
- );
84
53
  throw createError({
85
54
  statusCode: 500,
86
55
  message: "Internal Server Error",