@kosmojs/dev 0.0.6 → 0.0.8

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@kosmojs/dev",
4
- "version": "0.0.6",
4
+ "version": "0.0.8",
5
5
  "cacheVersion": "001",
6
6
  "author": "Slee Woo",
7
7
  "license": "MIT",
@@ -35,44 +35,46 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "chokidar": "^4.0.3",
38
+ "concurrently": "^9.2.1",
38
39
  "crc": "^4.3.2",
39
40
  "dotenv": "^17.2.3",
40
41
  "esbuild": "^0.27.0",
41
- "fs-extra": "^11.3.2",
42
42
  "ora": "^9.0.0",
43
43
  "picomatch": "^4.0.3",
44
+ "prompts": "^2.4.2",
44
45
  "tfusion": "^0.0.23",
45
46
  "tinyglobby": "^0.2.15",
46
47
  "ts-morph": "^27.0.2",
47
48
  "typescript": "^5.9.3",
48
- "concurrently": "^9.2.1",
49
- "prompts": "^2.4.2",
50
- "@kosmojs/api": "^0.0.6",
51
- "@kosmojs/devlib": "^0.0.6",
52
- "@kosmojs/fetch-generator": "^0.0.6",
53
- "@kosmojs/api-generator": "^0.0.6"
49
+ "@kosmojs/api": "^0.0.8",
50
+ "@kosmojs/api-generator": "^0.0.8",
51
+ "@kosmojs/devlib": "^0.0.8",
52
+ "@kosmojs/fetch-generator": "^0.0.8"
54
53
  },
55
54
  "devDependencies": {
56
- "@types/fs-extra": "^11.0.4",
57
- "@types/koa": "^3.0.1",
58
- "@types/picomatch": "^4.0.2",
59
- "vite": "^7.2.2",
60
55
  "@solidjs/router": "^0.15.4",
56
+ "@types/koa": "^3.0.1",
61
57
  "@types/koa__router": "^12.0.5",
62
58
  "@types/node": "^24.10.1",
59
+ "@types/picomatch": "^4.0.2",
63
60
  "@types/prompts": "^2.4.9",
64
61
  "@types/qs": "^6.14.0",
65
62
  "@types/react": "^19.2.3",
66
63
  "@types/react-dom": "^19.2.3",
67
64
  "@vitejs/plugin-react": "^5.1.1",
65
+ "@vitejs/plugin-vue": "^6.0.1",
66
+ "path-to-regexp": "^8.3.0",
68
67
  "qs": "^6.14.0",
69
68
  "react": "^19.2.0",
70
69
  "react-dom": "^19.2.0",
71
70
  "react-router": "^7.9.5",
72
71
  "solid-js": "^1.9.10",
73
72
  "tslib": "^2.8.1",
73
+ "vite": "^7.2.2",
74
74
  "vite-plugin-solid": "^2.11.10",
75
- "@kosmojs/config": "^0.0.6"
75
+ "vue": "^3.5.24",
76
+ "vue-router": "^4.6.3",
77
+ "@kosmojs/config": "^0.0.8"
76
78
  },
