@fabricorg/gen-capability 0.3.1 → 0.4.0
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/CHANGELOG.md +28 -0
- package/dist/index.cjs +189 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -1
- package/dist/index.d.ts +70 -1
- package/dist/index.js +184 -3
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c504d0a: Make generated artifacts carry their own weight instead of handing back a seam.
|
|
8
|
+
|
|
9
|
+
`gen-graphql` projects each view's JSON Schema into named GraphQL types rather than an opaque
|
|
10
|
+
`JSON` scalar, declares the Federation 2 `@link` directive, and emits `createResolvers()` — an
|
|
11
|
+
executable resolver map whose Query fields read through `ProjectionHost` and whose Mutation fields
|
|
12
|
+
submit through `submitAction()`. Shapes with no GraphQL projection (`oneOf`, `anyOf`, `allOf`, tuple
|
|
13
|
+
`items`, multi-type unions, non-local `$ref`) now fail the generator instead of silently degrading
|
|
14
|
+
to `JSON`; only a schema that genuinely admits any value projects as `JSON`. Recursive `#/$defs`
|
|
15
|
+
references resolve to a single named type.
|
|
16
|
+
|
|
17
|
+
`gen-conformance` emits a runnable suite alongside the plan. The ten Phase 1 checks split into eight
|
|
18
|
+
`MODULE_CONFORMANCE_CHECKS` a module verifies against a governed host and two
|
|
19
|
+
`PLATFORM_CONFORMANCE_CHECKS` a repository owns. A check a module cannot exercise reports
|
|
20
|
+
`not-applicable` with a reason rather than passing silently, and `@fabricorg/gen-conformance/memory`
|
|
21
|
+
ships a reference harness so a suite runs with no infrastructure.
|
|
22
|
+
|
|
23
|
+
`gen-capability` emits a usage contract with its own `formatVersion`, validated by
|
|
24
|
+
`assertUsageContract` and described by `USAGE_CONTRACT_JSON_SCHEMA`.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- Updated dependencies [c504d0a]
|
|
29
|
+
- @fabricorg/compiler@2.1.0
|
|
30
|
+
|
|
3
31
|
## 0.3.1
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -20,15 +20,201 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
USAGE_CONTRACT_FORMAT_VERSION: () => USAGE_CONTRACT_FORMAT_VERSION,
|
|
24
|
+
USAGE_CONTRACT_JSON_SCHEMA: () => USAGE_CONTRACT_JSON_SCHEMA,
|
|
25
|
+
assertUsageContract: () => assertUsageContract,
|
|
26
|
+
assertUsageContractDocument: () => assertUsageContractDocument,
|
|
27
|
+
buildUsageContract: () => buildUsageContract,
|
|
23
28
|
capabilityGenerator: () => capabilityGenerator
|
|
24
29
|
});
|
|
25
30
|
module.exports = __toCommonJS(index_exports);
|
|
26
31
|
var import_compiler = require("@fabricorg/compiler");
|
|
27
|
-
var
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
var USAGE_CONTRACT_FORMAT_VERSION = 1;
|
|
33
|
+
var STABILITIES = ["experimental", "beta", "stable", "deprecated"];
|
|
34
|
+
function fail(path, message) {
|
|
35
|
+
throw new Error(`Usage contract ${path} ${message}.`);
|
|
36
|
+
}
|
|
37
|
+
function requireString(value, path) {
|
|
38
|
+
if (typeof value !== "string" || !value.trim()) fail(path, "must be a non-empty string");
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
function requireArray(value, path) {
|
|
42
|
+
if (!Array.isArray(value)) fail(path, "must be an array");
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
function assertUsageContract(value, path = "capability") {
|
|
46
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail(path, "must be an object");
|
|
47
|
+
const contract = value;
|
|
48
|
+
if (contract.formatVersion !== USAGE_CONTRACT_FORMAT_VERSION) {
|
|
49
|
+
fail(`${path}.formatVersion`, `must be ${USAGE_CONTRACT_FORMAT_VERSION}, received ${JSON.stringify(contract.formatVersion)}`);
|
|
50
|
+
}
|
|
51
|
+
if (!/^[a-z][a-z0-9-]*$/.test(requireString(contract.namespace, `${path}.namespace`))) {
|
|
52
|
+
fail(`${path}.namespace`, "must be lowercase letters, numbers and hyphens");
|
|
53
|
+
}
|
|
54
|
+
requireString(contract.displayName, `${path}.displayName`);
|
|
55
|
+
requireString(contract.description, `${path}.description`);
|
|
56
|
+
if (!STABILITIES.includes(contract.stability)) {
|
|
57
|
+
fail(`${path}.stability`, `must be one of ${STABILITIES.join(", ")}`);
|
|
58
|
+
}
|
|
59
|
+
const actionIds = /* @__PURE__ */ new Set();
|
|
60
|
+
requireArray(contract.actions, `${path}.actions`).forEach((entry, index) => {
|
|
61
|
+
const action = entry;
|
|
62
|
+
const actionId = requireString(action?.actionId, `${path}.actions[${index}].actionId`);
|
|
63
|
+
if (actionIds.has(actionId)) fail(`${path}.actions[${index}]`, `repeats actionId "${actionId}"`);
|
|
64
|
+
actionIds.add(actionId);
|
|
65
|
+
if (!Number.isInteger(action.version)) fail(`${path}.actions[${index}].version`, "must be an integer");
|
|
66
|
+
if (action.requiredRoles !== void 0 && !Array.isArray(action.requiredRoles)) fail(`${path}.actions[${index}].requiredRoles`, "must be an array");
|
|
67
|
+
if (action.requiredPermissions !== void 0 && !Array.isArray(action.requiredPermissions)) fail(`${path}.actions[${index}].requiredPermissions`, "must be an array");
|
|
68
|
+
});
|
|
69
|
+
const viewKeys = /* @__PURE__ */ new Set();
|
|
70
|
+
requireArray(contract.views, `${path}.views`).forEach((entry, index) => {
|
|
71
|
+
const view = entry;
|
|
72
|
+
const name = requireString(view?.name, `${path}.views[${index}].name`);
|
|
73
|
+
const version = requireString(view?.version, `${path}.views[${index}].version`);
|
|
74
|
+
const key = `${name}@${version}`;
|
|
75
|
+
if (viewKeys.has(key)) fail(`${path}.views[${index}]`, `repeats view "${key}"`);
|
|
76
|
+
viewKeys.add(key);
|
|
77
|
+
if (!view.shape || typeof view.shape !== "object" || Array.isArray(view.shape)) fail(`${path}.views[${index}].shape`, "must be a JSON Schema object");
|
|
78
|
+
if (view.scope !== "tenant-space") fail(`${path}.views[${index}].scope`, 'must be "tenant-space"');
|
|
79
|
+
if (!Number.isInteger(view.snapshotVersion) || view.snapshotVersion < 1) fail(`${path}.views[${index}].snapshotVersion`, "must be a positive integer");
|
|
80
|
+
});
|
|
81
|
+
requireArray(contract.events, `${path}.events`).forEach((entry, index) => {
|
|
82
|
+
const event = entry;
|
|
83
|
+
requireString(event?.eventType, `${path}.events[${index}].eventType`);
|
|
84
|
+
if (!Number.isInteger(event.schemaVersion)) fail(`${path}.events[${index}].schemaVersion`, "must be an integer");
|
|
85
|
+
});
|
|
86
|
+
if (contract.extensions !== void 0) {
|
|
87
|
+
if (!contract.extensions || typeof contract.extensions !== "object" || Array.isArray(contract.extensions)) fail(`${path}.extensions`, "must be an object");
|
|
88
|
+
for (const namespace of Object.keys(contract.extensions)) {
|
|
89
|
+
if (!/^[a-z][a-z0-9.-]*\.[a-z0-9.-]+\/v[1-9][0-9]*$/.test(namespace)) {
|
|
90
|
+
fail(`${path}.extensions`, `has invalid extension namespace "${namespace}"`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function assertUsageContractDocument(value) {
|
|
96
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail("document", "must be an object");
|
|
97
|
+
const document = value;
|
|
98
|
+
if (!/^[0-9a-f]{64}$/.test(String(document.manifestDigest))) fail("document.manifestDigest", "must be a lowercase SHA-256 digest");
|
|
99
|
+
const generator = document.generator;
|
|
100
|
+
if (!generator || typeof generator !== "object" || Array.isArray(generator)) fail("document.generator", "must be an object");
|
|
101
|
+
requireString(generator.name, "document.generator.name");
|
|
102
|
+
requireString(generator.version, "document.generator.version");
|
|
103
|
+
assertUsageContract(document.capability);
|
|
104
|
+
}
|
|
105
|
+
var USAGE_CONTRACT_JSON_SCHEMA = {
|
|
106
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
107
|
+
title: "Fabric capability usage contract",
|
|
108
|
+
type: "object",
|
|
109
|
+
required: ["formatVersion", "namespace", "displayName", "description", "stability", "actions", "views", "events"],
|
|
110
|
+
properties: {
|
|
111
|
+
formatVersion: { type: "integer", enum: [USAGE_CONTRACT_FORMAT_VERSION] },
|
|
112
|
+
namespace: { type: "string", pattern: "^[a-z][a-z0-9-]*$" },
|
|
113
|
+
version: { type: "string" },
|
|
114
|
+
displayName: { type: "string", minLength: 1 },
|
|
115
|
+
description: { type: "string", minLength: 1 },
|
|
116
|
+
stability: { type: "string", enum: [...STABILITIES] },
|
|
117
|
+
deprecated: { type: "object" },
|
|
118
|
+
requirements: { type: "object" },
|
|
119
|
+
certification: { type: "object" },
|
|
120
|
+
extensions: { type: "object" },
|
|
121
|
+
actions: {
|
|
122
|
+
type: "array",
|
|
123
|
+
items: {
|
|
124
|
+
type: "object",
|
|
125
|
+
required: ["actionId", "version"],
|
|
126
|
+
properties: {
|
|
127
|
+
actionId: { type: "string" },
|
|
128
|
+
version: { type: "integer" },
|
|
129
|
+
parameterSchema: { type: "object" },
|
|
130
|
+
resultSchema: { type: "object" },
|
|
131
|
+
requiredRoles: { type: "array", items: { type: "string" } },
|
|
132
|
+
requiredPermissions: { type: "array", items: { type: "string" } },
|
|
133
|
+
execution: { type: "object" }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
views: {
|
|
138
|
+
type: "array",
|
|
139
|
+
items: {
|
|
140
|
+
type: "object",
|
|
141
|
+
required: ["name", "version", "shape", "scope", "snapshotVersion"],
|
|
142
|
+
properties: {
|
|
143
|
+
name: { type: "string" },
|
|
144
|
+
version: { type: "string" },
|
|
145
|
+
shape: { type: "object" },
|
|
146
|
+
scope: { type: "string", enum: ["tenant-space"] },
|
|
147
|
+
snapshotVersion: { type: "integer" },
|
|
148
|
+
usage: { type: "object" }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
events: {
|
|
153
|
+
type: "array",
|
|
154
|
+
items: {
|
|
155
|
+
type: "object",
|
|
156
|
+
required: ["eventType", "schemaVersion"],
|
|
157
|
+
properties: {
|
|
158
|
+
eventType: { type: "string" },
|
|
159
|
+
schemaVersion: { type: "integer" },
|
|
160
|
+
description: { type: "string" },
|
|
161
|
+
schema: { type: "object" }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
function buildUsageContract(module2) {
|
|
168
|
+
const capability = module2.capability;
|
|
169
|
+
if (!capability) return void 0;
|
|
170
|
+
return {
|
|
171
|
+
formatVersion: USAGE_CONTRACT_FORMAT_VERSION,
|
|
172
|
+
namespace: module2.namespace,
|
|
173
|
+
...module2.version === void 0 ? {} : { version: module2.version },
|
|
174
|
+
displayName: capability.displayName,
|
|
175
|
+
description: capability.description,
|
|
176
|
+
stability: capability.stability,
|
|
177
|
+
...capability.deprecated === void 0 ? {} : { deprecated: capability.deprecated },
|
|
178
|
+
...capability.requirements === void 0 ? {} : { requirements: capability.requirements },
|
|
179
|
+
...capability.certification === void 0 ? {} : { certification: capability.certification },
|
|
180
|
+
...capability.extensions === void 0 ? {} : { extensions: capability.extensions },
|
|
181
|
+
actions: module2.actions.map(({ actionId, version, parameterSchema, resultSchema, requiredRoles, requiredPermissions, execution }) => ({
|
|
182
|
+
actionId,
|
|
183
|
+
version,
|
|
184
|
+
parameterSchema,
|
|
185
|
+
resultSchema,
|
|
186
|
+
requiredRoles,
|
|
187
|
+
requiredPermissions,
|
|
188
|
+
execution
|
|
189
|
+
})),
|
|
190
|
+
views: module2.views.map(({ name, version, shape, scope, snapshotVersion, usage }) => ({ name, version, shape, scope, snapshotVersion, usage })),
|
|
191
|
+
events: module2.eventTypes.map(({ eventType, schemaVersion, description, schema }) => ({ eventType, schemaVersion, description, schema }))
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
var capabilityGenerator = {
|
|
195
|
+
name: "@fabricorg/gen-capability",
|
|
196
|
+
version: "0.4.0",
|
|
197
|
+
generate(ir) {
|
|
198
|
+
return ir.modules.flatMap((module2) => {
|
|
199
|
+
const capability = buildUsageContract(module2);
|
|
200
|
+
if (!capability) return [];
|
|
201
|
+
assertUsageContract(capability);
|
|
202
|
+
const document = {
|
|
203
|
+
generator: { name: capabilityGenerator.name, version: capabilityGenerator.version },
|
|
204
|
+
manifestDigest: ir.manifestDigest,
|
|
205
|
+
capability
|
|
206
|
+
};
|
|
207
|
+
return [{ path: `${module2.namespace}/capability.json`, content: (0, import_compiler.stableStringify)(document) }];
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
};
|
|
30
211
|
// Annotate the CommonJS export names for ESM import in node:
|
|
31
212
|
0 && (module.exports = {
|
|
213
|
+
USAGE_CONTRACT_FORMAT_VERSION,
|
|
214
|
+
USAGE_CONTRACT_JSON_SCHEMA,
|
|
215
|
+
assertUsageContract,
|
|
216
|
+
assertUsageContractDocument,
|
|
217
|
+
buildUsageContract,
|
|
32
218
|
capabilityGenerator
|
|
33
219
|
});
|
|
34
220
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"sourcesContent":["import { stableStringify, type GeneratorTarget } from \"@fabricorg/compiler\";\nexport const capabilityGenerator: GeneratorTarget = { name:\"@fabricorg/gen-capability\", version:\"0.3.1\", generate(ir) { return ir.modules.filter((module) => module.capability).map((module) => ({ path:`${module.namespace}/capability.json`, content:stableStringify({ generator:{name:capabilityGenerator.name,version:capabilityGenerator.version},manifestDigest:ir.manifestDigest,capability:{namespace:module.namespace,version:module.version,...module.capability,actions:module.actions.map(({actionId,version,parameterSchema,resultSchema,requiredRoles,requiredPermissions,execution})=>({actionId,version,parameterSchema,resultSchema,requiredRoles,requiredPermissions,execution})),views:module.views,events:module.eventTypes}}) })); } };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAsD;AAC/C,IAAM,sBAAuC,EAAE,MAAK,6BAA6B,SAAQ,SAAS,SAAS,IAAI;AAAE,SAAO,GAAG,QAAQ,OAAO,CAACA,YAAWA,QAAO,UAAU,EAAE,IAAI,CAACA,aAAY,EAAE,MAAK,GAAGA,QAAO,SAAS,oBAAoB,aAAQ,iCAAgB,EAAE,WAAU,EAAC,MAAK,oBAAoB,MAAK,SAAQ,oBAAoB,QAAO,GAAE,gBAAe,GAAG,gBAAe,YAAW,EAAC,WAAUA,QAAO,WAAU,SAAQA,QAAO,SAAQ,GAAGA,QAAO,YAAW,SAAQA,QAAO,QAAQ,IAAI,CAAC,EAAC,UAAS,SAAQ,iBAAgB,cAAa,eAAc,qBAAoB,UAAS,OAAK,EAAC,UAAS,SAAQ,iBAAgB,cAAa,eAAc,qBAAoB,UAAS,EAAE,GAAE,OAAMA,QAAO,OAAM,QAAOA,QAAO,WAAU,EAAC,CAAC,EAAE,EAAE;AAAG,EAAE;","names":["module"]}
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import { stableStringify, type GeneratorTarget } from \"@fabricorg/compiler\";\nimport type {\n\tActionExecutionContract,\n\tCapabilityMetadata,\n\tJsonValue,\n\tModuleManifest,\n\tPortableJsonSchema,\n} from \"@fabricorg/platform\";\n\n/**\n * Version of the usage contract document. Adopters negotiate on this, not on the\n * generator's package version, and bump it only when the serialized shape changes\n * in a way a consumer must detect.\n */\nexport const USAGE_CONTRACT_FORMAT_VERSION = 1 as const;\n\nexport interface UsageContractAction {\n\tactionId: string;\n\tversion: number;\n\tparameterSchema?: unknown;\n\tresultSchema?: unknown;\n\trequiredRoles?: string[];\n\trequiredPermissions?: string[];\n\texecution?: ActionExecutionContract;\n}\n\nexport interface UsageContractView {\n\tname: string;\n\tversion: string;\n\tshape: PortableJsonSchema;\n\tscope: \"tenant-space\";\n\tsnapshotVersion: number;\n\tusage?: ModuleManifest[\"views\"][number][\"usage\"];\n}\n\nexport interface UsageContractEvent {\n\teventType: string;\n\tschemaVersion: number;\n\tdescription?: string;\n\tschema?: PortableJsonSchema;\n}\n\n/**\n * What a capability promises its adopters: the governed operations it dispatches,\n * the view payloads it serves, the events it emits, and the namespaced extensions\n * an experience system interprets. Experience semantics stay inside `extensions`,\n * where ADR 0006 put them — this document never interprets them.\n */\nexport interface UsageContract {\n\tformatVersion: typeof USAGE_CONTRACT_FORMAT_VERSION;\n\tnamespace: string;\n\tversion?: string;\n\tdisplayName: string;\n\tdescription: string;\n\tstability: CapabilityMetadata[\"stability\"];\n\tdeprecated?: CapabilityMetadata[\"deprecated\"];\n\trequirements?: CapabilityMetadata[\"requirements\"];\n\tcertification?: CapabilityMetadata[\"certification\"];\n\textensions?: Record<string, JsonValue>;\n\tactions: UsageContractAction[];\n\tviews: UsageContractView[];\n\tevents: UsageContractEvent[];\n}\n\nexport interface UsageContractDocument {\n\tgenerator: { name: string; version: string };\n\tmanifestDigest: string;\n\tcapability: UsageContract;\n}\n\nconst STABILITIES = [\"experimental\", \"beta\", \"stable\", \"deprecated\"];\n\nfunction fail(path: string, message: string): never {\n\tthrow new Error(`Usage contract ${path} ${message}.`);\n}\n\nfunction requireString(value: unknown, path: string): string {\n\tif (typeof value !== \"string\" || !value.trim()) fail(path, \"must be a non-empty string\");\n\treturn value;\n}\n\nfunction requireArray(value: unknown, path: string): unknown[] {\n\tif (!Array.isArray(value)) fail(path, \"must be an array\");\n\treturn value;\n}\n\n/**\n * Structural validation an adopter can run before binding against a contract.\n * It checks the document's own shape; it does not re-validate the manifest it\n * was generated from.\n */\nexport function assertUsageContract(value: unknown, path = \"capability\"): asserts value is UsageContract {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) fail(path, \"must be an object\");\n\tconst contract = value as Record<string, unknown>;\n\tif (contract.formatVersion !== USAGE_CONTRACT_FORMAT_VERSION) {\n\t\tfail(`${path}.formatVersion`, `must be ${USAGE_CONTRACT_FORMAT_VERSION}, received ${JSON.stringify(contract.formatVersion)}`);\n\t}\n\tif (!/^[a-z][a-z0-9-]*$/.test(requireString(contract.namespace, `${path}.namespace`))) {\n\t\tfail(`${path}.namespace`, \"must be lowercase letters, numbers and hyphens\");\n\t}\n\trequireString(contract.displayName, `${path}.displayName`);\n\trequireString(contract.description, `${path}.description`);\n\tif (!STABILITIES.includes(contract.stability as string)) {\n\t\tfail(`${path}.stability`, `must be one of ${STABILITIES.join(\", \")}`);\n\t}\n\tconst actionIds = new Set<string>();\n\trequireArray(contract.actions, `${path}.actions`).forEach((entry, index) => {\n\t\tconst action = entry as Record<string, unknown>;\n\t\tconst actionId = requireString(action?.actionId, `${path}.actions[${index}].actionId`);\n\t\tif (actionIds.has(actionId)) fail(`${path}.actions[${index}]`, `repeats actionId \"${actionId}\"`);\n\t\tactionIds.add(actionId);\n\t\tif (!Number.isInteger(action.version)) fail(`${path}.actions[${index}].version`, \"must be an integer\");\n\t\tif (action.requiredRoles !== undefined && !Array.isArray(action.requiredRoles)) fail(`${path}.actions[${index}].requiredRoles`, \"must be an array\");\n\t\tif (action.requiredPermissions !== undefined && !Array.isArray(action.requiredPermissions)) fail(`${path}.actions[${index}].requiredPermissions`, \"must be an array\");\n\t});\n\tconst viewKeys = new Set<string>();\n\trequireArray(contract.views, `${path}.views`).forEach((entry, index) => {\n\t\tconst view = entry as Record<string, unknown>;\n\t\tconst name = requireString(view?.name, `${path}.views[${index}].name`);\n\t\tconst version = requireString(view?.version, `${path}.views[${index}].version`);\n\t\tconst key = `${name}@${version}`;\n\t\tif (viewKeys.has(key)) fail(`${path}.views[${index}]`, `repeats view \"${key}\"`);\n\t\tviewKeys.add(key);\n\t\tif (!view.shape || typeof view.shape !== \"object\" || Array.isArray(view.shape)) fail(`${path}.views[${index}].shape`, \"must be a JSON Schema object\");\n\t\tif (view.scope !== \"tenant-space\") fail(`${path}.views[${index}].scope`, 'must be \"tenant-space\"');\n\t\tif (!Number.isInteger(view.snapshotVersion) || (view.snapshotVersion as number) < 1) fail(`${path}.views[${index}].snapshotVersion`, \"must be a positive integer\");\n\t});\n\trequireArray(contract.events, `${path}.events`).forEach((entry, index) => {\n\t\tconst event = entry as Record<string, unknown>;\n\t\trequireString(event?.eventType, `${path}.events[${index}].eventType`);\n\t\tif (!Number.isInteger(event.schemaVersion)) fail(`${path}.events[${index}].schemaVersion`, \"must be an integer\");\n\t});\n\tif (contract.extensions !== undefined) {\n\t\tif (!contract.extensions || typeof contract.extensions !== \"object\" || Array.isArray(contract.extensions)) fail(`${path}.extensions`, \"must be an object\");\n\t\tfor (const namespace of Object.keys(contract.extensions as Record<string, unknown>)) {\n\t\t\tif (!/^[a-z][a-z0-9.-]*\\.[a-z0-9.-]+\\/v[1-9][0-9]*$/.test(namespace)) {\n\t\t\t\tfail(`${path}.extensions`, `has invalid extension namespace \"${namespace}\"`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function assertUsageContractDocument(value: unknown): asserts value is UsageContractDocument {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) fail(\"document\", \"must be an object\");\n\tconst document = value as Record<string, unknown>;\n\tif (!/^[0-9a-f]{64}$/.test(String(document.manifestDigest))) fail(\"document.manifestDigest\", \"must be a lowercase SHA-256 digest\");\n\tconst generator = document.generator as { name?: unknown; version?: unknown } | undefined;\n\tif (!generator || typeof generator !== \"object\" || Array.isArray(generator)) fail(\"document.generator\", \"must be an object\");\n\trequireString(generator.name, \"document.generator.name\");\n\trequireString(generator.version, \"document.generator.version\");\n\tassertUsageContract(document.capability);\n}\n\n/** Machine-readable shape of the usage contract, for adopters that validate with their own tooling. */\nexport const USAGE_CONTRACT_JSON_SCHEMA: PortableJsonSchema = {\n\t$schema: \"https://json-schema.org/draft/2020-12/schema\",\n\ttitle: \"Fabric capability usage contract\",\n\ttype: \"object\",\n\trequired: [\"formatVersion\", \"namespace\", \"displayName\", \"description\", \"stability\", \"actions\", \"views\", \"events\"],\n\tproperties: {\n\t\tformatVersion: { type: \"integer\", enum: [USAGE_CONTRACT_FORMAT_VERSION] },\n\t\tnamespace: { type: \"string\", pattern: \"^[a-z][a-z0-9-]*$\" },\n\t\tversion: { type: \"string\" },\n\t\tdisplayName: { type: \"string\", minLength: 1 },\n\t\tdescription: { type: \"string\", minLength: 1 },\n\t\tstability: { type: \"string\", enum: [...STABILITIES] },\n\t\tdeprecated: { type: \"object\" },\n\t\trequirements: { type: \"object\" },\n\t\tcertification: { type: \"object\" },\n\t\textensions: { type: \"object\" },\n\t\tactions: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\trequired: [\"actionId\", \"version\"],\n\t\t\t\tproperties: {\n\t\t\t\t\tactionId: { type: \"string\" },\n\t\t\t\t\tversion: { type: \"integer\" },\n\t\t\t\t\tparameterSchema: { type: \"object\" },\n\t\t\t\t\tresultSchema: { type: \"object\" },\n\t\t\t\t\trequiredRoles: { type: \"array\", items: { type: \"string\" } },\n\t\t\t\t\trequiredPermissions: { type: \"array\", items: { type: \"string\" } },\n\t\t\t\t\texecution: { type: \"object\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tviews: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\trequired: [\"name\", \"version\", \"shape\", \"scope\", \"snapshotVersion\"],\n\t\t\t\tproperties: {\n\t\t\t\t\tname: { type: \"string\" },\n\t\t\t\t\tversion: { type: \"string\" },\n\t\t\t\t\tshape: { type: \"object\" },\n\t\t\t\t\tscope: { type: \"string\", enum: [\"tenant-space\"] },\n\t\t\t\t\tsnapshotVersion: { type: \"integer\" },\n\t\t\t\t\tusage: { type: \"object\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tevents: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\trequired: [\"eventType\", \"schemaVersion\"],\n\t\t\t\tproperties: {\n\t\t\t\t\teventType: { type: \"string\" },\n\t\t\t\t\tschemaVersion: { type: \"integer\" },\n\t\t\t\t\tdescription: { type: \"string\" },\n\t\t\t\t\tschema: { type: \"object\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n};\n\nexport function buildUsageContract(module: ModuleManifest): UsageContract | undefined {\n\tconst capability = module.capability;\n\tif (!capability) return undefined;\n\treturn {\n\t\tformatVersion: USAGE_CONTRACT_FORMAT_VERSION,\n\t\tnamespace: module.namespace,\n\t\t...(module.version === undefined ? {} : { version: module.version }),\n\t\tdisplayName: capability.displayName,\n\t\tdescription: capability.description,\n\t\tstability: capability.stability,\n\t\t...(capability.deprecated === undefined ? {} : { deprecated: capability.deprecated }),\n\t\t...(capability.requirements === undefined ? {} : { requirements: capability.requirements }),\n\t\t...(capability.certification === undefined ? {} : { certification: capability.certification }),\n\t\t...(capability.extensions === undefined ? {} : { extensions: capability.extensions }),\n\t\tactions: module.actions.map(({ actionId, version, parameterSchema, resultSchema, requiredRoles, requiredPermissions, execution }) => ({\n\t\t\tactionId,\n\t\t\tversion,\n\t\t\tparameterSchema,\n\t\t\tresultSchema,\n\t\t\trequiredRoles,\n\t\t\trequiredPermissions,\n\t\t\texecution,\n\t\t})),\n\t\tviews: module.views.map(({ name, version, shape, scope, snapshotVersion, usage }) => ({ name, version, shape, scope, snapshotVersion, usage })),\n\t\tevents: module.eventTypes.map(({ eventType, schemaVersion, description, schema }) => ({ eventType, schemaVersion, description, schema })),\n\t};\n}\n\nexport const capabilityGenerator: GeneratorTarget = {\n\tname: \"@fabricorg/gen-capability\",\n\tversion: \"0.4.0\",\n\tgenerate(ir) {\n\t\treturn ir.modules.flatMap((module) => {\n\t\t\tconst capability = buildUsageContract(module);\n\t\t\tif (!capability) return [];\n\t\t\tassertUsageContract(capability);\n\t\t\tconst document: UsageContractDocument = {\n\t\t\t\tgenerator: { name: capabilityGenerator.name, version: capabilityGenerator.version },\n\t\t\t\tmanifestDigest: ir.manifestDigest,\n\t\t\t\tcapability,\n\t\t\t};\n\t\t\treturn [{ path: `${module.namespace}/capability.json`, content: stableStringify(document) }];\n\t\t});\n\t},\n};\n"],"mappings":"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","names":["module"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
import { GeneratorTarget } from '@fabricorg/compiler';
|
|
2
|
+
import { PortableJsonSchema, CapabilityMetadata, JsonValue, ActionExecutionContract, ModuleManifest } from '@fabricorg/platform';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Version of the usage contract document. Adopters negotiate on this, not on the
|
|
6
|
+
* generator's package version, and bump it only when the serialized shape changes
|
|
7
|
+
* in a way a consumer must detect.
|
|
8
|
+
*/
|
|
9
|
+
declare const USAGE_CONTRACT_FORMAT_VERSION: 1;
|
|
10
|
+
interface UsageContractAction {
|
|
11
|
+
actionId: string;
|
|
12
|
+
version: number;
|
|
13
|
+
parameterSchema?: unknown;
|
|
14
|
+
resultSchema?: unknown;
|
|
15
|
+
requiredRoles?: string[];
|
|
16
|
+
requiredPermissions?: string[];
|
|
17
|
+
execution?: ActionExecutionContract;
|
|
18
|
+
}
|
|
19
|
+
interface UsageContractView {
|
|
20
|
+
name: string;
|
|
21
|
+
version: string;
|
|
22
|
+
shape: PortableJsonSchema;
|
|
23
|
+
scope: "tenant-space";
|
|
24
|
+
snapshotVersion: number;
|
|
25
|
+
usage?: ModuleManifest["views"][number]["usage"];
|
|
26
|
+
}
|
|
27
|
+
interface UsageContractEvent {
|
|
28
|
+
eventType: string;
|
|
29
|
+
schemaVersion: number;
|
|
30
|
+
description?: string;
|
|
31
|
+
schema?: PortableJsonSchema;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What a capability promises its adopters: the governed operations it dispatches,
|
|
35
|
+
* the view payloads it serves, the events it emits, and the namespaced extensions
|
|
36
|
+
* an experience system interprets. Experience semantics stay inside `extensions`,
|
|
37
|
+
* where ADR 0006 put them — this document never interprets them.
|
|
38
|
+
*/
|
|
39
|
+
interface UsageContract {
|
|
40
|
+
formatVersion: typeof USAGE_CONTRACT_FORMAT_VERSION;
|
|
41
|
+
namespace: string;
|
|
42
|
+
version?: string;
|
|
43
|
+
displayName: string;
|
|
44
|
+
description: string;
|
|
45
|
+
stability: CapabilityMetadata["stability"];
|
|
46
|
+
deprecated?: CapabilityMetadata["deprecated"];
|
|
47
|
+
requirements?: CapabilityMetadata["requirements"];
|
|
48
|
+
certification?: CapabilityMetadata["certification"];
|
|
49
|
+
extensions?: Record<string, JsonValue>;
|
|
50
|
+
actions: UsageContractAction[];
|
|
51
|
+
views: UsageContractView[];
|
|
52
|
+
events: UsageContractEvent[];
|
|
53
|
+
}
|
|
54
|
+
interface UsageContractDocument {
|
|
55
|
+
generator: {
|
|
56
|
+
name: string;
|
|
57
|
+
version: string;
|
|
58
|
+
};
|
|
59
|
+
manifestDigest: string;
|
|
60
|
+
capability: UsageContract;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Structural validation an adopter can run before binding against a contract.
|
|
64
|
+
* It checks the document's own shape; it does not re-validate the manifest it
|
|
65
|
+
* was generated from.
|
|
66
|
+
*/
|
|
67
|
+
declare function assertUsageContract(value: unknown, path?: string): asserts value is UsageContract;
|
|
68
|
+
declare function assertUsageContractDocument(value: unknown): asserts value is UsageContractDocument;
|
|
69
|
+
/** Machine-readable shape of the usage contract, for adopters that validate with their own tooling. */
|
|
70
|
+
declare const USAGE_CONTRACT_JSON_SCHEMA: PortableJsonSchema;
|
|
71
|
+
declare function buildUsageContract(module: ModuleManifest): UsageContract | undefined;
|
|
3
72
|
declare const capabilityGenerator: GeneratorTarget;
|
|
4
73
|
|
|
5
|
-
export { capabilityGenerator };
|
|
74
|
+
export { USAGE_CONTRACT_FORMAT_VERSION, USAGE_CONTRACT_JSON_SCHEMA, type UsageContract, type UsageContractAction, type UsageContractDocument, type UsageContractEvent, type UsageContractView, assertUsageContract, assertUsageContractDocument, buildUsageContract, capabilityGenerator };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,74 @@
|
|
|
1
1
|
import { GeneratorTarget } from '@fabricorg/compiler';
|
|
2
|
+
import { PortableJsonSchema, CapabilityMetadata, JsonValue, ActionExecutionContract, ModuleManifest } from '@fabricorg/platform';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Version of the usage contract document. Adopters negotiate on this, not on the
|
|
6
|
+
* generator's package version, and bump it only when the serialized shape changes
|
|
7
|
+
* in a way a consumer must detect.
|
|
8
|
+
*/
|
|
9
|
+
declare const USAGE_CONTRACT_FORMAT_VERSION: 1;
|
|
10
|
+
interface UsageContractAction {
|
|
11
|
+
actionId: string;
|
|
12
|
+
version: number;
|
|
13
|
+
parameterSchema?: unknown;
|
|
14
|
+
resultSchema?: unknown;
|
|
15
|
+
requiredRoles?: string[];
|
|
16
|
+
requiredPermissions?: string[];
|
|
17
|
+
execution?: ActionExecutionContract;
|
|
18
|
+
}
|
|
19
|
+
interface UsageContractView {
|
|
20
|
+
name: string;
|
|
21
|
+
version: string;
|
|
22
|
+
shape: PortableJsonSchema;
|
|
23
|
+
scope: "tenant-space";
|
|
24
|
+
snapshotVersion: number;
|
|
25
|
+
usage?: ModuleManifest["views"][number]["usage"];
|
|
26
|
+
}
|
|
27
|
+
interface UsageContractEvent {
|
|
28
|
+
eventType: string;
|
|
29
|
+
schemaVersion: number;
|
|
30
|
+
description?: string;
|
|
31
|
+
schema?: PortableJsonSchema;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* What a capability promises its adopters: the governed operations it dispatches,
|
|
35
|
+
* the view payloads it serves, the events it emits, and the namespaced extensions
|
|
36
|
+
* an experience system interprets. Experience semantics stay inside `extensions`,
|
|
37
|
+
* where ADR 0006 put them — this document never interprets them.
|
|
38
|
+
*/
|
|
39
|
+
interface UsageContract {
|
|
40
|
+
formatVersion: typeof USAGE_CONTRACT_FORMAT_VERSION;
|
|
41
|
+
namespace: string;
|
|
42
|
+
version?: string;
|
|
43
|
+
displayName: string;
|
|
44
|
+
description: string;
|
|
45
|
+
stability: CapabilityMetadata["stability"];
|
|
46
|
+
deprecated?: CapabilityMetadata["deprecated"];
|
|
47
|
+
requirements?: CapabilityMetadata["requirements"];
|
|
48
|
+
certification?: CapabilityMetadata["certification"];
|
|
49
|
+
extensions?: Record<string, JsonValue>;
|
|
50
|
+
actions: UsageContractAction[];
|
|
51
|
+
views: UsageContractView[];
|
|
52
|
+
events: UsageContractEvent[];
|
|
53
|
+
}
|
|
54
|
+
interface UsageContractDocument {
|
|
55
|
+
generator: {
|
|
56
|
+
name: string;
|
|
57
|
+
version: string;
|
|
58
|
+
};
|
|
59
|
+
manifestDigest: string;
|
|
60
|
+
capability: UsageContract;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Structural validation an adopter can run before binding against a contract.
|
|
64
|
+
* It checks the document's own shape; it does not re-validate the manifest it
|
|
65
|
+
* was generated from.
|
|
66
|
+
*/
|
|
67
|
+
declare function assertUsageContract(value: unknown, path?: string): asserts value is UsageContract;
|
|
68
|
+
declare function assertUsageContractDocument(value: unknown): asserts value is UsageContractDocument;
|
|
69
|
+
/** Machine-readable shape of the usage contract, for adopters that validate with their own tooling. */
|
|
70
|
+
declare const USAGE_CONTRACT_JSON_SCHEMA: PortableJsonSchema;
|
|
71
|
+
declare function buildUsageContract(module: ModuleManifest): UsageContract | undefined;
|
|
3
72
|
declare const capabilityGenerator: GeneratorTarget;
|
|
4
73
|
|
|
5
|
-
export { capabilityGenerator };
|
|
74
|
+
export { USAGE_CONTRACT_FORMAT_VERSION, USAGE_CONTRACT_JSON_SCHEMA, type UsageContract, type UsageContractAction, type UsageContractDocument, type UsageContractEvent, type UsageContractView, assertUsageContract, assertUsageContractDocument, buildUsageContract, capabilityGenerator };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,190 @@
|
|
|
1
1
|
// index.ts
|
|
2
2
|
import { stableStringify } from "@fabricorg/compiler";
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
var USAGE_CONTRACT_FORMAT_VERSION = 1;
|
|
4
|
+
var STABILITIES = ["experimental", "beta", "stable", "deprecated"];
|
|
5
|
+
function fail(path, message) {
|
|
6
|
+
throw new Error(`Usage contract ${path} ${message}.`);
|
|
7
|
+
}
|
|
8
|
+
function requireString(value, path) {
|
|
9
|
+
if (typeof value !== "string" || !value.trim()) fail(path, "must be a non-empty string");
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
function requireArray(value, path) {
|
|
13
|
+
if (!Array.isArray(value)) fail(path, "must be an array");
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function assertUsageContract(value, path = "capability") {
|
|
17
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail(path, "must be an object");
|
|
18
|
+
const contract = value;
|
|
19
|
+
if (contract.formatVersion !== USAGE_CONTRACT_FORMAT_VERSION) {
|
|
20
|
+
fail(`${path}.formatVersion`, `must be ${USAGE_CONTRACT_FORMAT_VERSION}, received ${JSON.stringify(contract.formatVersion)}`);
|
|
21
|
+
}
|
|
22
|
+
if (!/^[a-z][a-z0-9-]*$/.test(requireString(contract.namespace, `${path}.namespace`))) {
|
|
23
|
+
fail(`${path}.namespace`, "must be lowercase letters, numbers and hyphens");
|
|
24
|
+
}
|
|
25
|
+
requireString(contract.displayName, `${path}.displayName`);
|
|
26
|
+
requireString(contract.description, `${path}.description`);
|
|
27
|
+
if (!STABILITIES.includes(contract.stability)) {
|
|
28
|
+
fail(`${path}.stability`, `must be one of ${STABILITIES.join(", ")}`);
|
|
29
|
+
}
|
|
30
|
+
const actionIds = /* @__PURE__ */ new Set();
|
|
31
|
+
requireArray(contract.actions, `${path}.actions`).forEach((entry, index) => {
|
|
32
|
+
const action = entry;
|
|
33
|
+
const actionId = requireString(action?.actionId, `${path}.actions[${index}].actionId`);
|
|
34
|
+
if (actionIds.has(actionId)) fail(`${path}.actions[${index}]`, `repeats actionId "${actionId}"`);
|
|
35
|
+
actionIds.add(actionId);
|
|
36
|
+
if (!Number.isInteger(action.version)) fail(`${path}.actions[${index}].version`, "must be an integer");
|
|
37
|
+
if (action.requiredRoles !== void 0 && !Array.isArray(action.requiredRoles)) fail(`${path}.actions[${index}].requiredRoles`, "must be an array");
|
|
38
|
+
if (action.requiredPermissions !== void 0 && !Array.isArray(action.requiredPermissions)) fail(`${path}.actions[${index}].requiredPermissions`, "must be an array");
|
|
39
|
+
});
|
|
40
|
+
const viewKeys = /* @__PURE__ */ new Set();
|
|
41
|
+
requireArray(contract.views, `${path}.views`).forEach((entry, index) => {
|
|
42
|
+
const view = entry;
|
|
43
|
+
const name = requireString(view?.name, `${path}.views[${index}].name`);
|
|
44
|
+
const version = requireString(view?.version, `${path}.views[${index}].version`);
|
|
45
|
+
const key = `${name}@${version}`;
|
|
46
|
+
if (viewKeys.has(key)) fail(`${path}.views[${index}]`, `repeats view "${key}"`);
|
|
47
|
+
viewKeys.add(key);
|
|
48
|
+
if (!view.shape || typeof view.shape !== "object" || Array.isArray(view.shape)) fail(`${path}.views[${index}].shape`, "must be a JSON Schema object");
|
|
49
|
+
if (view.scope !== "tenant-space") fail(`${path}.views[${index}].scope`, 'must be "tenant-space"');
|
|
50
|
+
if (!Number.isInteger(view.snapshotVersion) || view.snapshotVersion < 1) fail(`${path}.views[${index}].snapshotVersion`, "must be a positive integer");
|
|
51
|
+
});
|
|
52
|
+
requireArray(contract.events, `${path}.events`).forEach((entry, index) => {
|
|
53
|
+
const event = entry;
|
|
54
|
+
requireString(event?.eventType, `${path}.events[${index}].eventType`);
|
|
55
|
+
if (!Number.isInteger(event.schemaVersion)) fail(`${path}.events[${index}].schemaVersion`, "must be an integer");
|
|
56
|
+
});
|
|
57
|
+
if (contract.extensions !== void 0) {
|
|
58
|
+
if (!contract.extensions || typeof contract.extensions !== "object" || Array.isArray(contract.extensions)) fail(`${path}.extensions`, "must be an object");
|
|
59
|
+
for (const namespace of Object.keys(contract.extensions)) {
|
|
60
|
+
if (!/^[a-z][a-z0-9.-]*\.[a-z0-9.-]+\/v[1-9][0-9]*$/.test(namespace)) {
|
|
61
|
+
fail(`${path}.extensions`, `has invalid extension namespace "${namespace}"`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function assertUsageContractDocument(value) {
|
|
67
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) fail("document", "must be an object");
|
|
68
|
+
const document = value;
|
|
69
|
+
if (!/^[0-9a-f]{64}$/.test(String(document.manifestDigest))) fail("document.manifestDigest", "must be a lowercase SHA-256 digest");
|
|
70
|
+
const generator = document.generator;
|
|
71
|
+
if (!generator || typeof generator !== "object" || Array.isArray(generator)) fail("document.generator", "must be an object");
|
|
72
|
+
requireString(generator.name, "document.generator.name");
|
|
73
|
+
requireString(generator.version, "document.generator.version");
|
|
74
|
+
assertUsageContract(document.capability);
|
|
75
|
+
}
|
|
76
|
+
var USAGE_CONTRACT_JSON_SCHEMA = {
|
|
77
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
78
|
+
title: "Fabric capability usage contract",
|
|
79
|
+
type: "object",
|
|
80
|
+
required: ["formatVersion", "namespace", "displayName", "description", "stability", "actions", "views", "events"],
|
|
81
|
+
properties: {
|
|
82
|
+
formatVersion: { type: "integer", enum: [USAGE_CONTRACT_FORMAT_VERSION] },
|
|
83
|
+
namespace: { type: "string", pattern: "^[a-z][a-z0-9-]*$" },
|
|
84
|
+
version: { type: "string" },
|
|
85
|
+
displayName: { type: "string", minLength: 1 },
|
|
86
|
+
description: { type: "string", minLength: 1 },
|
|
87
|
+
stability: { type: "string", enum: [...STABILITIES] },
|
|
88
|
+
deprecated: { type: "object" },
|
|
89
|
+
requirements: { type: "object" },
|
|
90
|
+
certification: { type: "object" },
|
|
91
|
+
extensions: { type: "object" },
|
|
92
|
+
actions: {
|
|
93
|
+
type: "array",
|
|
94
|
+
items: {
|
|
95
|
+
type: "object",
|
|
96
|
+
required: ["actionId", "version"],
|
|
97
|
+
properties: {
|
|
98
|
+
actionId: { type: "string" },
|
|
99
|
+
version: { type: "integer" },
|
|
100
|
+
parameterSchema: { type: "object" },
|
|
101
|
+
resultSchema: { type: "object" },
|
|
102
|
+
requiredRoles: { type: "array", items: { type: "string" } },
|
|
103
|
+
requiredPermissions: { type: "array", items: { type: "string" } },
|
|
104
|
+
execution: { type: "object" }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
views: {
|
|
109
|
+
type: "array",
|
|
110
|
+
items: {
|
|
111
|
+
type: "object",
|
|
112
|
+
required: ["name", "version", "shape", "scope", "snapshotVersion"],
|
|
113
|
+
properties: {
|
|
114
|
+
name: { type: "string" },
|
|
115
|
+
version: { type: "string" },
|
|
116
|
+
shape: { type: "object" },
|
|
117
|
+
scope: { type: "string", enum: ["tenant-space"] },
|
|
118
|
+
snapshotVersion: { type: "integer" },
|
|
119
|
+
usage: { type: "object" }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
events: {
|
|
124
|
+
type: "array",
|
|
125
|
+
items: {
|
|
126
|
+
type: "object",
|
|
127
|
+
required: ["eventType", "schemaVersion"],
|
|
128
|
+
properties: {
|
|
129
|
+
eventType: { type: "string" },
|
|
130
|
+
schemaVersion: { type: "integer" },
|
|
131
|
+
description: { type: "string" },
|
|
132
|
+
schema: { type: "object" }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
function buildUsageContract(module) {
|
|
139
|
+
const capability = module.capability;
|
|
140
|
+
if (!capability) return void 0;
|
|
141
|
+
return {
|
|
142
|
+
formatVersion: USAGE_CONTRACT_FORMAT_VERSION,
|
|
143
|
+
namespace: module.namespace,
|
|
144
|
+
...module.version === void 0 ? {} : { version: module.version },
|
|
145
|
+
displayName: capability.displayName,
|
|
146
|
+
description: capability.description,
|
|
147
|
+
stability: capability.stability,
|
|
148
|
+
...capability.deprecated === void 0 ? {} : { deprecated: capability.deprecated },
|
|
149
|
+
...capability.requirements === void 0 ? {} : { requirements: capability.requirements },
|
|
150
|
+
...capability.certification === void 0 ? {} : { certification: capability.certification },
|
|
151
|
+
...capability.extensions === void 0 ? {} : { extensions: capability.extensions },
|
|
152
|
+
actions: module.actions.map(({ actionId, version, parameterSchema, resultSchema, requiredRoles, requiredPermissions, execution }) => ({
|
|
153
|
+
actionId,
|
|
154
|
+
version,
|
|
155
|
+
parameterSchema,
|
|
156
|
+
resultSchema,
|
|
157
|
+
requiredRoles,
|
|
158
|
+
requiredPermissions,
|
|
159
|
+
execution
|
|
160
|
+
})),
|
|
161
|
+
views: module.views.map(({ name, version, shape, scope, snapshotVersion, usage }) => ({ name, version, shape, scope, snapshotVersion, usage })),
|
|
162
|
+
events: module.eventTypes.map(({ eventType, schemaVersion, description, schema }) => ({ eventType, schemaVersion, description, schema }))
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
var capabilityGenerator = {
|
|
166
|
+
name: "@fabricorg/gen-capability",
|
|
167
|
+
version: "0.4.0",
|
|
168
|
+
generate(ir) {
|
|
169
|
+
return ir.modules.flatMap((module) => {
|
|
170
|
+
const capability = buildUsageContract(module);
|
|
171
|
+
if (!capability) return [];
|
|
172
|
+
assertUsageContract(capability);
|
|
173
|
+
const document = {
|
|
174
|
+
generator: { name: capabilityGenerator.name, version: capabilityGenerator.version },
|
|
175
|
+
manifestDigest: ir.manifestDigest,
|
|
176
|
+
capability
|
|
177
|
+
};
|
|
178
|
+
return [{ path: `${module.namespace}/capability.json`, content: stableStringify(document) }];
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
};
|
|
6
182
|
export {
|
|
183
|
+
USAGE_CONTRACT_FORMAT_VERSION,
|
|
184
|
+
USAGE_CONTRACT_JSON_SCHEMA,
|
|
185
|
+
assertUsageContract,
|
|
186
|
+
assertUsageContractDocument,
|
|
187
|
+
buildUsageContract,
|
|
7
188
|
capabilityGenerator
|
|
8
189
|
};
|
|
9
190
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"sourcesContent":["import { stableStringify, type GeneratorTarget } from \"@fabricorg/compiler\";\nexport const capabilityGenerator: GeneratorTarget = { name:\"@fabricorg/gen-capability\", version:\"0.3.1\", generate(ir) { return ir.modules.filter((module) => module.capability).map((module) => ({ path:`${module.namespace}/capability.json`, content:stableStringify({ generator:{name:capabilityGenerator.name,version:capabilityGenerator.version},manifestDigest:ir.manifestDigest,capability:{namespace:module.namespace,version:module.version,...module.capability,actions:module.actions.map(({actionId,version,parameterSchema,resultSchema,requiredRoles,requiredPermissions,execution})=>({actionId,version,parameterSchema,resultSchema,requiredRoles,requiredPermissions,execution})),views:module.views,events:module.eventTypes}}) })); } };\n"],"mappings":";AAAA,SAAS,uBAA6C;AAC/C,IAAM,sBAAuC,EAAE,MAAK,6BAA6B,SAAQ,SAAS,SAAS,IAAI;AAAE,SAAO,GAAG,QAAQ,OAAO,CAAC,WAAW,OAAO,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE,MAAK,GAAG,OAAO,SAAS,oBAAoB,SAAQ,gBAAgB,EAAE,WAAU,EAAC,MAAK,oBAAoB,MAAK,SAAQ,oBAAoB,QAAO,GAAE,gBAAe,GAAG,gBAAe,YAAW,EAAC,WAAU,OAAO,WAAU,SAAQ,OAAO,SAAQ,GAAG,OAAO,YAAW,SAAQ,OAAO,QAAQ,IAAI,CAAC,EAAC,UAAS,SAAQ,iBAAgB,cAAa,eAAc,qBAAoB,UAAS,OAAK,EAAC,UAAS,SAAQ,iBAAgB,cAAa,eAAc,qBAAoB,UAAS,EAAE,GAAE,OAAM,OAAO,OAAM,QAAO,OAAO,WAAU,EAAC,CAAC,EAAE,EAAE;AAAG,EAAE;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["import { stableStringify, type GeneratorTarget } from \"@fabricorg/compiler\";\nimport type {\n\tActionExecutionContract,\n\tCapabilityMetadata,\n\tJsonValue,\n\tModuleManifest,\n\tPortableJsonSchema,\n} from \"@fabricorg/platform\";\n\n/**\n * Version of the usage contract document. Adopters negotiate on this, not on the\n * generator's package version, and bump it only when the serialized shape changes\n * in a way a consumer must detect.\n */\nexport const USAGE_CONTRACT_FORMAT_VERSION = 1 as const;\n\nexport interface UsageContractAction {\n\tactionId: string;\n\tversion: number;\n\tparameterSchema?: unknown;\n\tresultSchema?: unknown;\n\trequiredRoles?: string[];\n\trequiredPermissions?: string[];\n\texecution?: ActionExecutionContract;\n}\n\nexport interface UsageContractView {\n\tname: string;\n\tversion: string;\n\tshape: PortableJsonSchema;\n\tscope: \"tenant-space\";\n\tsnapshotVersion: number;\n\tusage?: ModuleManifest[\"views\"][number][\"usage\"];\n}\n\nexport interface UsageContractEvent {\n\teventType: string;\n\tschemaVersion: number;\n\tdescription?: string;\n\tschema?: PortableJsonSchema;\n}\n\n/**\n * What a capability promises its adopters: the governed operations it dispatches,\n * the view payloads it serves, the events it emits, and the namespaced extensions\n * an experience system interprets. Experience semantics stay inside `extensions`,\n * where ADR 0006 put them — this document never interprets them.\n */\nexport interface UsageContract {\n\tformatVersion: typeof USAGE_CONTRACT_FORMAT_VERSION;\n\tnamespace: string;\n\tversion?: string;\n\tdisplayName: string;\n\tdescription: string;\n\tstability: CapabilityMetadata[\"stability\"];\n\tdeprecated?: CapabilityMetadata[\"deprecated\"];\n\trequirements?: CapabilityMetadata[\"requirements\"];\n\tcertification?: CapabilityMetadata[\"certification\"];\n\textensions?: Record<string, JsonValue>;\n\tactions: UsageContractAction[];\n\tviews: UsageContractView[];\n\tevents: UsageContractEvent[];\n}\n\nexport interface UsageContractDocument {\n\tgenerator: { name: string; version: string };\n\tmanifestDigest: string;\n\tcapability: UsageContract;\n}\n\nconst STABILITIES = [\"experimental\", \"beta\", \"stable\", \"deprecated\"];\n\nfunction fail(path: string, message: string): never {\n\tthrow new Error(`Usage contract ${path} ${message}.`);\n}\n\nfunction requireString(value: unknown, path: string): string {\n\tif (typeof value !== \"string\" || !value.trim()) fail(path, \"must be a non-empty string\");\n\treturn value;\n}\n\nfunction requireArray(value: unknown, path: string): unknown[] {\n\tif (!Array.isArray(value)) fail(path, \"must be an array\");\n\treturn value;\n}\n\n/**\n * Structural validation an adopter can run before binding against a contract.\n * It checks the document's own shape; it does not re-validate the manifest it\n * was generated from.\n */\nexport function assertUsageContract(value: unknown, path = \"capability\"): asserts value is UsageContract {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) fail(path, \"must be an object\");\n\tconst contract = value as Record<string, unknown>;\n\tif (contract.formatVersion !== USAGE_CONTRACT_FORMAT_VERSION) {\n\t\tfail(`${path}.formatVersion`, `must be ${USAGE_CONTRACT_FORMAT_VERSION}, received ${JSON.stringify(contract.formatVersion)}`);\n\t}\n\tif (!/^[a-z][a-z0-9-]*$/.test(requireString(contract.namespace, `${path}.namespace`))) {\n\t\tfail(`${path}.namespace`, \"must be lowercase letters, numbers and hyphens\");\n\t}\n\trequireString(contract.displayName, `${path}.displayName`);\n\trequireString(contract.description, `${path}.description`);\n\tif (!STABILITIES.includes(contract.stability as string)) {\n\t\tfail(`${path}.stability`, `must be one of ${STABILITIES.join(\", \")}`);\n\t}\n\tconst actionIds = new Set<string>();\n\trequireArray(contract.actions, `${path}.actions`).forEach((entry, index) => {\n\t\tconst action = entry as Record<string, unknown>;\n\t\tconst actionId = requireString(action?.actionId, `${path}.actions[${index}].actionId`);\n\t\tif (actionIds.has(actionId)) fail(`${path}.actions[${index}]`, `repeats actionId \"${actionId}\"`);\n\t\tactionIds.add(actionId);\n\t\tif (!Number.isInteger(action.version)) fail(`${path}.actions[${index}].version`, \"must be an integer\");\n\t\tif (action.requiredRoles !== undefined && !Array.isArray(action.requiredRoles)) fail(`${path}.actions[${index}].requiredRoles`, \"must be an array\");\n\t\tif (action.requiredPermissions !== undefined && !Array.isArray(action.requiredPermissions)) fail(`${path}.actions[${index}].requiredPermissions`, \"must be an array\");\n\t});\n\tconst viewKeys = new Set<string>();\n\trequireArray(contract.views, `${path}.views`).forEach((entry, index) => {\n\t\tconst view = entry as Record<string, unknown>;\n\t\tconst name = requireString(view?.name, `${path}.views[${index}].name`);\n\t\tconst version = requireString(view?.version, `${path}.views[${index}].version`);\n\t\tconst key = `${name}@${version}`;\n\t\tif (viewKeys.has(key)) fail(`${path}.views[${index}]`, `repeats view \"${key}\"`);\n\t\tviewKeys.add(key);\n\t\tif (!view.shape || typeof view.shape !== \"object\" || Array.isArray(view.shape)) fail(`${path}.views[${index}].shape`, \"must be a JSON Schema object\");\n\t\tif (view.scope !== \"tenant-space\") fail(`${path}.views[${index}].scope`, 'must be \"tenant-space\"');\n\t\tif (!Number.isInteger(view.snapshotVersion) || (view.snapshotVersion as number) < 1) fail(`${path}.views[${index}].snapshotVersion`, \"must be a positive integer\");\n\t});\n\trequireArray(contract.events, `${path}.events`).forEach((entry, index) => {\n\t\tconst event = entry as Record<string, unknown>;\n\t\trequireString(event?.eventType, `${path}.events[${index}].eventType`);\n\t\tif (!Number.isInteger(event.schemaVersion)) fail(`${path}.events[${index}].schemaVersion`, \"must be an integer\");\n\t});\n\tif (contract.extensions !== undefined) {\n\t\tif (!contract.extensions || typeof contract.extensions !== \"object\" || Array.isArray(contract.extensions)) fail(`${path}.extensions`, \"must be an object\");\n\t\tfor (const namespace of Object.keys(contract.extensions as Record<string, unknown>)) {\n\t\t\tif (!/^[a-z][a-z0-9.-]*\\.[a-z0-9.-]+\\/v[1-9][0-9]*$/.test(namespace)) {\n\t\t\t\tfail(`${path}.extensions`, `has invalid extension namespace \"${namespace}\"`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport function assertUsageContractDocument(value: unknown): asserts value is UsageContractDocument {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) fail(\"document\", \"must be an object\");\n\tconst document = value as Record<string, unknown>;\n\tif (!/^[0-9a-f]{64}$/.test(String(document.manifestDigest))) fail(\"document.manifestDigest\", \"must be a lowercase SHA-256 digest\");\n\tconst generator = document.generator as { name?: unknown; version?: unknown } | undefined;\n\tif (!generator || typeof generator !== \"object\" || Array.isArray(generator)) fail(\"document.generator\", \"must be an object\");\n\trequireString(generator.name, \"document.generator.name\");\n\trequireString(generator.version, \"document.generator.version\");\n\tassertUsageContract(document.capability);\n}\n\n/** Machine-readable shape of the usage contract, for adopters that validate with their own tooling. */\nexport const USAGE_CONTRACT_JSON_SCHEMA: PortableJsonSchema = {\n\t$schema: \"https://json-schema.org/draft/2020-12/schema\",\n\ttitle: \"Fabric capability usage contract\",\n\ttype: \"object\",\n\trequired: [\"formatVersion\", \"namespace\", \"displayName\", \"description\", \"stability\", \"actions\", \"views\", \"events\"],\n\tproperties: {\n\t\tformatVersion: { type: \"integer\", enum: [USAGE_CONTRACT_FORMAT_VERSION] },\n\t\tnamespace: { type: \"string\", pattern: \"^[a-z][a-z0-9-]*$\" },\n\t\tversion: { type: \"string\" },\n\t\tdisplayName: { type: \"string\", minLength: 1 },\n\t\tdescription: { type: \"string\", minLength: 1 },\n\t\tstability: { type: \"string\", enum: [...STABILITIES] },\n\t\tdeprecated: { type: \"object\" },\n\t\trequirements: { type: \"object\" },\n\t\tcertification: { type: \"object\" },\n\t\textensions: { type: \"object\" },\n\t\tactions: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\trequired: [\"actionId\", \"version\"],\n\t\t\t\tproperties: {\n\t\t\t\t\tactionId: { type: \"string\" },\n\t\t\t\t\tversion: { type: \"integer\" },\n\t\t\t\t\tparameterSchema: { type: \"object\" },\n\t\t\t\t\tresultSchema: { type: \"object\" },\n\t\t\t\t\trequiredRoles: { type: \"array\", items: { type: \"string\" } },\n\t\t\t\t\trequiredPermissions: { type: \"array\", items: { type: \"string\" } },\n\t\t\t\t\texecution: { type: \"object\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tviews: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\trequired: [\"name\", \"version\", \"shape\", \"scope\", \"snapshotVersion\"],\n\t\t\t\tproperties: {\n\t\t\t\t\tname: { type: \"string\" },\n\t\t\t\t\tversion: { type: \"string\" },\n\t\t\t\t\tshape: { type: \"object\" },\n\t\t\t\t\tscope: { type: \"string\", enum: [\"tenant-space\"] },\n\t\t\t\t\tsnapshotVersion: { type: \"integer\" },\n\t\t\t\t\tusage: { type: \"object\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tevents: {\n\t\t\ttype: \"array\",\n\t\t\titems: {\n\t\t\t\ttype: \"object\",\n\t\t\t\trequired: [\"eventType\", \"schemaVersion\"],\n\t\t\t\tproperties: {\n\t\t\t\t\teventType: { type: \"string\" },\n\t\t\t\t\tschemaVersion: { type: \"integer\" },\n\t\t\t\t\tdescription: { type: \"string\" },\n\t\t\t\t\tschema: { type: \"object\" },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n};\n\nexport function buildUsageContract(module: ModuleManifest): UsageContract | undefined {\n\tconst capability = module.capability;\n\tif (!capability) return undefined;\n\treturn {\n\t\tformatVersion: USAGE_CONTRACT_FORMAT_VERSION,\n\t\tnamespace: module.namespace,\n\t\t...(module.version === undefined ? {} : { version: module.version }),\n\t\tdisplayName: capability.displayName,\n\t\tdescription: capability.description,\n\t\tstability: capability.stability,\n\t\t...(capability.deprecated === undefined ? {} : { deprecated: capability.deprecated }),\n\t\t...(capability.requirements === undefined ? {} : { requirements: capability.requirements }),\n\t\t...(capability.certification === undefined ? {} : { certification: capability.certification }),\n\t\t...(capability.extensions === undefined ? {} : { extensions: capability.extensions }),\n\t\tactions: module.actions.map(({ actionId, version, parameterSchema, resultSchema, requiredRoles, requiredPermissions, execution }) => ({\n\t\t\tactionId,\n\t\t\tversion,\n\t\t\tparameterSchema,\n\t\t\tresultSchema,\n\t\t\trequiredRoles,\n\t\t\trequiredPermissions,\n\t\t\texecution,\n\t\t})),\n\t\tviews: module.views.map(({ name, version, shape, scope, snapshotVersion, usage }) => ({ name, version, shape, scope, snapshotVersion, usage })),\n\t\tevents: module.eventTypes.map(({ eventType, schemaVersion, description, schema }) => ({ eventType, schemaVersion, description, schema })),\n\t};\n}\n\nexport const capabilityGenerator: GeneratorTarget = {\n\tname: \"@fabricorg/gen-capability\",\n\tversion: \"0.4.0\",\n\tgenerate(ir) {\n\t\treturn ir.modules.flatMap((module) => {\n\t\t\tconst capability = buildUsageContract(module);\n\t\t\tif (!capability) return [];\n\t\t\tassertUsageContract(capability);\n\t\t\tconst document: UsageContractDocument = {\n\t\t\t\tgenerator: { name: capabilityGenerator.name, version: capabilityGenerator.version },\n\t\t\t\tmanifestDigest: ir.manifestDigest,\n\t\t\t\tcapability,\n\t\t\t};\n\t\t\treturn [{ path: `${module.namespace}/capability.json`, content: stableStringify(document) }];\n\t\t});\n\t},\n};\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fabricorg/gen-capability",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Capability usage contract generator for Fabric compiler IR.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -25,13 +25,14 @@
|
|
|
25
25
|
"CHANGELOG.md"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@fabricorg/compiler": "^2.
|
|
28
|
+
"@fabricorg/compiler": "^2.1.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.10.0",
|
|
32
32
|
"tsup": "^8.5.0",
|
|
33
33
|
"typescript": "^5.7.3",
|
|
34
|
-
"vitest": "^4.1.5"
|
|
34
|
+
"vitest": "^4.1.5",
|
|
35
|
+
"@fabricorg/platform": "^1.1.0"
|
|
35
36
|
},
|
|
36
37
|
"engines": {
|
|
37
38
|
"node": ">=20"
|
|
@@ -39,6 +40,9 @@
|
|
|
39
40
|
"publishConfig": {
|
|
40
41
|
"access": "public"
|
|
41
42
|
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@fabricorg/platform": "^1.1.0"
|
|
45
|
+
},
|
|
42
46
|
"scripts": {
|
|
43
47
|
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
44
48
|
"build": "tsup",
|