From daf32e4ac5e0086a164b2223eb0e45b52a411219 Mon Sep 17 00:00:00 2001 From: Jordan Last Date: Wed, 20 Sep 2023 14:25:56 -0500 Subject: [PATCH] hook up query and service for new functional syntax --- examples/query/src/index.ts | 9 ++- package.json | 2 +- .../generate_candid_and_canister_methods.ts | 4 +- .../azle_generate_rearchitecture/src/main.rs | 5 +- .../typescript_to_javascript/index.ts | 19 +------ src/compiler/utils/types.ts | 4 ++ src/lib_functional/candid/index.ts | 1 + src/lib_functional/candid/primitive.ts | 0 src/lib_functional/candid/reference/index.ts | 1 + src/lib_functional/candid/reference/record.ts | 0 .../candid/reference/service.ts | 55 +++++++++++++++++++ src/lib_functional/canister_methods/index.ts | 49 +++++++++++++++++ src/lib_functional/canister_methods/query.ts | 31 +++++++++++ src/lib_functional/canister_methods/update.ts | 1 + src/lib_functional/index.ts | 4 ++ src/lib_new/method_decorators.ts | 4 +- 16 files changed, 160 insertions(+), 29 deletions(-) create mode 100644 src/lib_functional/candid/index.ts create mode 100644 src/lib_functional/candid/primitive.ts create mode 100644 src/lib_functional/candid/reference/index.ts create mode 100644 src/lib_functional/candid/reference/record.ts create mode 100644 src/lib_functional/candid/reference/service.ts create mode 100644 src/lib_functional/canister_methods/index.ts create mode 100644 src/lib_functional/canister_methods/query.ts create mode 100644 src/lib_functional/canister_methods/update.ts create mode 100644 src/lib_functional/index.ts diff --git a/examples/query/src/index.ts b/examples/query/src/index.ts index ea93f039fe..339988b81e 100644 --- a/examples/query/src/index.ts +++ b/examples/query/src/index.ts @@ -1,8 +1,7 @@ import { query, Service, text } from 'azle'; -export default class extends Service { - @query([], text) - simpleQuery(): text { +export default Service({ + simpleQuery: query([], text, () => { return 'This is a query function'; - } -} + }) +}); diff --git a/package.json b/package.json index 71af544469..264e60cf53 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "bin": { "azle": "./bin.js" }, - "main": "./src/lib_new/index.ts", + "main": "./src/lib_functional/index.ts", "repository": { "type": "git", "url": "git+https://github.com/demergent-labs/azle.git" diff --git a/src/compiler/generate_candid_and_canister_methods.ts b/src/compiler/generate_candid_and_canister_methods.ts index 3cfdb141d1..5644417480 100644 --- a/src/compiler/generate_candid_and_canister_methods.ts +++ b/src/compiler/generate_candid_and_canister_methods.ts @@ -19,7 +19,7 @@ export function generateCandidAndCanisterMethods(mainJs: string): { script.runInContext(context); return { - candid: (sandbox.globalThis as any)._azleCandidService, - canisterMethods: (sandbox.globalThis as any)._azleCanisterMethods + candid: (sandbox.exports as any).canisterMethods.candid, + canisterMethods: (sandbox.exports as any).canisterMethods }; } diff --git a/src/compiler/typescript_to_rust/azle_generate_rearchitecture/src/main.rs b/src/compiler/typescript_to_rust/azle_generate_rearchitecture/src/main.rs index 76afa1872f..44e0e24370 100644 --- a/src/compiler/typescript_to_rust/azle_generate_rearchitecture/src/main.rs +++ b/src/compiler/typescript_to_rust/azle_generate_rearchitecture/src/main.rs @@ -278,8 +278,9 @@ fn main() -> Result<(), String> { let global = context.global_object().unwrap(); let exports = global.get_property("exports").unwrap(); - let class = exports.get_property("canisterClass").unwrap(); - let method = class.get_property(function_name).unwrap(); + let canister_methods = exports.get_property("canisterMethods").unwrap(); + let callbacks = canister_methods.get_property("callbacks").unwrap(); + let method = callbacks.get_property(function_name).unwrap(); let candid_args = if pass_arg_data { ic_cdk::api::call::arg_data_raw() } else { vec![] }; diff --git a/src/compiler/typescript_to_rust/typescript_to_javascript/index.ts b/src/compiler/typescript_to_rust/typescript_to_javascript/index.ts index 51c2dc2b3e..d4baa73638 100644 --- a/src/compiler/typescript_to_rust/typescript_to_javascript/index.ts +++ b/src/compiler/typescript_to_rust/typescript_to_javascript/index.ts @@ -33,34 +33,19 @@ export function compileTypeScriptToJavaScript( import { ic } from 'azle'; export { Principal } from '@dfinity/principal'; export * from './${tsPath}'; - import CanisterClass from './${tsPath}'; - `; - - const canisterClassInstantiation = ` - export const canisterClass = new CanisterClass(ic.id()); - `; - - const candidGeneration = ` -globalThis._azleCandidService = \`\${CanisterClass._azleCandidTypes.length > 0 ? CanisterClass._azleCandidTypes.join(';\\n') + ';\\n' : ''}service: (\${CanisterClass._azleCandidInitParams.join( - ', ' -)}) -> { - \${CanisterClass._azleCandidMethods.join('\\n ')} -}\n\` + import CanisterMethods from './${tsPath}'; -globalThis._azleCanisterMethods = CanisterClass._azleCanisterMethods; + export const canisterMethods = CanisterMethods; `; const canisterJavaScript = bundleAndTranspileJs(` ${globalThisProcess} ${imports} - ${canisterClassInstantiation} -${candidGeneration} `); const candidJavaScript = bundleAndTranspileJs(` ${globalThisProcess} ${imports} -${candidGeneration} `); return { diff --git a/src/compiler/utils/types.ts b/src/compiler/utils/types.ts index 66a8416590..b3a3e1a418 100644 --- a/src/compiler/utils/types.ts +++ b/src/compiler/utils/types.ts @@ -46,6 +46,7 @@ export type CompilerInfo = { }; export type CanisterMethods = { + candid: string; queries: CanisterMethod[]; updates: CanisterMethod[]; init?: CanisterMethod; @@ -53,6 +54,9 @@ export type CanisterMethods = { post_upgrade?: CanisterMethod; heartbeat?: CanisterMethod; inspect_message?: CanisterMethod; + callbacks: { + [key: string]: (...args: any) => any; + }; }; export type CanisterMethod = { diff --git a/src/lib_functional/candid/index.ts b/src/lib_functional/candid/index.ts new file mode 100644 index 0000000000..3ec8808d25 --- /dev/null +++ b/src/lib_functional/candid/index.ts @@ -0,0 +1 @@ +export * from './reference'; diff --git a/src/lib_functional/candid/primitive.ts b/src/lib_functional/candid/primitive.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/lib_functional/candid/reference/index.ts b/src/lib_functional/candid/reference/index.ts new file mode 100644 index 0000000000..f78beabc33 --- /dev/null +++ b/src/lib_functional/candid/reference/index.ts @@ -0,0 +1 @@ +export * from './service'; diff --git a/src/lib_functional/candid/reference/record.ts b/src/lib_functional/candid/reference/record.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/lib_functional/candid/reference/service.ts b/src/lib_functional/candid/reference/service.ts new file mode 100644 index 0000000000..8f351305bc --- /dev/null +++ b/src/lib_functional/candid/reference/service.ts @@ -0,0 +1,55 @@ +import { CanisterMethods } from '../../../compiler/utils/types'; +import { CanisterMethodInfo, query } from '../../canister_methods/query'; + +// type CanisterMethodType = 'query'; +// type CanisterMethods = (typeof query & { +// canisterMethodType: CanisterMethodType; +// })[]; + +type ServiceOptions = { + [key: string]: CanisterMethodInfo; +}; + +export function Service(serviceOptions: ServiceOptions): CanisterMethods { + const callbacks = Object.entries(serviceOptions).reduce((acc, entry) => { + const key = entry[0]; + const value = entry[1]; + + return { + ...acc, + [key]: value.callback + }; + }, {}); + + const queries = Object.entries(serviceOptions) + .filter((entry) => { + const key = entry[0]; + const value = entry[1]; + + return value.type === 'query'; + }) + .map((entry) => { + const key = entry[0]; + const value = entry[1]; + + return { + name: key + }; + }); + + // TODO loop through each key and simply grab the candid off + // TODO grab the init/post_upgrade candid as well + return { + candid: `service: () -> { + ${Object.entries(serviceOptions) + .map((entry) => { + return `${entry[0]}: ${entry[1].candid}`; + }) + .join('')} +} +`, + queries, + updates: [], + callbacks + }; +} diff --git a/src/lib_functional/canister_methods/index.ts b/src/lib_functional/canister_methods/index.ts new file mode 100644 index 0000000000..962901b010 --- /dev/null +++ b/src/lib_functional/canister_methods/index.ts @@ -0,0 +1,49 @@ +import { IDL } from '../../lib_new/index'; +import { ic } from '../../lib_new/ic'; + +export * from './query'; + +export function executeMethod( + paramCandid: any, + returnCandid: any, + args: any[], + callback: any +) { + const decoded = IDL.decode(paramCandid[0] as any, args[0]); + + const result = callback(decoded); + + if ( + result !== undefined && + result !== null && + typeof result.then === 'function' + ) { + result + .then((result: any) => { + // TODO this won't be accurate because we have most likely had + // TODO cross-canister calls + console.log(`final instructions: ${ic.instructionCounter()}`); + + // if (!manual) { + const encodeReadyResult = result === undefined ? [] : [result]; + const encoded = IDL.encode( + returnCandid[0] as any, + encodeReadyResult + ); + ic.replyRaw(new Uint8Array(encoded)); + // } + }) + .catch((error: any) => { + ic.trap(error.toString()); + }); + } else { + const encodeReadyResult = result === undefined ? [] : [result]; + + // if (!manual) { + const encoded = IDL.encode(returnCandid[0] as any, encodeReadyResult); + ic.replyRaw(new Uint8Array(encoded)); + // } + + console.log(`final instructions: ${ic.instructionCounter()}`); + } +} diff --git a/src/lib_functional/canister_methods/query.ts b/src/lib_functional/canister_methods/query.ts new file mode 100644 index 0000000000..014e504940 --- /dev/null +++ b/src/lib_functional/canister_methods/query.ts @@ -0,0 +1,31 @@ +import { + handleRecursiveParams, + handleRecursiveReturn +} from '../../lib_new/method_decorators'; +import { IDL } from '../../lib_new/index'; +import { ic } from '../../lib_new/ic'; +import { executeMethod } from '.'; + +export type CanisterMethodInfo = { + type: 'query'; + callback: (...args: any) => any; + candid: string; +}; + +// TODO execute the candid stuff and just store it on the function itself? +export function query( + paramsIdls: any, + returnIdl: any, + callback: any +): CanisterMethodInfo { + const paramCandid = handleRecursiveParams(paramsIdls); + const returnCandid = handleRecursiveReturn(returnIdl, paramCandid[2]); + + return { + type: 'query', + callback: (...args) => { + executeMethod(paramCandid, returnCandid, args, callback); + }, + candid: `(${paramCandid[1].join(', ')}) -> (${returnCandid[1]}) query;` + }; +} diff --git a/src/lib_functional/canister_methods/update.ts b/src/lib_functional/canister_methods/update.ts new file mode 100644 index 0000000000..e9acbfe80b --- /dev/null +++ b/src/lib_functional/canister_methods/update.ts @@ -0,0 +1 @@ +export function update() {} diff --git a/src/lib_functional/index.ts b/src/lib_functional/index.ts new file mode 100644 index 0000000000..7cd2820650 --- /dev/null +++ b/src/lib_functional/index.ts @@ -0,0 +1,4 @@ +export * from './canister_methods'; +export * from './candid'; +export * from '../lib_new/primitives'; +export * from '../lib_new/ic'; diff --git a/src/lib_new/method_decorators.ts b/src/lib_new/method_decorators.ts index 326a08b2cb..05832e4f12 100644 --- a/src/lib_new/method_decorators.ts +++ b/src/lib_new/method_decorators.ts @@ -174,7 +174,7 @@ function newTypesToStingArr(newTypes: CandidTypesDefs): string[] { ); } -function handleRecursiveParams( +export function handleRecursiveParams( idls: CandidClass[] ): [CandidClass[], CandidDef[], CandidTypesDefs] { const paramIdls = toParamCandidClasses(idls); @@ -182,7 +182,7 @@ function handleRecursiveParams( return [paramIdls, ...extractCandid(paramInfo, {})]; } -function handleRecursiveReturn( +export function handleRecursiveReturn( returnIdl: ReturnCandidClass, paramCandidTypeDefs: CandidTypesDefs ): [CandidClass[], CandidDef[], CandidTypesDefs] {