@absolutejs/manifest
Advanced tools
+151
-1
@@ -168,2 +168,75 @@ #!/usr/bin/env bun | ||
| }); | ||
| var productId = Type.String({ pattern: "^[a-z][a-z0-9_-]{0,63}$" }); | ||
| var productCopy = { | ||
| description: Type.String({ minLength: 1 }), | ||
| id: productId, | ||
| title: Type.String({ minLength: 1 }) | ||
| }; | ||
| var productOperation = Type.Union([ | ||
| Type.Literal("aggregate"), | ||
| Type.Literal("create"), | ||
| Type.Literal("delete"), | ||
| Type.Literal("detail"), | ||
| Type.Literal("list"), | ||
| Type.Literal("update") | ||
| ]); | ||
| var productProjection = Type.Object({ | ||
| blocks: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| category: Type.String({ minLength: 1 }), | ||
| componentExport: Type.String({ minLength: 1 }), | ||
| frameworks: Type.Optional(Type.Array(Type.Union(clientFrameworks.map((framework) => Type.Literal(framework))))), | ||
| props: jsonSchemaObject | ||
| }))), | ||
| connections: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| envKeys: Type.Optional(Type.Array(Type.String({ minLength: 1 }))), | ||
| kind: Type.Union([ | ||
| Type.Literal("none"), | ||
| Type.Literal("oauth"), | ||
| Type.Literal("secret") | ||
| ]), | ||
| setupTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })), | ||
| testTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })) | ||
| }))), | ||
| dataSources: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| operations: Type.Array(productOperation, { minItems: 1 }), | ||
| schema: jsonSchemaObject, | ||
| tools: Type.Optional(Type.Partial(Type.Object({ | ||
| aggregate: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| create: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| delete: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| detail: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| list: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| update: Type.String({ pattern: TOOL_NAME_PATTERN.source }) | ||
| }))) | ||
| }))), | ||
| events: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| schema: jsonSchemaObject, | ||
| source: Type.Union([ | ||
| Type.Literal("data"), | ||
| Type.Literal("package"), | ||
| Type.Literal("ui"), | ||
| Type.Literal("webhook") | ||
| ]) | ||
| }))), | ||
| healthChecks: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| tool: Type.String({ pattern: TOOL_NAME_PATTERN.source }) | ||
| }))), | ||
| releaseChecks: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| healthCheckIds: Type.Optional(Type.Array(productId)), | ||
| severity: Type.Union([ | ||
| Type.Literal("blocking"), | ||
| Type.Literal("warning") | ||
| ]) | ||
| }))), | ||
| workflowActions: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| tool: Type.String({ pattern: TOOL_NAME_PATTERN.source }) | ||
| }))) | ||
| }); | ||
| var manifestSchema = Type.Object({ | ||
@@ -209,2 +282,3 @@ contract: Type.Union([Type.Literal(1), Type.Literal(2)]), | ||
| }))), | ||
| product: Type.Optional(productProjection), | ||
| requires: Type.Optional(manifestRequirements), | ||
@@ -392,2 +466,75 @@ settings: jsonSchemaObject, | ||
| }; | ||
| var duplicateProductId = (product) => [ | ||
| ["blocks", product.blocks ?? []], | ||
| ["connections", product.connections ?? []], | ||
| ["dataSources", product.dataSources ?? []], | ||
| ["events", product.events ?? []], | ||
| ["healthChecks", product.healthChecks ?? []], | ||
| ["releaseChecks", product.releaseChecks ?? []], | ||
| ["workflowActions", product.workflowActions ?? []] | ||
| ].map(([group, entries]) => { | ||
| const ids = new Set; | ||
| const duplicate = entries.find((entry) => { | ||
| if (ids.has(entry.id)) | ||
| return true; | ||
| ids.add(entry.id); | ||
| return false; | ||
| }); | ||
| return duplicate ? `product.${group} contains duplicate id "${duplicate.id}"` : undefined; | ||
| }).find((failure) => failure !== undefined); | ||
| var connectionFailure = (manifest, connection, toolReference) => { | ||
| const setupFailure = toolReference(connection.setupTool, `product.connections "${connection.id}" setup`); | ||
| if (setupFailure) | ||
| return setupFailure; | ||
| const testFailure = toolReference(connection.testTool, `product.connections "${connection.id}" test`, true); | ||
| if (testFailure) | ||
| return testFailure; | ||
| const declaredEnv = new Set(manifest.requires?.env?.map((entry) => entry.key)); | ||
| const missingEnv = connection.envKeys?.find((key) => !declaredEnv.has(key)); | ||
| if (missingEnv) | ||
| return `product.connections "${connection.id}" references undeclared env key "${missingEnv}"`; | ||
| return; | ||
| }; | ||
| var productFailure = (manifest) => { | ||
| if (!manifest.product) | ||
| return; | ||
| if (manifest.contract !== 2) | ||
| return "product projections require manifest contract 2"; | ||
| const tools = manifest.tools ?? {}; | ||
| const toolReference = (reference, location, readOnly = false) => { | ||
| if (!reference) | ||
| return; | ||
| const tool = tools[reference]; | ||
| if (!tool) | ||
| return `${location} references missing tool "${reference}"`; | ||
| if (!tool.authorization) | ||
| return `${location} references legacy unguarded tool "${reference}"`; | ||
| if (readOnly && tool.authorization.effects.some((effect) => effect !== "read")) | ||
| return `${location} must reference a read-only tool`; | ||
| return; | ||
| }; | ||
| const duplicate = duplicateProductId(manifest.product); | ||
| if (duplicate) | ||
| return duplicate; | ||
| const actionFailure = (manifest.product.workflowActions ?? []).map((action) => toolReference(action.tool, `product.workflowActions "${action.id}"`)).find(Boolean); | ||
| if (actionFailure) | ||
| return actionFailure; | ||
| const sourceFailure = (manifest.product.dataSources ?? []).flatMap((source) => Object.entries(source.tools ?? {}).map(([operation, tool]) => toolReference(tool, `product.dataSources "${source.id}" operation "${operation}"`))).find(Boolean); | ||
| if (sourceFailure) | ||
| return sourceFailure; | ||
| const invalidConnection = (manifest.product.connections ?? []).map((connection) => connectionFailure(manifest, connection, toolReference)).find(Boolean); | ||
| if (invalidConnection) | ||
| return invalidConnection; | ||
| const healthIds = new Set(manifest.product.healthChecks?.map((check) => check.id)); | ||
| const healthFailure = (manifest.product.healthChecks ?? []).map((check) => toolReference(check.tool, `product.healthChecks "${check.id}"`, true)).find(Boolean); | ||
| if (healthFailure) | ||
| return healthFailure; | ||
| const releaseFailure = (manifest.product.releaseChecks ?? []).map((check) => { | ||
| const missingHealth = check.healthCheckIds?.find((id) => !healthIds.has(id)); | ||
| return missingHealth ? `product.releaseChecks "${check.id}" references missing health check "${missingHealth}"` : undefined; | ||
| }).find(Boolean); | ||
| if (releaseFailure) | ||
| return releaseFailure; | ||
| return; | ||
| }; | ||
| var validate = (candidate, source) => { | ||
@@ -401,2 +548,5 @@ if (!isManifestShaped(candidate)) | ||
| return invalid(invalidIntegration); | ||
| const invalidProduct = productFailure(candidate); | ||
| if (invalidProduct) | ||
| return invalid(invalidProduct); | ||
| if (candidate.contract === 1 && Object.values(candidate.tools ?? {}).some((tool) => tool.authorization !== undefined)) | ||
@@ -784,3 +934,3 @@ return invalid("tool authorization metadata requires manifest contract 2"); | ||
| //# debugId=6F9C6BAFFBC1EA6864756E2164756E21 | ||
| //# debugId=00A7BEA5C99C41F764756E2164756E21 | ||
| //# sourceMappingURL=cli.js.map |
+1
-1
@@ -16,2 +16,2 @@ export { defineImplementation, defineManifest } from "./defineManifest"; | ||
| export type { ManifestSecurityPosture, ManifestToolSecurityCode, ManifestToolSecurityIssue, ManifestToolSecurityPosture, } from "./security"; | ||
| export type { AdapterImplementation, AdapterSlot, AnyPackageManifest, AuthorizedManifestTool, AuthorizedRuntimeTool, AuthorizedWorkspaceTool, BridgedAITool, BridgedMcpTool, ClientFramework, EnvRequirement, LifecycleStep, ManifestCategory, ManifestIdentity, ManifestIntegration, ManifestDiscovery, ManifestRequirements, ManifestTool, LegacyManifestTool, LegacyRuntimeTool, LegacyWorkspaceTool, PackageManifest, PeerRequirement, RuntimeTool, ServiceRequirement, SettingsOf, SettingsPreset, ToolAnnotations, ToolAuthorization, ToolAuthorizationRequest, ToolAudience, ToolBindings, ToolEffect, ToolEnforcement, ToolExecution, ToolIdempotencyBinding, ToolResourceBinding, ToolSpendBinding, WiringImport, WiringPlacement, WiringRecipe, WiringSnippet, Workspace, WorkspaceCapability, WorkspaceTool, } from "./types"; | ||
| export type { AdapterImplementation, AdapterSlot, AnyPackageManifest, AuthorizedManifestTool, AuthorizedRuntimeTool, AuthorizedWorkspaceTool, BridgedAITool, BridgedMcpTool, ClientFramework, EnvRequirement, LifecycleStep, ManifestCategory, ManifestIdentity, ManifestIntegration, ManifestDiscovery, ManifestRequirements, ManifestConnection, ManifestDataSource, ManifestEventBinding, ManifestHealthCheck, ManifestProductProjection, ManifestReleaseCheck, ManifestVisualBlock, ManifestWorkflowAction, ManifestTool, LegacyManifestTool, LegacyRuntimeTool, LegacyWorkspaceTool, PackageManifest, PeerRequirement, RuntimeTool, ServiceRequirement, SettingsOf, SettingsPreset, ToolAnnotations, ToolAuthorization, ToolAuthorizationRequest, ToolAudience, ToolBindings, ToolEffect, ToolEnforcement, ToolExecution, ToolIdempotencyBinding, ToolResourceBinding, ToolSpendBinding, WiringImport, WiringPlacement, WiringRecipe, WiringSnippet, Workspace, WorkspaceCapability, WorkspaceTool, } from "./types"; |
+151
-1
@@ -506,2 +506,75 @@ // @bun | ||
| }); | ||
| var productId = Type.String({ pattern: "^[a-z][a-z0-9_-]{0,63}$" }); | ||
| var productCopy = { | ||
| description: Type.String({ minLength: 1 }), | ||
| id: productId, | ||
| title: Type.String({ minLength: 1 }) | ||
| }; | ||
| var productOperation = Type.Union([ | ||
| Type.Literal("aggregate"), | ||
| Type.Literal("create"), | ||
| Type.Literal("delete"), | ||
| Type.Literal("detail"), | ||
| Type.Literal("list"), | ||
| Type.Literal("update") | ||
| ]); | ||
| var productProjection = Type.Object({ | ||
| blocks: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| category: Type.String({ minLength: 1 }), | ||
| componentExport: Type.String({ minLength: 1 }), | ||
| frameworks: Type.Optional(Type.Array(Type.Union(clientFrameworks.map((framework) => Type.Literal(framework))))), | ||
| props: jsonSchemaObject | ||
| }))), | ||
| connections: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| envKeys: Type.Optional(Type.Array(Type.String({ minLength: 1 }))), | ||
| kind: Type.Union([ | ||
| Type.Literal("none"), | ||
| Type.Literal("oauth"), | ||
| Type.Literal("secret") | ||
| ]), | ||
| setupTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })), | ||
| testTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })) | ||
| }))), | ||
| dataSources: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| operations: Type.Array(productOperation, { minItems: 1 }), | ||
| schema: jsonSchemaObject, | ||
| tools: Type.Optional(Type.Partial(Type.Object({ | ||
| aggregate: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| create: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| delete: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| detail: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| list: Type.String({ pattern: TOOL_NAME_PATTERN.source }), | ||
| update: Type.String({ pattern: TOOL_NAME_PATTERN.source }) | ||
| }))) | ||
| }))), | ||
| events: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| schema: jsonSchemaObject, | ||
| source: Type.Union([ | ||
| Type.Literal("data"), | ||
| Type.Literal("package"), | ||
| Type.Literal("ui"), | ||
| Type.Literal("webhook") | ||
| ]) | ||
| }))), | ||
| healthChecks: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| tool: Type.String({ pattern: TOOL_NAME_PATTERN.source }) | ||
| }))), | ||
| releaseChecks: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| healthCheckIds: Type.Optional(Type.Array(productId)), | ||
| severity: Type.Union([ | ||
| Type.Literal("blocking"), | ||
| Type.Literal("warning") | ||
| ]) | ||
| }))), | ||
| workflowActions: Type.Optional(Type.Array(Type.Object({ | ||
| ...productCopy, | ||
| tool: Type.String({ pattern: TOOL_NAME_PATTERN.source }) | ||
| }))) | ||
| }); | ||
| var manifestSchema = Type.Object({ | ||
@@ -547,2 +620,3 @@ contract: Type.Union([Type.Literal(1), Type.Literal(2)]), | ||
| }))), | ||
| product: Type.Optional(productProjection), | ||
| requires: Type.Optional(manifestRequirements), | ||
@@ -603,2 +677,75 @@ settings: jsonSchemaObject, | ||
| }; | ||
| var duplicateProductId = (product) => [ | ||
| ["blocks", product.blocks ?? []], | ||
| ["connections", product.connections ?? []], | ||
| ["dataSources", product.dataSources ?? []], | ||
| ["events", product.events ?? []], | ||
| ["healthChecks", product.healthChecks ?? []], | ||
| ["releaseChecks", product.releaseChecks ?? []], | ||
| ["workflowActions", product.workflowActions ?? []] | ||
| ].map(([group, entries]) => { | ||
| const ids = new Set; | ||
| const duplicate = entries.find((entry) => { | ||
| if (ids.has(entry.id)) | ||
| return true; | ||
| ids.add(entry.id); | ||
| return false; | ||
| }); | ||
| return duplicate ? `product.${group} contains duplicate id "${duplicate.id}"` : undefined; | ||
| }).find((failure) => failure !== undefined); | ||
| var connectionFailure = (manifest, connection, toolReference) => { | ||
| const setupFailure = toolReference(connection.setupTool, `product.connections "${connection.id}" setup`); | ||
| if (setupFailure) | ||
| return setupFailure; | ||
| const testFailure = toolReference(connection.testTool, `product.connections "${connection.id}" test`, true); | ||
| if (testFailure) | ||
| return testFailure; | ||
| const declaredEnv = new Set(manifest.requires?.env?.map((entry) => entry.key)); | ||
| const missingEnv = connection.envKeys?.find((key) => !declaredEnv.has(key)); | ||
| if (missingEnv) | ||
| return `product.connections "${connection.id}" references undeclared env key "${missingEnv}"`; | ||
| return; | ||
| }; | ||
| var productFailure = (manifest) => { | ||
| if (!manifest.product) | ||
| return; | ||
| if (manifest.contract !== 2) | ||
| return "product projections require manifest contract 2"; | ||
| const tools = manifest.tools ?? {}; | ||
| const toolReference = (reference, location, readOnly = false) => { | ||
| if (!reference) | ||
| return; | ||
| const tool = tools[reference]; | ||
| if (!tool) | ||
| return `${location} references missing tool "${reference}"`; | ||
| if (!tool.authorization) | ||
| return `${location} references legacy unguarded tool "${reference}"`; | ||
| if (readOnly && tool.authorization.effects.some((effect) => effect !== "read")) | ||
| return `${location} must reference a read-only tool`; | ||
| return; | ||
| }; | ||
| const duplicate = duplicateProductId(manifest.product); | ||
| if (duplicate) | ||
| return duplicate; | ||
| const actionFailure = (manifest.product.workflowActions ?? []).map((action) => toolReference(action.tool, `product.workflowActions "${action.id}"`)).find(Boolean); | ||
| if (actionFailure) | ||
| return actionFailure; | ||
| const sourceFailure = (manifest.product.dataSources ?? []).flatMap((source) => Object.entries(source.tools ?? {}).map(([operation, tool]) => toolReference(tool, `product.dataSources "${source.id}" operation "${operation}"`))).find(Boolean); | ||
| if (sourceFailure) | ||
| return sourceFailure; | ||
| const invalidConnection = (manifest.product.connections ?? []).map((connection) => connectionFailure(manifest, connection, toolReference)).find(Boolean); | ||
| if (invalidConnection) | ||
| return invalidConnection; | ||
| const healthIds = new Set(manifest.product.healthChecks?.map((check) => check.id)); | ||
| const healthFailure = (manifest.product.healthChecks ?? []).map((check) => toolReference(check.tool, `product.healthChecks "${check.id}"`, true)).find(Boolean); | ||
| if (healthFailure) | ||
| return healthFailure; | ||
| const releaseFailure = (manifest.product.releaseChecks ?? []).map((check) => { | ||
| const missingHealth = check.healthCheckIds?.find((id) => !healthIds.has(id)); | ||
| return missingHealth ? `product.releaseChecks "${check.id}" references missing health check "${missingHealth}"` : undefined; | ||
| }).find(Boolean); | ||
| if (releaseFailure) | ||
| return releaseFailure; | ||
| return; | ||
| }; | ||
| var validate = (candidate, source) => { | ||
@@ -612,2 +759,5 @@ if (!isManifestShaped(candidate)) | ||
| return invalid(invalidIntegration); | ||
| const invalidProduct = productFailure(candidate); | ||
| if (invalidProduct) | ||
| return invalid(invalidProduct); | ||
| if (candidate.contract === 1 && Object.values(candidate.tools ?? {}).some((tool) => tool.authorization !== undefined)) | ||
@@ -814,3 +964,3 @@ return invalid("tool authorization metadata requires manifest contract 2"); | ||
| //# debugId=39F6B9A4611BBF5A64756E2164756E21 | ||
| //# debugId=1664E7A82F58D7F564756E2164756E21 | ||
| //# sourceMappingURL=index.js.map |
+40
-0
@@ -80,2 +80,42 @@ import { type AnyPackageManifest } from "./types"; | ||
| }>>>; | ||
| product: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{ | ||
| blocks: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| category: import("@sinclair/typebox").TString; | ||
| componentExport: import("@sinclair/typebox").TString; | ||
| frameworks: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"angular" | "client" | "react" | "svelte" | "vue">[]>>>; | ||
| props: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>; | ||
| }>>>; | ||
| connections: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| envKeys: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>; | ||
| kind: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"none">, import("@sinclair/typebox").TLiteral<"oauth">, import("@sinclair/typebox").TLiteral<"secret">]>; | ||
| setupTool: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| testTool: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| }>>>; | ||
| dataSources: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| operations: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"aggregate">, import("@sinclair/typebox").TLiteral<"create">, import("@sinclair/typebox").TLiteral<"delete">, import("@sinclair/typebox").TLiteral<"detail">, import("@sinclair/typebox").TLiteral<"list">, import("@sinclair/typebox").TLiteral<"update">]>>; | ||
| schema: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>; | ||
| tools: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{ | ||
| aggregate: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| create: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| delete: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| detail: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| list: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| update: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>; | ||
| }>>; | ||
| }>>>; | ||
| events: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| schema: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>; | ||
| source: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"data">, import("@sinclair/typebox").TLiteral<"package">, import("@sinclair/typebox").TLiteral<"ui">, import("@sinclair/typebox").TLiteral<"webhook">]>; | ||
| }>>>; | ||
| healthChecks: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| tool: import("@sinclair/typebox").TString; | ||
| }>>>; | ||
| releaseChecks: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| healthCheckIds: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TString>>; | ||
| severity: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"blocking">, import("@sinclair/typebox").TLiteral<"warning">]>; | ||
| }>>>; | ||
| workflowActions: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ | ||
| tool: import("@sinclair/typebox").TString; | ||
| }>>>; | ||
| }>>; | ||
| requires: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{ | ||
@@ -82,0 +122,0 @@ env: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{ |
+74
-0
@@ -47,2 +47,75 @@ import type { Static, TSchema } from "@sinclair/typebox"; | ||
| }; | ||
| export type ManifestVisualBlock = { | ||
| /** Stable package-local id used by application-model bindings. */ | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| category: string; | ||
| /** Serializable component props; secret values are never valid block props. */ | ||
| props: TSchema; | ||
| frameworks?: ReadonlyArray<ClientFramework>; | ||
| /** Exported component or host-resolved block identifier, never source code. */ | ||
| componentExport: string; | ||
| }; | ||
| export type ManifestDataSource = { | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| schema: TSchema; | ||
| operations: ReadonlyArray<"aggregate" | "create" | "delete" | "detail" | "list" | "update">; | ||
| /** operation → guarded manifest tool name */ | ||
| tools?: Partial<Record<"aggregate" | "create" | "delete" | "detail" | "list" | "update", string>>; | ||
| }; | ||
| export type ManifestWorkflowAction = { | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| /** Guarded manifest tool invoked by the workflow runtime. */ | ||
| tool: string; | ||
| }; | ||
| export type ManifestEventBinding = { | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| schema: TSchema; | ||
| source: "data" | "package" | "ui" | "webhook"; | ||
| }; | ||
| export type ManifestConnection = { | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| kind: "none" | "oauth" | "secret"; | ||
| /** References keys declared in requires.env; values never enter a manifest. */ | ||
| envKeys?: ReadonlyArray<string>; | ||
| setupTool?: string; | ||
| testTool?: string; | ||
| }; | ||
| export type ManifestHealthCheck = { | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| /** A guarded read-only manifest tool. */ | ||
| tool: string; | ||
| }; | ||
| export type ManifestReleaseCheck = { | ||
| id: string; | ||
| title: string; | ||
| description: string; | ||
| severity: "blocking" | "warning"; | ||
| healthCheckIds?: ReadonlyArray<string>; | ||
| }; | ||
| /** | ||
| * The customer-facing projection a no-code host may add to its shared | ||
| * application model. Projections only reference existing guarded tools and | ||
| * requirements; they cannot broaden package authority. | ||
| */ | ||
| export type ManifestProductProjection = { | ||
| blocks?: ReadonlyArray<ManifestVisualBlock>; | ||
| dataSources?: ReadonlyArray<ManifestDataSource>; | ||
| workflowActions?: ReadonlyArray<ManifestWorkflowAction>; | ||
| events?: ReadonlyArray<ManifestEventBinding>; | ||
| connections?: ReadonlyArray<ManifestConnection>; | ||
| healthChecks?: ReadonlyArray<ManifestHealthCheck>; | ||
| releaseChecks?: ReadonlyArray<ManifestReleaseCheck>; | ||
| }; | ||
| export type EnvRequirement = { | ||
@@ -291,2 +364,3 @@ /** 'GOOGLE_CLIENT_SECRET' */ | ||
| integration?: ManifestIntegration; | ||
| product?: ManifestProductProjection; | ||
| discovery?: ManifestDiscovery; | ||
@@ -293,0 +367,0 @@ requires?: ManifestRequirements; |
+1
-1
| { | ||
| "name": "@absolutejs/manifest", | ||
| "version": "0.7.3", | ||
| "version": "0.8.0", | ||
| "description": "The AbsoluteJS package manifest contract. Every @absolutejs/* package exports a typed manifest (settings schema, env requirements, adapter slots, wiring recipes, AI tools) from its ./manifest subpath; this package is the contract those manifests are written against, plus bridges that turn any manifest into an AI tool map or a remote MCP tool registry.", | ||
@@ -5,0 +5,0 @@ "repository": { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
365219
16.18%2852
17.08%