@plitzi/sdk-server 0.37.2 → 0.37.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1170 -0
- package/README.md +100 -7
- package/dist/actions.d.ts +6 -2
- package/dist/actions.js +5 -2
- package/dist/adapters/cloudAdapters.js +4 -3
- package/dist/adapters/jsonAdapters.js +28 -6
- package/dist/adapters/jsonAdapters.test.d.ts +1 -0
- package/dist/auth.d.ts +7 -4
- package/dist/auth.js +8 -6
- package/dist/core/auth/api.d.ts +29 -1
- package/dist/core/auth/api.js +47 -13
- package/dist/core/auth/createAuth.d.ts +4 -0
- package/dist/core/auth/createAuth.js +3 -3
- package/dist/core/auth/credentials.d.ts +3 -0
- package/dist/core/auth/credentials.js +1 -1
- package/dist/core/auth/csrf.d.ts +25 -1
- package/dist/core/auth/csrf.js +29 -4
- package/dist/core/auth/renewal.d.ts +26 -0
- package/dist/core/auth/renewal.js +24 -0
- package/dist/core/auth/routes.js +8 -6
- package/dist/core/auth/session.d.ts +45 -0
- package/dist/core/auth/session.js +47 -1
- package/dist/core/auth/sessionActivity.d.ts +11 -0
- package/dist/core/auth/sessionActivity.js +14 -0
- package/dist/core/auth/throttle.d.ts +15 -0
- package/dist/core/auth/throttle.js +29 -1
- package/dist/core/auth/totp.d.ts +9 -1
- package/dist/core/auth/totp.js +11 -6
- package/dist/core/createServer.actions.test.d.ts +1 -0
- package/dist/core/createServer.d.ts +14 -1
- package/dist/core/createServer.functions.test.d.ts +1 -0
- package/dist/core/createServer.js +22 -12
- package/dist/core/fontStore.js +1 -1
- package/dist/core/handlers/authRouteHandlers.d.ts +1 -1
- package/dist/core/handlers/authRouteHandlers.js +57 -21
- package/dist/core/handlers/csrfMiddleware.d.ts +23 -0
- package/dist/core/handlers/csrfMiddleware.js +31 -7
- package/dist/core/handlers/csrfMiddleware.test.d.ts +1 -0
- package/dist/core/handlers/oauthRouteHandlers.js +5 -3
- package/dist/core/handlers/socialRouteHandlers.d.ts +1 -1
- package/dist/core/handlers/socialRouteHandlers.js +2 -1
- package/dist/core/http/dispatcher.d.ts +9 -1
- package/dist/core/http/dispatcher.js +38 -11
- package/dist/core/http/navigation.d.ts +5 -2
- package/dist/core/http/navigation.js +7 -4
- package/dist/core/http/socketResponse.d.ts +18 -0
- package/dist/core/http/socketResponse.js +59 -0
- package/dist/core/http/sse.d.ts +26 -0
- package/dist/core/http/sse.js +78 -0
- package/dist/core/http/stages/authRoutes.js +3 -1
- package/dist/core/http/stages/exchangeRoute.test.d.ts +1 -0
- package/dist/core/http/stages/middlewares.d.ts +1 -1
- package/dist/core/http/stages/middlewares.js +16 -10
- package/dist/core/http/stages/middlewares.test.d.ts +1 -0
- package/dist/core/http/stages/oauth.js +2 -2
- package/dist/core/http/stages/sessionRenewal.d.ts +16 -0
- package/dist/core/http/stages/sessionRenewal.js +81 -0
- package/dist/core/http/stages/sessionRenewal.test.d.ts +1 -0
- package/dist/core/http/stages/signInRoute.d.ts +2 -0
- package/dist/core/http/stages/signInRoute.js +139 -0
- package/dist/core/http/stages/signInRoute.test.d.ts +1 -0
- package/dist/core/http/types.d.ts +9 -0
- package/dist/core/http/webExchange.d.ts +18 -0
- package/dist/core/http/webExchange.js +53 -0
- package/dist/core/oauth/authorize.js +37 -13
- package/dist/core/oauth/consentPage.js +11 -0
- package/dist/core/oauth/issueContext.d.ts +14 -0
- package/dist/core/oauth/issueContext.js +32 -0
- package/dist/core/oauth/records.d.ts +7 -0
- package/dist/core/oauth/register.d.ts +2 -0
- package/dist/core/oauth/register.js +32 -11
- package/dist/core/oauth/register.test.d.ts +1 -0
- package/dist/core/oauth/token.js +21 -6
- package/dist/core/oauth/token.test.d.ts +1 -0
- package/dist/core/requestParser.d.ts +4 -0
- package/dist/core/requestParser.js +14 -7
- package/dist/core/sdkAssets.js +1 -1
- package/dist/core/server/baseServer.d.ts +10 -0
- package/dist/core/server/baseServer.js +42 -11
- package/dist/core/server/closeOnSignals.js +4 -3
- package/dist/core/server/drain.d.ts +18 -0
- package/dist/core/server/drain.js +62 -0
- package/dist/core/server/drain.test.d.ts +1 -0
- package/dist/core/server/fleet/channel.d.ts +103 -0
- package/dist/core/server/fleet/channel.js +191 -0
- package/dist/core/server/fleet/channel.test.d.ts +1 -0
- package/dist/core/server/fleet/fixtures/fleetServer.d.ts +1 -0
- package/dist/core/server/fleet/fleet.integration.test.d.ts +1 -0
- package/dist/core/server/fleet/link.d.ts +23 -0
- package/dist/core/server/fleet/link.js +70 -0
- package/dist/core/server/fleet/relay.d.ts +11 -0
- package/dist/core/server/fleet/relay.js +104 -0
- package/dist/core/server/fleet/relay.test.d.ts +1 -0
- package/dist/core/server/fleet/role.d.ts +46 -0
- package/dist/core/server/fleet/role.js +59 -0
- package/dist/core/server/fleet/role.test.d.ts +1 -0
- package/dist/core/server/fleet/stores.d.ts +7 -0
- package/dist/core/server/fleet/stores.js +19 -0
- package/dist/core/server/fleet/supervisor.d.ts +26 -0
- package/dist/core/server/fleet/supervisor.js +108 -0
- package/dist/core/server/fleet/supervisor.test.d.ts +1 -0
- package/dist/core/server/pageServer.js +34 -5
- package/dist/core/services/action.js +10 -2
- package/dist/core/services/functionRoutes.d.ts +9 -0
- package/dist/core/services/functionRoutes.js +47 -0
- package/dist/core/services/realtime.d.ts +8 -0
- package/dist/core/services/realtime.js +57 -0
- package/dist/core/services/registry.js +6 -2
- package/dist/core/staticFiles.js +12 -4
- package/dist/core/staticFiles.test.d.ts +1 -0
- package/dist/core/transports.d.ts +13 -3
- package/dist/core/transports.js +14 -5
- package/dist/functions-api.d.ts +281 -0
- package/dist/functions.d.ts +19 -0
- package/dist/functions.js +5 -0
- package/dist/functionsRunner.d.ts +15 -0
- package/dist/functionsRunner.js +6 -0
- package/dist/handlers.d.ts +2 -2
- package/dist/handlers.js +2 -2
- package/dist/helpers/atomicFile.d.ts +10 -0
- package/dist/helpers/atomicFile.js +33 -0
- package/dist/helpers/atomicFile.test.d.ts +1 -0
- package/dist/helpers/buildResponseHelpers.js +35 -11
- package/dist/helpers/buildServerInfo.js +4 -2
- package/dist/helpers/buildServerInfo.test.d.ts +1 -0
- package/dist/helpers/cache/CompressedFileCache.d.ts +18 -0
- package/dist/helpers/cache/CompressedFileCache.js +44 -0
- package/dist/helpers/cache/CompressedFileCache.test.d.ts +1 -0
- package/dist/helpers/cache/cacheManager.d.ts +1 -1
- package/dist/helpers/cache/cacheManager.js +2 -1
- package/dist/helpers/cache/cacheManager.test.d.ts +1 -0
- package/dist/helpers/cache/index.d.ts +1 -1
- package/dist/helpers/cache/keys.d.ts +15 -1
- package/dist/helpers/cache/keys.js +47 -5
- package/dist/helpers/cache/serverCaches.d.ts +7 -1
- package/dist/helpers/compress.d.ts +3 -1
- package/dist/helpers/compress.js +11 -3
- package/dist/helpers/hydrationPayload.d.ts +11 -0
- package/dist/helpers/hydrationPayload.js +51 -0
- package/dist/helpers/hydrationPayload.test.d.ts +1 -0
- package/dist/helpers/metrics.d.ts +1 -1
- package/dist/helpers/metrics.js +3 -2
- package/dist/helpers/outboundGuard.d.ts +14 -6
- package/dist/helpers/outboundGuard.js +132 -8
- package/dist/helpers/paintedCookie.d.ts +8 -0
- package/dist/helpers/paintedCookie.js +13 -0
- package/dist/helpers/reportReactBuild.d.ts +9 -0
- package/dist/helpers/reportReactBuild.js +18 -0
- package/dist/helpers/reportReactBuild.test.d.ts +1 -0
- package/dist/helpers/serverLog.d.ts +25 -1
- package/dist/helpers/serverLog.js +68 -3
- package/dist/helpers/serverLog.test.d.ts +1 -0
- package/dist/helpers/wsFrame.d.ts +3 -0
- package/dist/helpers/wsFrame.js +5 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -2
- package/dist/kernel.d.ts +2 -1
- package/dist/kernel.js +3 -2
- package/dist/modules/actions/connectorWrite.js +2 -1
- package/dist/modules/actions/index.d.ts +29 -10
- package/dist/modules/actions/index.js +43 -6
- package/dist/modules/actions/jobs/failureStreak.d.ts +17 -0
- package/dist/modules/actions/jobs/failureStreak.js +47 -0
- package/dist/modules/actions/jobs/failureStreak.test.d.ts +1 -0
- package/dist/modules/actions/jobs/index.d.ts +2 -1
- package/dist/modules/actions/jobs/index.js +5 -3
- package/dist/modules/actions/jobs/memoryQueue.d.ts +3 -0
- package/dist/modules/actions/jobs/memoryQueue.js +17 -1
- package/dist/modules/actions/jobs/scheduler.d.ts +2 -0
- package/dist/modules/actions/jobs/scheduler.js +12 -7
- package/dist/modules/actions/jobs/worker.d.ts +3 -1
- package/dist/modules/actions/jobs/worker.js +9 -4
- package/dist/modules/actions/moduleFor.js +5 -2
- package/dist/modules/actions/runtime/errors.d.ts +12 -0
- package/dist/modules/actions/runtime/errors.js +16 -1
- package/dist/modules/actions/runtime/kvChange.d.ts +27 -0
- package/dist/modules/actions/runtime/kvChange.js +23 -0
- package/dist/modules/actions/runtime/kvList.d.ts +51 -0
- package/dist/modules/actions/runtime/kvList.js +52 -0
- package/dist/modules/actions/runtime/kvStore.d.ts +8 -0
- package/dist/modules/actions/runtime/kvStore.js +46 -20
- package/dist/modules/actions/runtime/memoryKv.d.ts +3 -0
- package/dist/modules/actions/runtime/memoryKv.js +19 -1
- package/dist/modules/actions/runtime/namespaceKv.d.ts +4 -6
- package/dist/modules/actions/runtime/namespaceKv.js +15 -3
- package/dist/modules/actions/runtime/namespaceKv.test.d.ts +1 -0
- package/dist/modules/actions/runtime/precheck.js +4 -8
- package/dist/modules/actions/runtime/rateLimit.d.ts +19 -0
- package/dist/modules/actions/runtime/rateLimit.js +19 -0
- package/dist/modules/actions/runtime/redisKv.d.ts +27 -0
- package/dist/modules/actions/runtime/redisKv.integration.test.d.ts +1 -0
- package/dist/modules/actions/runtime/redisKv.js +46 -0
- package/dist/modules/actions/runtime/report.js +2 -1
- package/dist/modules/actions/runtime/runAction.d.ts +10 -2
- package/dist/modules/actions/runtime/runAction.js +52 -116
- package/dist/modules/actions/runtime/runLogger.d.ts +5 -0
- package/dist/modules/actions/runtime/runLogger.js +8 -2
- package/dist/modules/actions/runtime/signing.d.ts +20 -0
- package/dist/modules/actions/runtime/signing.js +25 -0
- package/dist/modules/actions/runtime/signing.test.d.ts +1 -0
- package/dist/modules/actions/runtime/taskContext.d.ts +33 -0
- package/dist/modules/actions/runtime/taskContext.js +124 -0
- package/dist/modules/actions/tasks/builtins.js +5 -1
- package/dist/modules/actions/tasks/flow.js +81 -10
- package/dist/modules/actions/tasks/helpers.js +2 -2
- package/dist/modules/actions/tasks/http.js +2 -3
- package/dist/modules/actions/tasks/kv.js +39 -0
- package/dist/modules/actions/tasks/list.d.ts +2 -0
- package/dist/modules/actions/tasks/list.js +145 -0
- package/dist/modules/actions/tasks/realtime.d.ts +2 -0
- package/dist/modules/actions/tasks/realtime.js +104 -0
- package/dist/modules/actions/tasks/registry.d.ts +10 -1
- package/dist/modules/actions/tasks/registry.js +17 -6
- package/dist/modules/actions/transport/callHandler.js +5 -2
- package/dist/modules/actions/transport/catalogHandler.d.ts +5 -2
- package/dist/modules/actions/transport/catalogHandler.js +3 -2
- package/dist/modules/actions/transport/stream.d.ts +4 -5
- package/dist/modules/actions/transport/stream.js +12 -76
- package/dist/modules/actions/transport/webhookHandler.js +4 -3
- package/dist/modules/actions/types.d.ts +86 -3
- package/dist/modules/connectors/engine.js +3 -5
- package/dist/modules/functions/build.d.ts +22 -0
- package/dist/modules/functions/build.js +122 -0
- package/dist/modules/functions/build.test.d.ts +1 -0
- package/dist/modules/functions/capabilities.d.ts +22 -0
- package/dist/modules/functions/capabilities.js +228 -0
- package/dist/modules/functions/config.d.ts +34 -0
- package/dist/modules/functions/config.js +24 -0
- package/dist/modules/functions/context.d.ts +17 -0
- package/dist/modules/functions/context.js +88 -0
- package/dist/modules/functions/contract.d.ts +121 -0
- package/dist/modules/functions/contract.js +9 -0
- package/dist/modules/functions/driver.d.ts +36 -0
- package/dist/modules/functions/driver.js +150 -0
- package/dist/modules/functions/load.d.ts +15 -0
- package/dist/modules/functions/load.js +45 -0
- package/dist/modules/functions/load.test.d.ts +1 -0
- package/dist/modules/functions/local.d.ts +29 -0
- package/dist/modules/functions/local.js +61 -0
- package/dist/modules/functions/local.test.d.ts +1 -0
- package/dist/modules/functions/manifest.d.ts +24 -0
- package/dist/modules/functions/manifest.js +163 -0
- package/dist/modules/functions/manifest.test.d.ts +1 -0
- package/dist/modules/functions/native.d.ts +8 -0
- package/dist/modules/functions/native.js +21 -0
- package/dist/modules/functions/native.test.d.ts +1 -0
- package/dist/modules/functions/protocol.d.ts +216 -0
- package/dist/modules/functions/protocol.js +18 -0
- package/dist/modules/functions/routes.d.ts +36 -0
- package/dist/modules/functions/routes.js +181 -0
- package/dist/modules/functions/routes.test.d.ts +1 -0
- package/dist/modules/functions/runner/messages.d.ts +5 -0
- package/dist/modules/functions/runner/messages.js +188 -0
- package/dist/modules/functions/runner/remote.d.ts +19 -0
- package/dist/modules/functions/runner/remote.js +116 -0
- package/dist/modules/functions/runner/remote.test.d.ts +1 -0
- package/dist/modules/functions/runner/service.d.ts +32 -0
- package/dist/modules/functions/runner/service.js +209 -0
- package/dist/modules/functions/sandbox/guest.d.ts +45 -0
- package/dist/modules/functions/sandbox/guest.js +660 -0
- package/dist/modules/functions/sandbox/isolate.d.ts +37 -0
- package/dist/modules/functions/sandbox/isolate.js +347 -0
- package/dist/modules/functions/sandbox/isolate.test.d.ts +1 -0
- package/dist/modules/functions/sandbox/prelude.d.ts +2 -0
- package/dist/modules/functions/sandbox/prelude.js +49 -0
- package/dist/modules/functions/space.d.ts +40 -0
- package/dist/modules/functions/space.js +162 -0
- package/dist/modules/functions/testing/tasksOf.d.ts +4 -0
- package/dist/modules/functions/tryEntry.d.ts +9 -0
- package/dist/modules/functions/tryEntry.js +49 -0
- package/dist/modules/mongo/kv.js +31 -0
- package/dist/modules/mysql/accounts.js +19 -9
- package/dist/modules/mysql/index.d.ts +2 -1
- package/dist/modules/mysql/jobs/index.d.ts +1 -1
- package/dist/modules/mysql/jobs/kv.js +30 -0
- package/dist/modules/mysql/jobs/schema.d.ts +9 -0
- package/dist/modules/mysql/jobs/schema.js +21 -4
- package/dist/modules/mysql/schema.js +25 -0
- package/dist/modules/mysql/sessions.d.ts +1 -11
- package/dist/modules/mysql/sessions.js +6 -1
- package/dist/modules/realtime/declarations.d.ts +11 -0
- package/dist/modules/realtime/declarations.js +26 -0
- package/dist/modules/realtime/grants.d.ts +23 -0
- package/dist/modules/realtime/grants.js +61 -0
- package/dist/modules/realtime/handlers.d.ts +74 -0
- package/dist/modules/realtime/handlers.js +224 -0
- package/dist/modules/realtime/hub.d.ts +62 -0
- package/dist/modules/realtime/hub.js +141 -0
- package/dist/modules/realtime/index.d.ts +51 -0
- package/dist/modules/realtime/index.js +62 -0
- package/dist/modules/realtime/memoryPubSub.d.ts +10 -0
- package/dist/modules/realtime/memoryPubSub.js +43 -0
- package/dist/modules/realtime/realtime.test.d.ts +1 -0
- package/dist/modules/realtime/redisPubSub.d.ts +24 -0
- package/dist/modules/realtime/redisPubSub.js +36 -0
- package/dist/modules/realtime/redisPubSub.test.d.ts +1 -0
- package/dist/modules/realtime/socket.d.ts +25 -0
- package/dist/modules/realtime/socket.js +122 -0
- package/dist/modules/realtime/socket.test.d.ts +1 -0
- package/dist/modules/rsc/handler.d.ts +16 -0
- package/dist/modules/rsc/handler.js +17 -10
- package/dist/modules/rsc/handler.test.d.ts +1 -0
- package/dist/modules/rsc/resolveRscData.js +2 -1
- package/dist/modules/runtime/bundle.d.ts +24 -0
- package/dist/modules/runtime/bundle.js +102 -0
- package/dist/modules/runtime/contract.d.ts +37 -0
- package/dist/modules/runtime/contract.js +21 -0
- package/dist/modules/runtime/entry.test.d.ts +1 -0
- package/dist/modules/runtime/host.d.ts +38 -0
- package/dist/modules/runtime/host.js +68 -0
- package/dist/modules/runtime/inside.d.ts +15 -0
- package/dist/modules/runtime/inside.js +47 -0
- package/dist/modules/runtime/inside.test.d.ts +1 -0
- package/dist/modules/runtime/runner.d.ts +11 -0
- package/dist/modules/runtime/runner.js +38 -0
- package/dist/modules/runtime/runtime.test.d.ts +1 -0
- package/dist/modules/runtime/stages.d.ts +50 -0
- package/dist/modules/runtime/stages.js +117 -0
- package/dist/modules/ssr/Component.d.ts +3 -1
- package/dist/modules/ssr/Component.js +2 -1
- package/dist/modules/ssr/handler.js +10 -2
- package/dist/modules/ssr/loadPluginComponents.js +2 -1
- package/dist/modules/ssr/prepareRender.js +39 -10
- package/dist/modules/ssr/preview.d.ts +3 -0
- package/dist/modules/ssr/preview.js +17 -7
- package/dist/modules/ssr/redirect.test.d.ts +1 -0
- package/dist/modules/ssr/registerExternalPlugins.d.ts +6 -1
- package/dist/modules/ssr/registerExternalPlugins.js +19 -16
- package/dist/modules/ssr/registerExternalPlugins.test.d.ts +1 -0
- package/dist/modules/ssr/reportMissingPlugins.d.ts +9 -0
- package/dist/modules/ssr/reportMissingPlugins.js +24 -0
- package/dist/modules/ssr/reportMissingPlugins.test.d.ts +1 -0
- package/dist/modules/ssr/streamBody.d.ts +2 -2
- package/dist/modules/ssr/streamBody.js +4 -1
- package/dist/modules/ssr/template.js +1 -1
- package/dist/modules/ssr/views/template.ejs +8 -5
- package/dist/mysql.d.ts +1 -1
- package/dist/mysql.js +2 -2
- package/dist/oauth.js +2 -2
- package/dist/plugins/compile.js +9 -4
- package/dist/plugins/copy.js +3 -3
- package/dist/plugins/manager.d.ts +35 -3
- package/dist/plugins/manager.js +109 -38
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.js +7 -0
- package/package.json +39 -8
- package/skills/plitzi-authoring/SKILL.md +98 -14
- package/skills/plitzi-authoring/reference/accessibility.md +111 -0
- package/skills/plitzi-authoring/reference/authoring-errors.md +70 -0
- package/skills/plitzi-authoring/reference/data-and-visibility.md +84 -18
- package/skills/plitzi-authoring/reference/elements-and-styles.md +61 -7
- package/skills/plitzi-authoring/reference/flows.md +108 -17
- package/skills/plitzi-authoring/reference/lists.md +74 -0
- package/skills/plitzi-authoring/reference/performance.md +67 -0
- package/skills/plitzi-authoring/reference/plugins.md +167 -0
- package/skills/plitzi-authoring/reference/review-checklist.md +19 -2
- package/skills/plitzi-authoring/reference/templates.md +67 -27
- package/skills/plitzi-authoring/reference/testing.md +72 -5
- package/skills/plitzi-authoring/reference/validation.md +73 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
//#region src/modules/functions/driver.ts
|
|
2
|
+
/**
|
|
3
|
+
* What a definition declares, as the platform reads a manifest (`readManifest`) — nothing of it trusted there. Printed
|
|
4
|
+
* into the sandbox's guest and imported by a space runtime, like the driver below: self-contained for that.
|
|
5
|
+
*/
|
|
6
|
+
var describeFunctions = (definition) => {
|
|
7
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8
|
+
const listOf = (value) => Array.isArray(value) ? value : [];
|
|
9
|
+
const found = isRecord(definition) ? definition : {};
|
|
10
|
+
return {
|
|
11
|
+
hosts: listOf((isRecord(found.allow) ? found.allow : {}).hosts),
|
|
12
|
+
tasks: listOf(found.tasks).map((task) => isRecord(task) ? {
|
|
13
|
+
namespace: task.namespace,
|
|
14
|
+
action: task.action,
|
|
15
|
+
title: task.title,
|
|
16
|
+
description: task.description,
|
|
17
|
+
params: task.params
|
|
18
|
+
} : {}),
|
|
19
|
+
routes: isRecord(found.routes) ? Object.keys(found.routes) : []
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A space's functions, driven: one invocation of a definition — a task or a route, with a `ctx` whose every method is
|
|
24
|
+
* a call to the platform.
|
|
25
|
+
*
|
|
26
|
+
* The one driver there is. The sandbox's guest is handed this function's SOURCE and runs it inside the isolate
|
|
27
|
+
* (`isolate.ts`), and a space runtime imports it and runs it in its own process — so code behaves the same in both, down
|
|
28
|
+
* to `ctx`. Self-contained by contract for that: no import, nothing of this module's, only what `environment` brings.
|
|
29
|
+
*/
|
|
30
|
+
var createFunctionsDriver = (environment) => {
|
|
31
|
+
const { call, signal, responseOf, requestOf, wireOfResponse, refusal } = environment;
|
|
32
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33
|
+
const isCallable = (value) => typeof value === "function";
|
|
34
|
+
const listOf = (value) => Array.isArray(value) ? value : [];
|
|
35
|
+
/** A value as the wire can carry it; how a line reads is the platform's (`lineOf`), not the driver's. */
|
|
36
|
+
const wireValue = (value) => {
|
|
37
|
+
if (value instanceof Error) return `${value.name}: ${value.message}`;
|
|
38
|
+
if (value === void 0 || typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") return typeof value;
|
|
39
|
+
return value;
|
|
40
|
+
};
|
|
41
|
+
/** `ctx.log`, and whatever else the code writes a line with: onto its step, never failing the code for it. */
|
|
42
|
+
const log = (...values) => {
|
|
43
|
+
call({
|
|
44
|
+
op: "log",
|
|
45
|
+
values: values.map(wireValue)
|
|
46
|
+
}).catch(() => void 0);
|
|
47
|
+
};
|
|
48
|
+
const contextOf = (invocation) => {
|
|
49
|
+
const facts = isRecord(invocation.context) ? invocation.context : {};
|
|
50
|
+
const kvCall = (method) => (...args) => call({
|
|
51
|
+
op: "kv",
|
|
52
|
+
method,
|
|
53
|
+
args
|
|
54
|
+
});
|
|
55
|
+
const kv = {
|
|
56
|
+
get: kvCall("get"),
|
|
57
|
+
set: kvCall("set"),
|
|
58
|
+
delete: kvCall("delete"),
|
|
59
|
+
increment: kvCall("increment"),
|
|
60
|
+
swap: (key, expected, next, ttlSeconds) => kvCall("swap")(key, expected, next, ttlSeconds).then((written) => written === true),
|
|
61
|
+
listPut: kvCall("listPut"),
|
|
62
|
+
listRange: kvCall("listRange"),
|
|
63
|
+
listRemove: kvCall("listRemove"),
|
|
64
|
+
change: (key, change, lifetime) => environment.changeKv(kv, key, change, {
|
|
65
|
+
lifetime,
|
|
66
|
+
refusal
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
...facts,
|
|
71
|
+
kv,
|
|
72
|
+
fetch: async (url, init = {}) => {
|
|
73
|
+
const answer = await call({
|
|
74
|
+
op: "fetch",
|
|
75
|
+
url: String(url),
|
|
76
|
+
init
|
|
77
|
+
});
|
|
78
|
+
return responseOf(isRecord(answer) ? answer : {});
|
|
79
|
+
},
|
|
80
|
+
publish: async (topic, type, data) => {
|
|
81
|
+
await call({
|
|
82
|
+
op: "publish",
|
|
83
|
+
topic,
|
|
84
|
+
type,
|
|
85
|
+
data
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
grant: (topic, ttlSeconds) => call({
|
|
89
|
+
op: "grant",
|
|
90
|
+
topic,
|
|
91
|
+
ttlSeconds
|
|
92
|
+
}),
|
|
93
|
+
revoke: async (topic, grant) => {
|
|
94
|
+
await call({
|
|
95
|
+
op: "revoke",
|
|
96
|
+
topic,
|
|
97
|
+
grant
|
|
98
|
+
});
|
|
99
|
+
},
|
|
100
|
+
rateLimit: (bucket, limit) => call({
|
|
101
|
+
op: "rateLimit",
|
|
102
|
+
bucket,
|
|
103
|
+
limit
|
|
104
|
+
}),
|
|
105
|
+
sign: (value) => call({
|
|
106
|
+
op: "sign",
|
|
107
|
+
value
|
|
108
|
+
}),
|
|
109
|
+
verify: (value, signature) => call({
|
|
110
|
+
op: "verify",
|
|
111
|
+
value,
|
|
112
|
+
signature
|
|
113
|
+
}),
|
|
114
|
+
log,
|
|
115
|
+
emit: (chunk) => {
|
|
116
|
+
call({
|
|
117
|
+
op: "emit",
|
|
118
|
+
chunk
|
|
119
|
+
}).catch(() => void 0);
|
|
120
|
+
},
|
|
121
|
+
signal
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
/** One invocation: what a task returned (`null` for nothing), or the wire response a route answered. */
|
|
125
|
+
const invoke = async (definition, invocation) => {
|
|
126
|
+
const found = isRecord(definition) ? definition : {};
|
|
127
|
+
const ctx = contextOf(invocation);
|
|
128
|
+
if (invocation.kind === "task") {
|
|
129
|
+
const task = listOf(found.tasks).find((entry) => isRecord(entry) && `${String(entry.namespace)}.${String(entry.action)}` === invocation.name);
|
|
130
|
+
if (!isRecord(task) || !isCallable(task.run)) throw new Error(`This space's functions have no task "${String(invocation.name)}"`);
|
|
131
|
+
const value = await task.run(isRecord(invocation.params) ? invocation.params : {}, ctx);
|
|
132
|
+
return value === void 0 ? null : value;
|
|
133
|
+
}
|
|
134
|
+
const handler = (isRecord(found.routes) ? found.routes : {})[String(invocation.key)];
|
|
135
|
+
if (!isCallable(handler)) throw new Error(`This space's functions have no route "${String(invocation.key)}"`);
|
|
136
|
+
const request = requestOf(isRecord(invocation.request) ? invocation.request : {});
|
|
137
|
+
const wire = await wireOfResponse(await handler(request, {
|
|
138
|
+
...ctx,
|
|
139
|
+
params: invocation.params
|
|
140
|
+
}));
|
|
141
|
+
if (!wire) throw new Error(`Route "${String(invocation.key)}" answered something that is not a Response`);
|
|
142
|
+
return wire;
|
|
143
|
+
};
|
|
144
|
+
return {
|
|
145
|
+
invoke,
|
|
146
|
+
log
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
//#endregion
|
|
150
|
+
export { createFunctionsDriver, describeFunctions };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FunctionsSource } from './build';
|
|
2
|
+
import { FunctionsDefinition } from './contract';
|
|
3
|
+
/**
|
|
4
|
+
* A `functions/` directory as a source — the files the platform's rule counts, by their path inside it: what a space's
|
|
5
|
+
* functions are saved as, and what `loadFunctions` builds.
|
|
6
|
+
*/
|
|
7
|
+
export declare const readFunctionsDir: (dir: string | URL) => Promise<FunctionsSource>;
|
|
8
|
+
/**
|
|
9
|
+
* A server's own functions from a directory — a project's `functions/`, the working copy `plitzi functions` keeps —
|
|
10
|
+
* built exactly as the platform builds a space's (the same rules, one bundle) and loaded natively, for
|
|
11
|
+
* `createServer({ functions: { native } })`. The same on `node src/main.ts` and on a compiled server: nothing here
|
|
12
|
+
* depends on how the server itself runs. A directory with nothing in it is no functions; one that does not build, or
|
|
13
|
+
* whose `index.ts` exports no definition, stops the server with where it is wrong.
|
|
14
|
+
*/
|
|
15
|
+
export declare const loadFunctions: (dir: string | URL) => Promise<FunctionsDefinition[]>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { buildFunctions } from "./build.js";
|
|
2
|
+
import { readFunctionsSource } from "@plitzi/sdk-shared/actions";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
5
|
+
//#region src/modules/functions/load.ts
|
|
6
|
+
var nodeReader = {
|
|
7
|
+
list: async (dir) => (await readdir(dir, { withFileTypes: true })).map((entry) => ({
|
|
8
|
+
name: entry.name,
|
|
9
|
+
directory: entry.isDirectory()
|
|
10
|
+
})),
|
|
11
|
+
read: (file) => readFile(file, "utf8")
|
|
12
|
+
};
|
|
13
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14
|
+
/** Whether a module's default export has a definition's shape: what a server can register without surprises. */
|
|
15
|
+
var isFunctionsDefinition = (value) => {
|
|
16
|
+
if (!isRecord(value)) return false;
|
|
17
|
+
const { tasks, routes, allow } = value;
|
|
18
|
+
const tasksOk = tasks === void 0 || Array.isArray(tasks) && tasks.every((task) => isRecord(task) && typeof task.run === "function");
|
|
19
|
+
const routesOk = routes === void 0 || isRecord(routes) && Object.values(routes).every((route) => typeof route === "function");
|
|
20
|
+
const allowOk = allow === void 0 || isRecord(allow) && (allow.hosts === void 0 || Array.isArray(allow.hosts) && allow.hosts.every((host) => typeof host === "string"));
|
|
21
|
+
return tasksOk && routesOk && allowOk;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* A `functions/` directory as a source — the files the platform's rule counts, by their path inside it: what a space's
|
|
25
|
+
* functions are saved as, and what `loadFunctions` builds.
|
|
26
|
+
*/
|
|
27
|
+
var readFunctionsDir = (dir) => readFunctionsSource(typeof dir === "string" ? dir : fileURLToPath(dir), nodeReader);
|
|
28
|
+
/**
|
|
29
|
+
* A server's own functions from a directory — a project's `functions/`, the working copy `plitzi functions` keeps —
|
|
30
|
+
* built exactly as the platform builds a space's (the same rules, one bundle) and loaded natively, for
|
|
31
|
+
* `createServer({ functions: { native } })`. The same on `node src/main.ts` and on a compiled server: nothing here
|
|
32
|
+
* depends on how the server itself runs. A directory with nothing in it is no functions; one that does not build, or
|
|
33
|
+
* whose `index.ts` exports no definition, stops the server with where it is wrong.
|
|
34
|
+
*/
|
|
35
|
+
var loadFunctions = async (dir) => {
|
|
36
|
+
const source = await readFunctionsDir(dir);
|
|
37
|
+
if (!Object.keys(source).length) return [];
|
|
38
|
+
const { code } = await buildFunctions(source);
|
|
39
|
+
const loaded = await import(`data:text/javascript;base64,${Buffer.from(code).toString("base64")}`);
|
|
40
|
+
const definition = isRecord(loaded) ? loaded.default : void 0;
|
|
41
|
+
if (!isFunctionsDefinition(definition)) throw new Error("functions/index.ts exports its definition by default: export default defineFunctions({ … })");
|
|
42
|
+
return [definition];
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
export { loadFunctions, readFunctionsDir };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FunctionsSource } from './build';
|
|
2
|
+
import { FunctionLimits } from './protocol';
|
|
3
|
+
import { ActionRunResult } from '../actions';
|
|
4
|
+
import { FunctionsProblem } from '@plitzi/sdk-shared';
|
|
5
|
+
export type LocalFunctionsOptions = {
|
|
6
|
+
/** Credentials `ctx.fetch` may name, by id — a project's own, from its environment; none by default. */
|
|
7
|
+
credentials?: Record<string, Record<string, string>>;
|
|
8
|
+
/** As the platform's: a plan's limits, for code that must fit them there. */
|
|
9
|
+
limits?: Partial<FunctionLimits>;
|
|
10
|
+
fetchImpl?: typeof fetch;
|
|
11
|
+
};
|
|
12
|
+
export type LocalFunctions = {
|
|
13
|
+
/** Builds and checks the source as the platform does, and keeps it as what `tryTask` runs. */
|
|
14
|
+
load: (source: FunctionsSource) => Promise<{
|
|
15
|
+
ok: true;
|
|
16
|
+
tasks: string[];
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
problems: FunctionsProblem[];
|
|
20
|
+
}>;
|
|
21
|
+
/** One task of what was loaded, in an isolate, with its value, logs and error — the platform's Try, here. */
|
|
22
|
+
tryTask: (task: string, params: Record<string, unknown>) => Promise<ActionRunResult>;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* A space's functions run on this machine exactly as the platform runs them — the same build, the same checks, the same
|
|
26
|
+
* isolates and limits, `ctx` over the same actions module — so what works here works there. `kv` lives as long as this
|
|
27
|
+
* does. What `plitzi functions dev` is made of; needs `isolated-vm` and `core-js` installed, as any runner does.
|
|
28
|
+
*/
|
|
29
|
+
export declare const createLocalFunctions: ({ credentials, limits, fetchImpl }?: LocalFunctionsOptions) => LocalFunctions;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { functionsInHand } from "./space.js";
|
|
2
|
+
import { createActionsModule } from "../actions/index.js";
|
|
3
|
+
import { functionTryEntry } from "./tryEntry.js";
|
|
4
|
+
import { createIsolateRunner } from "./sandbox/isolate.js";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
//#region src/modules/functions/local.ts
|
|
7
|
+
/** Who a local run is for: somebody signed in, with nothing to forward. */
|
|
8
|
+
var LOCAL_USER = {
|
|
9
|
+
id: 0,
|
|
10
|
+
username: "local",
|
|
11
|
+
email: "local@localhost",
|
|
12
|
+
verified: true,
|
|
13
|
+
permissions: [],
|
|
14
|
+
roles: [],
|
|
15
|
+
token: ""
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* A space's functions run on this machine exactly as the platform runs them — the same build, the same checks, the same
|
|
19
|
+
* isolates and limits, `ctx` over the same actions module — so what works here works there. `kv` lives as long as this
|
|
20
|
+
* does. What `plitzi functions dev` is made of; needs `isolated-vm` and `core-js` installed, as any runner does.
|
|
21
|
+
*/
|
|
22
|
+
var createLocalFunctions = ({ credentials = {}, limits, fetchImpl } = {}) => {
|
|
23
|
+
const runner = createIsolateRunner({ concurrency: 1 });
|
|
24
|
+
let loaded;
|
|
25
|
+
const module = createActionsModule({
|
|
26
|
+
lookups: {
|
|
27
|
+
getAction: () => Promise.resolve(void 0),
|
|
28
|
+
getCredential: (_spaceId, identifier) => Promise.resolve(Object.hasOwn(credentials, identifier) ? credentials[identifier] : void 0),
|
|
29
|
+
getFunctions: () => Promise.resolve(loaded)
|
|
30
|
+
},
|
|
31
|
+
functions: {
|
|
32
|
+
runner,
|
|
33
|
+
...limits ? { limits } : {}
|
|
34
|
+
},
|
|
35
|
+
jobs: false,
|
|
36
|
+
...fetchImpl ? { fetchImpl } : {}
|
|
37
|
+
});
|
|
38
|
+
return {
|
|
39
|
+
load: async (source) => {
|
|
40
|
+
const prepared = await module.prepareFunctions(source);
|
|
41
|
+
if (!prepared.ok) return prepared;
|
|
42
|
+
loaded = functionsInHand(prepared.functions);
|
|
43
|
+
return {
|
|
44
|
+
ok: true,
|
|
45
|
+
tasks: prepared.functions.manifest.tasks.map((task) => `${task.namespace}.${task.action}`)
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
tryTask: (task, params) => module.runAction({
|
|
49
|
+
entry: functionTryEntry(task, params),
|
|
50
|
+
input: {},
|
|
51
|
+
callerId: "local",
|
|
52
|
+
user: LOCAL_USER,
|
|
53
|
+
spaceId: 0,
|
|
54
|
+
environment: "main",
|
|
55
|
+
trigger: "call",
|
|
56
|
+
runId: randomUUID()
|
|
57
|
+
})
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
//#endregion
|
|
61
|
+
export { createLocalFunctions };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FunctionsManifest } from '@plitzi/sdk-shared';
|
|
2
|
+
export declare const ROUTE_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
3
|
+
export type RouteMethod = (typeof ROUTE_METHODS)[number];
|
|
4
|
+
export type RouteKey = {
|
|
5
|
+
method: RouteMethod;
|
|
6
|
+
segments: string[];
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* A route key, `'<METHOD> /<path>'`: literal segments and `:params`, served under `/api/`. Anything else — a query, a
|
|
10
|
+
* wildcard, `..` — is not a key, so what a space may answer is only ever a path it spelled out.
|
|
11
|
+
*/
|
|
12
|
+
export declare const parseRouteKey: (key: string) => RouteKey | undefined;
|
|
13
|
+
export type ManifestReading = {
|
|
14
|
+
manifest: FunctionsManifest;
|
|
15
|
+
problems: string[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Reads what a bundle said it declares, and every rule it must meet — the one validator, at save and nowhere else
|
|
19
|
+
* afterwards, because what is stored is only ever what passed it.
|
|
20
|
+
*
|
|
21
|
+
* `reserved` is every namespace this deployment's own tasks use: a space's task may take none of them, so a step that
|
|
22
|
+
* names a platform task always runs the platform's.
|
|
23
|
+
*/
|
|
24
|
+
export declare const readManifest: (value: unknown, reserved: ReadonlySet<string>) => ManifestReading;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { taskName, taskNameProblem } from "../actions/tasks/registry.js";
|
|
2
|
+
//#region src/modules/functions/manifest.ts
|
|
3
|
+
var ROUTE_METHODS = [
|
|
4
|
+
"GET",
|
|
5
|
+
"POST",
|
|
6
|
+
"PUT",
|
|
7
|
+
"PATCH",
|
|
8
|
+
"DELETE"
|
|
9
|
+
];
|
|
10
|
+
var SEGMENT = /^(:[a-zA-Z][a-zA-Z0-9]*|[A-Za-z0-9._~-]+)$/;
|
|
11
|
+
var isRouteMethod = (method) => ROUTE_METHODS.some((known) => known === method);
|
|
12
|
+
/**
|
|
13
|
+
* A route key, `'<METHOD> /<path>'`: literal segments and `:params`, served under `/api/`. Anything else — a query, a
|
|
14
|
+
* wildcard, `..` — is not a key, so what a space may answer is only ever a path it spelled out.
|
|
15
|
+
*/
|
|
16
|
+
var parseRouteKey = (key) => {
|
|
17
|
+
const [method = "", path = "", ...rest] = key.trim().split(/\s+/);
|
|
18
|
+
if (rest.length || !isRouteMethod(method) || !path.startsWith("/")) return;
|
|
19
|
+
const segments = path.slice(1).split("/");
|
|
20
|
+
if (!segments.every((segment) => SEGMENT.test(segment) && segment !== "." && segment !== "..")) return;
|
|
21
|
+
return {
|
|
22
|
+
method,
|
|
23
|
+
segments
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
var HOST = /^(\*\.)?([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}$/;
|
|
27
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28
|
+
var stringOf = (value) => typeof value === "string" ? value : void 0;
|
|
29
|
+
var optionsOf = (value) => Array.isArray(value) ? value.flatMap((option) => {
|
|
30
|
+
const label = isRecord(option) ? stringOf(option.label) : void 0;
|
|
31
|
+
const optionValue = isRecord(option) ? stringOf(option.value) : void 0;
|
|
32
|
+
return label !== void 0 && optionValue !== void 0 ? [{
|
|
33
|
+
label,
|
|
34
|
+
value: optionValue
|
|
35
|
+
}] : [];
|
|
36
|
+
}) : void 0;
|
|
37
|
+
/**
|
|
38
|
+
* One param, rebuilt from what the bundle said rather than trusted: only the serializable shapes a step editor draws.
|
|
39
|
+
* A computed `type`, `when` or `options` is code, and a bundle's code runs in the sandbox, never in the builder.
|
|
40
|
+
*/
|
|
41
|
+
var paramOf = (value) => {
|
|
42
|
+
if (!isRecord(value)) return "is not an object";
|
|
43
|
+
const base = {
|
|
44
|
+
...typeof value.canBind === "boolean" ? { canBind: value.canBind } : {},
|
|
45
|
+
...typeof value.label === "string" ? { label: value.label } : {},
|
|
46
|
+
...typeof value.when === "boolean" ? { when: value.when } : {}
|
|
47
|
+
};
|
|
48
|
+
const defaultValue = value.defaultValue;
|
|
49
|
+
switch (value.type) {
|
|
50
|
+
case "text":
|
|
51
|
+
case "textarea": return {
|
|
52
|
+
...base,
|
|
53
|
+
type: value.type,
|
|
54
|
+
...typeof defaultValue === "string" || typeof defaultValue === "number" ? { defaultValue } : {}
|
|
55
|
+
};
|
|
56
|
+
case "codemirror-text":
|
|
57
|
+
case "codemirror-json": return {
|
|
58
|
+
...base,
|
|
59
|
+
type: value.type,
|
|
60
|
+
...typeof defaultValue === "string" ? { defaultValue } : {}
|
|
61
|
+
};
|
|
62
|
+
case "boolean": return {
|
|
63
|
+
...base,
|
|
64
|
+
type: "boolean",
|
|
65
|
+
...typeof defaultValue === "boolean" ? { defaultValue } : {}
|
|
66
|
+
};
|
|
67
|
+
case "elements": return {
|
|
68
|
+
...base,
|
|
69
|
+
type: "elements",
|
|
70
|
+
...Array.isArray(defaultValue) ? { defaultValue: defaultValue.filter((id) => typeof id === "string") } : {},
|
|
71
|
+
...typeof value.elementType === "string" ? { elementType: value.elementType } : {}
|
|
72
|
+
};
|
|
73
|
+
case "select": {
|
|
74
|
+
const options = optionsOf(value.options);
|
|
75
|
+
if (!options?.length) return "is a select with no options";
|
|
76
|
+
return {
|
|
77
|
+
...base,
|
|
78
|
+
type: "select",
|
|
79
|
+
options,
|
|
80
|
+
...typeof defaultValue === "string" ? { defaultValue } : {}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
default: return `has a type the builder cannot draw ("${String(value.type)}"): text, textarea, codemirror-text, codemirror-json, boolean, elements or select`;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Reads what a bundle said it declares, and every rule it must meet — the one validator, at save and nowhere else
|
|
88
|
+
* afterwards, because what is stored is only ever what passed it.
|
|
89
|
+
*
|
|
90
|
+
* `reserved` is every namespace this deployment's own tasks use: a space's task may take none of them, so a step that
|
|
91
|
+
* names a platform task always runs the platform's.
|
|
92
|
+
*/
|
|
93
|
+
var readManifest = (value, reserved) => {
|
|
94
|
+
const problems = [];
|
|
95
|
+
const raw = isRecord(value) ? value : {};
|
|
96
|
+
const hosts = Array.isArray(raw.hosts) ? raw.hosts.filter((host) => typeof host === "string") : [];
|
|
97
|
+
hosts.filter((host) => !HOST.test(host)).forEach((host) => {
|
|
98
|
+
problems.push(`allow.hosts: "${host}" is not a hostname (a name like api.example.com, or *.example.com)`);
|
|
99
|
+
});
|
|
100
|
+
const tasks = [];
|
|
101
|
+
const names = /* @__PURE__ */ new Set();
|
|
102
|
+
(Array.isArray(raw.tasks) ? raw.tasks : []).forEach((entry, index) => {
|
|
103
|
+
const task = isRecord(entry) ? entry : {};
|
|
104
|
+
const namespace = stringOf(task.namespace) ?? "";
|
|
105
|
+
const action = stringOf(task.action) ?? "";
|
|
106
|
+
const title = stringOf(task.title) ?? "";
|
|
107
|
+
const where = namespace && action ? `Task "${namespace}.${action}"` : `tasks[${String(index)}]`;
|
|
108
|
+
const nameProblem = taskNameProblem({
|
|
109
|
+
namespace,
|
|
110
|
+
action
|
|
111
|
+
}, reserved);
|
|
112
|
+
if (nameProblem) {
|
|
113
|
+
problems.push(nameProblem);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const name = taskName({
|
|
117
|
+
namespace,
|
|
118
|
+
action
|
|
119
|
+
});
|
|
120
|
+
if (names.has(name)) {
|
|
121
|
+
problems.push(`${where} is declared twice`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
names.add(name);
|
|
125
|
+
if (!title) problems.push(`${where} has no title`);
|
|
126
|
+
const params = {};
|
|
127
|
+
Object.entries(isRecord(task.params) ? task.params : {}).forEach(([key, param]) => {
|
|
128
|
+
const read = paramOf(param);
|
|
129
|
+
if (typeof read === "string") problems.push(`${where}: param "${key}" ${read}`);
|
|
130
|
+
else params[key] = read;
|
|
131
|
+
});
|
|
132
|
+
const description = stringOf(task.description);
|
|
133
|
+
tasks.push({
|
|
134
|
+
namespace,
|
|
135
|
+
action,
|
|
136
|
+
title,
|
|
137
|
+
...description ? { description } : {},
|
|
138
|
+
params
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
const routes = Array.isArray(raw.routes) ? raw.routes.filter((route) => typeof route === "string") : [];
|
|
142
|
+
const routed = /* @__PURE__ */ new Set();
|
|
143
|
+
routes.forEach((route) => {
|
|
144
|
+
const key = parseRouteKey(route);
|
|
145
|
+
if (!key) {
|
|
146
|
+
problems.push(`Route "${route}" is not "<GET|POST|PUT|PATCH|DELETE> /<path>" of literal segments and :params`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const shape = `${key.method} /${key.segments.map((segment) => segment.startsWith(":") ? ":" : segment).join("/")}`;
|
|
150
|
+
if (routed.has(shape)) problems.push(`Route "${route}" answers the same requests as another one`);
|
|
151
|
+
routed.add(shape);
|
|
152
|
+
});
|
|
153
|
+
return {
|
|
154
|
+
manifest: {
|
|
155
|
+
hosts,
|
|
156
|
+
tasks,
|
|
157
|
+
routes
|
|
158
|
+
},
|
|
159
|
+
problems
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
//#endregion
|
|
163
|
+
export { ROUTE_METHODS, parseRouteKey, readManifest };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FunctionsDefinition } from './contract';
|
|
2
|
+
import { ActionTask } from '../actions/types';
|
|
3
|
+
/**
|
|
4
|
+
* A server's own functions, loaded as they are: trusted code the deployment ships — a self-hosted server's, or a
|
|
5
|
+
* platform's own — run in the process with the run's context narrowed to what a function may see. The same code a
|
|
6
|
+
* space runs in the sandbox, loaded without one.
|
|
7
|
+
*/
|
|
8
|
+
export declare const nativeTasks: (definitions?: readonly FunctionsDefinition[]) => ActionTask<Record<string, unknown>>[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { functionContextFor } from "./context.js";
|
|
2
|
+
//#region src/modules/functions/native.ts
|
|
3
|
+
/**
|
|
4
|
+
* A server's own functions, loaded as they are: trusted code the deployment ships — a self-hosted server's, or a
|
|
5
|
+
* platform's own — run in the process with the run's context narrowed to what a function may see. The same code a
|
|
6
|
+
* space runs in the sandbox, loaded without one.
|
|
7
|
+
*/
|
|
8
|
+
var nativeTasks = (definitions = []) => definitions.flatMap((definition) => (definition.tasks ?? []).map((task) => {
|
|
9
|
+
const contextFor = (ctx) => functionContextFor(ctx, definition.allow?.hosts ?? []);
|
|
10
|
+
const { run, params } = task;
|
|
11
|
+
return {
|
|
12
|
+
namespace: task.namespace,
|
|
13
|
+
action: task.action,
|
|
14
|
+
title: task.title,
|
|
15
|
+
...task.description ? { description: task.description } : {},
|
|
16
|
+
params,
|
|
17
|
+
run: (values, ctx) => run(values, contextFor(ctx))
|
|
18
|
+
};
|
|
19
|
+
}));
|
|
20
|
+
//#endregion
|
|
21
|
+
export { nativeTasks };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|