From 40c99a6ade3f138625e7373837ca3eeaf001212b Mon Sep 17 00:00:00 2001 From: Scott Prutton Date: Sun, 19 Jan 2025 14:22:51 -0500 Subject: [PATCH] feat: sifuncs, resource_values, patchs, and input --- .../src/commands/generateSiSpecDatabase.ts | 182 +++++++++++++++--- bin/si-gen-cloud-control/src/spec/props.ts | 47 +++-- bin/si-gen-cloud-control/src/spec/siFuncs.ts | 105 ++++++++++ bin/si-gen-cloud-control/src/spec/sockets.ts | 56 +++++- bin/si-gen-cloud-control/test/spec_test.ts | 32 ++- deno.lock | 61 +++++- 6 files changed, 427 insertions(+), 56 deletions(-) create mode 100644 bin/si-gen-cloud-control/src/spec/siFuncs.ts diff --git a/bin/si-gen-cloud-control/src/commands/generateSiSpecDatabase.ts b/bin/si-gen-cloud-control/src/commands/generateSiSpecDatabase.ts index feea683169..485db768b2 100644 --- a/bin/si-gen-cloud-control/src/commands/generateSiSpecDatabase.ts +++ b/bin/si-gen-cloud-control/src/commands/generateSiSpecDatabase.ts @@ -1,7 +1,13 @@ -import { CfSchema, getServiceByName, loadCfDatabase } from "../cfDb.ts"; +import { + CfProperty, + CfSchema, + getServiceByName, + loadCfDatabase, +} from "../cfDb.ts"; import { createDefaultProp, createProp, + ExpandedPropSpec, isExpandedPropSpec, OnlyProperties, } from "../spec/props.ts"; @@ -13,7 +19,13 @@ import { PropSpec } from "../bindings/PropSpec.ts"; import { FuncSpec } from "../bindings/FuncSpec.ts"; import type { FuncSpecData } from "../bindings/FuncSpecData.ts"; import { SocketSpec } from "../bindings/SocketSpec.ts"; -import { createSocketFromProp } from "../spec/sockets.ts"; +import { + attrFuncInputSpecFromProp, + createSocketFromProp, +} from "../spec/sockets.ts"; +import { createSiFunc, getSiFuncId } from "../spec/siFuncs.ts"; +import { DefaultPropType } from "../spec/props.ts"; +import { FuncArgumentSpec } from "../bindings/FuncArgumentSpec.ts"; function pkgSpecFromCf(src: CfSchema): PkgSpec { const [aws, category, name] = src.typeName.split("::"); @@ -27,20 +39,32 @@ function pkgSpecFromCf(src: CfSchema): PkgSpec { const variantUniqueKey = ulid(); const assetFuncUniqueKey = ulid(); const schemaUniqueKey = ulid(); + const version = versionFromDate(); + + const onlyProperties: OnlyProperties = { + createOnly: normalizeOnlyProperties(src.createOnlyProperties), + readOnly: normalizeOnlyProperties(src.readOnlyProperties), + writeOnly: normalizeOnlyProperties(src.writeOnlyProperties), + }; - const domain: PropSpec = createDomainFromSrc(src); + const domain: PropSpec = createDomainFromSrc(src, onlyProperties); + const resourceValue: PropSpec = createResourceValueFromSrc( + src, + onlyProperties, + ); + createInputsInDomainFromResource(domain, resourceValue); const sockets = createSocketsFromDomain(domain); const variant: SchemaVariantSpec = { - version: "", + version, data: { - version: "", + version, link: null, color: "#b64017", displayName: name, componentType: "component", funcUniqueId: assetFuncUniqueKey, - description: null, + description: src.description, }, uniqueId: variantUniqueKey, deleted: false, @@ -54,7 +78,7 @@ function pkgSpecFromCf(src: CfSchema): PkgSpec { domain, secrets: createDefaultProp("secrets"), secretDefinition: null, - resourceValue: createDefaultProp("resource"), + resourceValue, rootPropFuncs: [], }; // TODO do an autopsy of a spec from module index to fill these prop specs @@ -64,7 +88,7 @@ function pkgSpecFromCf(src: CfSchema): PkgSpec { data: { name: src.typeName, category: `AWS ${category}`, - categoryName: name, + categoryName: null, uiHidden: false, defaultSchemaVariant: variantUniqueKey, }, @@ -82,11 +106,8 @@ function pkgSpecFromCf(src: CfSchema): PkgSpec { description: null, handler: "main", codeBase64: btoa( - "function main() {\n" + - " const asset = new AssetBuilder();\n" + - " return asset.build();\n" + - "}", - ), + "function main() { const asset = new AssetBuilder();return asset.build();}", + ).replace(/=/g, ""), backendKind: "jsSchemaVariantDefinition", responseType: "schemaVariantDefinition", hidden: false, @@ -105,7 +126,7 @@ function pkgSpecFromCf(src: CfSchema): PkgSpec { return { kind: "module", name: src.typeName, - version: "", + version, description: src.description, createdAt: new Date().toISOString(), createdBy: "Cagador", // TODO Figure out a better name @@ -113,11 +134,17 @@ function pkgSpecFromCf(src: CfSchema): PkgSpec { workspacePk: null, workspaceName: null, schemas: [schema], - funcs: [assetFunc], + funcs: [assetFunc].concat(createSiFuncs()).concat( + createResourcePayloadToValue(), + ), changeSets: [], // always empty }; } +function versionFromDate(): string { + return new Date().toISOString().replace(/[-:T.Z]/g, "").slice(0, 14); +} + export function generateSiSpecForService(serviceName: string) { const cf = getServiceByName(serviceName); return pkgSpecFromCf(cf); @@ -145,23 +172,54 @@ export async function generateSiSpecDatabase() { function createDomainFromSrc( src: CfSchema, + onlyProperties: OnlyProperties, ): PropSpec { - const onlyProperties: OnlyProperties = { - "createOnly": normalizeOnlyProperties(src.createOnlyProperties), - "readOnly": normalizeOnlyProperties(src.readOnlyProperties), - "writeOnly": normalizeOnlyProperties(src.writeOnlyProperties), - }; + return createRootFromProperties("domain", src.properties, onlyProperties); +} + +function createResourceValueFromSrc( + src: CfSchema, + onlyProperties: OnlyProperties, +): PropSpec { + return createRootFromProperties( + "resource_value", + pruneResourceValues(src.properties, onlyProperties), + onlyProperties, + ); +} - const domain: PropSpec = createDefaultProp("domain"); - Object.entries(src.properties).forEach(([name, cfData]) => { +function createRootFromProperties( + root_name: DefaultPropType, + properties: Record, + onlyProperties: OnlyProperties, +): PropSpec { + const root: ExpandedPropSpec = createDefaultProp(root_name); + Object.entries(properties).forEach(([name, cfData]) => { try { - domain.entries.push(createProp(name, cfData, onlyProperties)); + root.entries.push( + createProp(name, cfData, onlyProperties, [...root.metadata.propPath]), + ); } catch (e) { console.log(`Err ${e}`); } }); - return domain; + return root; +} + +function pruneResourceValues( + properties: Record, + onlyProperties: OnlyProperties, +): Record { + if (!properties || !onlyProperties?.readOnly) { + return {}; + } + + const readOnlySet = new Set(onlyProperties.readOnly); + return Object.fromEntries( + Object.entries(properties) + .filter(([name]) => readOnlySet.has(name)), + ); } function normalizeOnlyProperties(props: string[] | undefined): string[] { @@ -175,6 +233,25 @@ function normalizeOnlyProperties(props: string[] | undefined): string[] { return newProps; } +function createInputsInDomainFromResource( + domain: PropSpec, + resource: PropSpec, +) { + if (resource.kind === "object" && domain.kind === "object") { + resource.entries.forEach((resource: PropSpec) => { + const domainProp = domain.entries.find((d: PropSpec) => + d.name === resource.name + ); + if (domainProp?.data?.inputs) { + domainProp.data.funcUniqueId = getSiFuncId("si:identity"); + domainProp.data.inputs.push( + attrFuncInputSpecFromProp(resource as ExpandedPropSpec), + ); + } + }); + } +} + function createSocketsFromDomain(domain: PropSpec): SocketSpec[] { const sockets: SocketSpec[] = []; if (domain.kind == "object") { @@ -191,3 +268,60 @@ function createSocketsFromDomain(domain: PropSpec): SocketSpec[] { } return sockets; } + +function createResourcePayloadToValue(): FuncSpec[] { + const name = "si:resourcePayloadToValue"; + const data: FuncSpecData = { + name, + displayName: name, + description: null, + handler: "main", + codeBase64: + "YXN5bmMgZnVuY3Rpb24gbWFpbihhcmc6IElucHV0KTogUHJvbWlzZSA8IE91dHB1dCA+IHsKICAgIHJldHVybiBhcmcucGF5bG9hZCA/PyB7fTsKfQ", + backendKind: "jsAttribute", + responseType: "object", + hidden: false, + link: null, + }; + + const args: FuncArgumentSpec = { + name: "payload", + kind: "object", + elementKind: null, + uniqueId: ulid(), + deleted: false, + }; + + const func: FuncSpec = { + name, + uniqueId: ulid(), + data, + deleted: false, + isFromBuiltin: null, + arguments: [args], + }; + + return [func]; +} + +function createSiFuncs(): FuncSpec[] { + const ret: FuncSpec[] = []; + const siFuncs = [ + "si:identity", + "si:setArray", + "si:setBoolean", + "si:setInteger", + "si:setJson", + "si:setMap", + "si:setObject", + "si:setString", + "si:unset", + "si:validation", + ]; + + for (const func of siFuncs) { + ret.push(createSiFunc(func)); + } + + return ret; +} diff --git a/bin/si-gen-cloud-control/src/spec/props.ts b/bin/si-gen-cloud-control/src/spec/props.ts index a2a0feee62..98e4a42d4d 100644 --- a/bin/si-gen-cloud-control/src/spec/props.ts +++ b/bin/si-gen-cloud-control/src/spec/props.ts @@ -8,9 +8,9 @@ import { PropSpec } from "../bindings/PropSpec.ts"; import { PropSpecData } from "../bindings/PropSpecData.ts"; export type OnlyProperties = { - "createOnly": string[]; - "readOnly": string[]; - "writeOnly": string[]; + createOnly: string[]; + readOnly: string[]; + writeOnly: string[]; }; export function isExpandedPropSpec(prop: PropSpec): prop is ExpandedPropSpec { @@ -23,10 +23,11 @@ export function isExpandedPropSpec(prop: PropSpec): prop is ExpandedPropSpec { export type ExpandedPropSpec = & ({ - "metadata": { - "createOnly": boolean; - "readOnly": boolean; - "writeOnly": boolean; + metadata: { + createOnly?: boolean; + readOnly?: boolean; + writeOnly?: boolean; + propPath: string[]; }; }) & PropSpec; @@ -41,6 +42,7 @@ export function createProp( name: string, cfProp: CfProperty, onlyProperties: OnlyProperties, + propPath: string[], ) { const queue: CreatePropQueue = [ { @@ -56,7 +58,13 @@ export function createProp( const data = queue.shift(); if (!data) break; - const prop = createPropInner(data.name, data.cfProp, onlyProperties, queue); + const prop = createPropInner( + data.name, + data.cfProp, + onlyProperties, + propPath, + queue, + ); if (!data.addTo) { rootProp = prop; @@ -76,6 +84,7 @@ function createPropInner( name: string, cfProp: CfProperty, onlyProperties: OnlyProperties, + propPath: string[], queue: CreatePropQueue, ): ExpandedPropSpec { const propUniqueId = ulid(); @@ -84,7 +93,7 @@ function createPropInner( validationFormat: null, defaultValue: null, funcUniqueId: null, - inputs: null, + inputs: [], widgetKind: null, widgetOptions: null, hidden: false, @@ -92,14 +101,16 @@ function createPropInner( documentation: null, }; + propPath.push(name); const partialProp: unknown = { name, data, uniqueId: propUniqueId, metadata: { - "createOnly": onlyProperties.createOnly.includes(name), - "readOnly": onlyProperties.readOnly.includes(name), - "writeOnly": onlyProperties.writeOnly.includes(name), + createOnly: onlyProperties.createOnly.includes(name), + readOnly: onlyProperties.readOnly.includes(name), + writeOnly: onlyProperties.writeOnly.includes(name), + propPath, }, }; @@ -112,6 +123,7 @@ function createPropInner( const prop = partialProp as Extract; prop.kind = "number"; prop.data!.widgetKind = "Text"; + return prop; } else if (normalizedCfData.type === "boolean") { const prop = partialProp as Extract; @@ -190,11 +202,11 @@ function createPropInner( throw new Error("no matching kind"); } -type DefaultPropType = "domain" | "secrets" | "resource"; +export type DefaultPropType = "domain" | "secrets" | "resource_value"; export function createDefaultProp( type: DefaultPropType, -): Extract { +): Extract { const data: PropSpecData = { name: type, validationFormat: null, @@ -208,11 +220,16 @@ export function createDefaultProp( documentation: null, }; - return { + const prop: ExpandedPropSpec = { kind: "object", data, name: type, entries: [], uniqueId: ulid(), + metadata: { + propPath: ["root", type], + }, }; + + return prop; } diff --git a/bin/si-gen-cloud-control/src/spec/siFuncs.ts b/bin/si-gen-cloud-control/src/spec/siFuncs.ts new file mode 100644 index 0000000000..5d9bcf7f66 --- /dev/null +++ b/bin/si-gen-cloud-control/src/spec/siFuncs.ts @@ -0,0 +1,105 @@ +import { FuncSpec } from "../bindings/FuncSpec.ts"; +import { FuncSpecData } from "../bindings/FuncSpecData.ts"; +import { FuncSpecBackendKind } from "../bindings/FuncSpecBackendKind.ts"; +import { FuncSpecBackendResponseType } from "../bindings/FuncSpecBackendResponseType.ts"; +import { FuncArgumentSpec } from "../bindings/FuncArgumentSpec.ts"; +import { FuncArgumentKind } from "../bindings/FuncArgumentKind.ts"; + +interface FuncSpecInfo { + id: string; + kind: string; +} + +const funcSpecs: Record = { + "si:identity": { + id: "c6938e12287ab65f8ba8234559178413f2e2c02c44ea08384ed6687a36ec4f50", + kind: "identity", + }, + "si:setArray": { + id: "51049a590fb64860f159972012ac2657c629479a244d6bcc4b1b73ba4b29f87f", + kind: "array", + }, + "si:setBoolean": { + id: "577a7deea25cfad0d4b2dd1e1f3d96b86b8b1578605137b8c4128d644c86964b", + kind: "boolean", + }, + "si:setInteger": { + id: "7d384b237852f20b8dec2fbd2e644ffc6bde901d7dc937bd77f50a0d57e642a9", + kind: "integer", + }, + "si:setJson": { + id: "c48ahif4739799f3ab84bcb88495f93b27b47c31a341f8005a60ca39308909fd", + kind: "json", + }, + "si:setMap": { + id: "dea5084fbf6e7fe8328ac725852b96f4b5869b14d0fe9dd63a285fa876772496", + kind: "map", + }, + "si:setObject": { + id: "cb9bf94739799f3a8b84bcb88495f93b27b47c31a341f8005a60ca39308909fd", + kind: "object", + }, + "si:setString": { + id: "bbe86d1a2b92c3e34b72a407cca424878d3466d29ca60e56a251a52a0840bfbd", + kind: "string", + }, + "si:unset": { + id: "8143ff98fbe8954bb3ab89ee521335d45ba9a42b7b79289eff53b503c4392c37", + kind: "unset", + }, + "si:validation": { + id: "039ff70bc7922338978ab52a39156992b7d8e3390f0ef7e99d5b6ffd43141d8a", + kind: "validation", + }, +}; + +function createArgument(funcName: string, kind: string): FuncArgumentSpec[] { + if (kind === "unset") { + return []; + } + + const arg: FuncArgumentSpec = { + // For the identity function, use "identity" as the argument name + name: funcName === "si:identity" ? "identity" : "value", + // For identity and validation functions, use "any" as the kind + kind: (funcName === "si:identity" || funcName === "si:validation") + ? "any" + : kind as FuncArgumentKind, + elementKind: (kind === "array" || kind === "map") ? "any" : null, + uniqueId: null, + deleted: false, + }; + + return [arg]; +} +export function createSiFunc(name: string): FuncSpec { + const func = funcSpecs[name]; + if (!func) { + throw new Error(`Unknown function: ${name}`); + } + + const data: FuncSpecData = { + name, + displayName: null, + description: null, + handler: "", + codeBase64: "", + backendKind: func.kind as FuncSpecBackendKind, + responseType: func.kind as FuncSpecBackendResponseType, + hidden: false, + link: null, + }; + + return { + name, + uniqueId: func.id, + data, + deleted: false, + isFromBuiltin: null, + arguments: createArgument(name, func.kind), + }; +} + +export function getSiFuncId(kind: string): string { + return funcSpecs[kind].id; +} diff --git a/bin/si-gen-cloud-control/src/spec/sockets.ts b/bin/si-gen-cloud-control/src/spec/sockets.ts index 52acca7445..59fd5f27ae 100644 --- a/bin/si-gen-cloud-control/src/spec/sockets.ts +++ b/bin/si-gen-cloud-control/src/spec/sockets.ts @@ -1,15 +1,30 @@ import { ulid } from "https://deno.land/x/ulid@v0.3.0/mod.ts"; +import { AttrFuncInputSpec } from "../bindings/AttrFuncInputSpec.ts"; import { SocketSpec } from "../bindings/SocketSpec.ts"; +import { SocketSpecArity } from "../bindings/SocketSpecArity.ts"; import { SocketSpecKind } from "../bindings/SocketSpecKind.ts"; import { ExpandedPropSpec } from "./props.ts"; +import { getSiFuncId } from "./siFuncs.ts"; + +export const SI_SEPARATOR = "\u{b}"; export function createSocketFromProp( prop: ExpandedPropSpec, ): SocketSpec | null { if (prop.metadata.readOnly) { - return createSocket(prop.name, "output"); - } else if (prop.metadata.writeOnly || prop.metadata.readOnly) { - return createSocket(prop.name, "input"); + const socket = createSocket(prop.name, "output"); + if (socket.data) { + socket.data.funcUniqueId = getSiFuncId("si:identity"); + socket.inputs.push(attrFuncInputSpecFromProp(prop)); + } + return socket; + } else if (prop.metadata.writeOnly || prop.metadata.createOnly) { + const socket = createSocket(prop.name, "input"); + if (socket.data) { + prop?.data?.inputs?.push(attrFuncInputSpecFromSocket(socket)); + socket.data.funcUniqueId = getSiFuncId("si:identity"); + } + return socket; } return null; @@ -19,11 +34,11 @@ function createSocket(name: string, kind: SocketSpecKind): SocketSpec { const socketId = ulid(); const data = { - funcUniqueId: "", + funcUniqueId: null, kind, name, - connectionAnnotations: JSON.stringify([name]), - arity: "many", + connectionAnnotations: JSON.stringify([{ "tokens": [name] }]), + arity: "many" as SocketSpecArity, uiHidden: false, }; @@ -36,3 +51,32 @@ function createSocket(name: string, kind: SocketSpecKind): SocketSpec { return socket; } + +export function attrFuncInputSpecFromProp( + prop: ExpandedPropSpec, +): AttrFuncInputSpec { + const prop_path = prop.metadata.propPath.join(SI_SEPARATOR); + const attr: AttrFuncInputSpec = { + kind: "prop", + name: "identity", + prop_path, + unique_id: ulid(), + deleted: false, + }; + + return attr; +} + +export function attrFuncInputSpecFromSocket( + socket: SocketSpec, +): AttrFuncInputSpec { + const attr: AttrFuncInputSpec = { + kind: "inputSocket", + name: "identity", + socket_name: socket.name, + unique_id: ulid(), + deleted: false, + }; + + return attr; +} diff --git a/bin/si-gen-cloud-control/test/spec_test.ts b/bin/si-gen-cloud-control/test/spec_test.ts index 714c3e4cc4..b98b2d0176 100644 --- a/bin/si-gen-cloud-control/test/spec_test.ts +++ b/bin/si-gen-cloud-control/test/spec_test.ts @@ -8,7 +8,16 @@ import { import { generateSiSpecForService, } from "../src/commands/generateSiSpecDatabase.ts"; -import { PropSpec } from "../../../lib/si-pkg/bindings/PropSpec.ts"; +import { ExpandedPropSpec } from "../src/spec/props.ts"; + +const SET_BOOLEAN = + "577a7deea25cfad0d4b2dd1e1f3d96b86b8b1578605137b8c4128d644c86964b"; +const SET_INTEGER = + "7d384b237852f20b8dec2fbd2e644ffc6bde901d7dc937bd77f50a0d57e642a9"; +const SET_MAP = + "dea5084fbf6e7fe8328ac725852b96f4b5869b14d0fe9dd63a285fa876772496"; +const SET_OBJECT = + "cb9bf94739799f3a8b84bcb88495f93b27b47c31a341f8005a60ca39308909fd"; Deno.test(function generateServiceByName() { // Throws if the service does not exist @@ -22,37 +31,44 @@ Deno.test(function generateServiceByName() { assertInstanceOf(goodResult.schemas[0].variants, Array); assertEquals(goodResult.schemas[0].variants.length, 1); - const variant = goodResult.schemas[0].variants[0]; - assertInstanceOf(variant.domain, Object); - validateProps(variant.domain); + const domain = goodResult.schemas[0].variants[0].domain as ExpandedPropSpec; + assertInstanceOf(domain, Object); + assertInstanceOf(domain.metadata.propPath, Array); + assertEquals(domain.metadata.propPath, ["root", "domain"]); }); -function validateProps(prop: PropSpec) { +function validateProps(prop: ExpandedPropSpec) { switch (prop.kind) { case "boolean": assertEquals(prop.data?.widgetKind, "Checkbox"); + assertEquals(prop.data?.funcUniqueId, SET_BOOLEAN); break; case "number": case "string": assertEquals(prop.data?.widgetKind, "Text"); + assertEquals(prop.data?.funcUniqueId, SET_INTEGER); break; case "json": break; case "array": assertEquals(prop.data?.widgetKind, "Array"); assertExists(prop.typeProp); - validateProps(prop.typeProp); + validateProps(prop.typeProp as ExpandedPropSpec); break; case "map": assertEquals(prop.data?.widgetKind, "Map"); + assertEquals(prop.data?.funcUniqueId, SET_MAP); assertExists(prop.typeProp); - validateProps(prop.typeProp); + validateProps(prop.typeProp as ExpandedPropSpec); break; case "object": assertEquals(prop.data?.widgetKind, "Header"); + if (prop.name !== "domain") { + assertEquals(prop.data?.funcUniqueId, SET_OBJECT); + } assertExists(prop.entries); Object.values(prop.entries).forEach((entry) => { - validateProps(entry); + validateProps(entry as ExpandedPropSpec); }); break; default: diff --git a/deno.lock b/deno.lock index bbf2661173..1dfef1ffa6 100644 --- a/deno.lock +++ b/deno.lock @@ -10,13 +10,17 @@ "jsr:@deno/emit@0.46": "0.46.0", "jsr:@deno/graph@~0.73.1": "0.73.1", "jsr:@std/assert@0.223": "0.223.0", + "jsr:@std/assert@1": "1.0.10", "jsr:@std/bytes@0.223": "0.223.0", "jsr:@std/fmt@0.223": "0.223.0", "jsr:@std/fmt@~1.0.2": "1.0.3", "jsr:@std/fs@0.223": "0.223.0", + "jsr:@std/internal@^1.0.5": "1.0.5", "jsr:@std/io@0.223": "0.223.0", "jsr:@std/path@0.223": "0.223.0", "jsr:@std/text@~1.0.7": "1.0.9", + "npm:@apidevtools/json-schema-ref-parser@*": "11.7.3", + "npm:@apidevtools/json-schema-ref-parser@^11.7.3": "11.7.3", "npm:@types/debug@^4.1.7": "4.1.12", "npm:@types/jest@^27.4.1": "27.5.2", "npm:@types/js-yaml@^4.0.5": "4.0.9", @@ -25,6 +29,8 @@ "npm:@types/node@*": "22.5.4", "npm:@types/node@^18.19.59": "18.19.67", "npm:@typescript/vfs@^1.4.0": "1.6.0_typescript@4.9.5", + "npm:adze@*": "2.2.0", + "npm:adze@^2.2.0": "2.2.0", "npm:eslint@^8.57.1": "8.57.1", "npm:execa@^5.1.1": "5.1.1", "npm:fast-json-patch@^3.1.1": "3.1.1", @@ -32,6 +38,7 @@ "npm:joi@^17.11.0": "17.13.3", "npm:js-yaml@*": "4.1.0", "npm:js-yaml@^4.1.0": "4.1.0", + "npm:json-schema-typed@^8.0.1": "8.0.1", "npm:lodash-es@*": "4.17.21", "npm:lodash-es@^4.17.21": "4.17.21", "npm:node-fetch@2": "2.7.0", @@ -92,6 +99,12 @@ "@std/assert@0.223.0": { "integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24" }, + "@std/assert@1.0.10": { + "integrity": "59b5cbac5bd55459a19045d95cc7c2ff787b4f8527c0dd195078ff6f9481fbb3", + "dependencies": [ + "jsr:@std/internal" + ] + }, "@std/bytes@0.223.0": { "integrity": "84b75052cd8680942c397c2631318772b295019098f40aac5c36cead4cba51a8" }, @@ -104,17 +117,20 @@ "@std/fs@0.223.0": { "integrity": "3b4b0550b2c524cbaaa5a9170c90e96cbb7354e837ad1bdaf15fc9df1ae9c31c" }, + "@std/internal@1.0.5": { + "integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba" + }, "@std/io@0.223.0": { "integrity": "2d8c3c2ab3a515619b90da2c6ff5ea7b75a94383259ef4d02116b228393f84f1", "dependencies": [ - "jsr:@std/assert", + "jsr:@std/assert@0.223", "jsr:@std/bytes" ] }, "@std/path@0.223.0": { "integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989", "dependencies": [ - "jsr:@std/assert" + "jsr:@std/assert@0.223" ] }, "@std/text@1.0.9": { @@ -122,6 +138,14 @@ } }, "npm": { + "@apidevtools/json-schema-ref-parser@11.7.3": { + "integrity": "sha512-WApSdLdXEBb/1FUPca2lteASewEfpjEYJ8oXZP+0gExK5qSfsEKBKcA+WjY6Q4wvXwyv0+W6Kvc372pSceib9w==", + "dependencies": [ + "@jsdevtools/ono", + "@types/json-schema", + "js-yaml" + ] + }, "@esbuild/aix-ppc64@0.21.5": { "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==" }, @@ -362,6 +386,9 @@ "@jridgewell/sourcemap-codec" ] }, + "@jsdevtools/ono@7.1.3": { + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" + }, "@nodelib/fs.scandir@2.1.5": { "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dependencies": [ @@ -512,6 +539,9 @@ "@types/js-yaml@4.0.9": { "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==" }, + "@types/json-schema@7.0.15": { + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, "@types/lodash-es@4.17.12": { "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "dependencies": [ @@ -616,6 +646,14 @@ "acorn@8.14.0": { "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" }, + "adze@2.2.0": { + "integrity": "sha512-6QsG6nJajn0Nb2obiCXrv2THuKuERcNwVcKtSp2lalC8/x2jJi0Dv43A/xUnOhLytP7fMNqEswPVt027gXtxpg==", + "dependencies": [ + "@ungap/structured-clone", + "date-fns", + "picocolors" + ] + }, "ajv@6.12.6": { "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": [ @@ -762,6 +800,9 @@ "which" ] }, + "date-fns@3.6.0": { + "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==" + }, "debug@4.3.7": { "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": [ @@ -1244,6 +1285,9 @@ "json-schema-traverse@0.4.1": { "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-schema-typed@8.0.1": { + "integrity": "sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==" + }, "json-stable-stringify-without-jsonify@1.0.1": { "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" }, @@ -2214,7 +2258,9 @@ "https://deno.land/std@0.224.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e", "https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c", "https://deno.land/std@0.224.0/testing/_test_suite.ts": "f10a8a6338b60c403f07a76f3f46bdc9f1e1a820c0a1decddeb2949f7a8a0546", - "https://deno.land/std@0.224.0/testing/bdd.ts": "3e4de4ff6d8f348b5574661cef9501b442046a59079e201b849d0e74120d476b" + "https://deno.land/std@0.224.0/testing/bdd.ts": "3e4de4ff6d8f348b5574661cef9501b442046a59079e201b849d0e74120d476b", + "https://deno.land/x/json_schema_typed@v8.0.0/draft_07.ts": "1d8a7c80be7b9dd80c583e471fdfec5be526a9b039d1753a9c0f9aa2e8da8be5", + "https://deno.land/x/ulid@v0.3.0/mod.ts": "f7ff065b66abd485051fc68af23becef6ccc7e81f7774d7fcfd894a4b2da1984" }, "workspace": { "dependencies": [ @@ -2251,6 +2297,15 @@ ] } }, + "bin/si-gen-cloud-control": { + "dependencies": [ + "jsr:@cliffy/command@^1.0.0-rc.7", + "jsr:@std/assert@1", + "npm:@apidevtools/json-schema-ref-parser@^11.7.3", + "npm:adze@^2.2.0", + "npm:json-schema-typed@^8.0.1" + ] + }, "lib/ts-lib-deno": { "packageJson": { "dependencies": [