@happyvertical/smrt-core 0.38.25 → 0.38.26
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/manifest/static-manifest.js +2 -2
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/test-manifest-stub.js +2 -2
- package/dist/manifest/test-manifest-stub.js.map +1 -1
- package/dist/manifest.json +2 -2
- package/dist/smrt-knowledge.json +4 -4
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +129 -30
- package/dist/vite-plugin/index.js.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.d.ts +12 -0
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +1 -1
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/dist/vite-plugin/web-collections.d.ts +12 -0
- package/dist/vite-plugin/web-collections.d.ts.map +1 -1
- package/dist/vite-plugin/web-collections.js +4 -4
- package/dist/vite-plugin/web-collections.js.map +1 -1
- package/package.json +4 -4
package/dist/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
|
-
"timestamp":
|
|
3
|
+
"timestamp": 1783688012207,
|
|
4
4
|
"packageName": "@happyvertical/smrt-core",
|
|
5
|
-
"packageVersion": "0.38.
|
|
5
|
+
"packageVersion": "0.38.26",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-core:SmrtClass": {
|
|
8
8
|
"name": "smrtclass",
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-10T12:53:30.253Z",
|
|
4
4
|
"packageName": "@happyvertical/smrt-core",
|
|
5
|
-
"packageVersion": "0.38.
|
|
5
|
+
"packageVersion": "0.38.26",
|
|
6
6
|
"sourceManifestPath": "dist/manifest.json",
|
|
7
7
|
"agentDocPath": "AGENTS.md",
|
|
8
8
|
"sourceHashes": {
|
|
9
|
-
"manifest": "
|
|
10
|
-
"packageJson": "
|
|
9
|
+
"manifest": "ba1939aa15bc24f7b2c7afab6e67acbb659eb95950bfa192094f27e6ef910857",
|
|
10
|
+
"packageJson": "10ed64f544dff4a6dde408e676c2610865a5cdcd1507eb0b30fdaa9da2aeb422",
|
|
11
11
|
"agents": "3d72a7c7113be59dd66046c50acc3e2759735fae5e9a0c6b30801d3e193b773d"
|
|
12
12
|
},
|
|
13
13
|
"exports": [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAC;AAIlE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,qBAAqB,EAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAiC,MAAM,MAAM,CAAC;AAIlE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAoB5D,YAAY,EACV,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,6BAA6B,EAC7B,uBAAuB,EACvB,iBAAiB,EACjB,mBAAmB,EACnB,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC;AAalC,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,qBAAqB;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,kFAAkF;IAClF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4EAA4E;IAC5E,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,wEAAwE;IACxE,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC;;OAEG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,8CAA8C;IAC9C,SAAS,CAAC,EAAE;QACV,yDAAyD;QACzD,OAAO,EAAE,OAAO,CAAC;QACjB,wEAAwE;QACxE,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qEAAqE;QACrE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,mEAAmE;QACnE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,mDAAmD;QACnD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB;;;;WAIG;QACH,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB;;;WAGG;QACH,YAAY,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;QACrC;;;;WAIG;QACH,WAAW,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,OAAO,CAAC;YAAC,cAAc,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC9D,CAAC;IACF,mEAAmE;IACnE,SAAS,CAAC,EAAE,qBAAqB,GAAG,KAAK,CAAC;IAC1C;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AA+BD,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAG1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,mBAAmB,GAC5B,MAAM,CAaR;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAu5BlE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { findCliApiCoherenceViolations, generateSvelteKitRoutes, methodNameToKebab, resolveApiActionSet, validateCliIncludeAgainstApi } from "./sveltekit-generator.js";
|
|
2
|
-
import { buildWebCollectionDefinition, buildWebToolDescriptors, computeWebManifestHash, selectWebCollectionEntries } from "./web-collections.js";
|
|
1
|
+
import { findCliApiCoherenceViolations, generateSvelteKitRoutes, methodNameToKebab, resolveApiActionRouteConfig, resolveApiActionSet, validateCliIncludeAgainstApi } from "./sveltekit-generator.js";
|
|
2
|
+
import { buildWebCollectionDefinition, buildWebToolDescriptors, computeWebManifestHash, isCollectionManifestClass, selectWebCollectionEntries } from "./web-collections.js";
|
|
3
3
|
import { buildDomainKnowledgeManifest } from "../knowledge.js";
|
|
4
4
|
import { importWorkspaceModule } from "../utils/import-workspace-module.js";
|
|
5
5
|
import { discoverSmrtPackages } from "../manifest/discover-smrt-packages.js";
|
|
@@ -589,14 +589,54 @@ export { setupRoutes as default };
|
|
|
589
589
|
function lowerFirst(value) {
|
|
590
590
|
return value ? value[0].toLowerCase() + value.slice(1) : value;
|
|
591
591
|
}
|
|
592
|
-
|
|
592
|
+
var GENERATED_CLIENT_CRUD_METHODS = /* @__PURE__ */ new Set([
|
|
593
|
+
"list",
|
|
594
|
+
"get",
|
|
595
|
+
"create",
|
|
596
|
+
"update",
|
|
597
|
+
"delete"
|
|
598
|
+
]);
|
|
599
|
+
var GENERATED_CLIENT_BASE_METHODS = /* @__PURE__ */ new Set([...GENERATED_CLIENT_CRUD_METHODS, "search"]);
|
|
600
|
+
function findManifestObjectByName(manifest, name) {
|
|
601
|
+
return Object.entries(manifest.objects).find(([manifestKey, candidate]) => manifestKey === name || candidate.qualifiedName === name || candidate.className === name)?.[1];
|
|
602
|
+
}
|
|
603
|
+
function resolveCollectionItemObject(obj, manifest) {
|
|
604
|
+
const seen = /* @__PURE__ */ new Set();
|
|
605
|
+
let candidate = obj;
|
|
606
|
+
while (candidate) {
|
|
607
|
+
if (candidate.extendsTypeArg) {
|
|
608
|
+
const itemObject = findManifestObjectByName(manifest, candidate.extendsTypeArg);
|
|
609
|
+
if (itemObject) return itemObject;
|
|
610
|
+
}
|
|
611
|
+
if (candidate.className.endsWith("Collection")) {
|
|
612
|
+
const conventionalItem = findManifestObjectByName(manifest, candidate.className.slice(0, -10));
|
|
613
|
+
if (conventionalItem) return conventionalItem;
|
|
614
|
+
}
|
|
615
|
+
const parentName = candidate.extendsQualified || candidate.extends;
|
|
616
|
+
if (!parentName || seen.has(parentName)) return void 0;
|
|
617
|
+
seen.add(parentName);
|
|
618
|
+
candidate = findManifestObjectByName(manifest, parentName);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
function resolveApiClientDataInterfaceName(obj, manifest) {
|
|
622
|
+
if (!isCollectionManifestClass(manifest, obj)) return `${obj.className}Data`;
|
|
623
|
+
return `${resolveCollectionItemObject(obj, manifest)?.className || obj.className}Data`;
|
|
624
|
+
}
|
|
625
|
+
function uniqueApiClientEntries(manifest) {
|
|
626
|
+
const canonicalCollectionOwners = /* @__PURE__ */ new Map();
|
|
627
|
+
const objects = Object.entries(manifest.objects);
|
|
628
|
+
for (const [, obj] of objects) {
|
|
629
|
+
const current = canonicalCollectionOwners.get(obj.collection);
|
|
630
|
+
if (!current || isCollectionManifestClass(manifest, current) && !isCollectionManifestClass(manifest, obj)) canonicalCollectionOwners.set(obj.collection, obj);
|
|
631
|
+
}
|
|
632
|
+
const reservedCanonicalKeys = new Set(canonicalCollectionOwners.keys());
|
|
593
633
|
const usedKeys = /* @__PURE__ */ new Set();
|
|
594
634
|
return objects.map(([objectName, obj]) => {
|
|
595
|
-
|
|
596
|
-
|
|
635
|
+
const isCanonicalOwner = canonicalCollectionOwners.get(obj.collection) === obj;
|
|
636
|
+
let clientKey = isCanonicalOwner ? obj.collection : lowerFirst(obj.className);
|
|
597
637
|
const baseClientKey = clientKey;
|
|
598
638
|
let suffix = 2;
|
|
599
|
-
while (usedKeys.has(clientKey)) {
|
|
639
|
+
while (usedKeys.has(clientKey) || !isCanonicalOwner && reservedCanonicalKeys.has(clientKey)) {
|
|
600
640
|
clientKey = `${baseClientKey}${suffix}`;
|
|
601
641
|
suffix += 1;
|
|
602
642
|
}
|
|
@@ -615,28 +655,68 @@ function generateClientModule(manifest, options = {}) {
|
|
|
615
655
|
|
|
616
656
|
${CLIENT_FETCH_RUNTIME}
|
|
617
657
|
|
|
658
|
+
async function __smrtFetchActionResult(url, init) {
|
|
659
|
+
const body = await __smrtFetchJson(url, init);
|
|
660
|
+
return body &&
|
|
661
|
+
typeof body === 'object' &&
|
|
662
|
+
Object.prototype.hasOwnProperty.call(body, 'result')
|
|
663
|
+
? body.result
|
|
664
|
+
: body;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function __smrtActionUrl(url, options, pathParamNames, includeQuery) {
|
|
668
|
+
const values = options && typeof options === 'object' ? options : {};
|
|
669
|
+
const pathParams = new Set(pathParamNames);
|
|
670
|
+
let resolvedUrl = url;
|
|
671
|
+
for (const name of pathParamNames) {
|
|
672
|
+
const value = values[name];
|
|
673
|
+
if (value === undefined || value === null) {
|
|
674
|
+
throw new Error('Missing generated client route parameter: ' + name);
|
|
675
|
+
}
|
|
676
|
+
resolvedUrl = resolvedUrl.replace(
|
|
677
|
+
'[' + name + ']',
|
|
678
|
+
encodeURIComponent(String(value)),
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (!includeQuery) return resolvedUrl;
|
|
683
|
+
|
|
684
|
+
const searchParams = new URLSearchParams();
|
|
685
|
+
for (const [name, value] of Object.entries(values)) {
|
|
686
|
+
if (pathParams.has(name) || value === undefined) continue;
|
|
687
|
+
if (Array.isArray(value)) {
|
|
688
|
+
for (const item of value) searchParams.append(name, String(item));
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
searchParams.append(
|
|
692
|
+
name,
|
|
693
|
+
value !== null && typeof value === 'object'
|
|
694
|
+
? JSON.stringify(value)
|
|
695
|
+
: String(value),
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
const query = searchParams.toString();
|
|
700
|
+
return query ? resolvedUrl + '?' + query : resolvedUrl;
|
|
701
|
+
}
|
|
702
|
+
|
|
618
703
|
export function createClient(basePath = '/api/v1') {
|
|
619
|
-
return {${uniqueApiClientEntries(
|
|
704
|
+
return {${uniqueApiClientEntries(manifest).map(({ obj, clientKey }) => {
|
|
620
705
|
const { collection, methods = {} } = obj;
|
|
621
706
|
const exposedActions = resolveApiActionSet(obj);
|
|
622
707
|
const apiConfig = obj.decoratorConfig?.api;
|
|
623
|
-
const
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
const
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
};
|
|
633
|
-
const customMethodImpls = customMethods.map(([methodName, _method]) => {
|
|
634
|
-
const urlSegment = segmentFor(methodName);
|
|
635
|
-
return ` ${methodName}: (id, options) => __smrtFetchJson(basePath + '/${collection}/' + id + '/${urlSegment}', {
|
|
636
|
-
method: 'POST',
|
|
708
|
+
const customMethods = Object.entries(methods).filter(([name, method]) => !GENERATED_CLIENT_CRUD_METHODS.has(name) && method.isPublic && exposedActions.has(name));
|
|
709
|
+
const customMethodImpls = customMethods.map(([methodName, method]) => {
|
|
710
|
+
const routeConfig = resolveApiActionRouteConfig(methodName, method, apiConfig, { kebabRoutes: options.kebabRoutes }, isCollectionManifestClass(manifest, obj) ? "collection" : method.isStatic ? "collection" : "item");
|
|
711
|
+
const urlSegment = routeConfig.pathSegments.join("/");
|
|
712
|
+
return ` ${methodName}: (${routeConfig.scope === "collection" ? "options" : "id, options"}) => __smrtFetchActionResult(${`__smrtActionUrl(${routeConfig.scope === "collection" ? `basePath + '/${collection}/${urlSegment}'` : `basePath + '/${collection}/' + id + '/${urlSegment}'`}, options, ${JSON.stringify(routeConfig.pathParamNames)}, ${routeConfig.method === "GET"})`}, ${routeConfig.method === "GET" ? `{
|
|
713
|
+
method: 'GET',
|
|
714
|
+
headers: { 'Accept': 'application/json' }
|
|
715
|
+
}` : `{
|
|
716
|
+
method: '${routeConfig.method}',
|
|
637
717
|
headers: { 'Content-Type': 'application/json' },
|
|
638
718
|
body: JSON.stringify(options || {})
|
|
639
|
-
})`;
|
|
719
|
+
}`})`;
|
|
640
720
|
}).join(",\n");
|
|
641
721
|
return `
|
|
642
722
|
${clientKey}: {
|
|
@@ -900,17 +980,35 @@ ${Object.entries(obj.fields).map(([fieldName, field]) => {
|
|
|
900
980
|
updated_at?: string;
|
|
901
981
|
}`;
|
|
902
982
|
}).join("\n\n");
|
|
903
|
-
const apiClientInterface = uniqueApiClientEntries(
|
|
904
|
-
const {
|
|
905
|
-
const
|
|
983
|
+
const apiClientInterface = uniqueApiClientEntries(manifest).map(({ obj, clientKey }) => {
|
|
984
|
+
const { methods = {} } = obj;
|
|
985
|
+
const apiConfig = obj.decoratorConfig?.api;
|
|
986
|
+
const interfaceName = resolveApiClientDataInterfaceName(obj, manifest);
|
|
906
987
|
const exposedActions = resolveApiActionSet(obj);
|
|
907
|
-
const customMethods = Object.entries(methods).filter(([name, method]) => method.isPublic && exposedActions.has(name));
|
|
988
|
+
const customMethods = Object.entries(methods).filter(([name, method]) => !GENERATED_CLIENT_CRUD_METHODS.has(name) && method.isPublic && exposedActions.has(name));
|
|
908
989
|
const customMethodSignatures = customMethods.map(([methodName, method]) => {
|
|
990
|
+
const routeConfig = resolveApiActionRouteConfig(methodName, method, apiConfig, {}, isCollectionManifestClass(manifest, obj) ? "collection" : method.isStatic ? "collection" : "item");
|
|
909
991
|
const params = method.parameters || [];
|
|
910
|
-
|
|
992
|
+
const pathParamNames = new Set(routeConfig.pathParamNames);
|
|
993
|
+
const hasSingleOptionsParameter = params.length === 1 && params[0]?.name === "options";
|
|
994
|
+
const requiredPathProperties = routeConfig.pathParamNames.map((name) => `${name}: string`).join("; ");
|
|
995
|
+
let optionsType;
|
|
996
|
+
if (hasSingleOptionsParameter) {
|
|
997
|
+
const directOptionsType = mapTypeScriptType(params[0].type);
|
|
998
|
+
optionsType = requiredPathProperties ? `${directOptionsType} & { ${requiredPathProperties} }` : directOptionsType;
|
|
999
|
+
} else {
|
|
1000
|
+
const parameterNames = new Set(params.map((param) => param.name));
|
|
1001
|
+
const properties = params.map((param) => `${param.name}${pathParamNames.has(param.name) ? "" : "?"}: ${mapTypeScriptType(param.type)}`);
|
|
1002
|
+
for (const pathParamName of routeConfig.pathParamNames) if (!parameterNames.has(pathParamName)) properties.push(`${pathParamName}: string`);
|
|
1003
|
+
optionsType = properties.length > 0 ? `{ ${properties.join("; ")} }` : "Record<string, never>";
|
|
1004
|
+
}
|
|
1005
|
+
const optionsParameter = `${routeConfig.pathParamNames.length > 0 ? "options" : "options?"}: ${optionsType}`;
|
|
1006
|
+
return ` ${methodName}(${routeConfig.scope === "collection" ? optionsParameter : `id: string, ${optionsParameter}`}): Promise<any>;`;
|
|
911
1007
|
}).join("\n");
|
|
912
|
-
|
|
913
|
-
|
|
1008
|
+
const overriddenBaseMethods = customMethods.map(([methodName]) => methodName).filter((methodName) => GENERATED_CLIENT_BASE_METHODS.has(methodName));
|
|
1009
|
+
const crudOperationsType = overriddenBaseMethods.length > 0 ? `Omit<CrudOperations<${interfaceName}>, ${overriddenBaseMethods.map((methodName) => JSON.stringify(methodName)).join(" | ")}>` : `CrudOperations<${interfaceName}>`;
|
|
1010
|
+
if (customMethods.length > 0) return ` ${clientKey}: ${crudOperationsType} & {\n${customMethodSignatures}\n };`;
|
|
1011
|
+
else return ` ${clientKey}: ${crudOperationsType};`;
|
|
914
1012
|
}).join("\n");
|
|
915
1013
|
const webCollectionInterface = selectWebCollectionEntries(manifest).map(({ collection, obj }) => ` ${collection}: SmrtWebCollectionDefinition<import('@happyvertical/smrt-virt-types').${obj.className}Data>;`).join("\n");
|
|
916
1014
|
Object.entries(manifest.objects).flatMap(([_name, obj]) => Object.entries(obj.methods).map(([methodName, method]) => ({
|
|
@@ -989,7 +1087,8 @@ declare module '@happyvertical/smrt-virt-routes' {
|
|
|
989
1087
|
// list/search, a bare object for get/create/update — with snake_case field
|
|
990
1088
|
// names (created_at, updated_at). These declarations match that shape (no
|
|
991
1089
|
// envelope, no camelCase). Fetchers reject on non-2xx with a SmrtClientError
|
|
992
|
-
// (#1796).
|
|
1090
|
+
// (#1796). Shared CRUD wire types stay aligned with the prebuild declaration
|
|
1091
|
+
// path; Vite-only custom action declarations are layered onto them below.
|
|
993
1092
|
declare module '@happyvertical/smrt-virt-client' {
|
|
994
1093
|
/** Shape of a JSON error body carried by a rejected request (SmrtClientError.body). */
|
|
995
1094
|
export interface ApiError {
|