@happyvertical/smrt-core 0.40.42 → 0.40.44

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 (40) hide show
  1. package/AGENTS.md +12 -1
  2. package/README.md +24 -0
  3. package/agents/generators.md +3 -1
  4. package/dist/decorators/index.d.ts +12 -0
  5. package/dist/decorators/index.d.ts.map +1 -1
  6. package/dist/decorators/index.js.map +1 -1
  7. package/dist/generators/mcp.d.ts.map +1 -1
  8. package/dist/generators/mcp.js +1 -1
  9. package/dist/generators/mcp.js.map +1 -1
  10. package/dist/generators/tool-schema.d.ts.map +1 -1
  11. package/dist/generators/tool-schema.js +1 -1
  12. package/dist/generators/tool-schema.js.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/manifest/static-manifest.js +2 -2
  16. package/dist/manifest/static-manifest.js.map +1 -1
  17. package/dist/manifest/store.js +1 -1
  18. package/dist/manifest/test-manifest-stub.d.ts.map +1 -1
  19. package/dist/manifest/test-manifest-stub.js +100 -2
  20. package/dist/manifest/test-manifest-stub.js.map +1 -1
  21. package/dist/manifest.json +2 -2
  22. package/dist/prebuild/index.d.ts.map +1 -1
  23. package/dist/prebuild/index.js +23 -1
  24. package/dist/prebuild/index.js.map +1 -1
  25. package/dist/registry/types.d.ts +6 -0
  26. package/dist/registry/types.d.ts.map +1 -1
  27. package/dist/scanner/types.d.ts +30 -0
  28. package/dist/scanner/types.d.ts.map +1 -1
  29. package/dist/smrt-knowledge.json +8 -8
  30. package/dist/vite-plugin/index.d.ts.map +1 -1
  31. package/dist/vite-plugin/index.js +16 -4
  32. package/dist/vite-plugin/index.js.map +1 -1
  33. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
  34. package/dist/vite-plugin/sveltekit-generator.js +64 -35
  35. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  36. package/dist/vite-plugin/web-collections.d.ts +22 -2
  37. package/dist/vite-plugin/web-collections.d.ts.map +1 -1
  38. package/dist/vite-plugin/web-collections.js +37 -3
  39. package/dist/vite-plugin/web-collections.js.map +1 -1
  40. package/package.json +4 -4
@@ -19,6 +19,9 @@ var STANDARD_API_ACTIONS = [
19
19
  "update",
20
20
  "delete"
21
21
  ];
