From 032b9cd58afdd4bf23325136b917bcd3fc26fc1a Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 22 Jul 2024 12:46:51 +0000 Subject: [PATCH 1/2] Initial config setup --- js/package.json | 5 ++++- js/rollup.config.js | 9 +++++++-- js/src/{app.js => app.ts} | 0 js/tsconfig.json | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) rename js/src/{app.js => app.ts} (100%) create mode 100644 js/tsconfig.json diff --git a/js/package.json b/js/package.json index 9e575dc..0fc7377 100644 --- a/js/package.json +++ b/js/package.json @@ -15,7 +15,10 @@ "devDependencies": { "@rollup/plugin-commonjs": "^17.1.0", "@rollup/plugin-node-resolve": "^11.2.0", + "@rollup/plugin-typescript": "^11.1.6", "del-cli": "^3.0.1", - "rollup": "^2.41.0" + "rollup": "^2.41.0", + "tslib": "^2.6.3", + "typescript": "^5.4.5" } } diff --git a/js/rollup.config.js b/js/rollup.config.js index ff00cc6..5870aa7 100644 --- a/js/rollup.config.js +++ b/js/rollup.config.js @@ -1,13 +1,18 @@ import { nodeResolve } from "@rollup/plugin-node-resolve"; import commonjs from "@rollup/plugin-commonjs"; +import typescript from "@rollup/plugin-typescript"; export default { - input: "src/app.js", + input: "src/app.ts", output: { dir: "dist/src", format: "es", preserveModules: true, preserveModulesRoot: "src", }, - plugins: [nodeResolve(), commonjs()], + plugins: [ + nodeResolve(), + typescript({ compilerOptions: { noEmitOnError: true } }), + commonjs(), + ], }; diff --git a/js/src/app.js b/js/src/app.ts similarity index 100% rename from js/src/app.js rename to js/src/app.ts diff --git a/js/tsconfig.json b/js/tsconfig.json new file mode 100644 index 0000000..6e242ad --- /dev/null +++ b/js/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "lib": ["ES2020"], + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "noImplicitAny": false, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": false + }, + "include": ["src/**/*"] +} From 61ceea93f1dfddacb5822aa48224b13e9fe88e55 Mon Sep 17 00:00:00 2001 From: Eddy Ashton Date: Mon, 22 Jul 2024 12:59:51 +0000 Subject: [PATCH 2/2] Use types in Typescript --- README.md | 13 ++++++------- js/src/app.ts | 32 +++++++++++++++++--------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 8698fad..719489a 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Template repository for JavaScript and C++ CCF applications. -Note: For complete sample apps, see https://github.com/microsoft/ccf-app-samples. +Note: For complete sample apps, see https://github.com/microsoft/ccf-app-samples. ## Quickstart -The quickest way to build and run this sample CCF app is to checkout this repository locally in its development container by clicking: +The quickest way to build and run this sample CCF app is to checkout this repository locally in its development container by clicking: [![Open in VSCode](https://img.shields.io/static/v1?label=Open+in&message=VSCode&logo=visualstudiocode&color=007ACC&logoColor=007ACC&labelColor=2C2C32)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/ccf-app-template) All dependencies will be automatically installed (takes ~2 mins on first checkout). @@ -41,8 +41,8 @@ $ /opt/ccf_virtual/bin/sandbox.sh --js-app-bundle ./js/dist/ In another terminal: ```bash -$ curl -X POST https://127.0.0.1:8000/app/log?id=1 --cacert ./workspace/sandbox_common/service_cert.pem -H "Content-Type: application/json" --data '{"msg": "hello world"}' -$ curl https://127.0.0.1:8000/app/log?id=1 --cacert ./workspace/sandbox_common/service_cert.pem +$ curl -X POST "https://127.0.0.1:8000/app/log?id=1" --cacert ./workspace/sandbox_common/service_cert.pem -H "Content-Type: application/json" --data '{"msg": "hello world"}' +$ curl "https://127.0.0.1:8000/app/log?id=1" --cacert ./workspace/sandbox_common/service_cert.pem hello world ``` @@ -96,10 +96,9 @@ To start a test CCF network on a Linux environment, it requires [CCF to be intal The CCF network is started with one node and one member, please follow the [same governance steps as Docker](#network-governance) to initialize the network and check [CCF node config file documentation](https://microsoft.github.io/CCF/main/operations/configuration.html) - ### Managed CCF -The application can be tested using [Azure Managed CCF](https://techcommunity.microsoft.com/t5/azure-confidential-computing/microsoft-introduces-preview-of-azure-managed-confidential/ba-p/3648986) ``(Pre-release phase)``, you can create Azure Managed CCF service on your subscription, that will give you a ready CCF network +The application can be tested using [Azure Managed CCF](https://techcommunity.microsoft.com/t5/azure-confidential-computing/microsoft-introduces-preview-of-azure-managed-confidential/ba-p/3648986) `(Pre-release phase)`, you can create Azure Managed CCF service on your subscription, that will give you a ready CCF network - First, create the network's initial member certificate, please check [Certificates generation](https://microsoft.github.io/CCF/main/governance/adding_member.html) - Create a new Azure Managed CCF service (the initial member certificate required as input) @@ -107,7 +106,7 @@ The application can be tested using [Azure Managed CCF](https://techcommunity.mi - Deploy the application proposal, [using governance calls](https://microsoft.github.io/CCF/main/governance/proposals.html#creating-a-proposal) - Create and submit [an add users proposal](https://microsoft.github.io/CCF/main/governance/proposals.html#creating-a-proposal) -## C++ +## C++ CCF apps can also be written in C++. This offers better performance than JavaScript apps but requires a compilation step and a restart of the CCF node for deployment. diff --git a/js/src/app.ts b/js/src/app.ts index 9e2235c..ff5b720 100644 --- a/js/src/app.ts +++ b/js/src/app.ts @@ -1,6 +1,8 @@ -import { ccf } from "@microsoft/ccf-app/global"; +import * as ccfapp from "@microsoft/ccf-app"; -function parse_request_query(request) { +function parse_request_query(request: ccfapp.Request): { + [key: string]: string; +} { const elements = request.query.split("&"); const obj = {}; for (const kv of elements) { @@ -10,30 +12,30 @@ function parse_request_query(request) { return obj; } -export function write(request) { +const recordsMap = ccfapp.typedKv("records", ccfapp.string, ccfapp.string); + +export function write(request: ccfapp.Request): ccfapp.Response { const parsedQuery = parse_request_query(request); - if (parsedQuery.id === undefined) - { + if (parsedQuery.id === undefined) { return { body: { error: "Missing query parameter 'id'" } }; } - const id = ccf.strToBuf(parsedQuery.id); const params = request.body.json(); - ccf.kv["records"].set(id, ccf.strToBuf(params.msg)); + recordsMap.set(parsedQuery.id, params.msg); return {}; } -export function read(request) { +export function read(request: ccfapp.Request): ccfapp.Response { const parsedQuery = parse_request_query(request); - if (parsedQuery.id === undefined) - { + if (parsedQuery.id === undefined) { return { body: { error: "Missing query parameter 'id'" } }; } - const id = ccf.strToBuf(parsedQuery.id); - const msg = ccf.kv["records"].get(id); + const msg = recordsMap.get(parsedQuery.id); if (msg === undefined) { - return { body: { error: `Cannot find record for id \"${parsedQuery.id}\".` } }; + return { + body: { error: `Cannot find record for id \"${parsedQuery.id}\".` }, + }; } - return { body: ccf.bufToStr(msg) }; -} \ No newline at end of file + return { body: msg }; +}