@happyvertical/smrt-core 0.57.1 → 0.57.3
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/AGENTS.md +4 -0
- package/agents/generators.md +23 -0
- package/agents/object-runtime.md +8 -0
- package/dist/browser.d.ts +1 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/manifest/static-manifest.d.ts.map +1 -1
- package/dist/manifest/static-manifest.js +7 -2
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/store.js.map +1 -1
- package/dist/manifest.json +11 -2
- package/dist/object.d.ts +7 -2
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +8 -3
- package/dist/object.js.map +1 -1
- package/dist/registry/subclass-exposure.d.ts +84 -0
- package/dist/registry/subclass-exposure.d.ts.map +1 -0
- package/dist/registry/subclass-exposure.js +119 -0
- package/dist/registry/subclass-exposure.js.map +1 -0
- package/dist/registry/types.d.ts +22 -0
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +56 -14
- package/dist/registry.js.map +1 -1
- package/dist/scanner/manifest-generator.d.ts +27 -0
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +91 -0
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/smrt-knowledge.json +12 -9
- package/package.json +4 -4
|
@@ -228,6 +228,33 @@ export declare class ManifestGenerator {
|
|
|
228
228
|
* @param manifest - The manifest to process in-place
|
|
229
229
|
*/
|
|
230
230
|
mergeInheritedFields(manifest: SmartObjectManifest): void;
|
|
231
|
+
/**
|
|
232
|
+
* The model a model class directly extends, from this manifest or an
|
|
233
|
+
* external SMRT dependency's, or `undefined` when its parent is a framework
|
|
234
|
+
* base, a collection or unknown, or when the class is itself a collection.
|
|
235
|
+
*/
|
|
236
|
+
private findParentModel;
|
|
237
|
+
/**
|
|
238
|
+
* A model's config with the surfaces it inherits from its ancestors
|
|
239
|
+
* (`registry/subclass-exposure.ts`), computed without mutating `obj` or any
|
|
240
|
+
* external manifest entry.
|
|
241
|
+
*/
|
|
242
|
+
private subclassEffectiveConfig;
|
|
243
|
+
/**
|
|
244
|
+
* Give every model subclass in this manifest the generated surfaces and
|
|
245
|
+
* `sensitive` flag it leaves unset from its parent model. Without this an
|
|
246
|
+
* STI child such as `Person extends Profile` was generated with the open
|
|
247
|
+
* default surface, publishing every write and method `Profile` closes.
|
|
248
|
+
*/
|
|
249
|
+
private applySubclassExposureInheritance;
|
|
250
|
+
/**
|
|
251
|
+
* Fail the build when a model subclass's own `@smrt()` opens a generated
|
|
252
|
+
* operation (a CRUD verb or a parent method, on REST, MCP or CLI) that its
|
|
253
|
+
* parent model closes, or drops its parent's `sensitive: true`, without
|
|
254
|
+
* naming it in `widenParentExposure`. Runs after inheritance, so only a
|
|
255
|
+
* subclass's own config can trip it.
|
|
256
|
+
*/
|
|
257
|
+
private assertSubclassExposure;
|
|
231
258
|
/**
|
|
232
259
|
* Fail the build when a collection class opens a generated CRUD write (MCP
|
|
233
260
|
* or CLI) that its model keeps closed. Runs after inheritance, so only a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-generator.d.ts","sourceRoot":"","sources":["../../src/scanner/manifest-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"manifest-generator.d.ts","sourceRoot":"","sources":["../../src/scanner/manifest-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ import "./types.js";
|
|
|
8
8
|
import { loadExternalManifestSync, lookupInManifest } from "../manifest/manifest-loader.js";
|
|
9
9
|
import { VERBOSE_ENABLED } from "../registry/shared-state.js";
|
|
10
10
|
import { findCollectionWriteEscalations, formatCollectionWriteEscalations, inheritCollectionExposure } from "../registry/collection-exposure.js";
|
|
11
|
+
import { findStaleWidenings, findSubclassExposureEscalations, formatSubclassExposureEscalations, inheritSubclassExposure } from "../registry/subclass-exposure.js";
|
|
11
12
|
import { generateToolManifest } from "../tools/tool-generator.js";
|
|
12
13
|
import { createManifestClassNamePredicate, resolveApiMethodExposure, resolveCustomActionMetadata, resolveEffectiveActionMetadata } from "../generators/custom-action.js";
|
|
13
14
|
import { FIELD_UI_FORMATS, FIELD_UI_FORMAT_TYPES, FIELD_UI_WIDGETS, FIELD_UI_WIDGET_TYPES, RELATIONSHIP_ROLES, displayLabelFieldProblem, isFieldUIFormat, isFieldUIWidget, isRelationshipRole, resolveDisplayLabelField } from "../ui-metadata.js";
|
|
@@ -230,6 +231,7 @@ var ManifestGenerator = class {
|
|
|
230
231
|
this.injectTenantScopedFields(manifest);
|
|
231
232
|
this.applyReportSurfaceDefaults(manifest);
|
|
232
233
|
this.mergeInheritedFields(manifest);
|
|
234
|
+
this.assertSubclassExposure(manifest);
|
|
233
235
|
const objectsByName = new Map(Object.values(manifest.objects).map((objectDef) => [objectDef.className, objectDef]));
|
|
234
236
|
for (const objectDef of Object.values(manifest.objects)) {
|
|
235
237
|
const config = objectDef.decoratorConfig;
|
|
@@ -1114,6 +1116,7 @@ var ManifestGenerator = class {
|
|
|
1114
1116
|
}
|
|
1115
1117
|
logger.debug(`[manifest-generator] ✅ ${obj.className} now has ${Object.keys(mergedFields).length} fields (including inherited)`);
|
|
1116
1118
|
}
|
|
1119
|
+
this.applySubclassExposureInheritance(manifest, objectsByName);
|
|
1117
1120
|
for (const obj of Object.values(manifest.objects)) {
|
|
1118
1121
|
const isCollection = obj.extends === "SmrtCollection" || this.extendsCollection(obj, objectsByName);
|
|
1119
1122
|
if (!isCollection && !this.extendsAnyCollectionBase(obj, objectsByName)) continue;
|
|
@@ -1145,6 +1148,94 @@ var ManifestGenerator = class {
|
|
|
1145
1148
|
}
|
|
1146
1149
|
}
|
|
1147
1150
|
/**
|
|
1151
|
+
* The model a model class directly extends, from this manifest or an
|
|
1152
|
+
* external SMRT dependency's, or `undefined` when its parent is a framework
|
|
1153
|
+
* base, a collection or unknown, or when the class is itself a collection.
|
|
1154
|
+
*/
|
|
1155
|
+
findParentModel(obj, manifest, objectsByName) {
|
|
1156
|
+
const parentName = obj.extendsQualified || obj.extends;
|
|
1157
|
+
if (!parentName) return void 0;
|
|
1158
|
+
const simpleParent = this.simpleClassName(parentName);
|
|
1159
|
+
if (FRAMEWORK_ABSTRACT_BASE_NAMES.has(simpleParent) || FRAMEWORK_METHOD_BASE_NAMES.has(simpleParent) || isSmrtCollectionExtendsName(parentName)) return;
|
|
1160
|
+
if (this.extendsCollection(obj, objectsByName) || this.extendsAnyCollectionBase(obj, objectsByName)) return;
|
|
1161
|
+
let parent = (obj.extendsQualified ? manifest.objects[obj.extendsQualified] : void 0) ?? objectsByName.get(obj.extends ?? simpleParent);
|
|
1162
|
+
if (parent === obj) parent = void 0;
|
|
1163
|
+
if (!parent && manifest.smrtDependencies?.length) parent = this.loadParentFromExternalPackage(parentName, manifest.smrtDependencies, objectsByName);
|
|
1164
|
+
if (!parent || parent === obj) return void 0;
|
|
1165
|
+
if (this.extendsCollection(parent, objectsByName) || this.extendsAnyCollectionBase(parent, objectsByName)) return;
|
|
1166
|
+
return parent;
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* A model's config with the surfaces it inherits from its ancestors
|
|
1170
|
+
* (`registry/subclass-exposure.ts`), computed without mutating `obj` or any
|
|
1171
|
+
* external manifest entry.
|
|
1172
|
+
*/
|
|
1173
|
+
subclassEffectiveConfig(obj, manifest, objectsByName, memo, visiting = /* @__PURE__ */ new Set()) {
|
|
1174
|
+
const cached = memo.get(obj);
|
|
1175
|
+
if (cached) return cached;
|
|
1176
|
+
const own = obj.decoratorConfig || {};
|
|
1177
|
+
if (visiting.has(obj)) return own;
|
|
1178
|
+
visiting.add(obj);
|
|
1179
|
+
let config = own;
|
|
1180
|
+
const parent = this.findParentModel(obj, manifest, objectsByName);
|
|
1181
|
+
if (parent) {
|
|
1182
|
+
const inherited = inheritSubclassExposure(own, this.subclassEffectiveConfig(parent, manifest, objectsByName, memo, visiting));
|
|
1183
|
+
if (Object.keys(inherited).length > 0) config = {
|
|
1184
|
+
...own,
|
|
1185
|
+
...inherited
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
visiting.delete(obj);
|
|
1189
|
+
memo.set(obj, config);
|
|
1190
|
+
return config;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Give every model subclass in this manifest the generated surfaces and
|
|
1194
|
+
* `sensitive` flag it leaves unset from its parent model. Without this an
|
|
1195
|
+
* STI child such as `Person extends Profile` was generated with the open
|
|
1196
|
+
* default surface, publishing every write and method `Profile` closes.
|
|
1197
|
+
*/
|
|
1198
|
+
applySubclassExposureInheritance(manifest, objectsByName) {
|
|
1199
|
+
const memo = /* @__PURE__ */ new Map();
|
|
1200
|
+
const updates = [];
|
|
1201
|
+
for (const obj of Object.values(manifest.objects)) {
|
|
1202
|
+
const effective = this.subclassEffectiveConfig(obj, manifest, objectsByName, memo);
|
|
1203
|
+
if (effective !== (obj.decoratorConfig || {})) updates.push([obj, effective]);
|
|
1204
|
+
}
|
|
1205
|
+
for (const [obj, effective] of updates) {
|
|
1206
|
+
obj.decoratorConfig = effective;
|
|
1207
|
+
logger.debug(`[manifest-generator] ${obj.className} inherits generated-surface exposure from ${obj.extends}`);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Fail the build when a model subclass's own `@smrt()` opens a generated
|
|
1212
|
+
* operation (a CRUD verb or a parent method, on REST, MCP or CLI) that its
|
|
1213
|
+
* parent model closes, or drops its parent's `sensitive: true`, without
|
|
1214
|
+
* naming it in `widenParentExposure`. Runs after inheritance, so only a
|
|
1215
|
+
* subclass's own config can trip it.
|
|
1216
|
+
*/
|
|
1217
|
+
assertSubclassExposure(manifest) {
|
|
1218
|
+
const objectsByName = /* @__PURE__ */ new Map();
|
|
1219
|
+
for (const objectDef of Object.values(manifest.objects)) objectsByName.set(objectDef.className, objectDef);
|
|
1220
|
+
const memo = /* @__PURE__ */ new Map();
|
|
1221
|
+
const findings = [];
|
|
1222
|
+
for (const obj of Object.values(manifest.objects)) {
|
|
1223
|
+
const parent = this.findParentModel(obj, manifest, objectsByName);
|
|
1224
|
+
if (!parent) continue;
|
|
1225
|
+
const childConfig = this.subclassEffectiveConfig(obj, manifest, objectsByName, memo);
|
|
1226
|
+
const parentConfig = this.subclassEffectiveConfig(parent, manifest, objectsByName, memo);
|
|
1227
|
+
const escalations = findSubclassExposureEscalations(childConfig, parentConfig, Object.entries(parent.methods || {}).filter(([, method]) => method.isPublic !== false).map(([name]) => name));
|
|
1228
|
+
const stale = findStaleWidenings(childConfig, parentConfig);
|
|
1229
|
+
if (escalations.length > 0 || stale.length > 0) findings.push({
|
|
1230
|
+
subclass: obj.qualifiedName || obj.className,
|
|
1231
|
+
parent: parent.qualifiedName || parent.className,
|
|
1232
|
+
escalations,
|
|
1233
|
+
stale
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
if (findings.length > 0) throw new ConfigurationError(formatSubclassExposureEscalations(findings), "CONFIG_SUBCLASS_EXPOSURE");
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1148
1239
|
* Fail the build when a collection class opens a generated CRUD write (MCP
|
|
1149
1240
|
* or CLI) that its model keeps closed. Runs after inheritance, so only a
|
|
1150
1241
|
* collection's own `@smrt()` surface can trip it.
|