22
+ var GITIGNORE_MANAGED_BLOCK_START = "# BEGIN SMRT auto-generated routes (Vite plugin)";
23
+ var GITIGNORE_MANAGED_BLOCK_END = "# END SMRT auto-generated routes (Vite plugin)";
24
+ var LEGACY_GITIGNORE_HEADER = "# SMRT auto-generated routes (from Vite plugin)";
22
25
  /**
23
26
  * Extract simple class name from potentially qualified name.
24
27
  * Qualified names follow the pattern: @scope/package:ClassName
@@ -635,25 +638,28 @@ async function generateSvelteKitRoutes(projectRoot, manifest, options) {
635
638
  clearGeneratedRouteFiles(join(projectRoot, options.routesDir));
636
639
  clearGeneratedKnowledgeRoute(projectRoot, options);
637
640
  await generateSmrtConfigFile(projectRoot, manifest, options);
641
+ const generatedRoutePaths = [];
638
642
  let generatedCount = 0;
639
643
  let skippedCollections = 0;
640
644
  for (const [className, objectDef] of Object.entries(manifest.objects)) {
641
645
  if (isCollectionManifestClass(manifest, objectDef)) {
642
- if (await generateCollectionRoutesForObject(projectRoot, className, objectDef, manifest, options)) generatedCount++;
646
+ const collectionRoutePaths = await generateCollectionRoutesForObject(projectRoot, className, objectDef, manifest, options);
647
+ generatedRoutePaths.push(...collectionRoutePaths);
648
+ if (collectionRoutePaths.length > 0) generatedCount++;
643
649
  else {
644
650
  console.log(`[smrt] Skipping ${className} - no collection API routes to generate`);
645
651
  skippedCollections++;
646
652
  }
647
653
  continue;
648
654
  }
649
- await generateRoutesForObject(projectRoot, className, objectDef, manifest, options);
655
+ generatedRoutePaths.push(...await generateRoutesForObject(projectRoot, className, objectDef, manifest, options));
650
656
  generatedCount++;
651
657
  }
652
- if (options.knowledge?.api?.enabled) generateKnowledgeRoute(projectRoot, options);
653
- generateSyncApplyRoute(projectRoot, manifest, options);
654
- generateChangesRoute(projectRoot, manifest, options);
655
- generateEventsRoute(projectRoot, manifest, options, computeWebManifestHash(manifest));
656
- updateGitignore(projectRoot, options);
658
+ if (options.knowledge?.api?.enabled) generatedRoutePaths.push(generateKnowledgeRoute(projectRoot, options));
659
+ if (generateSyncApplyRoute(projectRoot, manifest, options)) generatedRoutePaths.push(join(projectRoot, options.routesDir, "sync", "apply", "+server.ts"));
660
+ if (generateChangesRoute(projectRoot, manifest, options)) generatedRoutePaths.push(join(projectRoot, options.routesDir, "_changes", "+server.ts"));
661
+ if (generateEventsRoute(projectRoot, manifest, options, computeWebManifestHash(manifest))) generatedRoutePaths.push(join(projectRoot, options.routesDir, "_events", "+server.ts"));
662
+ updateGitignore(projectRoot, options, generatedRoutePaths);
657
663
  const skippedMsg = skippedCollections > 0 ? ` (skipped ${skippedCollections} collection classes)` : "";
658
664
  console.log(`[smrt] Generated routes for ${generatedCount} SMRT objects${skippedMsg}`);
659
665
  }
@@ -686,7 +692,7 @@ function clearGeneratedKnowledgeRoute(projectRoot, options) {
686
692
  if (readFileSync(routePath, "utf-8").startsWith("// Auto-generated by @smrt/core vite plugin")) unlinkSync(routePath);
687
693
  }
688
694
  function generateKnowledgeRoute(projectRoot, options) {
689
- writeRoute(knowledgeRouteDir(projectRoot, options), "+server.ts", generateKnowledgeRouteTemplate(options.knowledge ?? {}, readKnowledgeRouteArtifact(projectRoot)));
695
+ return writeRoute(knowledgeRouteDir(projectRoot, options), "+server.ts", generateKnowledgeRouteTemplate(options.knowledge ?? {}, readKnowledgeRouteArtifact(projectRoot)));
690
696
  }
691
697
  function readKnowledgeRouteArtifact(projectRoot) {
692
698
  for (const relativePath of [".smrt/smrt-knowledge.json", "dist/smrt-knowledge.json"]) {
@@ -938,16 +944,20 @@ export async function getCollection<
938
944
  async function generateRoutesForObject(projectRoot, className, objectDef, manifest, options) {
939
945
  const collectionName = objectDef.collection;
940
946
  const routeDir = join(projectRoot, options.routesDir, collectionName);
947
+ const generatedRoutePaths = [];
941
948
  const apiConfig = objectDef.decoratorConfig?.api;
942
949
  if (apiConfig === false) {
943
950
  console.log(`[smrt] Skipping ${className} - API disabled`);
944
- return;
951
+ return generatedRoutePaths;
945
952
  }
946
953
  const includedActions = resolveStandardCrudActions(apiConfig);
947
- if (includedActions.includes("list") || includedActions.includes("create")) writeRoute(routeDir, "+server.ts", generateCollectionRouteTemplate(projectRoot, className, objectDef, manifest, includedActions, options, routeDir));
954
+ if (includedActions.includes("list") || includedActions.includes("create")) {
955
+ const collectionRoute = generateCollectionRouteTemplate(projectRoot, className, objectDef, manifest, includedActions, options, routeDir);
956
+ generatedRoutePaths.push(writeRoute(routeDir, "+server.ts", collectionRoute));
957
+ }
948
958
  if (includedActions.includes("get") || includedActions.includes("update") || includedActions.includes("delete")) {
949
959
  const itemRoute = generateItemRouteTemplate(projectRoot, className, objectDef, manifest, includedActions, options, join(routeDir, "[id]"));
950
- writeRoute(join(routeDir, "[id]"), "+server.ts", itemRoute);
960
+ generatedRoutePaths.push(writeRoute(join(routeDir, "[id]"), "+server.ts", itemRoute));
951
961
  }
952
962
  const customActions = Object.entries(objectDef.methods).filter(([name, method]) => !STANDARD_API_ACTIONS.includes(name) && method.isPublic && shouldIncludeInApi(name, apiConfig));
953
963
  const actionSpecs = [];
@@ -971,20 +981,24 @@ async function generateRoutesForObject(projectRoot, className, objectDef, manife
971
981
  }
972
982
  });
973
983
  }
974
- for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(actionSpecs)) writeRoute(actionRouteDir, "+server.ts", generateActionRouteTemplate(projectRoot, actionRouteDir, routeSpecs, objectDef, manifest, options));
984
+ for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(actionSpecs)) {
985
+ const actionRoute = generateActionRouteTemplate(projectRoot, actionRouteDir, routeSpecs, objectDef, manifest, options);
986
+ generatedRoutePaths.push(writeRoute(actionRouteDir, "+server.ts", actionRoute));
987
+ }
988
+ return generatedRoutePaths;
975
989
  }
976
990
  async function generateCollectionRoutesForObject(projectRoot, className, objectDef, manifest, options) {
991
+ const generatedRoutePaths = [];
977
992
  const apiConfig = objectDef.decoratorConfig?.api;
978
993
  if (apiConfig === false) {
979
994
  console.log(`[smrt] Skipping ${className} - API disabled`);
980
- return false;
995
+ return generatedRoutePaths;
981
996
  }
982
997
  const routeDir = join(projectRoot, options.routesDir, objectDef.collection);
983
998
  const lookupClassName = findItemClassRegistryKey(className, objectDef, manifest);
984
999
  const lookupObjectDef = findObjectDefByRegistryKey(manifest, lookupClassName);
985
1000
  const customActions = Object.entries(objectDef.methods).filter(([name, method]) => !STANDARD_API_ACTIONS.includes(name) && method.isPublic && shouldIncludeInApi(name, apiConfig));
986
- if (customActions.length === 0) return false;
987
- let generatedAnyRoutes = false;
1001
+ if (customActions.length === 0) return generatedRoutePaths;
988
1002
  const actionSpecs = [];
989
1003
  for (const [actionName, actionDef] of customActions) {
990
1004
  const routeConfig = resolveApiActionRouteConfig(actionName, actionDef, apiConfig, { kebabRoutes: options.kebabRoutes }, "collection");
@@ -1006,10 +1020,10 @@ async function generateCollectionRoutesForObject(projectRoot, className, objectD
1006
1020
  });
1007
1021
  }
1008
1022
  for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(actionSpecs)) {
1009
- writeRoute(actionRouteDir, "+server.ts", generateActionRouteTemplate(projectRoot, actionRouteDir, routeSpecs, objectDef, manifest, options));
1010
- generatedAnyRoutes = true;
1023
+ const actionRoute = generateActionRouteTemplate(projectRoot, actionRouteDir, routeSpecs, objectDef, manifest, options);
1024
+ generatedRoutePaths.push(writeRoute(actionRouteDir, "+server.ts", actionRoute));
1011
1025
  }
1012
- return generatedAnyRoutes;
1026
+ return generatedRoutePaths;
1013
1027
  }
1014
1028
  /**
1015
1029
  * Resolve the list of standard CRUD actions exposed by the API for a given
@@ -1120,6 +1134,7 @@ function writeRoute(dir, filename, content) {
1120
1134
  const filePath = join(dir, filename);
1121
1135
  writeFileSync(filePath, content, "utf-8");
1122
1136
  console.log(`[smrt] Generated: ${filePath}`);
1137
+ return filePath;
1123
1138
  } catch (error) {
1124
1139
  console.error(`[smrt] [ERROR] Failed to write route file:`);
1125
1140
  console.error(`[smrt] [ERROR] Directory: ${dir}`);
@@ -1582,28 +1597,42 @@ function rolesFrom(value: unknown): string[] {
1582
1597
  /**
1583
1598
  * Updates .gitignore to exclude auto-generated routes
1584
1599
  */
