@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
|
@@ -1,7 +1,5 @@
|
|
|
1
|
+
import { openEventStream } from "../../../core/http/sse.js";
|
|
1
2
|
//#region src/modules/actions/transport/stream.ts
|
|
2
|
-
/** How often a comment frame goes out. Short enough that a dead peer is noticed in seconds, long enough that an
|
|
3
|
-
* idle stream costs nothing worth counting. */
|
|
4
|
-
var HEARTBEAT_MS = 15e3;
|
|
5
3
|
/**
|
|
6
4
|
* How long a hand-rolled `EventSource` waits before reconnecting, if one ever gets here.
|
|
7
5
|
*
|
|
@@ -11,84 +9,22 @@ var HEARTBEAT_MS = 15e3;
|
|
|
11
9
|
*/
|
|
12
10
|
var RETRY_MS = 864e5;
|
|
13
11
|
/**
|
|
14
|
-
*
|
|
12
|
+
* Opens a run's Server-Sent Events response.
|
|
15
13
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
var MAX_BUFFERED_BYTES = 1e6;
|
|
21
|
-
var encode = (frame) => `event: ${frame.event}\ndata: ${JSON.stringify(frame.data)}\n\n`;
|
|
22
|
-
/** What the host has written but not yet handed to the socket. Node's own response reports it; the minimum raw
|
|
23
|
-
* response this server accepts does not have to, and a host that cannot say simply never trips the cap. */
|
|
24
|
-
var bufferedBytes = (raw) => {
|
|
25
|
-
const { writableLength } = raw;
|
|
26
|
-
return typeof writableLength === "number" ? writableLength : 0;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Opens a Server-Sent Events response.
|
|
30
|
-
*
|
|
31
|
-
* Written straight to the RAW response, never through the response helpers: those compress the body, set a
|
|
32
|
-
* Content-Length and end it in one go, which is precisely what a stream cannot do. `no-transform` says the same
|
|
33
|
-
* thing to every proxy in between, and `X-Accel-Buffering: no` says it to nginx, which otherwise holds frames
|
|
34
|
-
* until its buffer fills and turns a live stream into one late burst.
|
|
14
|
+
* The run's id travels on the response head rather than in a frame: a streaming step returns as soon as the stream
|
|
15
|
+
* OPENS — that is what makes it a stream — so anything it learns from a frame arrives after the flow has already
|
|
16
|
+
* carried on. The head is the one place a caller can read the id in time to cancel the run it just started.
|
|
35
17
|
*/
|
|
36
18
|
var openStream = (raw, onAbort, runId) => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
Connection: "keep-alive",
|
|
42
|
-
"X-Accel-Buffering": "no",
|
|
43
|
-
/**
|
|
44
|
-
* The run's id, on the response head rather than in a frame.
|
|
45
|
-
*
|
|
46
|
-
* A streaming step returns as soon as the stream OPENS — that is what makes it a stream — so anything it
|
|
47
|
-
* learns from a frame arrives after the flow has already carried on. The head is the one place a caller can
|
|
48
|
-
* read the id in time to cancel the run it just started.
|
|
49
|
-
*/
|
|
50
|
-
"X-Plitzi-Run-Id": runId
|
|
19
|
+
const stream = openEventStream(raw, {
|
|
20
|
+
onAbort,
|
|
21
|
+
headers: { "X-Plitzi-Run-Id": runId },
|
|
22
|
+
retryMs: RETRY_MS
|
|
51
23
|
});
|
|
52
|
-
raw.write(`retry: ${RETRY_MS}\n\n`);
|
|
53
|
-
const heartbeat = setInterval(() => {
|
|
54
|
-
if (!open) return;
|
|
55
|
-
try {
|
|
56
|
-
raw.write(": ping\n\n");
|
|
57
|
-
} catch {
|
|
58
|
-
open = false;
|
|
59
|
-
clearInterval(heartbeat);
|
|
60
|
-
onAbort();
|
|
61
|
-
}
|
|
62
|
-
}, HEARTBEAT_MS);
|
|
63
|
-
const close = () => {
|
|
64
|
-
if (!open) return;
|
|
65
|
-
open = false;
|
|
66
|
-
clearInterval(heartbeat);
|
|
67
|
-
try {
|
|
68
|
-
raw.end();
|
|
69
|
-
} catch {}
|
|
70
|
-
};
|
|
71
24
|
return {
|
|
72
|
-
send: (frame) =>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
raw.write(encode(frame));
|
|
76
|
-
if (bufferedBytes(raw) > MAX_BUFFERED_BYTES) {
|
|
77
|
-
open = false;
|
|
78
|
-
clearInterval(heartbeat);
|
|
79
|
-
onAbort();
|
|
80
|
-
try {
|
|
81
|
-
raw.end();
|
|
82
|
-
} catch {}
|
|
83
|
-
}
|
|
84
|
-
} catch {
|
|
85
|
-
open = false;
|
|
86
|
-
clearInterval(heartbeat);
|
|
87
|
-
onAbort();
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
close,
|
|
91
|
-
isOpen: () => open
|
|
25
|
+
send: (frame) => stream.send(frame.event, frame.data),
|
|
26
|
+
close: stream.close,
|
|
27
|
+
isOpen: stream.isOpen
|
|
92
28
|
};
|
|
93
29
|
};
|
|
94
30
|
/** Whether this caller asked for a stream. The negotiation is the client's, so a page that cannot read one never
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { serverLog } from "../../../helpers/serverLog.js";
|
|
1
2
|
import { findTriggerNode, triggerParams } from "../runtime/triggers.js";
|
|
2
3
|
import { ActionRunError } from "../runtime/errors.js";
|
|
3
4
|
import { precheckRun } from "../runtime/precheck.js";
|
|
@@ -75,7 +76,7 @@ var handleActionWebhook = async (deps) => {
|
|
|
75
76
|
* one without a single line of it changing. Fail closed, and say which document to fix.
|
|
76
77
|
*/
|
|
77
78
|
if (triggerHasStaleVerify(stepParams)) {
|
|
78
|
-
|
|
79
|
+
serverLog.error("Actions", `webhook "${actionId}" in space ${spaceId} carries a signature check in a format nothing reads any more, so it is refused. Name the signing credential on the trigger step.`);
|
|
79
80
|
await reject("unverifiable", "The signature check is in a format nothing reads any more; name the signing credential on the trigger step");
|
|
80
81
|
send(res, 503, { error: "Unavailable" });
|
|
81
82
|
return;
|
|
@@ -99,7 +100,7 @@ var handleActionWebhook = async (deps) => {
|
|
|
99
100
|
const secret = await resolveSecret(verify, spaceId, config.action?.lookups?.getCredential);
|
|
100
101
|
const check = verifySignature(verify, secret, req.headers, rawBody);
|
|
101
102
|
if (!check.ok) {
|
|
102
|
-
|
|
103
|
+
serverLog.warn("Actions", `webhook "${actionId}" rejected: ${check.reason}`);
|
|
103
104
|
await reject("invalid_signature", check.reason);
|
|
104
105
|
send(res, 401, { error: "Invalid signature" });
|
|
105
106
|
return;
|
|
@@ -182,7 +183,7 @@ var handleActionWebhook = async (deps) => {
|
|
|
182
183
|
status: result.status
|
|
183
184
|
});
|
|
184
185
|
} catch (error) {
|
|
185
|
-
|
|
186
|
+
serverLog.error("Actions", "webhook run failed", error);
|
|
186
187
|
send(res, 500, { accepted: false });
|
|
187
188
|
} finally {
|
|
188
189
|
releaseAbort();
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { ActionEmailSender } from './runtime/email';
|
|
2
|
+
import { FunctionsConfig } from '../functions/config';
|
|
3
|
+
import { SpaceFunctions } from '../functions/protocol';
|
|
4
|
+
import { KvChangeLifetime } from './runtime/kvChange';
|
|
5
|
+
import { KvListEntry, KvListPut, KvListPutOptions, KvListRange } from './runtime/kvList';
|
|
6
|
+
import { SpaceSigning } from './runtime/signing';
|
|
2
7
|
import { ActionEmailConfig, ActionJobQueue, ActionEntry, ActionLimits, ActionRejectRecord, ActionRunRecord, ActionRunStatus, ActionRunStep, ActionTriggerType, ConnectorManifest, Environment, InteractionCallbackParam, InteractionNode, InteractionNodeStatus, SpaceRevision, SSRUser } from '@plitzi/sdk-shared';
|
|
3
8
|
/** Resolved secret material, as the connector engine already models it. */
|
|
4
9
|
export type ActionCredential = Record<string, string>;
|
|
@@ -31,7 +36,7 @@ export type ActionDbDriver = {
|
|
|
31
36
|
/**
|
|
32
37
|
* Where a deployment keeps the `kv` tasks' data — Redis, Memcached, a table, whatever it already runs.
|
|
33
38
|
*
|
|
34
|
-
* Deliberately the DUMBEST possible surface:
|
|
39
|
+
* Deliberately the DUMBEST possible surface: six operations over strings, with no rule to obey. Everything that
|
|
35
40
|
* decides how a counter behaves — the key prefixing, the JSON round trip, and the one rule a rate limit lives or
|
|
36
41
|
* dies by — is `createKvStore`'s, above this. An adapter that had to remember "extend the TTL only when the
|
|
37
42
|
* counter did not exist" would be an adapter each deployment gets to write that rule wrongly in.
|
|
@@ -48,6 +53,12 @@ export type ActionKvAdapter = {
|
|
|
48
53
|
increment: (key: string, amount: number) => Promise<number>;
|
|
49
54
|
/** Sets a lifetime on a key that already exists. When to call it is decided above, never here. */
|
|
50
55
|
expire: (key: string, ttlSeconds: number) => Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Writes `next` only if the key still holds `expected` — or, with `expected` undefined, only if it holds nothing (a
|
|
58
|
+
* key past its lifetime holds nothing). Answers whether it wrote. Must be atomic: it is what lets two writers
|
|
59
|
+
* read, change and write the same value without one of them silently undoing the other.
|
|
60
|
+
*/
|
|
61
|
+
swap: (key: string, expected: string | undefined, next: string, ttlSeconds?: number) => Promise<boolean>;
|
|
51
62
|
};
|
|
52
63
|
/**
|
|
53
64
|
* The `kv` tasks' own view: values rather than strings, and a TTL that means what a caller expects.
|
|
@@ -60,6 +71,27 @@ export type ActionKvStore = {
|
|
|
60
71
|
set: (key: string, value: unknown, ttlSeconds?: number) => Promise<void>;
|
|
61
72
|
delete: (key: string) => Promise<void>;
|
|
62
73
|
increment: (key: string, amount: number, ttlSeconds?: number) => Promise<number>;
|
|
74
|
+
/**
|
|
75
|
+
* Writes `next` only if the key still holds `expected` — the value `get` answered — or, with `expected` undefined,
|
|
76
|
+
* only if it holds nothing. Answers whether it wrote: read, change, and write back with this, and a writer that
|
|
77
|
+
* lost the race is told so instead of undoing the other.
|
|
78
|
+
*/
|
|
79
|
+
swap: (key: string, expected: unknown, next: unknown, ttlSeconds?: number) => Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* Puts `entry` in the list — replacing the one with its id — keeping the highest `keep` by score, and answers what
|
|
82
|
+
* that dropped, for whatever it named to be let go of too. A list has no lifetime: it lives until its entries are
|
|
83
|
+
* removed.
|
|
84
|
+
*/
|
|
85
|
+
listPut: (list: string, entry: KvListEntry, options?: KvListPutOptions) => Promise<KvListPut>;
|
|
86
|
+
listRange: (list: string, range?: KvListRange) => Promise<KvListEntry[]>;
|
|
87
|
+
/** Takes the entry with `id` out of the list, and answers whether it was there. */
|
|
88
|
+
listRemove: (list: string, id: string) => Promise<boolean>;
|
|
89
|
+
/**
|
|
90
|
+
* Reads the key, hands its value to `change` and writes back what that answers — reading and asking again when
|
|
91
|
+
* somebody wrote in between, so no writer undoes another. `change` answering `undefined` writes nothing. Answers what
|
|
92
|
+
* was written. `lifetime` is seconds, or worked out from the value written.
|
|
93
|
+
*/
|
|
94
|
+
change: <T>(key: string, change: (current: unknown) => T | undefined | Promise<T | undefined>, lifetime?: KvChangeLifetime<T>) => Promise<T | undefined>;
|
|
63
95
|
};
|
|
64
96
|
/** Re-exported so the module's files import one place. One type for actions and connectors: it is one concept. */
|
|
65
97
|
export type { SpaceRevision } from '@plitzi/sdk-shared';
|
|
@@ -82,6 +114,12 @@ export type ActionLookups = {
|
|
|
82
114
|
listScheduledSpaces?: () => Promise<number[]>;
|
|
83
115
|
getCredential?: (spaceId: number, identifier: string) => Promise<ActionCredential | undefined>;
|
|
84
116
|
getConnector?: (spaceId: number, connectorId: string, at?: SpaceRevision) => Promise<ConnectorManifest | undefined>;
|
|
117
|
+
/**
|
|
118
|
+
* The space's own functions as of that revision — the bundle and what it declared when saved, run by the deployment's
|
|
119
|
+
* sandbox (`functions.runner`), or by the space's own runtime when it answers one with a `runner` of its own. Only
|
|
120
|
+
* asked when a run names a task the deployment does not have, or a request a path under `/api/`.
|
|
121
|
+
*/
|
|
122
|
+
getFunctions?: (spaceId: number, at?: SpaceRevision) => Promise<SpaceFunctions | undefined>;
|
|
85
123
|
};
|
|
86
124
|
/**
|
|
87
125
|
* The only door a task has to the outside world.
|
|
@@ -123,6 +161,41 @@ export type ActionTaskContext = {
|
|
|
123
161
|
email: ActionEmailSender;
|
|
124
162
|
/** Pushes a `data` frame to a streaming caller. A no-op when nobody negotiated a stream. */
|
|
125
163
|
emit: (chunk: unknown) => void;
|
|
164
|
+
/**
|
|
165
|
+
* A line for whoever reads the run: kept on the step that said it (`logs`), redacted like the rest of it, and shown
|
|
166
|
+
* wherever the run is — the builder's Try, the run history.
|
|
167
|
+
*/
|
|
168
|
+
log: (line: string) => void;
|
|
169
|
+
/**
|
|
170
|
+
* Publishes on one of this space's realtime channels, as the server — `undefined` when the server has none. What
|
|
171
|
+
* the `realtime.publish` task sends through.
|
|
172
|
+
*/
|
|
173
|
+
publish?: (topic: string, type: string, data: unknown) => Promise<void>;
|
|
174
|
+
/**
|
|
175
|
+
* A grant for one topic of a `grant: true` channel of this space — what `realtime.grant` hands the page, once the
|
|
176
|
+
* flow has decided the visitor may be there. `undefined` when the server has no realtime channels.
|
|
177
|
+
*/
|
|
178
|
+
grant?: (topic: string, ttlSeconds?: number) => Promise<string>;
|
|
179
|
+
/** Revokes `grant` for `topic` — or every grant for it, naming none — and lets go whoever is on it with one. */
|
|
180
|
+
revoke?: (topic: string, grant?: string) => Promise<void>;
|
|
181
|
+
/** Signs with the space's own key (`ActionsConfig.signingSecret`) — `undefined` when the deployment gave none. */
|
|
182
|
+
sign?: SpaceSigning['sign'];
|
|
183
|
+
verify?: SpaceSigning['verify'];
|
|
184
|
+
};
|
|
185
|
+
/** How the actions module reaches the server's realtime channels. Set by `createServer`, never by a deployment. */
|
|
186
|
+
export type ActionRealtime = {
|
|
187
|
+
publish: (space: {
|
|
188
|
+
spaceId: number;
|
|
189
|
+
environment: string;
|
|
190
|
+
}, topic: string, type: string, data: unknown) => Promise<void>;
|
|
191
|
+
grant: (space: {
|
|
192
|
+
spaceId: number;
|
|
193
|
+
environment: string;
|
|
194
|
+
}, topic: string, ttlSeconds?: number) => Promise<string>;
|
|
195
|
+
revoke: (space: {
|
|
196
|
+
spaceId: number;
|
|
197
|
+
environment: string;
|
|
198
|
+
}, topic: string, grant?: string) => Promise<void>;
|
|
126
199
|
};
|
|
127
200
|
/**
|
|
128
201
|
* One step a server action can take.
|
|
@@ -156,8 +229,8 @@ export type ActionTaskRegistry = {
|
|
|
156
229
|
/** What a deployment hands to `createServer` under `actions`. Absent → the module is never constructed. */
|
|
157
230
|
export type ActionsConfig = {
|
|
158
231
|
lookups: ActionLookups;
|
|
159
|
-
/**
|
|
160
|
-
|
|
232
|
+
/** Code of the server's own, and the sandbox for the spaces' — see `FunctionsConfig`. */
|
|
233
|
+
functions?: FunctionsConfig;
|
|
161
234
|
/** Ceilings a per-action document may tighten but never exceed. */
|
|
162
235
|
limits?: ActionLimits;
|
|
163
236
|
/** How many runs may be in flight at once. Counted per space and for the process as a whole. */
|
|
@@ -217,6 +290,14 @@ export type ActionsConfig = {
|
|
|
217
290
|
replayTtlMs?: number;
|
|
218
291
|
};
|
|
219
292
|
fetchImpl?: typeof fetch;
|
|
293
|
+
/** The server's realtime channels, for the `realtime.publish` task. Set by `createServer`. */
|
|
294
|
+
realtime?: ActionRealtime;
|
|
295
|
+
/**
|
|
296
|
+
* What each space's signatures are made from (`ctx.sign` / `ctx.verify` in its functions): at least 32 characters,
|
|
297
|
+
* the SAME on every replica — a key one signed is checked by whichever the next request reaches. Each space and
|
|
298
|
+
* environment signs with a key derived from it, so none can vouch for another. Absent, spaces sign nothing.
|
|
299
|
+
*/
|
|
300
|
+
signingSecret?: string;
|
|
220
301
|
};
|
|
221
302
|
/**
|
|
222
303
|
* Scheduled runs: how they are produced, how many run at once, and where they are kept while they wait.
|
|
@@ -316,4 +397,6 @@ export type ActionRunResult = {
|
|
|
316
397
|
* anybody allowed to debug the page. The trace above is for authoring and development servers alone.
|
|
317
398
|
*/
|
|
318
399
|
steps: ActionRunStep[];
|
|
400
|
+
/** Why the run failed, when a step said so for the caller (`ActionRefusal`). Absent for every other failure. */
|
|
401
|
+
error?: string;
|
|
319
402
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fetchOutbound } from "../../helpers/outboundGuard.js";
|
|
2
2
|
import { getByPath } from "./getByPath.js";
|
|
3
3
|
import { processTwig } from "@plitzi/sdk-shared/helpers/twigWrapper";
|
|
4
4
|
import { BODYLESS_METHODS, DEFAULT_READ_ENDPOINT, EMPTY_RESPONSE_METHODS } from "@plitzi/sdk-shared/connectors";
|
|
@@ -150,7 +150,6 @@ var fetchConnectorRecords = async ({ manifest, endpoint = DEFAULT_READ_ENDPOINT,
|
|
|
150
150
|
...renderEntries(read.query ?? {}, variables),
|
|
151
151
|
...renderFilters(resolved, connection.operators, variables)
|
|
152
152
|
}).forEach(([key, value]) => url.searchParams.set(key, value));
|
|
153
|
-
await assertOutboundAllowed(url);
|
|
154
153
|
const method = read.method ?? "GET";
|
|
155
154
|
const headers = {
|
|
156
155
|
...applyAuth(connection, variables, url),
|
|
@@ -158,7 +157,7 @@ var fetchConnectorRecords = async ({ manifest, endpoint = DEFAULT_READ_ENDPOINT,
|
|
|
158
157
|
};
|
|
159
158
|
const sendsBody = !BODYLESS_METHODS.includes(method);
|
|
160
159
|
if (sendsBody) headers["Content-Type"] = "application/json";
|
|
161
|
-
const response = await fetchImpl
|
|
160
|
+
const response = await fetchOutbound(fetchImpl, url, {
|
|
162
161
|
method,
|
|
163
162
|
headers,
|
|
164
163
|
body: sendsBody ? JSON.stringify(renderEntries(read.body ?? {}, variables)) : void 0
|
|
@@ -202,13 +201,12 @@ var writeConnectorRecord = async ({ manifest, credential = {}, action, resource,
|
|
|
202
201
|
};
|
|
203
202
|
const url = new URL(render(operation.path, variables), connection.baseUrl);
|
|
204
203
|
Object.entries(renderEntries(operation.query ?? {}, variables)).forEach(([key, value]) => url.searchParams.set(key, value));
|
|
205
|
-
await assertOutboundAllowed(url);
|
|
206
204
|
const headers = {
|
|
207
205
|
...applyAuth(connection, variables, url),
|
|
208
206
|
...renderEntries(operation.headers ?? {}, variables)
|
|
209
207
|
};
|
|
210
208
|
headers["Content-Type"] = "application/json";
|
|
211
|
-
const response = await fetchImpl
|
|
209
|
+
const response = await fetchOutbound(fetchImpl, url, {
|
|
212
210
|
method: operation.method,
|
|
213
211
|
headers,
|
|
214
212
|
body: BODYLESS_METHODS.includes(operation.method) ? void 0 : JSON.stringify(wrapBody(values, operation.bodyPath))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FunctionsProblem } from '@plitzi/sdk-shared';
|
|
2
|
+
/** A space's functions source: its files under `functions/`, by path (`index.ts`, `lib/feed.ts`). */
|
|
3
|
+
export type FunctionsSource = Record<string, string>;
|
|
4
|
+
/** One bundle, built from a source: a single web-standard ES module whose default export is the definition. */
|
|
5
|
+
export type FunctionsBuild = {
|
|
6
|
+
code: string;
|
|
7
|
+
bytes: number;
|
|
8
|
+
};
|
|
9
|
+
export declare class FunctionsBuildError extends Error {
|
|
10
|
+
readonly problems: FunctionsProblem[];
|
|
11
|
+
constructor(problems: FunctionsProblem[]);
|
|
12
|
+
}
|
|
13
|
+
/** The file a space's functions start from. */
|
|
14
|
+
export declare const FUNCTIONS_ENTRY = "index.ts";
|
|
15
|
+
/** The most a bundle may weigh: well under the smallest provider a runner may be (Workers take 3 MB compressed). */
|
|
16
|
+
export declare const MAX_FUNCTIONS_BYTES = 1000000;
|
|
17
|
+
/**
|
|
18
|
+
* Builds a space's functions into one bundle — the only way code reaches a runner, so what runs is always what the
|
|
19
|
+
* source says. Web-standard and self-contained: the space's own files, and the contract; a Node built-in or any other
|
|
20
|
+
* package is refused with where it was imported, because no runner could provide it.
|
|
21
|
+
*/
|
|
22
|
+
export declare const buildFunctions: (source: FunctionsSource) => Promise<FunctionsBuild>;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ActionRefusal } from "../actions/runtime/errors.js";
|
|
2
|
+
import { defineFunctions } from "./contract.js";
|
|
3
|
+
import { isFunctionsSourcePath } from "@plitzi/sdk-shared/actions";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import esbuild from "esbuild";
|
|
6
|
+
//#region src/modules/functions/build.ts
|
|
7
|
+
var FunctionsBuildError = class extends Error {
|
|
8
|
+
problems;
|
|
9
|
+
constructor(problems) {
|
|
10
|
+
super(problems.map(({ file, line, message }) => file ? `${file}:${String(line ?? 0)} ${message}` : message).join("\n"));
|
|
11
|
+
this.name = "FunctionsBuildError";
|
|
12
|
+
this.problems = problems;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
/** The file a space's functions start from. */
|
|
16
|
+
var FUNCTIONS_ENTRY = "index.ts";
|
|
17
|
+
/** The most a bundle may weigh: well under the smallest provider a runner may be (Workers take 3 MB compressed). */
|
|
18
|
+
var MAX_FUNCTIONS_BYTES = 1e6;
|
|
19
|
+
/** The one package a space's code may import: the contract, which is all it needs of the platform. */
|
|
20
|
+
var CONTRACT_SPECIFIER = "@plitzi/sdk-server/functions";
|
|
21
|
+
/**
|
|
22
|
+
* What that import is inside a bundle: the contract's own `defineFunctions` and `ActionRefusal`, each printed from
|
|
23
|
+
* itself so there is one definition of it — an identity, and the class a refusal is told apart by (its name).
|
|
24
|
+
*/
|
|
25
|
+
var CONTRACT_MODULE = [`export const defineFunctions = ${defineFunctions.toString()};`, `export const ActionRefusal = ${ActionRefusal.toString()};`].join("\n");
|
|
26
|
+
var normalize = (file) => path.posix.normalize(file).replace(/^\.\//, "");
|
|
27
|
+
var sourceProblems = (source) => {
|
|
28
|
+
const problems = [];
|
|
29
|
+
for (const file of Object.keys(source)) if (!isFunctionsSourcePath(file)) problems.push({
|
|
30
|
+
file,
|
|
31
|
+
message: "A file is a relative path under functions/, ending in .ts, .js, .mjs or .json"
|
|
32
|
+
});
|
|
33
|
+
if (!("index.ts" in source)) problems.push({ message: `Functions start from ${FUNCTIONS_ENTRY}, which exports the definition by default` });
|
|
34
|
+
return problems;
|
|
35
|
+
};
|
|
36
|
+
var loaderOf = (file) => {
|
|
37
|
+
if (file.endsWith(".json")) return "json";
|
|
38
|
+
return file.endsWith(".ts") ? "ts" : "js";
|
|
39
|
+
};
|
|
40
|
+
/** Resolves every import against the space's own files, and the contract; nothing on the disk is ever read. */
|
|
41
|
+
var sourcePlugin = (files) => ({
|
|
42
|
+
name: "plitzi-functions-source",
|
|
43
|
+
setup: (build) => {
|
|
44
|
+
build.onResolve({ filter: /.*/ }, (args) => {
|
|
45
|
+
if (args.path === CONTRACT_SPECIFIER) return {
|
|
46
|
+
path: CONTRACT_SPECIFIER,
|
|
47
|
+
namespace: "contract"
|
|
48
|
+
};
|
|
49
|
+
if (args.kind !== "entry-point" && !args.path.startsWith(".")) return { errors: [{ text: `"${args.path}" cannot be imported: functions import their own files and ${CONTRACT_SPECIFIER}, nothing else` }] };
|
|
50
|
+
const base = args.kind === "entry-point" ? "." : path.posix.dirname(args.importer);
|
|
51
|
+
const wanted = normalize(path.posix.join(base, args.path));
|
|
52
|
+
const found = [
|
|
53
|
+
wanted,
|
|
54
|
+
`${wanted}.ts`,
|
|
55
|
+
`${wanted}.js`,
|
|
56
|
+
`${wanted}/index.ts`
|
|
57
|
+
].find((candidate) => files.has(candidate));
|
|
58
|
+
return found ? {
|
|
59
|
+
path: found,
|
|
60
|
+
namespace: "functions"
|
|
61
|
+
} : { errors: [{ text: `"${args.path}" is not a file of this space's functions` }] };
|
|
62
|
+
});
|
|
63
|
+
build.onLoad({
|
|
64
|
+
filter: /.*/,
|
|
65
|
+
namespace: "contract"
|
|
66
|
+
}, () => ({
|
|
67
|
+
contents: CONTRACT_MODULE,
|
|
68
|
+
loader: "js"
|
|
69
|
+
}));
|
|
70
|
+
build.onLoad({
|
|
71
|
+
filter: /.*/,
|
|
72
|
+
namespace: "functions"
|
|
73
|
+
}, (args) => ({
|
|
74
|
+
contents: files.get(args.path) ?? "",
|
|
75
|
+
loader: loaderOf(args.path),
|
|
76
|
+
resolveDir: "."
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
var isMessage = (value) => typeof value === "object" && value !== null && "text" in value && typeof value.text === "string";
|
|
81
|
+
var failureMessages = (error) => typeof error === "object" && error !== null && "errors" in error && Array.isArray(error.errors) ? error.errors.filter(isMessage) : [];
|
|
82
|
+
var problemOf = ({ location, text }) => location ? {
|
|
83
|
+
file: location.file.replace(/^functions:/, ""),
|
|
84
|
+
line: location.line,
|
|
85
|
+
column: location.column,
|
|
86
|
+
message: text
|
|
87
|
+
} : { message: text };
|
|
88
|
+
/**
|
|
89
|
+
* Builds a space's functions into one bundle — the only way code reaches a runner, so what runs is always what the
|
|
90
|
+
* source says. Web-standard and self-contained: the space's own files, and the contract; a Node built-in or any other
|
|
91
|
+
* package is refused with where it was imported, because no runner could provide it.
|
|
92
|
+
*/
|
|
93
|
+
var buildFunctions = async (source) => {
|
|
94
|
+
const problems = sourceProblems(source);
|
|
95
|
+
if (problems.length) throw new FunctionsBuildError(problems);
|
|
96
|
+
const files = new Map(Object.entries(source).map(([file, text]) => [normalize(file), text]));
|
|
97
|
+
let result;
|
|
98
|
+
try {
|
|
99
|
+
result = await esbuild.build({
|
|
100
|
+
entryPoints: [FUNCTIONS_ENTRY],
|
|
101
|
+
bundle: true,
|
|
102
|
+
write: false,
|
|
103
|
+
format: "esm",
|
|
104
|
+
platform: "neutral",
|
|
105
|
+
target: "es2022",
|
|
106
|
+
logLevel: "silent",
|
|
107
|
+
plugins: [sourcePlugin(files)]
|
|
108
|
+
});
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const messages = failureMessages(error);
|
|
111
|
+
throw new FunctionsBuildError(messages.length ? messages.map(problemOf) : [{ message: error instanceof Error ? error.message : "The build failed" }]);
|
|
112
|
+
}
|
|
113
|
+
const code = result.outputFiles[0]?.text ?? "";
|
|
114
|
+
const bytes = Buffer.byteLength(code);
|
|
115
|
+
if (bytes > 1e6) throw new FunctionsBuildError([{ message: `Functions are at most ${String(MAX_FUNCTIONS_BYTES)} bytes built, and these are ${String(bytes)}` }]);
|
|
116
|
+
return {
|
|
117
|
+
code,
|
|
118
|
+
bytes
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
//#endregion
|
|
122
|
+
export { FUNCTIONS_ENTRY, FunctionsBuildError, MAX_FUNCTIONS_BYTES, buildFunctions };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FunctionContext } from './contract';
|
|
2
|
+
import { FunctionCall, WireBody, WireRequest, WireResponse } from './protocol';
|
|
3
|
+
/** A body as the wire carries it: as text when its type says it is text, base64 otherwise. */
|
|
4
|
+
export declare const wireBodyOf: (body: Body, contentType: string | null) => Promise<WireBody | null>;
|
|
5
|
+
export declare const bodyOf: (body: WireBody | null) => string | Uint8Array<ArrayBuffer> | null;
|
|
6
|
+
export declare const wireResponseOf: (response: Response) => Promise<WireResponse>;
|
|
7
|
+
export declare const wireRequestOf: (request: Request) => Promise<WireRequest>;
|
|
8
|
+
export declare const responseOf: ({ status, statusText, headers, body }: WireResponse) => Response;
|
|
9
|
+
/** An answer that crossed a boundary as a wire response — from a space's code, or from the platform — read, not trusted. */
|
|
10
|
+
export declare const wireResponseFrom: (value: unknown) => WireResponse;
|
|
11
|
+
/** A request that crossed as a wire request, as a web `Request` again — what a route handler outside the sandbox takes. */
|
|
12
|
+
export declare const requestFromWire: (value: unknown) => Request;
|
|
13
|
+
/**
|
|
14
|
+
* A call as the code sent it, read into what it claims to be — every field checked, because it was written by the
|
|
15
|
+
* space's code and carried by a runner, and neither is trusted here. The only place a call is read.
|
|
16
|
+
*/
|
|
17
|
+
export declare const readCall: (value: unknown) => FunctionCall;
|
|
18
|
+
/**
|
|
19
|
+
* Answers one call from a space's code with the run's own {@link FunctionContext} — the same object a self-hosted
|
|
20
|
+
* server hands its functions, so the sandbox can do exactly what native code can and not one thing more.
|
|
21
|
+
*/
|
|
22
|
+
export declare const answerCall: (ctx: FunctionContext, call: FunctionCall) => Promise<unknown>;
|