@treasuryspatial/plugin-manifest 0.1.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/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # @treasuryspatial/plugin-manifest
2
+
3
+ Contracts for:
4
+ - `PluginManifest` (plugin-owned)
5
+ - `ToolManifest` (product-owned)
6
+
7
+ This package is intentionally small and stable; it is consumed by all frontends.
@@ -0,0 +1,16 @@
1
+ import type { DefinitionManifest, ManifestVersion, UiSchema } from "../index";
2
+ import type { GhInputSchema } from "./types";
3
+ export type GhManifestBuildOptions = {
4
+ definitionId: string;
5
+ sessionId: string;
6
+ fileName?: string;
7
+ fileHash?: string;
8
+ fileSize?: number;
9
+ endpoints?: Record<string, string>;
10
+ manifestVersion?: ManifestVersion;
11
+ schemaVersion?: ManifestVersion;
12
+ uiSchemaOverride?: UiSchema;
13
+ defaultPanelTitle?: string;
14
+ };
15
+ export declare function buildDefinitionManifestFromGhInputs(inputs: GhInputSchema, options: GhManifestBuildOptions): DefinitionManifest;
16
+ //# sourceMappingURL=inputsToManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputsToManifest.d.ts","sourceRoot":"","sources":["../../src/gh/inputsToManifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAc,eAAe,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAC1F,OAAO,KAAK,EAAgB,aAAa,EAAiB,MAAM,SAAS,CAAC;AAE1E,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAqGF,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,sBAAsB,GAC9B,kBAAkB,CAwBpB"}
@@ -0,0 +1,116 @@
1
+ const DEFAULT_MANIFEST_VERSION = "1.0.0";
2
+ const DEFAULT_SCHEMA_VERSION = "1.0.0";
3
+ const DEFAULT_PANEL_ID = "parameters";
4
+ const DEFAULT_TAB_ID = "controls";
5
+ const slugifyId = (value) => value
6
+ .toLowerCase()
7
+ .replace(/[^a-z0-9._-]+/g, "-")
8
+ .replace(/^-+|-+$/g, "")
9
+ .slice(0, 64) || DEFAULT_PANEL_ID;
10
+ const toOptionType = (options) => {
11
+ if (!options || options.length === 0)
12
+ return "string";
13
+ const sample = options.find((opt) => opt.value !== undefined)?.value;
14
+ if (typeof sample === "number")
15
+ return "number";
16
+ if (typeof sample === "boolean")
17
+ return "boolean";
18
+ return "string";
19
+ };
20
+ const buildPropertySchema = (field) => {
21
+ const schema = {
22
+ type: field.type === "enum" ? toOptionType(field.options) : field.type,
23
+ };
24
+ if (field.label)
25
+ schema.title = field.label;
26
+ if (field.description)
27
+ schema.description = field.description;
28
+ if (field.default !== undefined)
29
+ schema.default = field.default;
30
+ if (field.min !== undefined)
31
+ schema.minimum = field.min;
32
+ if (field.max !== undefined)
33
+ schema.maximum = field.max;
34
+ if (field.step !== undefined)
35
+ schema.multipleOf = field.step;
36
+ if (field.options && field.options.length > 0)
37
+ schema.enum = field.options.map((opt) => opt.value);
38
+ return schema;
39
+ };
40
+ const buildRequestSchema = (inputs) => {
41
+ const properties = {};
42
+ const required = [];
43
+ inputs.fields.forEach((field) => {
44
+ properties[field.key] = buildPropertySchema(field);
45
+ if (field.required)
46
+ required.push(field.key);
47
+ });
48
+ const schema = {
49
+ $schema: "https://json-schema.org/draft/2020-12/schema",
50
+ type: "object",
51
+ properties,
52
+ additionalProperties: false,
53
+ };
54
+ if (required.length > 0)
55
+ schema.required = required;
56
+ return schema;
57
+ };
58
+ const buildDefaults = (inputs) => {
59
+ const defaults = {};
60
+ inputs.fields.forEach((field) => {
61
+ if (field.default !== undefined) {
62
+ defaults[field.key] = field.default;
63
+ }
64
+ });
65
+ return defaults;
66
+ };
67
+ const buildUiSchema = (inputs, defaultPanelTitle) => {
68
+ const groups = new Map();
69
+ inputs.fields.forEach((field) => {
70
+ const group = field.group?.trim() || DEFAULT_PANEL_ID;
71
+ const existing = groups.get(group) ?? [];
72
+ existing.push(field);
73
+ groups.set(group, existing);
74
+ });
75
+ const panels = Array.from(groups.entries()).map(([groupName, fields], index) => {
76
+ const id = slugifyId(groupName);
77
+ return {
78
+ id,
79
+ title: groupName === DEFAULT_PANEL_ID ? defaultPanelTitle ?? "parameters" : groupName,
80
+ tab: DEFAULT_TAB_ID,
81
+ order: index + 1,
82
+ fields: fields.map((field) => field.key),
83
+ };
84
+ });
85
+ return {
86
+ uiVersion: "1.0.0",
87
+ tabs: [{ id: DEFAULT_TAB_ID, label: "controls", order: 1 }],
88
+ panels,
89
+ layout: {
90
+ defaultPanelId: panels[0]?.id ?? DEFAULT_PANEL_ID,
91
+ panelOrder: panels.map((panel) => panel.id),
92
+ },
93
+ };
94
+ };
95
+ export function buildDefinitionManifestFromGhInputs(inputs, options) {
96
+ const manifestVersion = options.manifestVersion ?? DEFAULT_MANIFEST_VERSION;
97
+ const schemaVersion = options.schemaVersion ?? DEFAULT_SCHEMA_VERSION;
98
+ const requestSchema = buildRequestSchema(inputs);
99
+ const defaults = buildDefaults(inputs);
100
+ const uiSchema = options.uiSchemaOverride ?? buildUiSchema(inputs, options.defaultPanelTitle);
101
+ return {
102
+ manifestVersion,
103
+ schemaVersion,
104
+ definitionId: options.definitionId,
105
+ sessionId: options.sessionId,
106
+ fileName: options.fileName,
107
+ fileHash: options.fileHash,
108
+ fileSize: options.fileSize,
109
+ endpoints: options.endpoints,
110
+ schemas: {
111
+ request: requestSchema,
112
+ ui: uiSchema,
113
+ },
114
+ defaults,
115
+ };
116
+ }
@@ -0,0 +1,23 @@
1
+ export type GhInputFieldType = "number" | "integer" | "boolean" | "string" | "enum";
2
+ export type GhInputOption = {
3
+ value: string | number | boolean;
4
+ label: string;
5
+ };
6
+ export type GhInputField = {
7
+ key: string;
8
+ label?: string;
9
+ type: GhInputFieldType;
10
+ min?: number;
11
+ max?: number;
12
+ step?: number;
13
+ options?: GhInputOption[];
14
+ default?: unknown;
15
+ group?: string;
16
+ description?: string;
17
+ required?: boolean;
18
+ };
19
+ export type GhInputSchema = {
20
+ version?: string;
21
+ fields: GhInputField[];
22
+ };
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gh/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,EAAE,CAAC;CACxB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,106 @@
1
+ export type ManifestVersion = `${number}.${number}.${number}`;
2
+ export type PluginReleaseId = string;
3
+ export type JsonSchema = Record<string, unknown>;
4
+ export type UiSchema = Record<string, unknown>;
5
+ export type PluginEndpointId = string;
6
+ export type TaggingConfig = {
7
+ roleKey?: string;
8
+ roleKeys?: string[];
9
+ geometryRole?: string;
10
+ renderRole?: string;
11
+ idKey?: string;
12
+ packetKey?: string;
13
+ layerKey?: string;
14
+ materialKey?: string;
15
+ };
16
+ export type PluginManifest = {
17
+ manifestVersion: ManifestVersion;
18
+ schemaVersion: ManifestVersion;
19
+ pluginId: string;
20
+ routeId: string;
21
+ releaseId: PluginReleaseId;
22
+ endpoints: Record<PluginEndpointId, string>;
23
+ schemas: {
24
+ request: JsonSchema;
25
+ response?: JsonSchema;
26
+ ui?: UiSchema;
27
+ };
28
+ defaults: unknown;
29
+ presets?: Array<{
30
+ id: string;
31
+ label: string;
32
+ patch?: unknown;
33
+ params?: unknown;
34
+ }>;
35
+ capabilities?: {
36
+ supportsDebug?: boolean;
37
+ returnsPackets?: boolean;
38
+ returnsRenderMeshes?: boolean;
39
+ };
40
+ tagging?: TaggingConfig;
41
+ extensions?: Record<string, unknown>;
42
+ };
43
+ export type DefinitionManifest = {
44
+ manifestVersion: ManifestVersion;
45
+ schemaVersion: ManifestVersion;
46
+ definitionId: string;
47
+ sessionId: string;
48
+ fileName?: string;
49
+ fileHash?: string;
50
+ fileSize?: number;
51
+ endpoints?: Record<PluginEndpointId, string>;
52
+ schemas: {
53
+ request: JsonSchema;
54
+ response?: JsonSchema;
55
+ ui?: UiSchema;
56
+ };
57
+ defaults: unknown;
58
+ presets?: Array<{
59
+ id: string;
60
+ label: string;
61
+ patch?: unknown;
62
+ params?: unknown;
63
+ }>;
64
+ capabilities?: {
65
+ supportsDebug?: boolean;
66
+ returnsPackets?: boolean;
67
+ returnsRenderMeshes?: boolean;
68
+ };
69
+ tagging?: TaggingConfig;
70
+ extensions?: Record<string, unknown>;
71
+ };
72
+ export type ToolManifest = {
73
+ toolId: string;
74
+ label: string;
75
+ pipeline: Array<{
76
+ pluginId: string;
77
+ endpoint: PluginEndpointId;
78
+ parameterScope: string;
79
+ }>;
80
+ panels: Array<{
81
+ id: string;
82
+ title: string;
83
+ schemaRef: {
84
+ pluginId: string;
85
+ pointer: string;
86
+ };
87
+ }>;
88
+ actions?: Array<{
89
+ id: string;
90
+ label: string;
91
+ kind: "compute";
92
+ stage: string;
93
+ } | {
94
+ id: string;
95
+ label: string;
96
+ kind: "viewer";
97
+ method: string;
98
+ }>;
99
+ extensions?: Record<string, unknown>;
100
+ };
101
+ export type { GhInputField, GhInputFieldType, GhInputOption, GhInputSchema } from "./gh/types";
102
+ export { buildDefinitionManifestFromGhInputs } from "./gh/inputsToManifest";
103
+ export type { ManifestSchemas } from "./schemas";
104
+ export { loadSchemas, schemaUrls } from "./schemas";
105
+ export { createDefaultManifestValidator, createManifestValidator } from "./validate";
106
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { buildDefinitionManifestFromGhInputs } from "./gh/inputsToManifest";
2
+ export { loadSchemas, schemaUrls } from "./schemas";
3
+ export { createDefaultManifestValidator, createManifestValidator } from "./validate";
@@ -0,0 +1,14 @@
1
+ export type ManifestSchemas = {
2
+ pluginManifest: unknown;
3
+ definitionManifest: unknown;
4
+ uiSchema: unknown;
5
+ toolManifest: unknown;
6
+ };
7
+ export declare const schemaUrls: {
8
+ pluginManifest: string;
9
+ definitionManifest: string;
10
+ uiSchema: string;
11
+ toolManifest: string;
12
+ };
13
+ export declare function loadSchemas(): Promise<ManifestSchemas>;
14
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;CAKtB,CAAC;AAgBF,wBAAsB,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC,CAS5D"}
@@ -0,0 +1,27 @@
1
+ export const schemaUrls = {
2
+ pluginManifest: new URL("../schema/plugin-manifest.schema.json", import.meta.url).toString(),
3
+ definitionManifest: new URL("../schema/definition-manifest.schema.json", import.meta.url).toString(),
4
+ uiSchema: new URL("../schema/ui.schema.json", import.meta.url).toString(),
5
+ toolManifest: new URL("../schema/tool-manifest.schema.json", import.meta.url).toString(),
6
+ };
7
+ async function loadJson(url) {
8
+ if (typeof fetch === "function") {
9
+ const res = await fetch(url);
10
+ if (!res.ok) {
11
+ throw new Error(`Failed to load schema ${url}: ${res.status} ${res.statusText}`);
12
+ }
13
+ return res.json();
14
+ }
15
+ const { readFile } = await import("node:fs/promises");
16
+ const data = await readFile(new URL(url), "utf-8");
17
+ return JSON.parse(data);
18
+ }
19
+ export async function loadSchemas() {
20
+ const [pluginManifest, definitionManifest, uiSchema, toolManifest] = await Promise.all([
21
+ loadJson(schemaUrls.pluginManifest),
22
+ loadJson(schemaUrls.definitionManifest),
23
+ loadJson(schemaUrls.uiSchema),
24
+ loadJson(schemaUrls.toolManifest),
25
+ ]);
26
+ return { pluginManifest, definitionManifest, uiSchema, toolManifest };
27
+ }
@@ -0,0 +1,14 @@
1
+ import type { ManifestSchemas } from "./schemas";
2
+ export type ValidationResult = {
3
+ valid: boolean;
4
+ errors?: string[];
5
+ };
6
+ export type ManifestValidator = {
7
+ validatePluginManifest: (value: unknown) => ValidationResult;
8
+ validateDefinitionManifest: (value: unknown) => ValidationResult;
9
+ validateUiSchema: (value: unknown) => ValidationResult;
10
+ validateToolManifest: (value: unknown) => ValidationResult;
11
+ };
12
+ export declare function createManifestValidator(schemas: ManifestSchemas): ManifestValidator;
13
+ export declare function createDefaultManifestValidator(): Promise<ManifestValidator>;
14
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,sBAAsB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,CAAC;IAC7D,0BAA0B,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,CAAC;IACjE,gBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,CAAC;IACvD,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,CAAC;CAC5D,CAAC;AAiBF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,iBAAiB,CAcnF;AAED,wBAAsB,8BAA8B,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAGjF"}
@@ -0,0 +1,33 @@
1
+ import Ajv from "ajv";
2
+ import { loadSchemas } from "./schemas";
3
+ function formatErrors(errors) {
4
+ if (!errors || errors.length === 0)
5
+ return [];
6
+ return errors.map((error) => `${error.instancePath || "<root>"} ${error.message ?? "is invalid"}`.trim());
7
+ }
8
+ function buildValidator(ajv, schemaKey) {
9
+ return (value) => {
10
+ const valid = ajv.validate(schemaKey, value);
11
+ if (valid) {
12
+ return { valid: true };
13
+ }
14
+ return { valid: false, errors: formatErrors(ajv.errors) };
15
+ };
16
+ }
17
+ export function createManifestValidator(schemas) {
18
+ const ajv = new Ajv({ allErrors: true, strict: false });
19
+ ajv.addSchema(schemas.pluginManifest, "plugin-manifest");
20
+ ajv.addSchema(schemas.definitionManifest, "definition-manifest");
21
+ ajv.addSchema(schemas.uiSchema, "ui-schema");
22
+ ajv.addSchema(schemas.toolManifest, "tool-manifest");
23
+ return {
24
+ validatePluginManifest: buildValidator(ajv, "plugin-manifest"),
25
+ validateDefinitionManifest: buildValidator(ajv, "definition-manifest"),
26
+ validateUiSchema: buildValidator(ajv, "ui-schema"),
27
+ validateToolManifest: buildValidator(ajv, "tool-manifest"),
28
+ };
29
+ }
30
+ export async function createDefaultManifestValidator() {
31
+ const schemas = await loadSchemas();
32
+ return createManifestValidator(schemas);
33
+ }
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@treasuryspatial/plugin-manifest",
3
+ "version": "0.1.3",
4
+ "type": "module",
5
+ "license": "UNLICENSED",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "schema"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "dependencies": {
22
+ "ajv": "^8.17.1"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc -b",
26
+ "typecheck": "tsc -b --pretty false --noEmit"
27
+ }
28
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://base2.design/schema/definition-manifest.schema.json",
4
+ "title": "Base2 Composer Definition Manifest",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "manifestVersion",
9
+ "schemaVersion",
10
+ "definitionId",
11
+ "sessionId",
12
+ "schemas",
13
+ "defaults"
14
+ ],
15
+ "properties": {
16
+ "manifestVersion": { "$ref": "#/$defs/semver" },
17
+ "schemaVersion": { "$ref": "#/$defs/semver" },
18
+ "definitionId": { "type": "string", "minLength": 1 },
19
+ "sessionId": { "type": "string", "minLength": 1 },
20
+ "fileName": { "type": "string" },
21
+ "fileHash": { "type": "string" },
22
+ "fileSize": { "type": "integer", "minimum": 0 },
23
+ "endpoints": {
24
+ "type": "object",
25
+ "propertyNames": { "$ref": "#/$defs/id" },
26
+ "additionalProperties": { "type": "string", "minLength": 1 }
27
+ },
28
+ "schemas": {
29
+ "type": "object",
30
+ "additionalProperties": false,
31
+ "required": ["request"],
32
+ "properties": {
33
+ "request": { "$ref": "#/$defs/jsonSchema" },
34
+ "response": { "$ref": "#/$defs/jsonSchema" },
35
+ "ui": { "$ref": "#/$defs/uiSchema" }
36
+ }
37
+ },
38
+ "defaults": {},
39
+ "presets": {
40
+ "type": "array",
41
+ "items": {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "required": ["id", "label"],
45
+ "properties": {
46
+ "id": { "$ref": "#/$defs/id" },
47
+ "label": { "type": "string" },
48
+ "patch": {},
49
+ "params": {}
50
+ }
51
+ }
52
+ },
53
+ "capabilities": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "properties": {
57
+ "supportsDebug": { "type": "boolean" },
58
+ "returnsPackets": { "type": "boolean" },
59
+ "returnsRenderMeshes": { "type": "boolean" }
60
+ }
61
+ },
62
+ "tagging": { "$ref": "#/$defs/tagging" },
63
+ "extensions": {
64
+ "type": "object",
65
+ "additionalProperties": true
66
+ }
67
+ },
68
+ "$defs": {
69
+ "semver": {
70
+ "type": "string",
71
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
72
+ },
73
+ "id": {
74
+ "type": "string",
75
+ "pattern": "^[A-Za-z0-9._-]+$"
76
+ },
77
+ "jsonSchema": {
78
+ "oneOf": [
79
+ { "type": "object" },
80
+ { "type": "boolean" }
81
+ ]
82
+ },
83
+ "uiSchema": {
84
+ "type": "object"
85
+ },
86
+ "tagging": {
87
+ "type": "object",
88
+ "additionalProperties": false,
89
+ "properties": {
90
+ "roleKey": { "type": "string", "minLength": 1 },
91
+ "roleKeys": {
92
+ "type": "array",
93
+ "items": { "type": "string", "minLength": 1 }
94
+ },
95
+ "geometryRole": { "type": "string", "minLength": 1 },
96
+ "renderRole": { "type": "string", "minLength": 1 },
97
+ "idKey": { "type": "string", "minLength": 1 },
98
+ "packetKey": { "type": "string", "minLength": 1 },
99
+ "layerKey": { "type": "string", "minLength": 1 },
100
+ "materialKey": { "type": "string", "minLength": 1 }
101
+ }
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,104 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://base2.design/schema/plugin-manifest.schema.json",
4
+ "title": "Base2 Composer Plugin Manifest",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "manifestVersion",
9
+ "schemaVersion",
10
+ "pluginId",
11
+ "routeId",
12
+ "releaseId",
13
+ "endpoints",
14
+ "schemas",
15
+ "defaults"
16
+ ],
17
+ "properties": {
18
+ "manifestVersion": { "$ref": "#/$defs/semver" },
19
+ "schemaVersion": { "$ref": "#/$defs/semver" },
20
+ "pluginId": { "type": "string", "minLength": 1 },
21
+ "routeId": { "type": "string", "minLength": 1 },
22
+ "releaseId": { "type": "string", "minLength": 1 },
23
+ "endpoints": {
24
+ "type": "object",
25
+ "propertyNames": { "$ref": "#/$defs/id" },
26
+ "additionalProperties": { "type": "string", "minLength": 1 }
27
+ },
28
+ "schemas": {
29
+ "type": "object",
30
+ "additionalProperties": false,
31
+ "required": ["request"],
32
+ "properties": {
33
+ "request": { "$ref": "#/$defs/jsonSchema" },
34
+ "response": { "$ref": "#/$defs/jsonSchema" },
35
+ "ui": { "$ref": "#/$defs/uiSchema" }
36
+ }
37
+ },
38
+ "defaults": {},
39
+ "presets": {
40
+ "type": "array",
41
+ "items": {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "required": ["id", "label"],
45
+ "properties": {
46
+ "id": { "$ref": "#/$defs/id" },
47
+ "label": { "type": "string" },
48
+ "patch": {},
49
+ "params": {}
50
+ }
51
+ }
52
+ },
53
+ "capabilities": {
54
+ "type": "object",
55
+ "additionalProperties": false,
56
+ "properties": {
57
+ "supportsDebug": { "type": "boolean" },
58
+ "returnsPackets": { "type": "boolean" },
59
+ "returnsRenderMeshes": { "type": "boolean" }
60
+ }
61
+ },
62
+ "tagging": { "$ref": "#/$defs/tagging" },
63
+ "extensions": {
64
+ "type": "object",
65
+ "additionalProperties": true
66
+ }
67
+ },
68
+ "$defs": {
69
+ "semver": {
70
+ "type": "string",
71
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
72
+ },
73
+ "id": {
74
+ "type": "string",
75
+ "pattern": "^[A-Za-z0-9._-]+$"
76
+ },
77
+ "jsonSchema": {
78
+ "oneOf": [
79
+ { "type": "object" },
80
+ { "type": "boolean" }
81
+ ]
82
+ },
83
+ "uiSchema": {
84
+ "type": "object"
85
+ },
86
+ "tagging": {
87
+ "type": "object",
88
+ "additionalProperties": false,
89
+ "properties": {
90
+ "roleKey": { "type": "string", "minLength": 1 },
91
+ "roleKeys": {
92
+ "type": "array",
93
+ "items": { "type": "string", "minLength": 1 }
94
+ },
95
+ "geometryRole": { "type": "string", "minLength": 1 },
96
+ "renderRole": { "type": "string", "minLength": 1 },
97
+ "idKey": { "type": "string", "minLength": 1 },
98
+ "packetKey": { "type": "string", "minLength": 1 },
99
+ "layerKey": { "type": "string", "minLength": 1 },
100
+ "materialKey": { "type": "string", "minLength": 1 }
101
+ }
102
+ }
103
+ }
104
+ }
@@ -0,0 +1,88 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://base2.design/schema/tool-manifest.schema.json",
4
+ "title": "Composer Tool Manifest",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["toolId", "label", "pipeline", "panels"],
8
+ "properties": {
9
+ "toolId": { "$ref": "#/$defs/id" },
10
+ "label": { "type": "string" },
11
+ "pipeline": {
12
+ "type": "array",
13
+ "items": { "$ref": "#/$defs/pipelineStep" }
14
+ },
15
+ "panels": {
16
+ "type": "array",
17
+ "items": { "$ref": "#/$defs/panelRef" }
18
+ },
19
+ "actions": {
20
+ "type": "array",
21
+ "items": { "$ref": "#/$defs/action" }
22
+ },
23
+ "extensions": {
24
+ "type": "object",
25
+ "additionalProperties": true
26
+ }
27
+ },
28
+ "$defs": {
29
+ "id": {
30
+ "type": "string",
31
+ "pattern": "^[A-Za-z0-9._-]+$"
32
+ },
33
+ "pipelineStep": {
34
+ "type": "object",
35
+ "additionalProperties": false,
36
+ "required": ["pluginId", "endpoint", "parameterScope"],
37
+ "properties": {
38
+ "pluginId": { "$ref": "#/$defs/id" },
39
+ "endpoint": { "$ref": "#/$defs/id" },
40
+ "parameterScope": { "type": "string" }
41
+ }
42
+ },
43
+ "panelRef": {
44
+ "type": "object",
45
+ "additionalProperties": false,
46
+ "required": ["id", "title", "schemaRef"],
47
+ "properties": {
48
+ "id": { "$ref": "#/$defs/id" },
49
+ "title": { "type": "string" },
50
+ "schemaRef": {
51
+ "type": "object",
52
+ "additionalProperties": false,
53
+ "required": ["pluginId", "pointer"],
54
+ "properties": {
55
+ "pluginId": { "$ref": "#/$defs/id" },
56
+ "pointer": { "type": "string" }
57
+ }
58
+ }
59
+ }
60
+ },
61
+ "action": {
62
+ "oneOf": [
63
+ {
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "required": ["id", "label", "kind", "stage"],
67
+ "properties": {
68
+ "id": { "$ref": "#/$defs/id" },
69
+ "label": { "type": "string" },
70
+ "kind": { "const": "compute" },
71
+ "stage": { "type": "string" }
72
+ }
73
+ },
74
+ {
75
+ "type": "object",
76
+ "additionalProperties": false,
77
+ "required": ["id", "label", "kind", "method"],
78
+ "properties": {
79
+ "id": { "$ref": "#/$defs/id" },
80
+ "label": { "type": "string" },
81
+ "kind": { "const": "viewer" },
82
+ "method": { "type": "string" }
83
+ }
84
+ }
85
+ ]
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,217 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://base2.design/schema/ui.schema.json",
4
+ "title": "Composer UI Schema",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "uiVersion": { "$ref": "#/$defs/semver" },
9
+ "tabs": {
10
+ "type": "array",
11
+ "items": { "$ref": "#/$defs/tab" }
12
+ },
13
+ "panels": {
14
+ "type": "array",
15
+ "items": { "$ref": "#/$defs/panel" }
16
+ },
17
+ "layout": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "properties": {
21
+ "defaultPanelId": { "$ref": "#/$defs/id" },
22
+ "panelOrder": {
23
+ "type": "array",
24
+ "items": { "$ref": "#/$defs/id" }
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "$defs": {
30
+ "semver": {
31
+ "type": "string",
32
+ "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"
33
+ },
34
+ "id": {
35
+ "type": "string",
36
+ "pattern": "^[A-Za-z0-9._-]+$"
37
+ },
38
+ "tab": {
39
+ "type": "object",
40
+ "additionalProperties": false,
41
+ "required": ["id", "label"],
42
+ "properties": {
43
+ "id": { "$ref": "#/$defs/id" },
44
+ "label": { "type": "string" },
45
+ "order": { "type": "integer" },
46
+ "description": { "type": "string" }
47
+ }
48
+ },
49
+ "panel": {
50
+ "type": "object",
51
+ "additionalProperties": false,
52
+ "required": ["id", "title"],
53
+ "properties": {
54
+ "id": { "$ref": "#/$defs/id" },
55
+ "title": { "type": "string" },
56
+ "tab": { "$ref": "#/$defs/id" },
57
+ "order": { "type": "integer" },
58
+ "description": { "type": "string" },
59
+ "fields": {
60
+ "type": "array",
61
+ "items": { "$ref": "#/$defs/fieldRef" }
62
+ },
63
+ "sections": {
64
+ "type": "array",
65
+ "items": { "$ref": "#/$defs/section" }
66
+ }
67
+ }
68
+ },
69
+ "section": {
70
+ "type": "object",
71
+ "additionalProperties": false,
72
+ "required": ["id", "title", "fields"],
73
+ "properties": {
74
+ "id": { "$ref": "#/$defs/id" },
75
+ "title": { "type": "string" },
76
+ "description": { "type": "string" },
77
+ "fields": {
78
+ "type": "array",
79
+ "items": { "$ref": "#/$defs/fieldRef" }
80
+ }
81
+ }
82
+ },
83
+ "fieldRef": {
84
+ "oneOf": [
85
+ { "type": "string" },
86
+ { "$ref": "#/$defs/field" }
87
+ ]
88
+ },
89
+ "field": {
90
+ "type": "object",
91
+ "additionalProperties": false,
92
+ "required": ["key"],
93
+ "properties": {
94
+ "key": { "type": "string" },
95
+ "label": { "type": "string" },
96
+ "control": {
97
+ "type": "string",
98
+ "enum": ["range", "number", "toggle", "select", "color", "text", "textarea", "file", "action", "array", "oneOf"]
99
+ },
100
+ "min": { "type": "number" },
101
+ "max": { "type": "number" },
102
+ "step": { "type": "number" },
103
+ "unit": { "type": "string" },
104
+ "placeholder": { "type": "string" },
105
+ "rows": { "type": "integer", "minimum": 1 },
106
+ "helpText": { "type": "string" },
107
+ "options": {
108
+ "type": "array",
109
+ "items": {
110
+ "type": "object",
111
+ "additionalProperties": false,
112
+ "required": ["value", "label"],
113
+ "properties": {
114
+ "value": { "type": ["string", "number", "boolean"] },
115
+ "label": { "type": "string" }
116
+ }
117
+ }
118
+ },
119
+ "visibleWhen": { "$ref": "#/$defs/expr" },
120
+ "disabledWhen": { "$ref": "#/$defs/expr" },
121
+ "itemLabel": { "type": "string" },
122
+ "itemDefaults": {},
123
+ "itemFields": {
124
+ "type": "array",
125
+ "items": { "$ref": "#/$defs/fieldRef" }
126
+ },
127
+ "fields": {
128
+ "type": "array",
129
+ "items": { "$ref": "#/$defs/fieldRef" }
130
+ },
131
+ "minItems": { "type": "integer", "minimum": 0 },
132
+ "maxItems": { "type": "integer", "minimum": 0 },
133
+ "variants": {
134
+ "type": "array",
135
+ "items": { "$ref": "#/$defs/variant" }
136
+ },
137
+ "discriminator": { "type": "string" },
138
+ "effects": {
139
+ "type": "object",
140
+ "additionalProperties": false,
141
+ "properties": {
142
+ "onChange": {
143
+ "type": "array",
144
+ "items": { "$ref": "#/$defs/effect" }
145
+ }
146
+ }
147
+ },
148
+ "actionId": { "$ref": "#/$defs/id" }
149
+ }
150
+ },
151
+ "variant": {
152
+ "type": "object",
153
+ "additionalProperties": false,
154
+ "required": ["id", "label", "fields"],
155
+ "properties": {
156
+ "id": { "$ref": "#/$defs/id" },
157
+ "label": { "type": "string" },
158
+ "fields": {
159
+ "type": "array",
160
+ "items": { "$ref": "#/$defs/fieldRef" }
161
+ }
162
+ }
163
+ },
164
+ "effect": {
165
+ "type": "object",
166
+ "additionalProperties": false,
167
+ "required": ["kind", "path"],
168
+ "properties": {
169
+ "kind": { "type": "string", "enum": ["set", "patch"] },
170
+ "path": { "type": "string" },
171
+ "value": {},
172
+ "when": { "$ref": "#/$defs/expr" }
173
+ }
174
+ },
175
+ "expr": {
176
+ "oneOf": [
177
+ { "$ref": "#/$defs/compare" },
178
+ { "$ref": "#/$defs/logic" }
179
+ ]
180
+ },
181
+ "compare": {
182
+ "type": "object",
183
+ "additionalProperties": false,
184
+ "properties": {
185
+ "path": { "type": "string" },
186
+ "key": { "type": "string" },
187
+ "truthy": {},
188
+ "equals": {},
189
+ "notEquals": {},
190
+ "gt": { "type": "number" },
191
+ "gte": { "type": "number" },
192
+ "lt": { "type": "number" },
193
+ "lte": { "type": "number" },
194
+ "in": { "type": "array" }
195
+ },
196
+ "anyOf": [
197
+ { "required": ["path"] },
198
+ { "required": ["key"] }
199
+ ]
200
+ },
201
+ "logic": {
202
+ "type": "object",
203
+ "additionalProperties": false,
204
+ "properties": {
205
+ "all": {
206
+ "type": "array",
207
+ "items": { "$ref": "#/$defs/expr" }
208
+ },
209
+ "any": {
210
+ "type": "array",
211
+ "items": { "$ref": "#/$defs/expr" }
212
+ },
213
+ "not": { "$ref": "#/$defs/expr" }
214
+ }
215
+ }
216
+ }
217
+ }