1585
- function updateGitignore(projectRoot, options) {
1600
+ function updateGitignore(projectRoot, options, generatedRoutePaths) {
1586
1601
  const gitignorePath = join(projectRoot, ".gitignore");
1587
- const patternsToAdd = ["# SMRT auto-generated routes (from Vite plugin)", `${options.routesDir}/**/+server.ts`];
1588
- if (options.knowledge?.api?.enabled) {
1589
- const knowledgeRoute = relative(projectRoot, join(knowledgeRouteDir(projectRoot, options), "+server.ts")).replaceAll("\\", "/");
1590
- patternsToAdd.push(knowledgeRoute);
1591
- }
1592
1602
  let gitignoreContent = "";
1593
1603
  if (existsSync(gitignorePath)) gitignoreContent = readFileSync(gitignorePath, "utf-8");
1594
- let needsUpdate = false;
1595
- const linesToAdd = [];
1596
- for (const pattern of patternsToAdd) if (!gitignoreContent.includes(pattern)) {
1597
- linesToAdd.push(pattern);
1598
- needsUpdate = true;
1604
+ const generatedPaths = [...new Set(generatedRoutePaths.map((path) => gitignorePatternForPath(relative(projectRoot, path))))].sort((a, b) => a.localeCompare(b));
1605
+ const updatedContent = updateGeneratedRouteIgnoreBlock(gitignoreContent, options.routesDir, generatedPaths);
1606
+ if (updatedContent !== gitignoreContent) {
1607
+ writeFileSync(gitignorePath, updatedContent, "utf-8");
1608
+ console.log("[smrt] Updated .gitignore with generated route paths");
1599
1609
  }
1600
- if (needsUpdate) {
1601
- if (gitignoreContent.length > 0 && !gitignoreContent.endsWith("\n")) gitignoreContent += "\n";
1602
- if (gitignoreContent.length > 0 && !gitignoreContent.endsWith("\n\n")) gitignoreContent += "\n";
1603
- gitignoreContent += `${linesToAdd.join("\n")}\n`;
1604
- writeFileSync(gitignorePath, gitignoreContent, "utf-8");
1605
- console.log("[smrt] Updated .gitignore with generated route patterns");
1610
+ }
1611
+ function gitignorePatternForPath(path) {
1612
+ return path.replaceAll("\\", "/").replaceAll(/([*?[\]\\!#])/g, "\\$1");
1613
+ }
1614
+ function updateGeneratedRouteIgnoreBlock(gitignoreContent, routesDir, generatedPaths) {
1615
+ const lines = gitignoreContent.split("\n");
1616
+ const startIndex = lines.indexOf(GITIGNORE_MANAGED_BLOCK_START);
1617
+ const endIndex = lines.indexOf(GITIGNORE_MANAGED_BLOCK_END);
1618
+ const managedBlock = [
1619
+ GITIGNORE_MANAGED_BLOCK_START,
1620
+ ...generatedPaths,
1621
+ GITIGNORE_MANAGED_BLOCK_END
1622
+ ];
1623
+ if (startIndex !== -1 || endIndex !== -1) {
1624
+ if (startIndex === -1 || endIndex < startIndex) return gitignoreContent;
1625
+ lines.splice(startIndex, endIndex - startIndex + 1, ...generatedPaths.length > 0 ? managedBlock : []);
1626
+ return lines.join("\n");
1606
1627
  }
1628
+ const legacyPattern = `${routesDir.replaceAll("\\", "/")}/**/+server.ts`;
1629
+ const legacyIndex = lines.findIndex((line, index) => line === LEGACY_GITIGNORE_HEADER && lines[index + 1] === legacyPattern);
1630
+ if (legacyIndex !== -1) lines.splice(legacyIndex, 2);
1631
+ if (generatedPaths.length === 0) return lines.join("\n");
1632
+ let updatedContent = lines.join("\n");
1633
+ if (updatedContent.length > 0 && !updatedContent.endsWith("\n")) updatedContent += "\n";
1634
+ if (updatedContent.length > 0 && !updatedContent.endsWith("\n\n")) updatedContent += "\n";
1635
+ return `${updatedContent}${managedBlock.join("\n")}\n`;
1607
1636
  }
1608
1637
  //#endregion
1609
1638
  export { findCliApiCoherenceViolations, generateSvelteKitRoutes, methodNameToKebab, resolveApiActionRouteConfig, resolveApiActionSet, validateCliIncludeAgainstApi };