77
79
  "scripts": {
78
80
  "build": "esbuilder src/index.ts src/base-plugin/routes.ts src/base-plugin/worker.ts src/stub-generator/index.ts src/cli/cli.ts src/cli/index.ts",
@@ -1,5 +1,5 @@
1
1
  // src/base-plugin/routes.ts
2
- import { dirname, join, resolve as resolve3 } from "node:path";
2
+ import { dirname as dirname2, join, resolve as resolve3 } from "node:path";
3
3
  import crc3 from "crc/crc32";
4
4
  import picomatch from "picomatch";
5
5
  import { glob } from "tinyglobby";
@@ -267,11 +267,11 @@ var typeResolverFactory = ({ appRoot }) => {
267
267
  };
268
268
 
269
269
  // src/base-plugin/cache.ts
270
- import { resolve as resolve2 } from "node:path";
270
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
271
+ import { dirname, resolve as resolve2 } from "node:path";
271
272
  import crc2 from "crc/crc32";
272
- import fsx from "fs-extra";
273
273
  import self from "@kosmojs/dev/package.json" with { type: "json" };
274
- import { pathResolver } from "@kosmojs/devlib";
274
+ import { pathExists, pathResolver } from "@kosmojs/devlib";
275
275
  var cacheFactory = (route, {
276
276
  appRoot,
277
277
  sourceFolder,
@@ -282,9 +282,9 @@ var cacheFactory = (route, {
282
282
  sourceFolder
283
283
  }).resolve("apiLibDir", route.importPath, "cache.json");
284
284
  const getCache = async (opt) => {
285
- if (await fsx.exists(cacheFile)) {
285
+ if (await pathExists(cacheFile)) {
286
286
  try {
287
- const cache = JSON.parse(await fsx.readFile(cacheFile, "utf8"));
287
+ const cache = JSON.parse(await readFile(cacheFile, "utf8"));
288
288
  return opt?.validate ? validateCache(cache) : cache;
289
289
  } catch (_e) {
290
290
  }
@@ -307,7 +307,8 @@ var cacheFactory = (route, {
307
307
  ] = await generateFileHash(file);
308
308
  }
309
309
  const cache = { ...rest, hash, referencedFiles };
310
- await fsx.outputJson(cacheFile, cache, { spaces: 2 });
310
+ await mkdir(dirname(cacheFile), { recursive: true });
311
+ await writeFile(cacheFile, JSON.stringify(cache, null, 2), "utf8");
311
312
  return cache;
312
313
  };
313
314
  const validateCache = async (cache) => {
@@ -339,7 +340,7 @@ var cacheFactory = (route, {
339
340
  var generateFileHash = async (file, extraContext) => {
340
341
  let fileContent;
341
342
  try {
342
- fileContent = await fsx.readFile(file, "utf8");
343
+ fileContent = await readFile(file, "utf8");
343
344
  } catch (_e) {
344
345
  return 0;
345
346
  }
@@ -361,6 +362,43 @@ var resolved_types_default = "{{#each resolvedTypes}}\nexport type {{name}} = {{
361
362
  var types_default = '{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n "{{name}}"{{#unless isRequired}}?{{/unless}}:{{#if isRest}} Array<{{/if}}\n {{#if refinement}}{{refinement.text}}{{else}}string{{/if}}\n {{#if isRest}}>{{/if}}\n {{/each}}\n};\n\n{{#each payloadTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n\n{{#each responseTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n';
362
363
 
363
364
  // src/base-plugin/routes.ts
365
+ var API_INDEX_PATTERN = "index.ts";
366
+ var PAGE_INDEX_PATTERN = "index.{tsx,vue}";
367
+ var ROUTE_FILE_PATTERNS = [
368
+ `${defaults.apiDir}/**/${API_INDEX_PATTERN}`,
369
+ `${defaults.pagesDir}/**/${PAGE_INDEX_PATTERN}`
370
+ ];
371
+ var resolveRouteFile = (file, { appRoot, sourceFolder }) => {
372
+ const [_sourceFolder, folder, ...rest] = resolve3(appRoot, file).replace(`${appRoot}/`, "").split("/");
373
+ if (!folder || _sourceFolder !== sourceFolder || rest.length < 2) {
374
+ return;
375
+ }
376
+ return picomatch.isMatch(join(folder, ...rest), ROUTE_FILE_PATTERNS) ? [folder, rest.join("/")] : void 0;
377
+ };
378
+ var resolveRouteEntry = (_file, { appRoot, sourceFolder }) => {
379
+ const resolvedPaths = resolveRouteFile(_file, { appRoot, sourceFolder });
380
+ if (!resolvedPaths) {
381
+ return;
382
+ }
383
+ const [folder, file] = resolvedPaths;
384
+ const fileFullpath = join(appRoot, sourceFolder, folder, file);
385
+ const pathTokens = pathTokensFactory(dirname2(file));
386
+ const name = pathTokens.map((e) => e.orig).join("/");
387
+ const importPath = dirname2(file);
388
+ const importName = [
389
+ importPath.split(/\[/)[0].replace(/^\W+|\W+$/g, "").replace(/\W+/g, "_"),
390
+ crc3(importPath)
391
+ ].join("_");
392
+ return {
393
+ name,
394
+ folder,
395
+ file,
396
+ fileFullpath,
397
+ pathTokens,
398
+ importPath,
399
+ importName
400
+ };
401
+ };
364
402
  var routes_default = async (pluginOptions) => {
365
403
  const {
366
404
  appRoot,
@@ -381,44 +419,11 @@ var routes_default = async (pluginOptions) => {
381
419
  getSourceFile,
382
420
  refreshSourceFile
383
421
  } = typeResolverFactory(pluginOptions);
384
- const routeFilePatterns = [
385
- `${defaults.apiDir}/**/index.ts`,
386
- `${defaults.pagesDir}/**/index.{ts,tsx,vue,svelte}`
387
- ];
388
- const resolveRouteFile = (file) => {
389
- const [_sourceFolder, folder, ...rest] = resolve3(appRoot, file).replace(`${appRoot}/`, "").split("/");
390
- if (!folder || _sourceFolder !== sourceFolder || rest.length < 2) {
391
- return;
392
- }
393
- return picomatch.isMatch(join(folder, ...rest), routeFilePatterns) ? [folder, rest.join("/")] : void 0;
394
- };
395
422
  const resolversFactory = (routeFiles2) => {
396
423
  const resolvers = /* @__PURE__ */ new Map();
397
- const entries = routeFiles2.flatMap((_file) => {
398
- const resolvedPaths = resolveRouteFile(_file);
399
- if (!resolvedPaths) {
400
- return [];
401
- }
402
- const [folder, file] = resolvedPaths;
403
- const fileFullpath = join(appRoot, sourceFolder, folder, file);
404
- const pathTokens = pathTokensFactory(dirname(file));
405
- const name = pathTokens.map((e) => e.orig).join("/");
406
- const importPath = dirname(file);
407
- const importName = [
408
- importPath.split(/\[/)[0].replace(/^\W+|\W+$/g, "").replace(/\W+/g, "_"),
409
- crc3(importPath)
410
- ].join("_");
411
- return [
412
- {
413
- name,
414
- folder,
415
- file,
416
- fileFullpath,
417
- pathTokens,
418
- importPath,
419
- importName
420
- }
421
- ];
424
+ const entries = routeFiles2.flatMap((file) => {
425
+ const entry = resolveRouteEntry(file, pluginOptions);
426
+ return entry ? [entry] : [];
422
427
  });
423
428
  for (const entry of entries.filter((e) => e.folder === defaults.apiDir)) {
424
429
  const {
@@ -461,7 +466,7 @@ var routes_default = async (pluginOptions) => {
461
466
  withReferencedFiles: true,
462
467
  sourceFile: getSourceFile(fileFullpath),
463
468
  relpathResolver(path) {
464
- return join(sourceFolder, defaults.apiDir, dirname(file), path);
469
+ return join(sourceFolder, defaults.apiDir, dirname2(file), path);
465
470
  }
466
471
  }
467
472
  );
@@ -597,22 +602,23 @@ var routes_default = async (pluginOptions) => {
597
602
  }
598
603
  return resolvers;
599
604
  };
600
- const routeFiles = await glob(routeFilePatterns, {
605
+ const routeFiles = await glob(ROUTE_FILE_PATTERNS, {
601
606
  cwd: resolve3(appRoot, sourceFolder),
602
607
  absolute: true,
603
608
  onlyFiles: true,
604
609
  ignore: [
605
- `${defaults.apiDir}/index.ts`,
606
- `${defaults.pagesDir}/index.ts{x,}`
610
+ `${defaults.apiDir}/${API_INDEX_PATTERN}`,
611
+ `${defaults.pagesDir}/${PAGE_INDEX_PATTERN}`
607
612
  ]
608
613
  });
609
614
  return {
610
615
  resolvers: resolversFactory(routeFiles),
611
- resolversFactory,
612
- resolveRouteFile
616
+ resolversFactory
613
617
  };
614
618
  };
615
619
  export {
616
- routes_default as default
620
+ routes_default as default,
621
+ resolveRouteEntry,
622
+ resolveRouteFile
617
623
  };
618
624
  //# sourceMappingURL=routes.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/base-plugin/routes.ts", "../../src/base-plugin/ast.ts", "../../src/base-plugin/cache.ts", "../../src/base-plugin/templates/resolved-types.hbs", "../../src/base-plugin/templates/types.hbs"],
4
- "sourcesContent": ["import { dirname, join, resolve } from \"node:path\";\n\nimport crc from \"crc/crc32\";\nimport picomatch from \"picomatch\";\nimport { glob } from \"tinyglobby\";\n\nimport {\n type ApiRoute,\n defaults,\n type PageRoute,\n type PluginOptionsResolved,\n pathResolver,\n pathTokensFactory,\n type RouteEntry,\n type RouteResolver,\n render,\n renderToFile,\n} from \"@kosmojs/devlib\";\n\nimport { resolveRouteSignature, typeResolverFactory } from \"./ast\";\nimport { cacheFactory } from \"./cache\";\n\nimport resolvedTypesTpl from \"./templates/resolved-types.hbs\";\nimport typesFileTpl from \"./templates/types.hbs\";\n\nexport type Resolvers = Map<string, RouteResolver>;\n\nexport type ResolveRouteFile = (file: string) =>\n | [\n // Either `apiDir` or `pagesDir`\n folder: string,\n // Path to a file within the folder, nested at least one level deep\n file: string,\n ]\n | undefined;\n\nexport type ResolversFactory = (\n routeFiles: Array<string>,\n) => Map<string, RouteResolver>;\n\nexport default async (\n pluginOptions: PluginOptionsResolved,\n): Promise<{\n resolvers: Resolvers;\n resolversFactory: ResolversFactory;\n resolveRouteFile: ResolveRouteFile;\n}> => {\n const {\n appRoot,\n sourceFolder,\n generators = [],\n formatters = [],\n refineTypeName,\n } = pluginOptions;\n\n let resolveTypes = false;\n\n for (const { options } of generators) {\n if (options?.resolveTypes) {\n resolveTypes = true;\n }\n }\n\n const {\n //\n literalTypesResolver,\n getSourceFile,\n refreshSourceFile,\n } = typeResolverFactory(pluginOptions);\n\n const routeFilePatterns = [\n `${defaults.apiDir}/**/index.ts`,\n `${defaults.pagesDir}/**/index.{ts,tsx,vue,svelte}`,\n ];\n\n const resolveRouteFile: ResolveRouteFile = (file) => {\n const [_sourceFolder, folder, ...rest] = resolve(appRoot, file)\n .replace(`${appRoot}/`, \"\")\n .split(\"/\");\n\n /**\n * Ensure the file:\n * - is under the correct source root (`sourceFolder`)\n * - belongs to a known route folder (`apiDir` or `pagesDir`)\n * - is nested at least one level deep (not a direct child of the folder)\n */\n if (!folder || _sourceFolder !== sourceFolder || rest.length < 2) {\n return;\n }\n\n return picomatch.isMatch(join(folder, ...rest), routeFilePatterns)\n ? [folder, rest.join(\"/\")]\n : undefined;\n };\n\n const resolversFactory: ResolversFactory = (routeFiles) => {\n const resolvers = new Map<\n string, // fileFullpath\n RouteResolver\n >();\n\n const entries: Array<RouteEntry> = routeFiles.flatMap((_file) => {\n const resolvedPaths = resolveRouteFile(_file);\n\n if (!resolvedPaths) {\n return [];\n }\n\n const [folder, file] = resolvedPaths;\n\n const fileFullpath = join(appRoot, sourceFolder, folder, file);\n\n const pathTokens = pathTokensFactory(dirname(file));\n\n const name = pathTokens.map((e) => e.orig).join(\"/\");\n\n const importPath = dirname(file);\n\n const importName = [\n importPath\n .split(/\\[/)[0]\n .replace(/^\\W+|\\W+$/g, \"\")\n .replace(/\\W+/g, \"_\"),\n crc(importPath),\n ].join(\"_\");\n\n return [\n {\n name,\n folder,\n file,\n fileFullpath,\n pathTokens,\n importPath,\n importName,\n },\n ];\n });\n\n for (const entry of entries.filter((e) => e.folder === defaults.apiDir)) {\n const {\n name,\n file,\n folder,\n fileFullpath,\n pathTokens,\n importPath,\n importName,\n } = entry;\n\n const handler: RouteResolver[\"handler\"] = async (updatedFile) => {\n const paramsSchema = pathTokens.flatMap((e) => {\n return e.param ? [e.param] : [];\n });\n\n const optionalParams = paramsSchema.length\n ? !paramsSchema.some((e) => e.isRequired)\n : true;\n\n const { getCache, persistCache } = cacheFactory(\n { file, fileFullpath, importName, importPath },\n {\n appRoot,\n sourceFolder,\n extraContext: { resolveTypes },\n },\n );\n\n let cache = await getCache({ validate: true });\n\n if (!cache) {\n if (updatedFile === fileFullpath) {\n await refreshSourceFile(fileFullpath);\n }\n\n const {\n typeDeclarations,\n paramsRefinements,\n methods,\n payloadTypes,\n responseTypes,\n referencedFiles = [],\n } = await resolveRouteSignature(\n { importName, fileFullpath, optionalParams },\n {\n withReferencedFiles: true,\n sourceFile: getSourceFile(fileFullpath),\n relpathResolver(path) {\n return join(sourceFolder, defaults.apiDir, dirname(file), path);\n },\n },\n );\n\n const numericParams = paramsRefinements\n ? paramsRefinements.flatMap(({ text, index }) => {\n if (text === \"number\") {\n const param = paramsSchema.at(index);\n return param ? [param.name] : [];\n }\n return [];\n })\n : [];\n\n const typesFile = pathResolver({ appRoot, sourceFolder }).resolve(\n \"apiLibDir\",\n importPath,\n \"types.ts\",\n );\n\n const params: ApiRoute[\"params\"] = {\n id: [\"ParamsT\", crc(name)].join(\"\"),\n schema: paramsSchema,\n resolvedType: undefined,\n };\n\n const typesFileContent = render(typesFileTpl, {\n params,\n paramsSchema: paramsSchema.map((param, index) => {\n return {\n ...param,\n refinement: paramsRefinements?.at(index),\n };\n }),\n typeDeclarations,\n payloadTypes,\n responseTypes,\n });\n\n const resolvedTypes = resolveTypes\n ? literalTypesResolver(typesFileContent, {\n overrides: [...payloadTypes, ...responseTypes].reduce(\n (map: Record<string, string>, { id, skipValidation }) => {\n if (skipValidation) {\n map[id] = \"never\";\n }\n return map;\n },\n { [refineTypeName]: refineTypeName },\n ),\n withProperties: [params.id, ...payloadTypes.map((e) => e.id)],\n formatters,\n })\n : undefined;\n\n /**\n * Deploy types.ts file; required by core generators (like fetch).\n * If types resolved, write resolved types;\n * otherwise write original types extracted from API route.\n * */\n await renderToFile(\n typesFile,\n resolvedTypes ? resolvedTypesTpl : typesFileContent,\n { resolvedTypes },\n );\n\n params.resolvedType = resolvedTypes?.find(\n (e) => e.name === params.id,\n );\n\n cache = await persistCache({\n params,\n methods,\n typeDeclarations,\n numericParams,\n // text was needed at writing types.ts file, dropping from cache\n payloadTypes: payloadTypes.map(({ text, ...rest }) => {\n return {\n ...rest,\n resolvedType: resolvedTypes?.find((e) => e.name === rest.id),\n };\n }),\n responseTypes: responseTypes.map(({ text, ...rest }) => {\n return {\n ...rest,\n resolvedType: resolvedTypes?.find((e) => e.name === rest.id),\n };\n }),\n referencedFiles,\n });\n }\n\n const route: ApiRoute = {\n name,\n pathTokens,\n params: cache.params,\n numericParams: cache.numericParams,\n optionalParams,\n importName,\n importPath,\n folder,\n file,\n fileFullpath,\n methods: cache.methods,\n typeDeclarations: cache.typeDeclarations,\n payloadTypes: cache.payloadTypes,\n responseTypes: cache.responseTypes,\n referencedFiles: Object.keys(cache.referencedFiles).map(\n // expand referenced files path,\n // they are stored as relative in cache\n (e) => resolve(appRoot, e),\n ),\n };\n\n return {\n kind: \"api\",\n route,\n };\n };\n\n resolvers.set(fileFullpath, { name, handler });\n }\n\n for (const entry of entries.filter((e) => e.folder === defaults.pagesDir)) {\n const {\n //\n name,\n folder,\n file,\n fileFullpath,\n pathTokens,\n importPath,\n importName,\n } = entry;\n\n const handler: RouteResolver[\"handler\"] = async () => {\n const route: PageRoute = {\n name,\n pathTokens,\n params: {\n schema: pathTokens.flatMap((e) => (e.param ? [e.param] : [])),\n },\n folder,\n file,\n fileFullpath,\n importPath,\n importName,\n };\n\n return {\n kind: \"page\",\n route,\n };\n };\n\n resolvers.set(fileFullpath, { name, handler });\n }\n\n return resolvers;\n };\n\n const routeFiles = await glob(routeFilePatterns, {\n cwd: resolve(appRoot, sourceFolder),\n absolute: true,\n onlyFiles: true,\n ignore: [\n `${defaults.apiDir}/index.ts`,\n `${defaults.pagesDir}/index.ts{x,}`,\n ],\n });\n\n return {\n resolvers: resolversFactory(routeFiles),\n resolversFactory,\n resolveRouteFile,\n };\n};\n", "import { resolve } from \"node:path\";\n\nimport crc from \"crc/crc32\";\nimport { flattener } from \"tfusion\";\nimport {\n type CallExpression,\n type Identifier,\n type Node,\n Project,\n type ProjectOptions,\n type SourceFile,\n SyntaxKind,\n} from \"ts-morph\";\n\nimport { type HTTPMethod, HTTPMethods } from \"@kosmojs/api\";\nimport type {\n ApiRoute,\n PayloadType,\n PluginOptionsResolved,\n ResponseType,\n TypeDeclaration,\n} from \"@kosmojs/devlib\";\n\ntype PathResolver = (path: string) => string;\n\nexport const createProject = (opts?: ProjectOptions) => new Project(opts);\n\nexport const resolveRouteSignature = async (\n route: Pick<ApiRoute, \"importName\" | \"fileFullpath\" | \"optionalParams\">,\n opts?: {\n relpathResolver?: PathResolver;\n sourceFile?: SourceFile;\n withReferencedFiles?: boolean;\n },\n) => {\n const {\n sourceFile = createProject().addSourceFileAtPath(route.fileFullpath),\n } = { ...opts };\n\n const [typeDeclarations, referencedFiles] = extractTypeDeclarations(\n sourceFile,\n opts,\n );\n\n const defaultExport = extractDefaultExport(sourceFile);\n\n const paramsRefinements = defaultExport\n ? extractParamsRefinements(defaultExport)\n : undefined;\n\n const methods = defaultExport\n ? extractRouteMethods(defaultExport, route)\n : [];\n\n const payloadTypes = methods.flatMap((e) => {\n return e.payloadType ? [e.payloadType] : [];\n });\n\n const responseTypes = methods.flatMap((e) => {\n return e.responseType ? [e.responseType] : [];\n });\n\n return {\n typeDeclarations,\n paramsRefinements,\n methods: methods.map((e) => e.method),\n payloadTypes,\n responseTypes,\n referencedFiles,\n };\n};\n\nexport const extractDefaultExport = (\n sourceFile: SourceFile,\n): CallExpression | undefined => {\n const [defaultExport] = sourceFile\n .getExportAssignments()\n .flatMap((exportAssignment) => {\n if (exportAssignment.isExportEquals()) {\n return [];\n }\n const callExpression = exportAssignment.getExpression();\n return callExpression.isKind(SyntaxKind.CallExpression)\n ? [callExpression]\n : [];\n });\n return defaultExport;\n};\n\nexport const extractParamsRefinements = (\n callExpression: CallExpression,\n):\n | Array<{\n index: number;\n text: string;\n }>\n | undefined => {\n const [firstGeneric] = extractGenerics(callExpression);\n\n if (!firstGeneric?.node.isKind(SyntaxKind.TupleType)) {\n return;\n }\n\n const tupleElements = firstGeneric.node.getElements();\n\n if (!tupleElements?.length) {\n return;\n }\n\n return tupleElements.map((node, index) => {\n return {\n index,\n text: node.getText(),\n };\n });\n};\n\nexport const extractRouteMethods = (\n callExpression: CallExpression,\n route: Pick<ApiRoute, \"importName\" | \"optionalParams\">,\n): Array<{\n method: HTTPMethod;\n payloadType: (PayloadType & { text: string }) | undefined;\n responseType: (ResponseType & { text: string }) | undefined;\n}> => {\n const funcDeclaration =\n callExpression.getFirstChildByKind(SyntaxKind.ArrowFunction) ||\n callExpression.getFirstChildByKind(SyntaxKind.FunctionExpression);\n\n if (!funcDeclaration) {\n return [];\n }\n\n const arrayLiteralExpression = funcDeclaration.getFirstChildByKind(\n SyntaxKind.ArrayLiteralExpression,\n );\n\n if (!arrayLiteralExpression) {\n return [];\n }\n\n const callExpressions: Array<[CallExpression, HTTPMethod]> = [];\n\n for (const e of arrayLiteralExpression.getChildrenOfKind(\n SyntaxKind.CallExpression,\n )) {\n const name = e.getExpression().getText() as HTTPMethod;\n if (HTTPMethods[name]) {\n callExpressions.push([e, name]);\n }\n }\n\n const methods = [];\n\n const skipValidationFilter = (e: string) => /@skip-validation/.test(e);\n\n for (const [callExpression, method] of callExpressions) {\n const [payloadGeneric, responseGeneric] = extractGenerics(callExpression);\n\n const payloadText = payloadGeneric?.node\n ? payloadGeneric.node.getChildren().length === 0\n ? \"{}\"\n : payloadGeneric.node.getFullText()\n : undefined;\n\n const responseText = responseGeneric?.node.getText();\n\n const responseType = responseText\n ? {\n id: [\"ResponseT\", crc(route.importName + method)].join(\"\"),\n method,\n skipValidation: responseGeneric?.comments\n ? responseGeneric.comments.some(skipValidationFilter)\n : false,\n text: [\"never\", \"object\"].includes(responseText)\n ? \"{}\"\n : responseText,\n resolvedType: undefined,\n }\n : undefined;\n\n const payloadType = payloadText\n ? {\n id: [\"PayloadT\", crc(route.importName + method)].join(\"\"),\n responseTypeId: responseType?.id,\n method,\n skipValidation: payloadGeneric?.comments\n ? payloadGeneric.comments.some(skipValidationFilter)\n : false,\n isOptional: payloadText\n ? payloadText === \"{}\" || route.optionalParams\n : true,\n text: payloadText,\n resolvedType: undefined,\n }\n : undefined;\n\n methods.push({\n method,\n payloadType,\n responseType,\n });\n }\n\n return methods;\n};\n\nexport const extractTypeDeclarations = (\n sourceFile: SourceFile,\n opts?: {\n relpathResolver?: PathResolver;\n withReferencedFiles?: boolean;\n },\n): [d: Array<TypeDeclaration>, f?: Array<string>] => {\n const declarations: Array<TypeDeclaration> = [];\n\n const referencedFiles: Array<string> | undefined = opts?.withReferencedFiles\n ? []\n : undefined;\n\n for (const declaration of sourceFile.getImportDeclarations()) {\n const modulePath = declaration.getModuleSpecifierValue();\n\n const path = /^\\.\\.?\\/?/.test(modulePath)\n ? opts?.relpathResolver\n ? opts.relpathResolver(modulePath)\n : modulePath\n : modulePath;\n\n const typeOnlyDeclaration = declaration.isTypeOnly();\n\n const defaultImport = typeOnlyDeclaration\n ? declaration.getDefaultImport()\n : undefined;\n\n if (defaultImport) {\n const name = defaultImport.getText();\n const text = `import type ${name} from \"${path}\";`;\n declarations.push({\n importDeclaration: {\n name,\n path,\n },\n text,\n });\n if (referencedFiles) {\n referencedFiles.push(...getReferencedFiles(defaultImport));\n }\n }\n\n for (const namedImport of declaration.getNamedImports()) {\n if (namedImport.isTypeOnly() || typeOnlyDeclaration) {\n const nameNode = namedImport.getNameNode();\n const name = nameNode.getText();\n const alias = namedImport.getAliasNode()?.getText();\n const nameText = alias ? `${name} as ${alias}` : name;\n\n declarations.push({\n importDeclaration: {\n name,\n alias,\n path,\n },\n text: `import type { ${nameText} } from \"${path}\";`,\n });\n\n if (referencedFiles) {\n if (nameNode.isKind(SyntaxKind.Identifier)) {\n referencedFiles.push(...getReferencedFiles(nameNode));\n }\n }\n }\n }\n }\n\n for (const declaration of sourceFile.getTypeAliases()) {\n const name = declaration.getName();\n const text = declaration.getFullText().trim();\n declarations.push({\n typeAliasDeclaration: { name },\n text,\n });\n }\n\n for (const declaration of sourceFile.getInterfaces()) {\n const name = declaration.getName();\n const text = declaration.getFullText().trim();\n declarations.push({\n interfaceDeclaration: { name },\n text,\n });\n }\n\n for (const declaration of sourceFile.getEnums()) {\n const name = declaration.getName();\n const text = declaration.getFullText().trim();\n declarations.push({\n enumDeclaration: { name },\n text,\n });\n }\n\n for (const declaration of sourceFile.getExportDeclarations()) {\n const typeOnlyDeclaration = declaration.isTypeOnly();\n\n const modulePath = declaration.getModuleSpecifierValue();\n\n const path = modulePath\n ? /^\\.\\.?\\/?/.test(modulePath)\n ? opts?.relpathResolver\n ? opts.relpathResolver(modulePath)\n : modulePath\n : modulePath\n : undefined;\n\n for (const namedExport of declaration.getNamedExports()) {\n if (namedExport.isTypeOnly() || typeOnlyDeclaration) {\n const nameNode = namedExport.getNameNode();\n const name = nameNode.getText();\n const alias = namedExport.getAliasNode()?.getText();\n const nameText = alias ? `${name} as ${alias}` : name;\n\n declarations.push({\n exportDeclaration: {\n name,\n alias: alias ?? name,\n path,\n },\n text: path\n ? `export type { ${nameText} } from \"${path}\";`\n : `export type { ${nameText} };`,\n });\n\n if (referencedFiles) {\n if (nameNode.isKind(SyntaxKind.Identifier)) {\n referencedFiles.push(...getReferencedFiles(nameNode));\n }\n }\n }\n }\n }\n\n return referencedFiles\n ? [declarations, [...new Set<string>(referencedFiles)]]\n : [declarations];\n};\n\nconst getReferencedFiles = (importIdentifier: Identifier): Array<string> => {\n // ambient modules may have declarations in multiple files\n const declarations =\n importIdentifier //\n ?.getSymbol()\n ?.getAliasedSymbol()\n ?.getDeclarations() || [];\n\n return declarations.flatMap((e) => {\n const sourceFile = e.getSourceFile();\n return sourceFile //\n ? [sourceFile.getFilePath()]\n : [];\n });\n};\n\nconst extractGenerics = (\n callExpression: CallExpression,\n): Array<{ node: Node; comments: Array<string> }> => {\n return callExpression.getTypeArguments().map((node) => {\n return {\n node,\n comments: node\n .getLeadingCommentRanges()\n .map((range) => range.getText().trim()),\n };\n });\n};\n\nexport const typeResolverFactory = ({ appRoot }: PluginOptionsResolved) => {\n const project = createProject({\n tsConfigFilePath: resolve(appRoot, \"tsconfig.json\"),\n skipAddingFilesFromTsConfig: true,\n });\n\n const literalTypesResolver = (\n literalTypes: string,\n options: Parameters<typeof flattener>[2],\n ) => {\n const sourceFile = project.createSourceFile(\n `${crc(literalTypes)}-${Date.now()}.ts`,\n literalTypes,\n { overwrite: true },\n );\n\n const resolvedTypes = flattener(project, sourceFile, {\n ...options,\n stripComments: true,\n });\n\n project.removeSourceFile(sourceFile);\n\n return resolvedTypes;\n };\n\n return {\n getSourceFile: (fileFullpath: string) => {\n return (\n project.getSourceFile(fileFullpath) ||\n project.addSourceFileAtPath(fileFullpath)\n );\n },\n refreshSourceFile: async (fileFullpath: string) => {\n const sourceFile = project.getSourceFile(fileFullpath);\n if (sourceFile) {\n await sourceFile.refreshFromFileSystem();\n }\n },\n literalTypesResolver,\n };\n};\n", "import { resolve } from \"node:path\";\n\nimport crc from \"crc/crc32\";\nimport fsx from \"fs-extra\";\n\n/**\n * Import from published package to ensure correct version at runtime.\n * Local import would be bundled with pre-bump version; this external\n * import resolves to the actual published package.json.\n * */\nimport self from \"@kosmojs/dev/package.json\" with { type: \"json\" };\nimport { type ApiRoute, pathResolver } from \"@kosmojs/devlib\";\n\nexport type Cache = {\n hash: number;\n referencedFiles: Record<string, number>;\n} & Pick<\n ApiRoute,\n | \"params\"\n | \"methods\"\n | \"typeDeclarations\"\n | \"numericParams\"\n | \"payloadTypes\"\n | \"responseTypes\"\n>;\n\ntype ExtraContext = Record<string | number, unknown>;\n\nexport const cacheFactory = (\n route: Pick<ApiRoute, \"file\" | \"fileFullpath\" | \"importName\" | \"importPath\">,\n {\n appRoot,\n sourceFolder,\n extraContext,\n }: {\n appRoot: string;\n sourceFolder: string;\n extraContext?: ExtraContext;\n },\n) => {\n const cacheFile = pathResolver({\n appRoot,\n sourceFolder,\n }).resolve(\"apiLibDir\", route.importPath, \"cache.json\");\n\n const getCache = async (opt?: {\n validate?: boolean;\n }): Promise<Cache | undefined> => {\n if (await fsx.exists(cacheFile)) {\n try {\n const cache = JSON.parse(await fsx.readFile(cacheFile, \"utf8\"));\n return opt?.validate //\n ? validateCache(cache)\n : cache;\n } catch (_e) {}\n }\n return undefined;\n };\n\n const persistCache = async ({\n referencedFiles: _referencedFiles,\n ...rest\n }: Omit<Cache, \"hash\" | \"referencedFiles\"> & {\n referencedFiles: Array<string>;\n }): Promise<Cache> => {\n const hash = await generateFileHash(route.fileFullpath, {\n ...extraContext,\n });\n\n const referencedFiles: Cache[\"referencedFiles\"] = {};\n\n for (const file of _referencedFiles) {\n referencedFiles[\n // Strip project root to ensure cached paths are relative\n // and portable across environments (CI, local, etc.)\n file.replace(`${appRoot}/`, \"\")\n ] = await generateFileHash(file);\n }\n\n const cache = { ...rest, hash, referencedFiles };\n\n await fsx.outputJson(cacheFile, cache, { spaces: 2 });\n\n return cache;\n };\n\n const validateCache = async (\n cache: Cache | undefined,\n ): Promise<Cache | undefined> => {\n if (!cache?.hash) {\n return;\n }\n\n if (!cache.typeDeclarations || !cache.referencedFiles) {\n // incomplete cache\n return;\n }\n\n const hash = await generateFileHash(route.fileFullpath, {\n ...extraContext,\n });\n\n if (!identicalHashSum(cache.hash, hash)) {\n // route itself updated\n return;\n }\n\n for (const [file, hash] of Object.entries(cache.referencedFiles)) {\n if (\n !identicalHashSum(hash, await generateFileHash(resolve(appRoot, file)))\n ) {\n // some referenced file updated\n return;\n }\n }\n\n return cache;\n };\n\n return {\n getCache,\n validateCache,\n persistCache,\n };\n};\n\nconst generateFileHash = async (\n file: string,\n extraContext?: ExtraContext,\n): Promise<number> => {\n let fileContent: string | undefined;\n try {\n fileContent = await fsx.readFile(file, \"utf8\");\n } catch (_e) {\n // file could be deleted since last build\n return 0;\n }\n return fileContent\n ? crc(\n JSON.stringify({\n ...extraContext,\n [self.cacheVersion]: fileContent,\n }),\n )\n : 0;\n};\n\n// return true if sums are identical\nconst identicalHashSum = (a: number, b: number) => {\n return a === b;\n};\n", "{{#each resolvedTypes}}\nexport type {{name}} = {{text}};\n{{/each}}\n", "{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n \"{{name}}\"{{#unless isRequired}}?{{/unless}}:{{#if isRest}} Array<{{/if}}\n {{#if refinement}}{{refinement.text}}{{else}}string{{/if}}\n {{#if isRest}}>{{/if}}\n {{/each}}\n};\n\n{{#each payloadTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n\n{{#each responseTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n"],
5
- "mappings": "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",
6
- "names": ["resolve", "crc", "pathResolver", "callExpression", "resolve", "crc", "hash", "resolve", "routeFiles", "crc", "pathResolver"]
4
+ "sourcesContent": ["import { dirname, join, resolve } from \"node:path\";\n\nimport crc from \"crc/crc32\";\nimport picomatch from \"picomatch\";\nimport { glob } from \"tinyglobby\";\n\nimport {\n type ApiRoute,\n defaults,\n type PageRoute,\n type PluginOptionsResolved,\n pathResolver,\n pathTokensFactory,\n type RouteEntry,\n type RouteResolver,\n render,\n renderToFile,\n} from \"@kosmojs/devlib\";\n\nimport { resolveRouteSignature, typeResolverFactory } from \"./ast\";\nimport { cacheFactory } from \"./cache\";\n\nimport resolvedTypesTpl from \"./templates/resolved-types.hbs\";\nimport typesFileTpl from \"./templates/types.hbs\";\n\ntype Resolvers = Map<string, RouteResolver>;\n\ntype ResolveRouteFile = (\n file: string,\n opts: Pick<PluginOptionsResolved, \"appRoot\" | \"sourceFolder\">,\n) =>\n | [\n // Either `apiDir` or `pagesDir`\n folder: string,\n // Path to a file within the folder, nested at least one level deep\n file: string,\n ]\n | undefined;\n\ntype ResolveRouteEntry = (\n file: string,\n opts: Pick<PluginOptionsResolved, \"appRoot\" | \"sourceFolder\">,\n) => RouteEntry | undefined;\n\ntype ResolversFactory = (\n routeFiles: Array<string>,\n) => Map<string, RouteResolver>;\n\n// Only `index.ts` files matter for API endpoints\nconst API_INDEX_PATTERN = \"index.ts\";\n\n// Match component endpoints for Solid/React (.tsx) and Vue (.vue).\nconst PAGE_INDEX_PATTERN = \"index.{tsx,vue}\";\n\nconst ROUTE_FILE_PATTERNS = [\n `${defaults.apiDir}/**/${API_INDEX_PATTERN}`,\n `${defaults.pagesDir}/**/${PAGE_INDEX_PATTERN}`,\n];\n\nexport const resolveRouteFile: ResolveRouteFile = (\n file,\n { appRoot, sourceFolder },\n) => {\n const [_sourceFolder, folder, ...rest] = resolve(appRoot, file)\n .replace(`${appRoot}/`, \"\")\n .split(\"/\");\n\n /**\n * Ensure the file:\n * - is under the correct source root (`sourceFolder`)\n * - belongs to a known route folder (`apiDir` or `pagesDir`)\n * - is nested at least one level deep (not a direct child of the folder)\n */\n if (!folder || _sourceFolder !== sourceFolder || rest.length < 2) {\n return;\n }\n\n return picomatch.isMatch(join(folder, ...rest), ROUTE_FILE_PATTERNS)\n ? [folder, rest.join(\"/\")]\n : undefined;\n};\n\nexport const resolveRouteEntry: ResolveRouteEntry = (\n _file,\n { appRoot, sourceFolder },\n) => {\n const resolvedPaths = resolveRouteFile(_file, { appRoot, sourceFolder });\n\n if (!resolvedPaths) {\n return;\n }\n\n const [folder, file] = resolvedPaths;\n\n const fileFullpath = join(appRoot, sourceFolder, folder, file);\n\n const pathTokens = pathTokensFactory(dirname(file));\n\n const name = pathTokens.map((e) => e.orig).join(\"/\");\n\n const importPath = dirname(file);\n\n const importName = [\n importPath\n .split(/\\[/)[0]\n .replace(/^\\W+|\\W+$/g, \"\")\n .replace(/\\W+/g, \"_\"),\n crc(importPath),\n ].join(\"_\");\n\n return {\n name,\n folder,\n file,\n fileFullpath,\n pathTokens,\n importPath,\n importName,\n };\n};\n\nexport default async (\n pluginOptions: PluginOptionsResolved,\n): Promise<{\n resolvers: Resolvers;\n resolversFactory: ResolversFactory;\n}> => {\n const {\n appRoot,\n sourceFolder,\n generators = [],\n formatters = [],\n refineTypeName,\n } = pluginOptions;\n\n let resolveTypes = false;\n\n for (const { options } of generators) {\n if (options?.resolveTypes) {\n resolveTypes = true;\n }\n }\n\n const {\n //\n literalTypesResolver,\n getSourceFile,\n refreshSourceFile,\n } = typeResolverFactory(pluginOptions);\n\n const resolversFactory: ResolversFactory = (routeFiles) => {\n const resolvers = new Map<\n string, // fileFullpath\n RouteResolver\n >();\n\n const entries: Array<RouteEntry> = routeFiles.flatMap((file) => {\n const entry = resolveRouteEntry(file, pluginOptions);\n return entry ? [entry] : [];\n });\n\n // handle api routes\n for (const entry of entries.filter((e) => e.folder === defaults.apiDir)) {\n const {\n name,\n file,\n folder,\n fileFullpath,\n pathTokens,\n importPath,\n importName,\n } = entry;\n\n const handler: RouteResolver[\"handler\"] = async (updatedFile) => {\n const paramsSchema = pathTokens.flatMap((e) => {\n return e.param ? [e.param] : [];\n });\n\n const optionalParams = paramsSchema.length\n ? !paramsSchema.some((e) => e.isRequired)\n : true;\n\n const { getCache, persistCache } = cacheFactory(\n { file, fileFullpath, importName, importPath },\n {\n appRoot,\n sourceFolder,\n extraContext: { resolveTypes },\n },\n );\n\n let cache = await getCache({ validate: true });\n\n if (!cache) {\n if (updatedFile === fileFullpath) {\n await refreshSourceFile(fileFullpath);\n }\n\n const {\n typeDeclarations,\n paramsRefinements,\n methods,\n payloadTypes,\n responseTypes,\n referencedFiles = [],\n } = await resolveRouteSignature(\n { importName, fileFullpath, optionalParams },\n {\n withReferencedFiles: true,\n sourceFile: getSourceFile(fileFullpath),\n relpathResolver(path) {\n return join(sourceFolder, defaults.apiDir, dirname(file), path);\n },\n },\n );\n\n const numericParams = paramsRefinements\n ? paramsRefinements.flatMap(({ text, index }) => {\n if (text === \"number\") {\n const param = paramsSchema.at(index);\n return param ? [param.name] : [];\n }\n return [];\n })\n : [];\n\n const typesFile = pathResolver({ appRoot, sourceFolder }).resolve(\n \"apiLibDir\",\n importPath,\n \"types.ts\",\n );\n\n const params: ApiRoute[\"params\"] = {\n id: [\"ParamsT\", crc(name)].join(\"\"),\n schema: paramsSchema,\n resolvedType: undefined,\n };\n\n const typesFileContent = render(typesFileTpl, {\n params,\n paramsSchema: paramsSchema.map((param, index) => {\n return {\n ...param,\n refinement: paramsRefinements?.at(index),\n };\n }),\n typeDeclarations,\n payloadTypes,\n responseTypes,\n });\n\n const resolvedTypes = resolveTypes\n ? literalTypesResolver(typesFileContent, {\n overrides: [...payloadTypes, ...responseTypes].reduce(\n (map: Record<string, string>, { id, skipValidation }) => {\n if (skipValidation) {\n map[id] = \"never\";\n }\n return map;\n },\n { [refineTypeName]: refineTypeName },\n ),\n withProperties: [params.id, ...payloadTypes.map((e) => e.id)],\n formatters,\n })\n : undefined;\n\n /**\n * Deploy types.ts file; required by core generators (like fetch).\n * If types resolved, write resolved types;\n * otherwise write original types extracted from API route.\n * */\n await renderToFile(\n typesFile,\n resolvedTypes ? resolvedTypesTpl : typesFileContent,\n { resolvedTypes },\n );\n\n params.resolvedType = resolvedTypes?.find(\n (e) => e.name === params.id,\n );\n\n cache = await persistCache({\n params,\n methods,\n typeDeclarations,\n numericParams,\n // text was needed at writing types.ts file, dropping from cache\n payloadTypes: payloadTypes.map(({ text, ...rest }) => {\n return {\n ...rest,\n resolvedType: resolvedTypes?.find((e) => e.name === rest.id),\n };\n }),\n responseTypes: responseTypes.map(({ text, ...rest }) => {\n return {\n ...rest,\n resolvedType: resolvedTypes?.find((e) => e.name === rest.id),\n };\n }),\n referencedFiles,\n });\n }\n\n const route: ApiRoute = {\n name,\n pathTokens,\n params: cache.params,\n numericParams: cache.numericParams,\n optionalParams,\n importName,\n importPath,\n folder,\n file,\n fileFullpath,\n methods: cache.methods,\n typeDeclarations: cache.typeDeclarations,\n payloadTypes: cache.payloadTypes,\n responseTypes: cache.responseTypes,\n referencedFiles: Object.keys(cache.referencedFiles).map(\n // expand referenced files path,\n // they are stored as relative in cache\n (e) => resolve(appRoot, e),\n ),\n };\n\n return {\n kind: \"api\",\n route,\n };\n };\n\n resolvers.set(fileFullpath, { name, handler });\n }\n\n // handle page routes\n for (const entry of entries.filter((e) => e.folder === defaults.pagesDir)) {\n const {\n //\n name,\n folder,\n file,\n fileFullpath,\n pathTokens,\n importPath,\n importName,\n } = entry;\n\n const handler: RouteResolver[\"handler\"] = async () => {\n const route: PageRoute = {\n name,\n pathTokens,\n params: {\n schema: pathTokens.flatMap((e) => (e.param ? [e.param] : [])),\n },\n folder,\n file,\n fileFullpath,\n importPath,\n importName,\n };\n\n return {\n kind: \"page\",\n route,\n };\n };\n\n resolvers.set(fileFullpath, { name, handler });\n }\n\n return resolvers;\n };\n\n const routeFiles = await glob(ROUTE_FILE_PATTERNS, {\n cwd: resolve(appRoot, sourceFolder),\n absolute: true,\n onlyFiles: true,\n ignore: [\n `${defaults.apiDir}/${API_INDEX_PATTERN}`,\n `${defaults.pagesDir}/${PAGE_INDEX_PATTERN}`,\n ],\n });\n\n return {\n resolvers: resolversFactory(routeFiles),\n resolversFactory,\n };\n};\n", "import { resolve } from \"node:path\";\n\nimport crc from \"crc/crc32\";\nimport { flattener } from \"tfusion\";\nimport {\n type CallExpression,\n type Identifier,\n type Node,\n Project,\n type ProjectOptions,\n type SourceFile,\n SyntaxKind,\n} from \"ts-morph\";\n\nimport { type HTTPMethod, HTTPMethods } from \"@kosmojs/api\";\nimport type {\n ApiRoute,\n PayloadType,\n PluginOptionsResolved,\n ResponseType,\n TypeDeclaration,\n} from \"@kosmojs/devlib\";\n\ntype PathResolver = (path: string) => string;\n\nexport const createProject = (opts?: ProjectOptions) => new Project(opts);\n\nexport const resolveRouteSignature = async (\n route: Pick<ApiRoute, \"importName\" | \"fileFullpath\" | \"optionalParams\">,\n opts?: {\n relpathResolver?: PathResolver;\n sourceFile?: SourceFile;\n withReferencedFiles?: boolean;\n },\n) => {\n const {\n sourceFile = createProject().addSourceFileAtPath(route.fileFullpath),\n } = { ...opts };\n\n const [typeDeclarations, referencedFiles] = extractTypeDeclarations(\n sourceFile,\n opts,\n );\n\n const defaultExport = extractDefaultExport(sourceFile);\n\n const paramsRefinements = defaultExport\n ? extractParamsRefinements(defaultExport)\n : undefined;\n\n const methods = defaultExport\n ? extractRouteMethods(defaultExport, route)\n : [];\n\n const payloadTypes = methods.flatMap((e) => {\n return e.payloadType ? [e.payloadType] : [];\n });\n\n const responseTypes = methods.flatMap((e) => {\n return e.responseType ? [e.responseType] : [];\n });\n\n return {\n typeDeclarations,\n paramsRefinements,\n methods: methods.map((e) => e.method),\n payloadTypes,\n responseTypes,\n referencedFiles,\n };\n};\n\nexport const extractDefaultExport = (\n sourceFile: SourceFile,\n): CallExpression | undefined => {\n const [defaultExport] = sourceFile\n .getExportAssignments()\n .flatMap((exportAssignment) => {\n if (exportAssignment.isExportEquals()) {\n return [];\n }\n const callExpression = exportAssignment.getExpression();\n return callExpression.isKind(SyntaxKind.CallExpression)\n ? [callExpression]\n : [];\n });\n return defaultExport;\n};\n\nexport const extractParamsRefinements = (\n callExpression: CallExpression,\n):\n | Array<{\n index: number;\n text: string;\n }>\n | undefined => {\n const [firstGeneric] = extractGenerics(callExpression);\n\n if (!firstGeneric?.node.isKind(SyntaxKind.TupleType)) {\n return;\n }\n\n const tupleElements = firstGeneric.node.getElements();\n\n if (!tupleElements?.length) {\n return;\n }\n\n return tupleElements.map((node, index) => {\n return {\n index,\n text: node.getText(),\n };\n });\n};\n\nexport const extractRouteMethods = (\n callExpression: CallExpression,\n route: Pick<ApiRoute, \"importName\" | \"optionalParams\">,\n): Array<{\n method: HTTPMethod;\n payloadType: (PayloadType & { text: string }) | undefined;\n responseType: (ResponseType & { text: string }) | undefined;\n}> => {\n const funcDeclaration =\n callExpression.getFirstChildByKind(SyntaxKind.ArrowFunction) ||\n callExpression.getFirstChildByKind(SyntaxKind.FunctionExpression);\n\n if (!funcDeclaration) {\n return [];\n }\n\n const arrayLiteralExpression = funcDeclaration.getFirstChildByKind(\n SyntaxKind.ArrayLiteralExpression,\n );\n\n if (!arrayLiteralExpression) {\n return [];\n }\n\n const callExpressions: Array<[CallExpression, HTTPMethod]> = [];\n\n for (const e of arrayLiteralExpression.getChildrenOfKind(\n SyntaxKind.CallExpression,\n )) {\n const name = e.getExpression().getText() as HTTPMethod;\n if (HTTPMethods[name]) {\n callExpressions.push([e, name]);\n }\n }\n\n const methods = [];\n\n const skipValidationFilter = (e: string) => /@skip-validation/.test(e);\n\n for (const [callExpression, method] of callExpressions) {\n const [payloadGeneric, responseGeneric] = extractGenerics(callExpression);\n\n const payloadText = payloadGeneric?.node\n ? payloadGeneric.node.getChildren().length === 0\n ? \"{}\"\n : payloadGeneric.node.getFullText()\n : undefined;\n\n const responseText = responseGeneric?.node.getText();\n\n const responseType = responseText\n ? {\n id: [\"ResponseT\", crc(route.importName + method)].join(\"\"),\n method,\n skipValidation: responseGeneric?.comments\n ? responseGeneric.comments.some(skipValidationFilter)\n : false,\n text: [\"never\", \"object\"].includes(responseText)\n ? \"{}\"\n : responseText,\n resolvedType: undefined,\n }\n : undefined;\n\n const payloadType = payloadText\n ? {\n id: [\"PayloadT\", crc(route.importName + method)].join(\"\"),\n responseTypeId: responseType?.id,\n method,\n skipValidation: payloadGeneric?.comments\n ? payloadGeneric.comments.some(skipValidationFilter)\n : false,\n isOptional: payloadText\n ? payloadText === \"{}\" || route.optionalParams\n : true,\n text: payloadText,\n resolvedType: undefined,\n }\n : undefined;\n\n methods.push({\n method,\n payloadType,\n responseType,\n });\n }\n\n return methods;\n};\n\nexport const extractTypeDeclarations = (\n sourceFile: SourceFile,\n opts?: {\n relpathResolver?: PathResolver;\n withReferencedFiles?: boolean;\n },\n): [d: Array<TypeDeclaration>, f?: Array<string>] => {\n const declarations: Array<TypeDeclaration> = [];\n\n const referencedFiles: Array<string> | undefined = opts?.withReferencedFiles\n ? []\n : undefined;\n\n for (const declaration of sourceFile.getImportDeclarations()) {\n const modulePath = declaration.getModuleSpecifierValue();\n\n const path = /^\\.\\.?\\/?/.test(modulePath)\n ? opts?.relpathResolver\n ? opts.relpathResolver(modulePath)\n : modulePath\n : modulePath;\n\n const typeOnlyDeclaration = declaration.isTypeOnly();\n\n const defaultImport = typeOnlyDeclaration\n ? declaration.getDefaultImport()\n : undefined;\n\n if (defaultImport) {\n const name = defaultImport.getText();\n const text = `import type ${name} from \"${path}\";`;\n declarations.push({\n importDeclaration: {\n name,\n path,\n },\n text,\n });\n if (referencedFiles) {\n referencedFiles.push(...getReferencedFiles(defaultImport));\n }\n }\n\n for (const namedImport of declaration.getNamedImports()) {\n if (namedImport.isTypeOnly() || typeOnlyDeclaration) {\n const nameNode = namedImport.getNameNode();\n const name = nameNode.getText();\n const alias = namedImport.getAliasNode()?.getText();\n const nameText = alias ? `${name} as ${alias}` : name;\n\n declarations.push({\n importDeclaration: {\n name,\n alias,\n path,\n },\n text: `import type { ${nameText} } from \"${path}\";`,\n });\n\n if (referencedFiles) {\n if (nameNode.isKind(SyntaxKind.Identifier)) {\n referencedFiles.push(...getReferencedFiles(nameNode));\n }\n }\n }\n }\n }\n\n for (const declaration of sourceFile.getTypeAliases()) {\n const name = declaration.getName();\n const text = declaration.getFullText().trim();\n declarations.push({\n typeAliasDeclaration: { name },\n text,\n });\n }\n\n for (const declaration of sourceFile.getInterfaces()) {\n const name = declaration.getName();\n const text = declaration.getFullText().trim();\n declarations.push({\n interfaceDeclaration: { name },\n text,\n });\n }\n\n for (const declaration of sourceFile.getEnums()) {\n const name = declaration.getName();\n const text = declaration.getFullText().trim();\n declarations.push({\n enumDeclaration: { name },\n text,\n });\n }\n\n for (const declaration of sourceFile.getExportDeclarations()) {\n const typeOnlyDeclaration = declaration.isTypeOnly();\n\n const modulePath = declaration.getModuleSpecifierValue();\n\n const path = modulePath\n ? /^\\.\\.?\\/?/.test(modulePath)\n ? opts?.relpathResolver\n ? opts.relpathResolver(modulePath)\n : modulePath\n : modulePath\n : undefined;\n\n for (const namedExport of declaration.getNamedExports()) {\n if (namedExport.isTypeOnly() || typeOnlyDeclaration) {\n const nameNode = namedExport.getNameNode();\n const name = nameNode.getText();\n const alias = namedExport.getAliasNode()?.getText();\n const nameText = alias ? `${name} as ${alias}` : name;\n\n declarations.push({\n exportDeclaration: {\n name,\n alias: alias ?? name,\n path,\n },\n text: path\n ? `export type { ${nameText} } from \"${path}\";`\n : `export type { ${nameText} };`,\n });\n\n if (referencedFiles) {\n if (nameNode.isKind(SyntaxKind.Identifier)) {\n referencedFiles.push(...getReferencedFiles(nameNode));\n }\n }\n }\n }\n }\n\n return referencedFiles\n ? [declarations, [...new Set<string>(referencedFiles)]]\n : [declarations];\n};\n\nconst getReferencedFiles = (importIdentifier: Identifier): Array<string> => {\n // ambient modules may have declarations in multiple files\n const declarations =\n importIdentifier //\n ?.getSymbol()\n ?.getAliasedSymbol()\n ?.getDeclarations() || [];\n\n return declarations.flatMap((e) => {\n const sourceFile = e.getSourceFile();\n return sourceFile //\n ? [sourceFile.getFilePath()]\n : [];\n });\n};\n\nconst extractGenerics = (\n callExpression: CallExpression,\n): Array<{ node: Node; comments: Array<string> }> => {\n return callExpression.getTypeArguments().map((node) => {\n return {\n node,\n comments: node\n .getLeadingCommentRanges()\n .map((range) => range.getText().trim()),\n };\n });\n};\n\nexport const typeResolverFactory = ({ appRoot }: PluginOptionsResolved) => {\n const project = createProject({\n tsConfigFilePath: resolve(appRoot, \"tsconfig.json\"),\n skipAddingFilesFromTsConfig: true,\n });\n\n const literalTypesResolver = (\n literalTypes: string,\n options: Parameters<typeof flattener>[2],\n ) => {\n const sourceFile = project.createSourceFile(\n `${crc(literalTypes)}-${Date.now()}.ts`,\n literalTypes,\n { overwrite: true },\n );\n\n const resolvedTypes = flattener(project, sourceFile, {\n ...options,\n stripComments: true,\n });\n\n project.removeSourceFile(sourceFile);\n\n return resolvedTypes;\n };\n\n return {\n getSourceFile: (fileFullpath: string) => {\n return (\n project.getSourceFile(fileFullpath) ||\n project.addSourceFileAtPath(fileFullpath)\n );\n },\n refreshSourceFile: async (fileFullpath: string) => {\n const sourceFile = project.getSourceFile(fileFullpath);\n if (sourceFile) {\n await sourceFile.refreshFromFileSystem();\n }\n },\n literalTypesResolver,\n };\n};\n", "import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\n\nimport crc from \"crc/crc32\";\n\n/**\n * Import from published package to ensure correct version at runtime.\n * Local import would be bundled with pre-bump version; this external\n * import resolves to the actual published package.json.\n * */\nimport self from \"@kosmojs/dev/package.json\" with { type: \"json\" };\nimport { type ApiRoute, pathExists, pathResolver } from \"@kosmojs/devlib\";\n\nexport type Cache = {\n hash: number;\n referencedFiles: Record<string, number>;\n} & Pick<\n ApiRoute,\n | \"params\"\n | \"methods\"\n | \"typeDeclarations\"\n | \"numericParams\"\n | \"payloadTypes\"\n | \"responseTypes\"\n>;\n\ntype ExtraContext = Record<string | number, unknown>;\n\nexport const cacheFactory = (\n route: Pick<ApiRoute, \"file\" | \"fileFullpath\" | \"importName\" | \"importPath\">,\n {\n appRoot,\n sourceFolder,\n extraContext,\n }: {\n appRoot: string;\n sourceFolder: string;\n extraContext?: ExtraContext;\n },\n) => {\n const cacheFile = pathResolver({\n appRoot,\n sourceFolder,\n }).resolve(\"apiLibDir\", route.importPath, \"cache.json\");\n\n const getCache = async (opt?: {\n validate?: boolean;\n }): Promise<Cache | undefined> => {\n if (await pathExists(cacheFile)) {\n try {\n const cache = JSON.parse(await readFile(cacheFile, \"utf8\"));\n return opt?.validate //\n ? validateCache(cache)\n : cache;\n } catch (_e) {}\n }\n return undefined;\n };\n\n const persistCache = async ({\n referencedFiles: _referencedFiles,\n ...rest\n }: Omit<Cache, \"hash\" | \"referencedFiles\"> & {\n referencedFiles: Array<string>;\n }): Promise<Cache> => {\n const hash = await generateFileHash(route.fileFullpath, {\n ...extraContext,\n });\n\n const referencedFiles: Cache[\"referencedFiles\"] = {};\n\n for (const file of _referencedFiles) {\n referencedFiles[\n // Strip project root to ensure cached paths are relative\n // and portable across environments (CI, local, etc.)\n file.replace(`${appRoot}/`, \"\")\n ] = await generateFileHash(file);\n }\n\n const cache = { ...rest, hash, referencedFiles };\n\n await mkdir(dirname(cacheFile), { recursive: true });\n await writeFile(cacheFile, JSON.stringify(cache, null, 2), \"utf8\");\n\n return cache;\n };\n\n const validateCache = async (\n cache: Cache | undefined,\n ): Promise<Cache | undefined> => {\n if (!cache?.hash) {\n return;\n }\n\n if (!cache.typeDeclarations || !cache.referencedFiles) {\n // incomplete cache\n return;\n }\n\n const hash = await generateFileHash(route.fileFullpath, {\n ...extraContext,\n });\n\n if (!identicalHashSum(cache.hash, hash)) {\n // route itself updated\n return;\n }\n\n for (const [file, hash] of Object.entries(cache.referencedFiles)) {\n if (\n !identicalHashSum(hash, await generateFileHash(resolve(appRoot, file)))\n ) {\n // some referenced file updated\n return;\n }\n }\n\n return cache;\n };\n\n return {\n getCache,\n validateCache,\n persistCache,\n };\n};\n\nconst generateFileHash = async (\n file: string,\n extraContext?: ExtraContext,\n): Promise<number> => {\n let fileContent: string | undefined;\n try {\n fileContent = await readFile(file, \"utf8\");\n } catch (_e) {\n // file could be deleted since last build\n return 0;\n }\n return fileContent\n ? crc(\n JSON.stringify({\n ...extraContext,\n [self.cacheVersion]: fileContent,\n }),\n )\n : 0;\n};\n\n// return true if sums are identical\nconst identicalHashSum = (a: number, b: number) => {\n return a === b;\n};\n", "{{#each resolvedTypes}}\nexport type {{name}} = {{text}};\n{{/each}}\n", "{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n \"{{name}}\"{{#unless isRequired}}?{{/unless}}:{{#if isRest}} Array<{{/if}}\n {{#if refinement}}{{refinement.text}}{{else}}string{{/if}}\n {{#if isRest}}>{{/if}}\n {{/each}}\n};\n\n{{#each payloadTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n\n{{#each responseTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n"],
5
+ "mappings": "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",
6
+ "names": ["dirname", "resolve", "crc", "pathResolver", "callExpression", "resolve", "crc", "hash", "resolve", "dirname", "crc", "routeFiles", "pathResolver"]
7
7
  }
@@ -7,7 +7,7 @@ import {
7
7
  } from "@kosmojs/devlib";
8
8
 
9
9
  // src/base-plugin/routes.ts
10
- import { dirname, join, resolve as resolve3 } from "node:path";
10
+ import { dirname as dirname2, join, resolve as resolve3 } from "node:path";
11
11
  import crc3 from "crc/crc32";
12
12
  import picomatch from "picomatch";
13
13
  import { glob } from "tinyglobby";
@@ -275,11 +275,11 @@ var typeResolverFactory = ({ appRoot: appRoot2 }) => {
275
275
  };
276
276
 
277
277
  // src/base-plugin/cache.ts
278
- import { resolve as resolve2 } from "node:path";
278
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
279
+ import { dirname, resolve as resolve2 } from "node:path";
279
280
  import crc2 from "crc/crc32";
280
- import fsx from "fs-extra";
281
281
  import self from "@kosmojs/dev/package.json" with { type: "json" };
282
- import { pathResolver } from "@kosmojs/devlib";
282
+ import { pathExists, pathResolver } from "@kosmojs/devlib";
283
283
  var cacheFactory = (route, {
284
284
  appRoot: appRoot2,
285
285
  sourceFolder: sourceFolder2,
@@ -290,9 +290,9 @@ var cacheFactory = (route, {
290
290
  sourceFolder: sourceFolder2
291
291
  }).resolve("apiLibDir", route.importPath, "cache.json");
292
292
  const getCache = async (opt) => {
293
- if (await fsx.exists(cacheFile)) {
293
+ if (await pathExists(cacheFile)) {
294
294
  try {
295
- const cache = JSON.parse(await fsx.readFile(cacheFile, "utf8"));
295
+ const cache = JSON.parse(await readFile(cacheFile, "utf8"));
296
296
  return opt?.validate ? validateCache(cache) : cache;
297
297
  } catch (_e) {
298
298
  }
@@ -315,7 +315,8 @@ var cacheFactory = (route, {
315
315
  ] = await generateFileHash(file);
316
316
  }
317
317
  const cache = { ...rest, hash, referencedFiles };
318
- await fsx.outputJson(cacheFile, cache, { spaces: 2 });
318
+ await mkdir(dirname(cacheFile), { recursive: true });
319
+ await writeFile(cacheFile, JSON.stringify(cache, null, 2), "utf8");
319
320
  return cache;
320
321
  };
321
322
  const validateCache = async (cache) => {
@@ -347,7 +348,7 @@ var cacheFactory = (route, {
347
348
  var generateFileHash = async (file, extraContext) => {
348
349
  let fileContent;
349
350
  try {
350
- fileContent = await fsx.readFile(file, "utf8");
351
+ fileContent = await readFile(file, "utf8");
351
352
  } catch (_e) {
352
353
  return 0;
353
354
  }
@@ -369,6 +370,43 @@ var resolved_types_default = "{{#each resolvedTypes}}\nexport type {{name}} = {{
369
370
  var types_default = '{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n "{{name}}"{{#unless isRequired}}?{{/unless}}:{{#if isRest}} Array<{{/if}}\n {{#if refinement}}{{refinement.text}}{{else}}string{{/if}}\n {{#if isRest}}>{{/if}}\n {{/each}}\n};\n\n{{#each payloadTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n\n{{#each responseTypes}}\nexport type {{id}} = {{text}};\n{{/each}}\n';
370
371
 
371
372
  // src/base-plugin/routes.ts
373
+ var API_INDEX_PATTERN = "index.ts";
374
+ var PAGE_INDEX_PATTERN = "index.{tsx,vue}";
375
+ var ROUTE_FILE_PATTERNS = [
376
+ `${defaults.apiDir}/**/${API_INDEX_PATTERN}`,
377
+ `${defaults.pagesDir}/**/${PAGE_INDEX_PATTERN}`
378
+ ];
379
+ var resolveRouteFile = (file, { appRoot: appRoot2, sourceFolder: sourceFolder2 }) => {
380
+ const [_sourceFolder, folder, ...rest] = resolve3(appRoot2, file).replace(`${appRoot2}/`, "").split("/");
381
+ if (!folder || _sourceFolder !== sourceFolder2 || rest.length < 2) {
382
+ return;
383
+ }
384
+ return picomatch.isMatch(join(folder, ...rest), ROUTE_FILE_PATTERNS) ? [folder, rest.join("/")] : void 0;
385
+ };
386
+ var resolveRouteEntry = (_file, { appRoot: appRoot2, sourceFolder: sourceFolder2 }) => {
387
+ const resolvedPaths = resolveRouteFile(_file, { appRoot: appRoot2, sourceFolder: sourceFolder2 });
388
+ if (!resolvedPaths) {
389
+ return;
390
+ }
391
+ const [folder, file] = resolvedPaths;
392
+ const fileFullpath = join(appRoot2, sourceFolder2, folder, file);
393
+ const pathTokens = pathTokensFactory(dirname2(file));
394
+ const name = pathTokens.map((e) => e.orig).join("/");
395
+ const importPath = dirname2(file);
396
+ const importName = [
397
+ importPath.split(/\[/)[0].replace(/^\W+|\W+$/g, "").replace(/\W+/g, "_"),
398
+ crc3(importPath)
399
+ ].join("_");
400
+ return {
401
+ name,
402
+ folder,
403
+ file,
404
+ fileFullpath,
405
+ pathTokens,
406
+ importPath,
407
+ importName
408
+ };
409
+ };
372
410
  var routes_default = async (pluginOptions) => {
373
411
  const {
374
412
  appRoot: appRoot2,
@@ -389,44 +427,11 @@ var routes_default = async (pluginOptions) => {
389
427
  getSourceFile,
390
428
  refreshSourceFile
391
429
  } = typeResolverFactory(pluginOptions);
392
- const routeFilePatterns = [
393
- `${defaults.apiDir}/**/index.ts`,
394
- `${defaults.pagesDir}/**/index.{ts,tsx,vue,svelte}`
395
- ];
396
- const resolveRouteFile2 = (file) => {
397
- const [_sourceFolder, folder, ...rest] = resolve3(appRoot2, file).replace(`${appRoot2}/`, "").split("/");
398
- if (!folder || _sourceFolder !== sourceFolder2 || rest.length < 2) {
399
- return;
400
- }
401
- return picomatch.isMatch(join(folder, ...rest), routeFilePatterns) ? [folder, rest.join("/")] : void 0;
402
- };
403
430
  const resolversFactory2 = (routeFiles2) => {
404
431
  const resolvers2 = /* @__PURE__ */ new Map();
405
- const entries = routeFiles2.flatMap((_file) => {
406
- const resolvedPaths = resolveRouteFile2(_file);
407
- if (!resolvedPaths) {
408
- return [];
409
- }
410
- const [folder, file] = resolvedPaths;
411
- const fileFullpath = join(appRoot2, sourceFolder2, folder, file);
412
- const pathTokens = pathTokensFactory(dirname(file));
413
- const name = pathTokens.map((e) => e.orig).join("/");
414
- const importPath = dirname(file);
415
- const importName = [
416
- importPath.split(/\[/)[0].replace(/^\W+|\W+$/g, "").replace(/\W+/g, "_"),
417
- crc3(importPath)
418
- ].join("_");
419
- return [
420
- {
421
- name,
422
- folder,
423
- file,
424
- fileFullpath,
425
- pathTokens,
426
- importPath,
427
- importName
428
- }
429
- ];
432
+ const entries = routeFiles2.flatMap((file) => {
433
+ const entry = resolveRouteEntry(file, pluginOptions);
434
+ return entry ? [entry] : [];
430
435
  });
431
436
  for (const entry of entries.filter((e) => e.folder === defaults.apiDir)) {
432
437
  const {
@@ -469,7 +474,7 @@ var routes_default = async (pluginOptions) => {
469
474
  withReferencedFiles: true,
470
475
  sourceFile: getSourceFile(fileFullpath),
471
476
  relpathResolver(path) {
472
- return join(sourceFolder2, defaults.apiDir, dirname(file), path);
477
+ return join(sourceFolder2, defaults.apiDir, dirname2(file), path);
473
478
  }
474
479
  }
475
480
  );
@@ -605,19 +610,18 @@ var routes_default = async (pluginOptions) => {
605
610
  }
606
611
  return resolvers2;
607
612
  };
608
- const routeFiles = await glob(routeFilePatterns, {
613
+ const routeFiles = await glob(ROUTE_FILE_PATTERNS, {
609
614
  cwd: resolve3(appRoot2, sourceFolder2),
610
615
  absolute: true,
611
616
  onlyFiles: true,
612
617
  ignore: [
613
- `${defaults.apiDir}/index.ts`,
614
- `${defaults.pagesDir}/index.ts{x,}`
618
+ `${defaults.apiDir}/${API_INDEX_PATTERN}`,
619
+ `${defaults.pagesDir}/${PAGE_INDEX_PATTERN}`
615
620
  ]
616
621
  });
617
622
  return {
618
623
  resolvers: resolversFactory2(routeFiles),
619
- resolversFactory: resolversFactory2,
620
- resolveRouteFile: resolveRouteFile2
624
+ resolversFactory: resolversFactory2
621
625
  };
622
626
  };
623
627
 
@@ -644,12 +648,7 @@ var resolvedOptions = {
644
648
  var { appRoot, sourceFolder } = resolvedOptions;
645
649
  var watchHandlers = [];
646
650
  var resolvedRoutes = /* @__PURE__ */ new Map();
647
- var {
648
- //
649
- resolvers,
650
- resolversFactory,
651
- resolveRouteFile
652
- } = await routes_default(resolvedOptions);
651
+ var { resolvers, resolversFactory } = await routes_default(resolvedOptions);
653
652
  var { resolve: resolve4 } = pathResolver3({ appRoot, sourceFolder });
654
653
  var spinnerFactory = (startText) => {
655
654
  const id = [startText, Date.now().toString()].map(crc4).join(":");
@@ -761,7 +760,7 @@ watcher.on("all", async (event, file) => {
761
760
  if (event.endsWith("Dir")) {
762
761
  return;
763
762
  }
764
- if (!resolveRouteFile(file)) {
763
+ if (!resolveRouteFile(file, { appRoot, sourceFolder })) {
765
764
  return;
766
765
  }
767
766
  const match = {