diff --git a/.pnp.cjs b/.pnp.cjs index f036e2327..0c2d16467 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -6820,6 +6820,7 @@ const RAW_RUNTIME_STATE = ["@types/ws", "npm:8.5.5"],\ ["@typescript-eslint/eslint-plugin", "virtual:36b10b38a2f3e49d8cd162fbeda8e49e065ae2d0ebbbd25b0a3339d0203e0ec0394d852d27989cf9f4297d5cf181367ebbc4ea51690fe53337f9c0c2783178a4#npm:5.62.0"],\ ["@zilliz/milvus2-sdk-node", "npm:2.2.21"],\ + ["change-case", "npm:4.1.2"],\ ["emittery", "npm:1.0.1"],\ ["emittery-0-13", [\ "emittery",\ @@ -10799,6 +10800,18 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["capital-case", [\ + ["npm:1.0.4", {\ + "packageLocation": "./.yarn/cache/capital-case-npm-1.0.4-90f8a4641d-913c04c487.zip/node_modules/capital-case/",\ + "packageDependencies": [\ + ["capital-case", "npm:1.0.4"],\ + ["no-case", "npm:3.0.4"],\ + ["tslib", "npm:2.5.3"],\ + ["upper-case-first", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["ccount", [\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/ccount-npm-1.1.0-c87febc594-4fd7d15919.zip/node_modules/ccount/",\ @@ -10836,6 +10849,27 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["change-case", [\ + ["npm:4.1.2", {\ + "packageLocation": "./.yarn/cache/change-case-npm-4.1.2-9c42f72b39-7e6bc68c59.zip/node_modules/change-case/",\ + "packageDependencies": [\ + ["change-case", "npm:4.1.2"],\ + ["camel-case", "npm:4.1.2"],\ + ["capital-case", "npm:1.0.4"],\ + ["constant-case", "npm:3.0.4"],\ + ["dot-case", "npm:3.0.4"],\ + ["header-case", "npm:2.0.4"],\ + ["no-case", "npm:3.0.4"],\ + ["param-case", "npm:3.0.4"],\ + ["pascal-case", "npm:3.1.2"],\ + ["path-case", "npm:3.0.4"],\ + ["sentence-case", "npm:3.0.4"],\ + ["snake-case", "npm:3.0.4"],\ + ["tslib", "npm:2.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["character-entities", [\ ["npm:1.2.4", {\ "packageLocation": "./.yarn/cache/character-entities-npm-1.2.4-a5c359383c-9e13a6232e.zip/node_modules/character-entities/",\ @@ -11307,6 +11341,18 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["constant-case", [\ + ["npm:3.0.4", {\ + "packageLocation": "./.yarn/cache/constant-case-npm-3.0.4-118b472e28-2a4d10cc73.zip/node_modules/constant-case/",\ + "packageDependencies": [\ + ["constant-case", "npm:3.0.4"],\ + ["no-case", "npm:3.0.4"],\ + ["tslib", "npm:2.5.3"],\ + ["upper-case", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["content-disposition", [\ ["npm:0.5.2", {\ "packageLocation": "./.yarn/cache/content-disposition-npm-0.5.2-1f3e0caef2-c252b0daf9.zip/node_modules/content-disposition/",\ @@ -15023,6 +15069,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["header-case", [\ + ["npm:2.0.4", {\ + "packageLocation": "./.yarn/cache/header-case-npm-2.0.4-7d19e19e6d-401cbd5479.zip/node_modules/header-case/",\ + "packageDependencies": [\ + ["header-case", "npm:2.0.4"],\ + ["capital-case", "npm:1.0.4"],\ + ["tslib", "npm:2.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["history", [\ ["npm:4.10.1", {\ "packageLocation": "./.yarn/cache/history-npm-4.10.1-ee217563ae-44fc15ef05.zip/node_modules/history/",\ @@ -17949,6 +18006,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["path-case", [\ + ["npm:3.0.4", {\ + "packageLocation": "./.yarn/cache/path-case-npm-3.0.4-5a1981bc0c-b150b466fc.zip/node_modules/path-case/",\ + "packageDependencies": [\ + ["path-case", "npm:3.0.4"],\ + ["dot-case", "npm:3.0.4"],\ + ["tslib", "npm:2.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["path-exists", [\ ["npm:3.0.0", {\ "packageLocation": "./.yarn/cache/path-exists-npm-3.0.0-e80371aa68-6479d25601.zip/node_modules/path-exists/",\ @@ -20968,6 +21036,18 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["sentence-case", [\ + ["npm:3.0.4", {\ + "packageLocation": "./.yarn/cache/sentence-case-npm-3.0.4-ed6888d0bc-e98889c53a.zip/node_modules/sentence-case/",\ + "packageDependencies": [\ + ["sentence-case", "npm:3.0.4"],\ + ["no-case", "npm:3.0.4"],\ + ["tslib", "npm:2.5.3"],\ + ["upper-case-first", "npm:2.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["serialize-javascript", [\ ["npm:6.0.1", {\ "packageLocation": "./.yarn/cache/serialize-javascript-npm-6.0.1-fac87289ed-918ab48d61.zip/node_modules/serialize-javascript/",\ @@ -21237,6 +21317,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["snake-case", [\ + ["npm:3.0.4", {\ + "packageLocation": "./.yarn/cache/snake-case-npm-3.0.4-67f447c30d-b33d2573a0.zip/node_modules/snake-case/",\ + "packageDependencies": [\ + ["snake-case", "npm:3.0.4"],\ + ["dot-case", "npm:3.0.4"],\ + ["tslib", "npm:2.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["sockjs", [\ ["npm:0.3.24", {\ "packageLocation": "./.yarn/cache/sockjs-npm-0.3.24-ecb3909016-e3657d51f0.zip/node_modules/sockjs/",\ @@ -22676,6 +22767,26 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["upper-case", [\ + ["npm:2.0.2", {\ + "packageLocation": "./.yarn/cache/upper-case-npm-2.0.2-6cf3bda96c-6e63b06361.zip/node_modules/upper-case/",\ + "packageDependencies": [\ + ["upper-case", "npm:2.0.2"],\ + ["tslib", "npm:2.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["upper-case-first", [\ + ["npm:2.0.2", {\ + "packageLocation": "./.yarn/cache/upper-case-first-npm-2.0.2-8e0c5a851a-28c69870d2.zip/node_modules/upper-case-first/",\ + "packageDependencies": [\ + ["upper-case-first", "npm:2.0.2"],\ + ["tslib", "npm:2.5.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["uri-js", [\ ["npm:4.4.1", {\ "packageLocation": "./.yarn/cache/uri-js-npm-4.4.1-66d11cbcaf-284fedd1b1.zip/node_modules/uri-js/",\ diff --git a/.yarn/cache/capital-case-npm-1.0.4-90f8a4641d-913c04c487.zip b/.yarn/cache/capital-case-npm-1.0.4-90f8a4641d-913c04c487.zip new file mode 100644 index 000000000..a6494bceb Binary files /dev/null and b/.yarn/cache/capital-case-npm-1.0.4-90f8a4641d-913c04c487.zip differ diff --git a/.yarn/cache/change-case-npm-4.1.2-9c42f72b39-7e6bc68c59.zip b/.yarn/cache/change-case-npm-4.1.2-9c42f72b39-7e6bc68c59.zip new file mode 100644 index 000000000..37623c7c0 Binary files /dev/null and b/.yarn/cache/change-case-npm-4.1.2-9c42f72b39-7e6bc68c59.zip differ diff --git a/.yarn/cache/constant-case-npm-3.0.4-118b472e28-2a4d10cc73.zip b/.yarn/cache/constant-case-npm-3.0.4-118b472e28-2a4d10cc73.zip new file mode 100644 index 000000000..4e53f66dc Binary files /dev/null and b/.yarn/cache/constant-case-npm-3.0.4-118b472e28-2a4d10cc73.zip differ diff --git a/.yarn/cache/header-case-npm-2.0.4-7d19e19e6d-401cbd5479.zip b/.yarn/cache/header-case-npm-2.0.4-7d19e19e6d-401cbd5479.zip new file mode 100644 index 000000000..ccdc900d7 Binary files /dev/null and b/.yarn/cache/header-case-npm-2.0.4-7d19e19e6d-401cbd5479.zip differ diff --git a/.yarn/cache/path-case-npm-3.0.4-5a1981bc0c-b150b466fc.zip b/.yarn/cache/path-case-npm-3.0.4-5a1981bc0c-b150b466fc.zip new file mode 100644 index 000000000..7bb83488b Binary files /dev/null and b/.yarn/cache/path-case-npm-3.0.4-5a1981bc0c-b150b466fc.zip differ diff --git a/.yarn/cache/sentence-case-npm-3.0.4-ed6888d0bc-e98889c53a.zip b/.yarn/cache/sentence-case-npm-3.0.4-ed6888d0bc-e98889c53a.zip new file mode 100644 index 000000000..609c5d315 Binary files /dev/null and b/.yarn/cache/sentence-case-npm-3.0.4-ed6888d0bc-e98889c53a.zip differ diff --git a/.yarn/cache/snake-case-npm-3.0.4-67f447c30d-b33d2573a0.zip b/.yarn/cache/snake-case-npm-3.0.4-67f447c30d-b33d2573a0.zip new file mode 100644 index 000000000..96717ecc9 Binary files /dev/null and b/.yarn/cache/snake-case-npm-3.0.4-67f447c30d-b33d2573a0.zip differ diff --git a/.yarn/cache/upper-case-first-npm-2.0.2-8e0c5a851a-28c69870d2.zip b/.yarn/cache/upper-case-first-npm-2.0.2-8e0c5a851a-28c69870d2.zip new file mode 100644 index 000000000..27365c32d Binary files /dev/null and b/.yarn/cache/upper-case-first-npm-2.0.2-8e0c5a851a-28c69870d2.zip differ diff --git a/.yarn/cache/upper-case-npm-2.0.2-6cf3bda96c-6e63b06361.zip b/.yarn/cache/upper-case-npm-2.0.2-6cf3bda96c-6e63b06361.zip new file mode 100644 index 000000000..5a7e217e7 Binary files /dev/null and b/.yarn/cache/upper-case-npm-2.0.2-6cf3bda96c-6e63b06361.zip differ diff --git a/packages/node/package.json b/packages/node/package.json index b7eddb37b..f77e84e33 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -40,6 +40,7 @@ "dependencies": { "@ironclad/rivet-core": "workspace:^", "@zilliz/milvus2-sdk-node": "^2.2.21", + "change-case": "^4.1.2", "emittery": "^1.0.1", "emittery-0-13": "npm:emittery@^0.13.1", "lodash": "^4.17.21", diff --git a/packages/node/src/api.ts b/packages/node/src/api.ts index 904386da0..6a2a765f8 100644 --- a/packages/node/src/api.ts +++ b/packages/node/src/api.ts @@ -1,14 +1,25 @@ import { + ArrayDataValue, + BoolDataValue, DataValue, + DateDataValue, + DateTimeDataValue, ExternalFunction, GraphId, GraphProcessor, NativeApi, NodeRegistration, + NodeGraph, + NumberDataValue, + ObjectDataValue, + ProcessContext, ProcessEvents, Project, + ProjectId, Settings, StringPluginConfigurationSpec, + StringDataValue, + VectorDataValue, deserializeProject, globalRivetNodeRegistry, } from '@ironclad/rivet-core'; @@ -20,6 +31,80 @@ import { NodeNativeApi } from './native/NodeNativeApi.js'; import { mapValues } from 'lodash-es'; import { AttachedData } from '../../core/src/utils/serialization/serializationUtils.js'; +export type LoosedDataValue = T extends StringDataValue + ? StringDataValue | string + : T extends NumberDataValue + ? NumberDataValue | number + : T extends BoolDataValue + ? BoolDataValue | boolean + : T extends DateTimeDataValue + ? DateTimeDataValue | Date + : T extends ObjectDataValue + ? ObjectDataValue | Record + : T extends ArrayDataValue + ? ArrayDataValue | string[] + : T extends ArrayDataValue + ? ArrayDataValue | number[] + : T extends ArrayDataValue + ? ArrayDataValue | boolean[] + : T extends ArrayDataValue + ? ArrayDataValue | Date[] + : T extends ArrayDataValue + ? ArrayDataValue | Record[] + : DataValue; + +export function looseToDataValue(value: LoosedDataValue): DataValue { + if (typeof value === 'string') { + return { type: 'string', value }; + } + + if (typeof value === 'number') { + return { type: 'number', value }; + } + + if (typeof value === 'boolean') { + return { type: 'boolean', value }; + } + + if (value == null) { + return { type: 'any', value }; + } + + if ('type' in value && typeof value.type === 'string' && 'value' in value) { + return value as DataValue; + } + + if (value instanceof Date) { + return { type: 'datetime', value: value.toISOString() }; + } + + if (Array.isArray(value)) { + if (value.length === 0) { + return { type: 'any[]', value }; + } + + if (typeof value[0] === 'string') { + return { type: 'string[]', value: value as string[] }; + } + + if (typeof value[0] === 'number') { + return { type: 'number[]', value: value as number[] }; + } + + if (typeof value[0] === 'boolean') { + return { type: 'boolean[]', value: value as boolean[] }; + } + + if (value[0] instanceof Date) { + return { type: 'datetime[]', value: (value as Date[]).map((v) => v.toISOString()) }; + } + + return { type: 'any[]', value }; + } + + return { type: 'object', value }; +} + export async function loadProjectFromFile(path: string): Promise { const content = await readFile(path, { encoding: 'utf8' }); return loadProjectFromString(content); @@ -39,12 +124,13 @@ export function loadProjectAndAttachedDataFromString(content: string): [Project, return deserializeProject(content); } -export type LooseDataValue = DataValue | string | number | boolean; - -export type RunGraphOptions = { - graph: string; - inputs?: Record; - context?: Record; +export type RunGraphOptions< + Inputs extends {} = Record>, + GraphNameOrId extends string = string, +> = { + graph: GraphNameOrId; + inputs?: Inputs; + context?: Record>; remoteDebugger?: RivetDebuggerServer; nativeApi?: NativeApi; externalFunctions?: { @@ -64,19 +150,59 @@ export async function runGraphInFile(path: string, options: RunGraphOptions): Pr return runGraph(project, options); } -export function createProcessor(project: Project, options: RunGraphOptions) { - const { graph, inputs = {}, context = {}, registry } = options; +type TypedProject = { + metadata: { + id: string; + }; + graphs: {}; +}; + +type TypedGraphInfo = { + metadata: { + id: string; + name: string; + description: string; + }; + + inputs: object; + outputs: object; +}; + +type TypedOptions = Pick< + { + [P in keyof T['graphs']]: T['graphs'][P] extends TypedGraphInfo + ? RunGraphOptions + : RunGraphOptions; + }, + GraphName +>[GraphName]; + +type Outputs = Pick< + { + [P in keyof T['graphs']]: T['graphs'][P] extends TypedGraphInfo + ? T['graphs'][P]['outputs'] + : Record; + }, + GraphName +>[GraphName]; + +export function createProcessor( + project: T, + options: TypedOptions, +) { + const { graph, inputs = {}, context = {} } = options; + const asProject = project as unknown as Project; const graphId = graph in project.graphs ? graph - : Object.values(project.graphs).find((g) => g.metadata?.name === graph)?.metadata?.id; + : Object.values(asProject.graphs).find((g) => g.metadata?.name === graph)?.metadata?.id; if (!graphId) { throw new Error('Graph not found'); } - const processor = new GraphProcessor(project, graphId as GraphId, options.registry); + const processor = new GraphProcessor(asProject, graphId as GraphId, options.registry); if (options.remoteDebugger) { options.remoteDebugger.attach(processor); @@ -146,37 +272,8 @@ export function createProcessor(project: Project, options: RunGraphOptions) { processor.abort(); }); - const resolvedInputs: Record = mapValues(inputs, (value): DataValue => { - if (typeof value === 'string') { - return { type: 'string', value }; - } - - if (typeof value === 'number') { - return { type: 'number', value }; - } - - if (typeof value === 'boolean') { - return { type: 'boolean', value }; - } - - return value; - }); - - const resolvedContextValues: Record = mapValues(context, (value): DataValue => { - if (typeof value === 'string') { - return { type: 'string', value }; - } - - if (typeof value === 'number') { - return { type: 'number', value }; - } - - if (typeof value === 'boolean') { - return { type: 'boolean', value }; - } - - return value; - }); + const resolvedInputs: Record = mapValues(inputs, (value) => looseToDataValue(value as any)); + const resolvedContextValues: Record = mapValues(context, (value) => looseToDataValue(value)); let pluginEnv = options.pluginEnv; if (!pluginEnv) { @@ -204,7 +301,7 @@ export function createProcessor(project: Project, options: RunGraphOptions) { resolvedContextValues, ); - return outputs; + return outputs as Outputs; }, }; } diff --git a/packages/node/src/typeGeneration.ts b/packages/node/src/typeGeneration.ts new file mode 100644 index 000000000..45111f365 --- /dev/null +++ b/packages/node/src/typeGeneration.ts @@ -0,0 +1,244 @@ +import { + DataType, + GraphId, + GraphInputNode, + GraphOutputNode, + Nodes, + Project, + ScalarDataType, + getScalarTypeOf, + isArrayDataType, + isFunctionDataType, +} from '@ironclad/rivet-core'; +import ts from 'typescript'; +import { pascalCase } from 'change-case'; +import { loadProjectFromFile } from './api.js'; + +const dataValueTypeToDataValueName: Record = { + string: 'Rivet.StringDataValue', + number: 'Rivet.NumberDataValue', + object: 'Rivet.ObjectDataValue', + boolean: 'Rivet.BoolDataValue', + date: 'Rivet.DateDataValue', + any: 'Rivet.DataValue', + 'chat-message': 'Rivet.ChatMessageDataValue', + 'control-flow-excluded': 'Rivet.ControlFlowExcludedDataValue', + 'gpt-function': 'Rivet.GptFunctionDataValue', + datetime: 'Rivet.DateTimeDataValue', + time: 'Rivet.TimeDataValue', + vector: 'Rivet.VectorDataValue', +}; + +function createProjectInterface(project: Project) { + // Create a new TypeScript source file + const sourceFile = ts.createSourceFile('temp.ts', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS); + + // Create a printer to output the generated code + const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); + + // Create an array to hold the statements (interfaces) we'll add to the source file + const statements: ts.Statement[] = []; + + const graphTypes: ts.InterfaceDeclaration[] = []; + + let projectName = pascalCase(project.metadata?.title ?? 'Untitled Project').replace(/[^a-zA-Z0-9]/g, ''); + projectName = `Project_${projectName}`; + + // Iterate over the graphs in the project + for (const graphId in project.graphs) { + const graph = project.graphs[graphId as GraphId]!; + + let graphName = pascalCase(graph.metadata?.name ?? 'Untitled Graph').replace(/[^a-zA-Z0-9]/g, ''); + graphName = `Graph_${graphName}`; + + // Create property signatures for the inputs and outputs + const inputProperties: ts.PropertySignature[] = []; + const outputProperties: ts.PropertySignature[] = []; + + const inputNames = new Set(); + const outputNames = new Set(); + + // Iterate over nodes to find input and output nodes + for (const node of (graph.nodes as Nodes[]).filter( + (n): n is GraphInputNode | GraphOutputNode => n.type === 'graphInput' || n.type === 'graphOutput', + )) { + const { dataType } = node.data; + + let codeTypeName: string; + let codeTypeGeneric: ts.TypeNode | undefined; + if (isArrayDataType(dataType)) { + codeTypeName = 'Rivet.ArrayDataValue'; + codeTypeGeneric = ts.factory.createTypeReferenceNode( + dataValueTypeToDataValueName[getScalarTypeOf(dataType)], + undefined, + ); + } else if (isFunctionDataType(dataType)) { + codeTypeName = 'Rivet.FunctionDataValue'; + codeTypeGeneric = ts.factory.createTypeReferenceNode( + dataValueTypeToDataValueName[getScalarTypeOf(dataType)], + undefined, + ); + } else { + codeTypeName = dataValueTypeToDataValueName[dataType]; + } + + if (node.type === 'graphInput' && !inputNames.has(node.data.id)) { + inputProperties.push( + ts.factory.createPropertySignature( + undefined, + ts.factory.createStringLiteral(node.data.id), + undefined, + ts.factory.createTypeReferenceNode('Rivet.LoosedDataValue', [ + ts.factory.createTypeReferenceNode(codeTypeName, codeTypeGeneric ? [codeTypeGeneric] : undefined), + ]), + ), + ); + inputNames.add(node.data.id); + } else if (node.type === 'graphOutput' && !outputNames.has(node.data.id)) { + outputProperties.push( + ts.factory.createPropertySignature( + undefined, + node.data.id, + undefined, + ts.factory.createTypeReferenceNode(codeTypeName, codeTypeGeneric ? [codeTypeGeneric] : undefined), + ), + ); + outputNames.add(node.data.id); + } + } + + // Create the interfaces for the inputs and outputs + const inputInterface = ts.factory.createInterfaceDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + `${graphName}_Inputs`, + undefined, + undefined, + inputProperties, + ); + const outputInterface = ts.factory.createInterfaceDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + `${graphName}_Outputs`, + undefined, + undefined, + outputProperties, + ); + + // Add the interfaces to the statements array + statements.push(inputInterface, outputInterface); + + // Create a type for the graph + const graphType = ts.factory.createInterfaceDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + graphName, + undefined, + undefined, + [ + ts.factory.createPropertySignature( + undefined, + 'metadata', + undefined, + ts.factory.createTypeLiteralNode([ + ts.factory.createPropertySignature( + undefined, + 'id', + undefined, + ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(graphId)), + ), + ts.factory.createPropertySignature( + undefined, + 'name', + undefined, + ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(graph.metadata?.name ?? '')), + ), + ts.factory.createPropertySignature( + undefined, + 'description', + undefined, + ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(graph.metadata?.description ?? '')), + ), + ]), + ), + ts.factory.createPropertySignature( + undefined, + 'inputs', + undefined, + ts.factory.createTypeReferenceNode(`${graphName}_Inputs`, undefined), + ), + ts.factory.createPropertySignature( + undefined, + 'outputs', + undefined, + ts.factory.createTypeReferenceNode(`${graphName}_Outputs`, undefined), + ), + ], + ); + + statements.push(graphType); + + graphTypes.push(graphType); + } + + // Create a type for the project + const projectGraphsType = ts.factory.createInterfaceDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + `${projectName}_Graphs`, + undefined, + undefined, + graphTypes.map((graphType) => + ts.factory.createPropertySignature( + undefined, + graphType.name, + undefined, + ts.factory.createTypeReferenceNode(graphType.name, undefined), + ), + ), + ); + + // Add the project type to the statements array + statements.push(projectGraphsType); + + const projectType = ts.factory.createInterfaceDeclaration( + [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], + projectName, + undefined, + undefined, + [ + ts.factory.createPropertySignature( + undefined, + 'metadata', + undefined, + ts.factory.createTypeLiteralNode([ + ts.factory.createPropertySignature( + undefined, + 'id', + undefined, + ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(project.metadata.id, true)), + ), + ]), + ), + ts.factory.createPropertySignature( + undefined, + 'graphs', + undefined, + ts.factory.createTypeReferenceNode(`${projectName}_Graphs`, undefined), + ), + ], + ); + + statements.push(projectType); + + // Update the source file with the new statements + const updatedSourceFile = ts.factory.updateSourceFile(sourceFile, statements); + + // Print the updated source file + const result = `import * as Rivet from '@ironclad/rivet-node'; + +${printer.printFile(updatedSourceFile)}`; + + return result; +} + +const path = '/Users/Shared/ironclad/ironclad/harbor/packages/leaf-app-server/src/ai-chatbot/ai-chatbot.rivet-project'; +const project = await loadProjectFromFile(path); + +console.log(createProjectInterface(project)); diff --git a/yarn.lock b/yarn.lock index 5ef66d27e..e298a8fc8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4099,6 +4099,7 @@ __metadata: "@types/ws": "npm:^8.5.5" "@typescript-eslint/eslint-plugin": "npm:^5.50.0" "@zilliz/milvus2-sdk-node": "npm:^2.2.21" + change-case: "npm:^4.1.2" emittery: "npm:^1.0.1" emittery-0-13: "npm:emittery@^0.13.1" esbuild: "npm:^0.18.17" @@ -7114,6 +7115,17 @@ __metadata: languageName: node linkType: hard +"capital-case@npm:^1.0.4": + version: 1.0.4 + resolution: "capital-case@npm:1.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + upper-case-first: "npm:^2.0.2" + checksum: 913c04c48763e2d9e38ffb9b08e2b8a22824eb8a5882e35924db857694b022c3d23496962919b25cf8577fe1151657b32937b7ef2d086e7997b162219cefc16f + languageName: node + linkType: hard + "ccount@npm:^1.0.0": version: 1.1.0 resolution: "ccount@npm:1.1.0" @@ -7149,6 +7161,26 @@ __metadata: languageName: node linkType: hard +"change-case@npm:^4.1.2": + version: 4.1.2 + resolution: "change-case@npm:4.1.2" + dependencies: + camel-case: "npm:^4.1.2" + capital-case: "npm:^1.0.4" + constant-case: "npm:^3.0.4" + dot-case: "npm:^3.0.4" + header-case: "npm:^2.0.4" + no-case: "npm:^3.0.4" + param-case: "npm:^3.0.4" + pascal-case: "npm:^3.1.2" + path-case: "npm:^3.0.4" + sentence-case: "npm:^3.0.4" + snake-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: 7e6bc68c5961de7742a7a7e3f13c53031912c0911c7a2d59d6c8a1a8e5f3e47655ea3ccb402d6843c99c0fd219d2913f7d823df05367e0ac6efb65dcbb21ade0 + languageName: node + linkType: hard + "character-entities-legacy@npm:^1.0.0": version: 1.1.4 resolution: "character-entities-legacy@npm:1.1.4" @@ -7568,6 +7600,17 @@ __metadata: languageName: node linkType: hard +"constant-case@npm:^3.0.4": + version: 3.0.4 + resolution: "constant-case@npm:3.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + upper-case: "npm:^2.0.2" + checksum: 2a4d10cc736f8f6c2dd6f42e009f2fbb722f852bdcab447c221d4871cf67ceb329f11c551f85059d6415ff06fdf59447987d5df68b91630daa4e8f54302e3288 + languageName: node + linkType: hard + "content-disposition@npm:0.5.2": version: 0.5.2 resolution: "content-disposition@npm:0.5.2" @@ -10466,6 +10509,16 @@ __metadata: languageName: node linkType: hard +"header-case@npm:^2.0.4": + version: 2.0.4 + resolution: "header-case@npm:2.0.4" + dependencies: + capital-case: "npm:^1.0.4" + tslib: "npm:^2.0.3" + checksum: 401cbd54796cf233983d5da9c8fbfb49a4bc8dc60e7ea3e81ef06f8084614c5f41220048d6b623314de344beac3a11f2c8e2594b093c5abc115bf2453be54c4f + languageName: node + linkType: hard + "history@npm:^4.9.0": version: 4.10.1 resolution: "history@npm:4.10.1" @@ -13020,6 +13073,16 @@ __metadata: languageName: node linkType: hard +"path-case@npm:^3.0.4": + version: 3.0.4 + resolution: "path-case@npm:3.0.4" + dependencies: + dot-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: b150b466fc8cf5b90e5afbbe04da72fc8a48061c4132d9df67067501f70e035842a4838950b61b518797d185083d1a5bb6dad01bc376bbbe08a68531d075fc61 + languageName: node + linkType: hard + "path-exists@npm:^3.0.0": version: 3.0.0 resolution: "path-exists@npm:3.0.0" @@ -15015,6 +15078,17 @@ __metadata: languageName: node linkType: hard +"sentence-case@npm:^3.0.4": + version: 3.0.4 + resolution: "sentence-case@npm:3.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + upper-case-first: "npm:^2.0.2" + checksum: e98889c53afe8b21f632ed8d7e941141f855ebcf4e3eea14f1d2e8f23e41e657757cdc561c18f7a4b7d51fcdf3bfac1bc5ddaeb589092c7c1ea3dfe869978372 + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.0, serialize-javascript@npm:^6.0.1": version: 6.0.1 resolution: "serialize-javascript@npm:6.0.1" @@ -15252,6 +15326,16 @@ __metadata: languageName: node linkType: hard +"snake-case@npm:^3.0.4": + version: 3.0.4 + resolution: "snake-case@npm:3.0.4" + dependencies: + dot-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: b33d2573a0e33397e29cf2bb97e7dded7bf8be7efc53051bba85bd4888917277ae174f328d831424b3f9e5a6095823bcc11a62af0e9c77c88f127aa53a3d98bb + languageName: node + linkType: hard + "sockjs@npm:^0.3.24": version: 0.3.24 resolution: "sockjs@npm:0.3.24" @@ -16413,6 +16497,24 @@ __metadata: languageName: node linkType: hard +"upper-case-first@npm:^2.0.2": + version: 2.0.2 + resolution: "upper-case-first@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 28c69870d26b67dabf1423fe48250fcb2b018b2bf3e4b697ebd85bf48a7e3eb278050f7ab98e5d3d2464a58cfa2ca1b4e2ec513fd5534c7bbf1f2441fd35c8e7 + languageName: node + linkType: hard + +"upper-case@npm:^2.0.2": + version: 2.0.2 + resolution: "upper-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 6e63b063617770c22bf13c2cf112dda7235ee8c559ee7b199ab57593bf6e87383aaed416045cad8b9687e33554345c78a8ecd7e3878bca367ca7da29121b8feb + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1"