mirror of
https://github.com/noodlapp/noodl-cloudservice.git
synced 2026-01-11 23:02:54 +01:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
413e7b3fcd | ||
|
|
c89f7ef796 | ||
|
|
a4d5cea021 | ||
|
|
454ad91136 | ||
|
|
8d53400fdb | ||
|
|
c2f102f603 |
10
.github/dependabot.yml
vendored
Normal file
10
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
# Always increase the version requirement
|
||||
# to match the new version.
|
||||
versioning-strategy: increase
|
||||
39
.github/workflows/publish-npm.yml
vendored
Normal file
39
.github/workflows/publish-npm.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Publish to NPM
|
||||
|
||||
on:
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
||||
concurrency:
|
||||
group: "publish-npm"
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: packages/noodl-cloudservice
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node env 🏗
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies 🏗
|
||||
run: npm install
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Publish
|
||||
run: npm publish --access=public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
@@ -58,3 +58,16 @@ This package contains the docker image of the Noodl Self Hosted Cloud Service.
|
||||
**Description**: The **`MAX_UPLOAD_SIZE`** variable specifies the maximum allowed size for file uploads in the application.
|
||||
|
||||
**Default Value: `20mb`**
|
||||
|
||||
### `NOODL_CLOUD_RUNTIMES_LOCATION`
|
||||
|
||||
**Description**: The **`NOODL_CLOUD_RUNTIMES_LOCATION`** variable specifies the URL location where to find the runtime to use.
|
||||
|
||||
To use the Noodl hosted cloud runtimes, use this URL:
|
||||
`https://runtimes.noodl.cloud/{runtime}.js`
|
||||
|
||||
`{runtime}` will be replaced with the desired runtime by the Cloud Functions.
|
||||
|
||||
If this variable is not provided then the built in cloud runtime will be used.
|
||||
|
||||
**Default Value: `undefined`**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@noodl/cloudservice-docker",
|
||||
"version": "0.2.4",
|
||||
"version": "0.3.0",
|
||||
"description": "Low-code for when experience matter",
|
||||
"author": "Noodl <info@noodl.net>",
|
||||
"homepage": "https://noodl.net",
|
||||
|
||||
21
packages/noodl-cloudservice/LICENSE
Normal file
21
packages/noodl-cloudservice/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Future Platforms AB
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
108
packages/noodl-cloudservice/package-lock.json
generated
108
packages/noodl-cloudservice/package-lock.json
generated
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "@noodl/cloudservice",
|
||||
"version": "1.0.0",
|
||||
"version": "0.2.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@noodl/cloudservice",
|
||||
"version": "1.0.0",
|
||||
"version": "0.2.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noodl/cloud-runtime": "^0.6.3",
|
||||
"isolated-vm": "^4.4.2",
|
||||
"node-fetch": "2.6.7",
|
||||
"parse-server": "^4.10.4",
|
||||
@@ -16,6 +17,7 @@
|
||||
"winston-mongodb": "^5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.21",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
@@ -655,6 +657,11 @@
|
||||
"tslib": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@noodl/cloud-runtime": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@noodl/cloud-runtime/-/cloud-runtime-0.6.3.tgz",
|
||||
"integrity": "sha512-RZtzTSi4I5UVBEMVAhmA1OX7Gqo5mcVkHWWm51oCNk/7benNa/D+PEUmGl5VMicVrJUG+/Ca6KI+9xq0D+kr1A=="
|
||||
},
|
||||
"node_modules/@parse/fs-files-adapter": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.0.tgz",
|
||||
@@ -937,12 +944,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express": {
|
||||
"version": "4.17.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
|
||||
"integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
|
||||
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
|
||||
"dependencies": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "*",
|
||||
"@types/express-serve-static-core": "^4.17.33",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
@@ -975,6 +982,17 @@
|
||||
"express-unless": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express/node_modules/@types/express-serve-static-core": {
|
||||
"version": "4.17.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz",
|
||||
"integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*",
|
||||
"@types/send": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/fs-capacitor": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz",
|
||||
@@ -1046,6 +1064,20 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
|
||||
},
|
||||
"node_modules/@types/send": {
|
||||
"version": "0.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
||||
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
|
||||
"dependencies": {
|
||||
"@types/mime": "^1",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/send/node_modules/@types/mime": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
|
||||
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
|
||||
},
|
||||
"node_modules/@types/serve-static": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz",
|
||||
@@ -1450,6 +1482,17 @@
|
||||
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/apollo-server-express/node_modules/@types/express": {
|
||||
"version": "4.17.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
|
||||
"integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
|
||||
"dependencies": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/apollo-server-express/node_modules/subscriptions-transport-ws": {
|
||||
"version": "0.9.19",
|
||||
"resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz",
|
||||
@@ -7368,6 +7411,11 @@
|
||||
"tslib": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"@noodl/cloud-runtime": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@noodl/cloud-runtime/-/cloud-runtime-0.6.3.tgz",
|
||||
"integrity": "sha512-RZtzTSi4I5UVBEMVAhmA1OX7Gqo5mcVkHWWm51oCNk/7benNa/D+PEUmGl5VMicVrJUG+/Ca6KI+9xq0D+kr1A=="
|
||||
},
|
||||
"@parse/fs-files-adapter": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.0.tgz",
|
||||
@@ -7615,14 +7663,27 @@
|
||||
}
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
|
||||
"integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
|
||||
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
|
||||
"requires": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "*",
|
||||
"@types/express-serve-static-core": "^4.17.33",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/express-serve-static-core": {
|
||||
"version": "4.17.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz",
|
||||
"integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==",
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/range-parser": "*",
|
||||
"@types/send": "*"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/express-jwt": {
|
||||
@@ -7723,6 +7784,22 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
|
||||
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
|
||||
},
|
||||
"@types/send": {
|
||||
"version": "0.17.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
||||
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
|
||||
"requires": {
|
||||
"@types/mime": "^1",
|
||||
"@types/node": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/mime": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
|
||||
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/serve-static": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz",
|
||||
@@ -8042,6 +8119,17 @@
|
||||
"type-is": "^1.6.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/express": {
|
||||
"version": "4.17.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
|
||||
"integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
|
||||
"requires": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "*",
|
||||
"@types/qs": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"subscriptions-transport-ws": {
|
||||
"version": "0.9.19",
|
||||
"resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@noodl/cloudservice",
|
||||
"version": "0.2.4",
|
||||
"version": "0.3.0",
|
||||
"description": "Low-code for when experience matter",
|
||||
"author": "Noodl <info@noodl.net>",
|
||||
"homepage": "https://noodl.net",
|
||||
@@ -18,6 +18,7 @@
|
||||
"build": "npm run build:clean && npm run build:ts && npm run build:static"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noodl/cloud-runtime": "^0.6.3",
|
||||
"isolated-vm": "^4.4.2",
|
||||
"node-fetch": "2.6.7",
|
||||
"parse-server": "^4.10.4",
|
||||
@@ -25,7 +26,8 @@
|
||||
"winston-mongodb": "^5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.2.2",
|
||||
"ts-node": "^10.9.2"
|
||||
"@types/express": "^4.17.21",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,12 @@ fs.cpSync(
|
||||
dist,
|
||||
{ recursive: true }
|
||||
);
|
||||
|
||||
// Copy the noodl cloud runtime to the dist folder
|
||||
fs.copyFile(
|
||||
path.join(__dirname, "../node_modules/@noodl/cloud-runtime/dist/main.js"),
|
||||
path.join(__dirname, "../dist/static/cloud-runtime.js"),
|
||||
(err) => {
|
||||
if (err) throw err;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -219,17 +219,7 @@ export async function createContext(global: ContextGlobalState, env: CreateConte
|
||||
);
|
||||
}
|
||||
|
||||
const _defaultRuntime = process.env.NOODL_DEFAULT_CLOUD_RUNTIME;
|
||||
let runtime = cloudRuntime || _defaultRuntime;
|
||||
if (!runtime.endsWith(".js")) runtime = runtime + ".js";
|
||||
|
||||
console.log("- Using runtime: " + runtime);
|
||||
const snapshot = await getRuntimeSnapshot(
|
||||
(process.env.NOODL_CLOUD_RUNTIMES_LOCATION ||
|
||||
"https://runtimes.noodl.cloud") +
|
||||
"/" +
|
||||
runtime
|
||||
);
|
||||
const snapshot = await getRuntimeSnapshot(cloudRuntime);
|
||||
|
||||
console.log("- Starting up isolate");
|
||||
const isolate = new ivm.Isolate({ memoryLimit: env.memoryLimit, snapshot });
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import fetch from "node-fetch";
|
||||
import ivm from "isolated-vm";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
// Create a snapshot of a given runtime if needed
|
||||
// of serve from the cache
|
||||
@@ -21,20 +23,39 @@ async function fetchRuntime(url: string) {
|
||||
return createSnapshot(script)
|
||||
}
|
||||
|
||||
export async function getRuntimeSnapshot(url: string) {
|
||||
if (snapshots[url]) {
|
||||
try {
|
||||
await snapshots[url];
|
||||
} catch (e) {
|
||||
console.log(`Disposing runtime snapshot due to error in create: `, e);
|
||||
delete snapshots[url];
|
||||
export async function getRuntimeSnapshot(functionRuntimeVersion: string) {
|
||||
const cloudRuntimeUrl = process.env.NOODL_CLOUD_RUNTIMES_LOCATION;
|
||||
if (cloudRuntimeUrl) {
|
||||
const url = cloudRuntimeUrl.replace("{runtime}", functionRuntimeVersion);
|
||||
if (snapshots[url]) {
|
||||
try {
|
||||
await snapshots[url];
|
||||
} catch (e) {
|
||||
console.log(`Disposing runtime snapshot due to error in create: `, e);
|
||||
delete snapshots[url];
|
||||
}
|
||||
}
|
||||
|
||||
if (!snapshots[url]) {
|
||||
snapshots[url] = fetchRuntime(url);
|
||||
}
|
||||
}
|
||||
|
||||
if (snapshots[url]) {
|
||||
console.log("- Using runtime: " + url);
|
||||
return snapshots[url];
|
||||
} else {
|
||||
return snapshots[url] = fetchRuntime(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a snapshot with the builtin cloud runtime
|
||||
if (!snapshots['__builtin']) {
|
||||
const filePath = path.join(__dirname, '../static/cloud-runtime.js');
|
||||
if (!fs.existsSync(filePath)) {
|
||||
throw new Error("Failed to find builtin cloud runtime: " + filePath);
|
||||
}
|
||||
|
||||
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
||||
snapshots['__builtin'] = Promise.resolve(createSnapshot(fileContent));
|
||||
|
||||
console.log("- Using runtime: builtin");
|
||||
}
|
||||
|
||||
return snapshots['__builtin'];
|
||||
}
|
||||
|
||||
@@ -1,97 +1,14 @@
|
||||
import { NoodlParseServerOptions, createNoodlParseServer } from "./parse";
|
||||
import { executeFunction } from "./function";
|
||||
import { CFVersion, deployFunctions, getLatestVersion } from "./function-deploy";
|
||||
import { Logger } from "./logger";
|
||||
import type { Request, Response, NextFunction } from "express"
|
||||
import { NoodlParseServerOptions, NoodlParseServerResult, createNoodlParseServer } from "./parse";
|
||||
import { routeFunctions } from "./routes/functions";
|
||||
import { routeFunctionsAdmin } from "./routes/functions-admin";
|
||||
|
||||
function createMiddleware(noodlServer) {
|
||||
return async function middleware(req, res, next) {
|
||||
function createMiddleware(noodlServer: NoodlParseServerResult) {
|
||||
return async function middleware(req: Request, res: Response, next: NextFunction) {
|
||||
if (req.url.startsWith('/functions/') && req.method === 'POST') {
|
||||
try {
|
||||
const path = req.url;
|
||||
const functionId = decodeURIComponent(path.split('/')[2]);
|
||||
|
||||
if (functionId === undefined)
|
||||
return next()
|
||||
|
||||
console.log('Running cloud function ' + functionId);
|
||||
|
||||
let requestVersion = req.headers['x-noodl-cloud-version'];
|
||||
let version: CFVersion = requestVersion
|
||||
? { functionVersion: requestVersion }
|
||||
: await getLatestVersion(noodlServer.options)
|
||||
|
||||
// Execute the request
|
||||
const cfResponse = await executeFunction({
|
||||
port: noodlServer.options.port,
|
||||
appId: noodlServer.options.appId,
|
||||
masterKey: noodlServer.options.masterKey,
|
||||
version,
|
||||
logger: new Logger(noodlServer),
|
||||
headers: req.headers,
|
||||
functionId,
|
||||
body: req.body,
|
||||
timeOut: noodlServer.functionOptions.timeOut,
|
||||
memoryLimit: noodlServer.functionOptions.memoryLimit,
|
||||
})
|
||||
|
||||
if (cfResponse.headers) {
|
||||
res.status(cfResponse.statusCode)
|
||||
.set(cfResponse.headers)
|
||||
.send(cfResponse.body)
|
||||
} else {
|
||||
res.status(cfResponse.statusCode)
|
||||
.set({ 'Content-Type': 'application/json' })
|
||||
.send(cfResponse.body)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Something went wrong when running function', e)
|
||||
res.status(400).json({
|
||||
error: "Something when wrong..."
|
||||
})
|
||||
}
|
||||
routeFunctions(noodlServer, req, res, next);
|
||||
} else if (req.url.startsWith('/functions-admin')) {
|
||||
if (req.headers['x-parse-master-key'] !== noodlServer.options.masterKey) {
|
||||
return res.status(401).json({
|
||||
message: 'Not authorized'
|
||||
})
|
||||
}
|
||||
|
||||
if (req.headers['x-parse-application-id'] !== noodlServer.options.appId) {
|
||||
return res.status(401).json({
|
||||
message: 'Not authorized'
|
||||
})
|
||||
}
|
||||
|
||||
// Deploy a new version
|
||||
if (req.method === 'POST' && req.url === "/functions-admin/deploy") {
|
||||
if (!req.body || typeof req.body.deploy !== "string" || typeof req.body.runtime !== "string") {
|
||||
return res.status(400).json({
|
||||
message: 'Must supply deploy and runtime'
|
||||
})
|
||||
}
|
||||
|
||||
console.log('Uploading deploy...')
|
||||
const { version } = await deployFunctions({
|
||||
port: noodlServer.options.port,
|
||||
appId: noodlServer.options.appId,
|
||||
masterKey: noodlServer.options.masterKey,
|
||||
runtime: req.body.runtime,
|
||||
data: req.body.deploy
|
||||
})
|
||||
|
||||
console.log('Upload completed, version: ' + version)
|
||||
res.json({
|
||||
status: 'success',
|
||||
version
|
||||
})
|
||||
} else if (req.method === 'GET' && req.url === "/functions-admin/info") {
|
||||
res.json({
|
||||
version: '1.0'
|
||||
})
|
||||
} else res.status(400).json({
|
||||
message: 'Function not supported'
|
||||
})
|
||||
|
||||
routeFunctionsAdmin(noodlServer, req, res, next);
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
@@ -104,7 +21,7 @@ export function createNoodlServer(options: NoodlParseServerOptions) {
|
||||
const cfMiddleware = createMiddleware(noodlServer);
|
||||
|
||||
// Combine the Noodl Cloud Function middleware with the Parse middleware into one middleware.
|
||||
const middleware = (req: Request, res: Response, next: () => void) => {
|
||||
const middleware = (req: Request, res: Response, next: NextFunction) => {
|
||||
cfMiddleware(req, res, () => {
|
||||
noodlServer.server.app(req, res, next);
|
||||
});
|
||||
|
||||
52
packages/noodl-cloudservice/src/routes/functions-admin.ts
Normal file
52
packages/noodl-cloudservice/src/routes/functions-admin.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import type { Request, Response, NextFunction } from "express"
|
||||
import { NoodlParseServerResult } from "../parse"
|
||||
import { deployFunctions } from "../function-deploy"
|
||||
|
||||
export async function routeFunctionsAdmin(
|
||||
noodlServer: NoodlParseServerResult,
|
||||
req: Request,
|
||||
res: Response,
|
||||
_next: NextFunction
|
||||
) {
|
||||
if (req.headers['x-parse-master-key'] !== noodlServer.options.masterKey) {
|
||||
return res.status(401).json({
|
||||
message: 'Not authorized'
|
||||
})
|
||||
}
|
||||
|
||||
if (req.headers['x-parse-application-id'] !== noodlServer.options.appId) {
|
||||
return res.status(401).json({
|
||||
message: 'Not authorized'
|
||||
})
|
||||
}
|
||||
|
||||
// Deploy a new version
|
||||
if (req.method === 'POST' && req.url === "/functions-admin/deploy") {
|
||||
if (!req.body || typeof req.body.deploy !== "string" || typeof req.body.runtime !== "string") {
|
||||
return res.status(400).json({
|
||||
message: 'Must supply deploy and runtime'
|
||||
})
|
||||
}
|
||||
|
||||
console.log('Uploading deploy...')
|
||||
const { version } = await deployFunctions({
|
||||
port: noodlServer.options.port,
|
||||
appId: noodlServer.options.appId,
|
||||
masterKey: noodlServer.options.masterKey,
|
||||
runtime: req.body.runtime,
|
||||
data: req.body.deploy
|
||||
})
|
||||
|
||||
console.log('Upload completed, version: ' + version)
|
||||
res.json({
|
||||
status: 'success',
|
||||
version
|
||||
})
|
||||
} else if (req.method === 'GET' && req.url === "/functions-admin/info") {
|
||||
res.json({
|
||||
version: '1.0'
|
||||
})
|
||||
} else res.status(400).json({
|
||||
message: 'Function not supported'
|
||||
})
|
||||
}
|
||||
57
packages/noodl-cloudservice/src/routes/functions.ts
Normal file
57
packages/noodl-cloudservice/src/routes/functions.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Request, Response, NextFunction } from "express"
|
||||
import { executeFunction } from "../function";
|
||||
import { CFVersion, getLatestVersion } from "../function-deploy";
|
||||
import { Logger } from "../logger";
|
||||
import { NoodlParseServerResult } from "../parse";
|
||||
|
||||
export async function routeFunctions(
|
||||
noodlServer: NoodlParseServerResult,
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
try {
|
||||
const path = req.url;
|
||||
const functionId = decodeURIComponent(path.split("/")[2]);
|
||||
|
||||
if (functionId === undefined) return next();
|
||||
|
||||
console.log("Running cloud function " + functionId);
|
||||
|
||||
let requestVersion = req.headers["x-noodl-cloud-version"];
|
||||
let version: CFVersion = requestVersion
|
||||
? { functionVersion: String(requestVersion) }
|
||||
: await getLatestVersion(noodlServer.options);
|
||||
|
||||
// Execute the request
|
||||
const cfResponse = await executeFunction({
|
||||
port: noodlServer.options.port,
|
||||
appId: noodlServer.options.appId,
|
||||
masterKey: noodlServer.options.masterKey,
|
||||
version,
|
||||
logger: new Logger(noodlServer),
|
||||
headers: req.headers,
|
||||
functionId,
|
||||
body: req.body,
|
||||
timeOut: noodlServer.functionOptions.timeOut,
|
||||
memoryLimit: noodlServer.functionOptions.memoryLimit,
|
||||
});
|
||||
|
||||
if (cfResponse.headers) {
|
||||
res
|
||||
.status(cfResponse.statusCode)
|
||||
.set(cfResponse.headers)
|
||||
.send(cfResponse.body);
|
||||
} else {
|
||||
res
|
||||
.status(cfResponse.statusCode)
|
||||
.set({ "Content-Type": "application/json" })
|
||||
.send(cfResponse.body);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Something went wrong when running function", e);
|
||||
res.status(400).json({
|
||||
error: "Something when wrong...",
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user