@pulse-compute/cli 0.0.0 → 1.0.0-beta.1
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/API.md +539 -0
- package/CHANGELOG.md +47 -0
- package/README.md +70 -1
- package/bin/pulse.js +15 -0
- package/bin/pulsewasm-extract.js +22 -0
- package/cli-spec.json +575 -0
- package/completions/_pulse +106 -0
- package/completions/pulse.bash +31 -0
- package/completions/pulse.fish +76 -0
- package/docs/README.md +77 -0
- package/docs/architecture/current-contracts.md +381 -0
- package/docs/architecture/overview.md +93 -0
- package/docs/architecture/vision.md +515 -0
- package/docs/concepts/bodies.md +186 -0
- package/docs/concepts/compilation-and-lowering.md +496 -0
- package/docs/concepts/contracts-and-providers.md +158 -0
- package/docs/concepts/effects-and-continuations.md +243 -0
- package/docs/concepts/entities-and-adapters.md +71 -0
- package/docs/concepts/package-owned-lowering.md +175 -0
- package/docs/concepts/targets-and-hosts.md +62 -0
- package/docs/contributing/README.md +38 -0
- package/docs/contributing/adding-core-provider.md +315 -0
- package/docs/contributing/adding-first-party-lowerer.md +327 -0
- package/docs/contributing/entities-lowering.md +91 -0
- package/docs/contributing/package-lowerer-contract.md +383 -0
- package/docs/contributing/pulse-aware-packages.md +149 -0
- package/docs/examples.md +112 -0
- package/docs/fixtures/inspect-fetch-composition.selected.json +181 -0
- package/docs/getting-started.md +128 -0
- package/docs/guides/compatibility-imports.md +60 -0
- package/docs/guides/deploying-fastly.md +188 -0
- package/docs/guides/deploying-node.md +143 -0
- package/docs/guides/events.md +233 -0
- package/docs/guides/fastly-capabilities.md +153 -0
- package/docs/guides/fetching-and-composition.md +101 -0
- package/docs/guides/grip.md +94 -0
- package/docs/guides/json-schemas.md +233 -0
- package/docs/guides/migrating-from-express.md +192 -0
- package/docs/guides/project-lifecycle.md +143 -0
- package/docs/guides/routing.md +184 -0
- package/docs/guides/troubleshooting.md +47 -0
- package/docs/maintainers/README.md +60 -0
- package/docs/maintainers/codex-maintainer.md +71 -0
- package/docs/maintainers/documentation-deployment.md +147 -0
- package/docs/maintainers/documentation-system.md +58 -0
- package/docs/maintainers/documentation-versioning.md +65 -0
- package/docs/maintainers/maintainer-charter.md +84 -0
- package/docs/maintainers/maintenance-policy.json +778 -0
- package/docs/maintainers/maintenance-policy.md +124 -0
- package/docs/maintainers/npm-publishing.md +154 -0
- package/docs/maintainers/plugin-readiness.json +19 -0
- package/docs/maintainers/plugin-readiness.md +31 -0
- package/docs/maintainers/public-site.md +158 -0
- package/docs/maintainers/release-acceptance.md +250 -0
- package/docs/maintainers/release-manifest.md +88 -0
- package/docs/maintainers/repository-setup.md +145 -0
- package/docs/maintainers/scope-policy.md +93 -0
- package/docs/maintainers/support-and-triage.md +74 -0
- package/docs/maintainers/testing.md +288 -0
- package/docs/packages/README.md +59 -0
- package/docs/packages/assets.md +85 -0
- package/docs/packages/cli.md +190 -0
- package/docs/packages/crypto.md +71 -0
- package/docs/packages/entities.md +129 -0
- package/docs/packages/grip.md +82 -0
- package/docs/packages/implementation-packages.md +113 -0
- package/docs/packages/jwt.md +55 -0
- package/docs/packages/provider-fastly.md +217 -0
- package/docs/packages/pulse.md +159 -0
- package/docs/packages/runtime.md +256 -0
- package/docs/preview-scope.md +142 -0
- package/docs/reference/README.md +33 -0
- package/docs/reference/cli-spec.json +575 -0
- package/docs/reference/cli.md +457 -0
- package/docs/reference/compatibility-matrix.md +169 -0
- package/docs/reference/diagnostics.md +1872 -0
- package/docs/reference/documentation-versions.json +14 -0
- package/docs/reference/environment.md +347 -0
- package/docs/reference/handler-authoring.md +264 -0
- package/docs/reference/project-config.md +554 -0
- package/docs/reference/project-config.schema.json +918 -0
- package/docs/reference/release-manifest.json +427 -0
- package/docs/reference/shell-completion.md +23 -0
- package/documentation-site.json +661 -0
- package/documentation-versions.json +14 -0
- package/examples/01-hello-json/.pulse/.gitignore +3 -0
- package/examples/01-hello-json/.pulse/config.ts +16 -0
- package/examples/01-hello-json/README.md +119 -0
- package/examples/01-hello-json/package.json +20 -0
- package/examples/01-hello-json/src/index.ts +9 -0
- package/examples/01-hello-json/tests/pulse.harness.ts +22 -0
- package/examples/01-hello-json/tsconfig.json +14 -0
- package/examples/02-request-schema/.pulse/.gitignore +3 -0
- package/examples/02-request-schema/.pulse/config.ts +17 -0
- package/examples/02-request-schema/README.md +145 -0
- package/examples/02-request-schema/package.json +20 -0
- package/examples/02-request-schema/src/index.ts +18 -0
- package/examples/02-request-schema/src/schemas.ts +20 -0
- package/examples/02-request-schema/tests/pulse.harness.ts +37 -0
- package/examples/02-request-schema/tsconfig.json +14 -0
- package/examples/03-fetch-composition/.pulse/.gitignore +3 -0
- package/examples/03-fetch-composition/.pulse/config.ts +31 -0
- package/examples/03-fetch-composition/README.md +210 -0
- package/examples/03-fetch-composition/package.json +20 -0
- package/examples/03-fetch-composition/src/index.ts +60 -0
- package/examples/03-fetch-composition/tests/pulse.harness.ts +47 -0
- package/examples/03-fetch-composition/tsconfig.json +14 -0
- package/examples/05-fastly-capabilities/.pulse/.gitignore +3 -0
- package/examples/05-fastly-capabilities/.pulse/config.ts +57 -0
- package/examples/05-fastly-capabilities/README.md +257 -0
- package/examples/05-fastly-capabilities/package.json +22 -0
- package/examples/05-fastly-capabilities/src/index.ts +55 -0
- package/examples/05-fastly-capabilities/tests/pulse.harness.ts +66 -0
- package/examples/05-fastly-capabilities/tsconfig.json +14 -0
- package/examples/07-opaque-proxy/.pulse/.gitignore +3 -0
- package/examples/07-opaque-proxy/.pulse/config.ts +38 -0
- package/examples/07-opaque-proxy/README.md +150 -0
- package/examples/07-opaque-proxy/package.json +21 -0
- package/examples/07-opaque-proxy/src/index.ts +9 -0
- package/examples/07-opaque-proxy/tests/pulse.harness.ts +25 -0
- package/examples/07-opaque-proxy/tsconfig.json +14 -0
- package/examples/09-router-lowering/.pulse/.gitignore +3 -0
- package/examples/09-router-lowering/.pulse/config.ts +22 -0
- package/examples/09-router-lowering/README.md +287 -0
- package/examples/09-router-lowering/package.json +22 -0
- package/examples/09-router-lowering/src/index.ts +65 -0
- package/examples/09-router-lowering/tests/pulse.harness.ts +91 -0
- package/examples/09-router-lowering/tsconfig.json +14 -0
- package/examples/10-entities-tools/.pulse/.gitignore +4 -0
- package/examples/10-entities-tools/.pulse/config.ts +23 -0
- package/examples/10-entities-tools/README.md +165 -0
- package/examples/10-entities-tools/package.json +21 -0
- package/examples/10-entities-tools/src/handlers.ts +15 -0
- package/examples/10-entities-tools/src/index.ts +31 -0
- package/examples/10-entities-tools/src/schemas.ts +18 -0
- package/examples/10-entities-tools/tests/pulse.harness.ts +40 -0
- package/examples/10-entities-tools/tools-facade.cjs +158 -0
- package/examples/10-entities-tools/tsconfig.json +14 -0
- package/examples/11-events/.pulse/.gitignore +4 -0
- package/examples/11-events/.pulse/config.ts +24 -0
- package/examples/11-events/README.md +194 -0
- package/examples/11-events/package.json +20 -0
- package/examples/11-events/src/index.ts +27 -0
- package/examples/11-events/src/schemas.ts +19 -0
- package/examples/11-events/tests/pulse.harness.ts +34 -0
- package/examples/11-events/tsconfig.json +15 -0
- package/examples/12-mcp-proxy/.pulse/.gitignore +3 -0
- package/examples/12-mcp-proxy/.pulse/config.ts +25 -0
- package/examples/12-mcp-proxy/README.md +149 -0
- package/examples/12-mcp-proxy/package.json +20 -0
- package/examples/12-mcp-proxy/src/index.ts +17 -0
- package/examples/12-mcp-proxy/tests/pulse.harness.ts +29 -0
- package/examples/12-mcp-proxy/tsconfig.json +14 -0
- package/examples/13-jwt-es256/.pulse/config.ts +19 -0
- package/examples/13-jwt-es256/README.md +195 -0
- package/examples/13-jwt-es256/package.json +21 -0
- package/examples/13-jwt-es256/src/index.ts +21 -0
- package/examples/13-jwt-es256/tests/pulse.harness.ts +54 -0
- package/examples/13-jwt-es256/tsconfig.json +14 -0
- package/examples/README.md +36 -0
- package/package.json +66 -6
- package/project-config.schema.json +918 -0
- package/release-manifest.json +427 -0
- package/src/command-spec.js +279 -0
- package/src/completion.js +113 -0
- package/src/diagnostics.js +350 -0
- package/src/documentation.js +45 -0
- package/src/index.d.ts +133 -0
- package/src/index.js +15 -0
- package/src/internal/command-executor.d.ts +29 -0
- package/src/internal/command-executor.js +143 -0
- package/src/internal/command-plan.d.ts +9 -0
- package/src/internal/command-plan.js +73 -0
- package/src/internal/command-reporter.d.ts +15 -0
- package/src/internal/command-reporter.js +133 -0
- package/src/internal/command-request.d.ts +35 -0
- package/src/internal/command-request.js +154 -0
- package/src/internal/node-http.js +54 -0
- package/src/internal/project-context.d.ts +66 -0
- package/src/internal/project-context.js +175 -0
- package/src/project-config-reference.js +4 -0
- package/src/project-config-schema.d.ts +23 -0
- package/src/project-config-schema.js +271 -0
- package/src/project-config.js +724 -0
- package/src/project-execution.js +2930 -0
- package/src/provider-drivers.js +3 -0
- package/src/target-support.js +3 -0
- package/src/typescript-module-loader.js +269 -0
- package/src/workflow.js +78 -0
- package/src/workspace.js +82 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# `@pulse-compute/pulse`
|
|
2
|
+
|
|
3
|
+
`@pulse-compute/pulse` is the conventional application-authoring package for a
|
|
4
|
+
Pulse project. It owns the project-aware `Pulse` application root, deferred
|
|
5
|
+
configuration factory, and static schema declarations while reusing the
|
|
6
|
+
provider-neutral runtime contract.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @pulse-compute/pulse@1.0.0-beta.1
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The package exposes two supported entry points:
|
|
15
|
+
|
|
16
|
+
- `@pulse-compute/pulse` for `Pulse`, `defineConfig`, and runtime-owned
|
|
17
|
+
authoring types;
|
|
18
|
+
- `@pulse-compute/pulse/schema` for `schema`, `response`, and
|
|
19
|
+
`defineSchemaRegistry`.
|
|
20
|
+
|
|
21
|
+
## Application root
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { Pulse } from '@pulse-compute/pulse'
|
|
25
|
+
|
|
26
|
+
const app = new Pulse({ auto: true })
|
|
27
|
+
|
|
28
|
+
app.get('/health', async (ctx) => {
|
|
29
|
+
return ctx.json({ ok: true })
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
export default app
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`Pulse` extends the same live `Router` implementation exposed by
|
|
36
|
+
`@pulse-compute/runtime`; it does not introduce a second routing or execution
|
|
37
|
+
system. Compiler analysis normalizes the application into the canonical Router
|
|
38
|
+
IR before target selection and provider realization.
|
|
39
|
+
|
|
40
|
+
`Pulse` also owns root-only static event registration:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
app.on('device.reading', { schema: 'events.DeviceReading' }, async (ctx) => {
|
|
44
|
+
const reading = ctx.event.payload
|
|
45
|
+
await ctx.config.get('MODE')
|
|
46
|
+
void reading
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
app.on('system.tick', { schema: null }, async (ctx) => {
|
|
50
|
+
void ctx.event.type
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Event types and schema IDs are literal compiler inputs, every type has one
|
|
55
|
+
owner, and non-null schemas must resolve through the project registry. Event
|
|
56
|
+
handlers receive a non-HTTP context and complete with `void`. The compiler
|
|
57
|
+
places HTTP and event handlers in separate planes of one application-entry
|
|
58
|
+
table. Eligible event handlers can lower through the conditional
|
|
59
|
+
provider-neutral Native event ABI. Node has a bounded invocation-scoped
|
|
60
|
+
reference ingress and outbound-acceptance adapter for direct JavaScript/Native
|
|
61
|
+
parity, but no public event bus, deployment listener, delivery guarantee, or
|
|
62
|
+
other provider target support is implied.
|
|
63
|
+
|
|
64
|
+
The complete authoring, frame, queue, target, diagnostic, and no-call boundary
|
|
65
|
+
is documented in [Static events and outbound emission](../guides/events.md).
|
|
66
|
+
|
|
67
|
+
The statically analyzable root forms are:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
new Pulse({ auto: true })
|
|
71
|
+
new Pulse(configFactory)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Aliases, subclasses, factories returning `Pulse`, mounted `Pulse` instances, and
|
|
75
|
+
re-exported application roots remain outside the initial single-entry grammar.
|
|
76
|
+
Use `Router` for mounted and child applications.
|
|
77
|
+
|
|
78
|
+
## Project configuration
|
|
79
|
+
|
|
80
|
+
Canonical configuration is one synchronous deferred factory:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { defineConfig } from '@pulse-compute/pulse'
|
|
84
|
+
|
|
85
|
+
export default defineConfig((scope) => ({
|
|
86
|
+
pulse: {
|
|
87
|
+
entry: 'src/index.ts',
|
|
88
|
+
tests: 'tests/pulse.harness.ts',
|
|
89
|
+
defaultProfile: 'local',
|
|
90
|
+
strict: true,
|
|
91
|
+
reporting: 'info',
|
|
92
|
+
},
|
|
93
|
+
local: {
|
|
94
|
+
host: 'node',
|
|
95
|
+
target: 'native',
|
|
96
|
+
apiBase: scope.config('API_BASE'),
|
|
97
|
+
token: scope.secret('API_TOKEN'),
|
|
98
|
+
},
|
|
99
|
+
}))
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The scope produces symbolic configuration and secret references only. It does
|
|
103
|
+
not expose selected-profile state, resolved values, commands, or ambient
|
|
104
|
+
environment authority.
|
|
105
|
+
|
|
106
|
+
## Schema declarations
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import {
|
|
110
|
+
defineSchemaRegistry,
|
|
111
|
+
response,
|
|
112
|
+
schema,
|
|
113
|
+
} from '@pulse-compute/pulse/schema'
|
|
114
|
+
|
|
115
|
+
interface User {
|
|
116
|
+
id: number
|
|
117
|
+
name: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export default defineSchemaRegistry({
|
|
121
|
+
schemas: {
|
|
122
|
+
'app.User': schema<User>(),
|
|
123
|
+
},
|
|
124
|
+
responses: {
|
|
125
|
+
'app.UserResponse': response(200, 'app.User'),
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Schema calls are static declarations consumed by the compiler. They do not add
|
|
131
|
+
runtime reflection or generic JSON parsing to the guest module.
|
|
132
|
+
|
|
133
|
+
## Async-shaped handlers and execution state
|
|
134
|
+
|
|
135
|
+
Conventional projects require async-shaped handlers. Native lowering erases the
|
|
136
|
+
wrapper and lowers only recognized Pulse effects; it does not add Promise or
|
|
137
|
+
Asyncify runtimes.
|
|
138
|
+
|
|
139
|
+
See [Managed handler TypeScript and
|
|
140
|
+
JavaScript](../reference/handler-authoring.md) for the canonical static source
|
|
141
|
+
rules and JavaScript-only boundary, and the [compatibility
|
|
142
|
+
matrix](../reference/compatibility-matrix.md) for four-mode support.
|
|
143
|
+
|
|
144
|
+
`ctx.state` is an execution-scoped string map. HTTP executions share it across
|
|
145
|
+
the forward Router cursor, mounted routers, error recovery, and Native
|
|
146
|
+
continuation resumption; event executions share it across their continuation
|
|
147
|
+
resumption. It is reset between HTTP requests and event invocations and does
|
|
148
|
+
not expose enumeration, object values, or persistence.
|
|
149
|
+
|
|
150
|
+
## Ownership boundary
|
|
151
|
+
|
|
152
|
+
This package owns application ergonomics and declarations. It does not own
|
|
153
|
+
Handler IR, effects, continuations, Native lowering, provider lifecycle, or
|
|
154
|
+
provider-specific bootstraps. Fastly and other host realization remains in the
|
|
155
|
+
corresponding provider package.
|
|
156
|
+
|
|
157
|
+
For the lower-level static Router and complete context contract, see
|
|
158
|
+
[`@pulse-compute/runtime`](./runtime.md). For project orchestration, see
|
|
159
|
+
[`@pulse-compute/cli`](./cli.md).
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# `@pulse-compute/runtime`
|
|
2
|
+
|
|
3
|
+
`@pulse-compute/runtime` is the canonical, provider-neutral TypeScript authoring surface for Pulse applications. Install it in every canonical project and import handler types or the static `Router` marker from the package root.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @pulse-compute/runtime@1.0.0-beta.1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
A project created by `pulse init` depends on the public
|
|
12
|
+
`@pulse-compute/pulse` conventional application package, which re-exports these
|
|
13
|
+
runtime types for convenience. Public package availability remains
|
|
14
|
+
release-manifest-owned.
|
|
15
|
+
|
|
16
|
+
Conventional `.pulse` projects require async-shaped managed handlers and report `PULSE_HANDLER_ASYNC_REQUIRED` for synchronous forms. The compiler erases the wrapper and lowers trusted awaited Pulse effects through the Promise-free effect/continuation machinery.
|
|
17
|
+
|
|
18
|
+
## Minimal handler
|
|
19
|
+
|
|
20
|
+
<!-- pulse-doc-source: examples/01-hello-json/src/index.ts -->
|
|
21
|
+
```ts
|
|
22
|
+
import { Pulse } from '@pulse-compute/pulse'
|
|
23
|
+
|
|
24
|
+
const app = new Pulse({ auto: true })
|
|
25
|
+
|
|
26
|
+
app.get('/health', async (ctx) => ctx.json({ ok: true }))
|
|
27
|
+
app.get('/hello', async (ctx) => ctx.json({ message: 'hello from Pulse' }))
|
|
28
|
+
app.get('/*', async (ctx) => ctx.text('not found', { status: 404 }))
|
|
29
|
+
|
|
30
|
+
export default app
|
|
31
|
+
```
|
|
32
|
+
<!-- /pulse-doc-source -->
|
|
33
|
+
|
|
34
|
+
The source-bound example is the conventional authoring shape. Managed handlers are async-shaped, while `ctx` remains the handler's only authority.
|
|
35
|
+
|
|
36
|
+
## Public contract
|
|
37
|
+
|
|
38
|
+
The package exports:
|
|
39
|
+
|
|
40
|
+
- `PulseRequest` for method, URL, path, headers, bounded text, and bounded JSON reads;
|
|
41
|
+
- `PulseFetchInit` and `PulseFetchResponse` for canonical outbound fetches;
|
|
42
|
+
- structured and opaque response types;
|
|
43
|
+
- `PulseExecutionContext`, shared by HTTP and event handlers, with state, logging,
|
|
44
|
+
fetch, config, secret, KV, keyed parallel, and one-way event emission;
|
|
45
|
+
- `PulseContext` with the shared authority plus HTTP request and response construction;
|
|
46
|
+
- `PulseEvent`, `PulseEventContext`, and `PulseEventHandler` for exact type,
|
|
47
|
+
immutable schema payload, non-HTTP authority, and void completion;
|
|
48
|
+
- `PulseResult`, `Handler`, `PulseRouteContext`, `RouteHandler`, `RouterMiddleware`, `RouterErrorHandler`, and `RouterNext`;
|
|
49
|
+
- `Router`, the compile-time marker for static route topology;
|
|
50
|
+
- `RUNTIME_API_VERSION`, currently `pulse.runtime-authoring.v4`, and `ROUTER_API_VERSION`, currently `pulse.router-authoring.v2`.
|
|
51
|
+
|
|
52
|
+
The complete type-by-type reference is in [Canonical API](../../API.md).
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Static Router applications
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { Router } from '@pulse-compute/runtime'
|
|
59
|
+
|
|
60
|
+
const app = new Router()
|
|
61
|
+
app.use(async (ctx, next) => {
|
|
62
|
+
if (!ctx.req.header('authorization')) return ctx.text('Unauthorized', { status: 401 })
|
|
63
|
+
return next()
|
|
64
|
+
})
|
|
65
|
+
app.get('/health', async (ctx) => ctx.json({ ok: true }))
|
|
66
|
+
app.get('/users/:id', async (ctx) => ctx.json({ id: ctx.param('id') }))
|
|
67
|
+
export default app
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The compiler extracts and flattens static routes, middleware, mounts, and error entries before normal canonical lowering. `return next()` and `return next(error)` are terminal control transfers; the current handler never resumes. The marker does not dispatch through a JavaScript runtime. See [Static Router authoring](../guides/routing.md).
|
|
71
|
+
|
|
72
|
+
## Request access
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
const method = ctx.req.method
|
|
76
|
+
const path = ctx.req.path
|
|
77
|
+
const requestId = ctx.req.header('x-request-id')
|
|
78
|
+
const text = await ctx.req.text()
|
|
79
|
+
const input = await ctx.req.json<{ name: string }>('app.CreateUserInput')
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Schema-backed JSON reads use an exact ID declared by the selected `.pulse/config.ts` profile:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const input = await ctx.req.json<CreateUserInput>('app.CreateUserInput')
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
See [Explicit JSON schemas](../guides/json-schemas.md).
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## Async and execution state
|
|
92
|
+
|
|
93
|
+
Native targets treat `async` and trusted `await` as authoring notation. The compiler erases the async wrapper, lowers awaited Pulse effects into the existing continuation state machine, warns when `await` wraps a proven synchronous `ctx` value, and rejects arbitrary library awaits for native selection. No Promise runtime or Asyncify transform is linked.
|
|
94
|
+
|
|
95
|
+
The exact accepted source shapes, `ctx.parallel` record restrictions, and
|
|
96
|
+
JavaScript-only forms live in [Managed handler TypeScript and
|
|
97
|
+
JavaScript](../reference/handler-authoring.md). The tested four-mode claims live
|
|
98
|
+
in the [compatibility matrix](../reference/compatibility-matrix.md).
|
|
99
|
+
|
|
100
|
+
`ctx.state` is a synchronous execution-local string map:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
ctx.state.set('request-id', 'r1')
|
|
104
|
+
const requestId = ctx.state.get('request-id') // string | undefined
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For HTTP, state is visible across forward middleware, mounted Routers, error
|
|
108
|
+
recovery, and effect continuation resume. Event handlers use the same state
|
|
109
|
+
surface across continuation resume. State is isolated between HTTP requests and
|
|
110
|
+
between event invocations.
|
|
111
|
+
|
|
112
|
+
With project `pulse.strict: true` (the default), schema-less request JSON is rejected. Explicit `pulse.strict: false` enables the byte-bounded `host-generic-json` capability for reachable schema-less calls; the native plan and manifest report that dynamic-host choice. Schema-bound JSON remains specialized in either mode.
|
|
113
|
+
|
|
114
|
+
## Event context and Native ingress
|
|
115
|
+
|
|
116
|
+
Static event handlers receive `PulseEventContext<Payload>`:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
app.on('device.reading', { schema: 'events.DeviceReading' }, async (ctx) => {
|
|
120
|
+
const reading = ctx.event.payload
|
|
121
|
+
const mode = await ctx.config.get('MODE')
|
|
122
|
+
ctx.state.set('last-mode', mode)
|
|
123
|
+
void reading
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
`ctx.event.type` is the exact registered event type. The payload is validated
|
|
128
|
+
against the registration schema and detached before entry; a `schema: null`
|
|
129
|
+
registration receives `null`. Event contexts expose shared execution authority
|
|
130
|
+
but no request, route, response, middleware, or Router-transfer surface, and
|
|
131
|
+
handlers complete with `void`.
|
|
132
|
+
|
|
133
|
+
Eligible event handlers lower to the provider-neutral Native plan and execute
|
|
134
|
+
through the conditional `pulse.native-event-abi.v1` entry. Event-only and mixed
|
|
135
|
+
artifacts are supported; HTTP-only Native bytes remain unchanged. Node wraps
|
|
136
|
+
this entry with an invocation-scoped bounded FIFO reference adapter for direct
|
|
137
|
+
JavaScript/Native parity. That adapter is provider-maintainer infrastructure,
|
|
138
|
+
not a public listener, deployment transport, or process-global bus.
|
|
139
|
+
|
|
140
|
+
## Outbound events
|
|
141
|
+
|
|
142
|
+
HTTP and event handlers can create a one-way, schema-bound effect:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
await ctx.emit('device.led.set', {
|
|
146
|
+
schema: 'events.DeviceLedSet',
|
|
147
|
+
payload: { enabled: true },
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
await ctx.emit('system.tick', { schema: null })
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The call must be awaited directly or through an awaited `ctx.parallel` group.
|
|
154
|
+
Event type and schema IDs must be literal at compilation; non-null schemas must
|
|
155
|
+
resolve in the project registry and require a payload, while `schema: null`
|
|
156
|
+
forbids one. JavaScript and Native execution validate and detach the same frame
|
|
157
|
+
before host acceptance and return `undefined`. Native suspends and resumes
|
|
158
|
+
through the ordinary effect/continuation protocol. The Node reference adapter
|
|
159
|
+
records exact accepted frames independently from its FIFO ingress queue, so it
|
|
160
|
+
never performs automatic loopback. It does not deliver a receipt, persistence,
|
|
161
|
+
retry, or public provider transport.
|
|
162
|
+
|
|
163
|
+
`ctx.emit` is not a call operation. The runtime exposes no request/reply
|
|
164
|
+
correlation, automatic local dispatch, `ctx.call`, or reserved call capability.
|
|
165
|
+
See [Static events and outbound emission](../guides/events.md) for the frame,
|
|
166
|
+
queue, target, and Native-extension details.
|
|
167
|
+
|
|
168
|
+
## Logging
|
|
169
|
+
|
|
170
|
+
`ctx.log` exposes four synchronous string methods:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
ctx.log.error('failed to publish event')
|
|
174
|
+
ctx.log.warn('retrying origin request')
|
|
175
|
+
ctx.log.info('user created')
|
|
176
|
+
ctx.log.debug('decoded request body')
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The active profile’s flat `reporting` setting resolves `off`, `error`, `warn`,
|
|
180
|
+
`info`, or `debug`; the default is `info`. Native lowering removes calls below
|
|
181
|
+
the resolved threshold and writes enabled messages through the synchronous
|
|
182
|
+
`pulse_log(level, ptr, len)` host ABI. JavaScript targets use the same threshold
|
|
183
|
+
and provider-owned destination at runtime.
|
|
184
|
+
|
|
185
|
+
Logging is not a Pulse effect and cannot suspend a handler. Sink failures are
|
|
186
|
+
request-contained, and known request secrets are redacted before managed output.
|
|
187
|
+
Messages are strings only; structured logging and application-significant side
|
|
188
|
+
effects inside message expressions are outside the Beta contract.
|
|
189
|
+
|
|
190
|
+
## Responses
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
return ctx.json({ ok: true }, { status: 201 })
|
|
194
|
+
return ctx.text('not found', { status: 404 })
|
|
195
|
+
return ctx.response({ status: 204 })
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
A schema-backed JSON response names its compiled schema:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
return ctx.json(output, { schema: 'app.CreateUserOutput' })
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Host capabilities
|
|
205
|
+
|
|
206
|
+
Canonical host work is requested through `ctx`:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
const upstream = await ctx.fetch('https://api.example.test/items').json('app.ItemList')
|
|
210
|
+
const mode = await ctx.config.get('MODE')
|
|
211
|
+
const token = await ctx.secret.get('API_TOKEN')
|
|
212
|
+
const session = await ctx.kv<{ userId: number }>('sessions').get('current')
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Those calls are compiled into explicit effects and validated against the selected provider. See [Compilation and lowering](../concepts/compilation-and-lowering.md).
|
|
216
|
+
|
|
217
|
+
## Structured and opaque fetch results
|
|
218
|
+
|
|
219
|
+
A response can be inspected as bounded structured data:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
const item = await ctx.fetch('https://api.example.test/item').json<{ id: number }>('app.Item')
|
|
223
|
+
return ctx.json(item)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Or returned directly as an opaque pass-through response:
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
return ctx.fetch('https://assets.example.test/archive.bin')
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Opaque bodies are returnable but not inspectable or iterable. See [Structured and opaque bodies](../concepts/bodies.md).
|
|
233
|
+
|
|
234
|
+
## Deliberate exclusions
|
|
235
|
+
|
|
236
|
+
The runtime contract does not expose:
|
|
237
|
+
|
|
238
|
+
- arbitrary Promise construction or general Promise semantics under native lowering;
|
|
239
|
+
- ambient `process.env`, global fetch, timers, or randomness;
|
|
240
|
+
- provider SDK objects or provider-specific namespaces;
|
|
241
|
+
- arbitrary binary body inspection;
|
|
242
|
+
- userland stream transforms or background tasks;
|
|
243
|
+
- raw sockets.
|
|
244
|
+
|
|
245
|
+
The compiler rejects unsupported forms rather than treating them as
|
|
246
|
+
provider-dependent behavior. See the
|
|
247
|
+
[Beta scope](../preview-scope.md).
|
|
248
|
+
|
|
249
|
+
## Package and installed references
|
|
250
|
+
|
|
251
|
+
The npm tarball includes:
|
|
252
|
+
|
|
253
|
+
- `docs/API.md` — the canonical API reference;
|
|
254
|
+
- `docs/preview-scope.md` — the supported and excluded Beta surface.
|
|
255
|
+
|
|
256
|
+
For workflow and project configuration, use [`@pulse-compute/cli`](./cli.md).
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Beta scope
|
|
2
|
+
|
|
3
|
+
Pulse `1.0.0-beta.1` is a Beta of one provider-neutral application contract
|
|
4
|
+
with explicit Native and JavaScript execution targets. The intended 1.0
|
|
5
|
+
surface is present, but deliberate corrections may still occur before the
|
|
6
|
+
stable `1.0.0` release.
|
|
7
|
+
|
|
8
|
+
The Beta is intentionally strict: Pulse builds the target selected by the
|
|
9
|
+
active `.pulse/config.ts` profile, and unsupported source stops at the exact
|
|
10
|
+
lowering boundary with a stable diagnostic. Pulse never silently switches
|
|
11
|
+
targets.
|
|
12
|
+
|
|
13
|
+
## Supported application behavior
|
|
14
|
+
|
|
15
|
+
- Async-shaped provider-neutral TypeScript handlers; trusted Pulse awaits lower
|
|
16
|
+
into explicit effects and continuations without a Promise runtime.
|
|
17
|
+
- Static Router v2 with terminal middleware, route fallthrough, error
|
|
18
|
+
middleware, GET/HEAD/POST routes, exact paths, named parameters, trailing
|
|
19
|
+
wildcards, and acyclic mounts.
|
|
20
|
+
- Basic branching and structured object, array, and scalar manipulation.
|
|
21
|
+
- Request method, URL, path, headers, text, and JSON access.
|
|
22
|
+
- Bounded, memoized structured body decoding.
|
|
23
|
+
- Explicit TypeScript JSON schema declarations and literal schema IDs.
|
|
24
|
+
- GET, HEAD, and POST fetch effects.
|
|
25
|
+
- Independent Native effect grouping, dependent continuation chains, and
|
|
26
|
+
explicit cross-target `ctx.parallel({ ... })` keyed groups.
|
|
27
|
+
- HTTP status and headers as ordinary response data.
|
|
28
|
+
- JSON, text, custom, and direct pass-through responses.
|
|
29
|
+
- Exact-name config and secret reads.
|
|
30
|
+
- Named KV `get` and `put`.
|
|
31
|
+
- Opaque host-owned binary and stream pass-through.
|
|
32
|
+
- Stateless package-root GRIP request classification, response subscription and
|
|
33
|
+
handoff framing, and configured request-bound broadcast.
|
|
34
|
+
- Synchronous string logging through `ctx.log.error`, `warn`, `info`, and
|
|
35
|
+
`debug`, with flat profile reporting thresholds and provider-owned output.
|
|
36
|
+
- Root-only static `Pulse.on` declarations, immutable schema-validated event
|
|
37
|
+
contexts, and one-way `ctx.emit` acceptance through the bounded Node
|
|
38
|
+
JavaScript/Native reference adapter.
|
|
39
|
+
- Provider-neutral portable Wasm and configured Native Node or Fastly builds.
|
|
40
|
+
- Direct JavaScript execution and deterministic source packaging for Node and
|
|
41
|
+
Fastly.
|
|
42
|
+
|
|
43
|
+
## Execution contract
|
|
44
|
+
|
|
45
|
+
The Beta has two target classes and four explicitly selected
|
|
46
|
+
execution modes over one application model:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
source
|
|
50
|
+
├─ Node / Native → canonical analysis → Pulse-owned Wasm → Node realization
|
|
51
|
+
├─ Node / JavaScript → graph-backed loader → live packages → Node lifecycle
|
|
52
|
+
├─ Fastly / Native → canonical analysis → direct-host-ABI bin/main.wasm
|
|
53
|
+
└─ Fastly / JavaScript → deterministic source package → Fastly JS runtime candidate
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Native source that crosses the supported lowering boundary fails visibly with a
|
|
57
|
+
stable diagnostic. JavaScript core Router execution, request/response lifecycle,
|
|
58
|
+
eligibility inspection, effects, package realizations, source packaging, schema
|
|
59
|
+
enforcement, target integrity, and bounded GRIP realization are implemented.
|
|
60
|
+
Native/JavaScript conformance covers Router context, body handling, fetch
|
|
61
|
+
projections, configuration, secrets, KV, schema codecs, GRIP framing, logging,
|
|
62
|
+
and target identity. All declared Node and Fastly full-target-support gates are
|
|
63
|
+
satisfied for the implemented four-mode contract.
|
|
64
|
+
|
|
65
|
+
Fastly JavaScript candidate evidence compiles the deterministic source package
|
|
66
|
+
with the exact pinned downstream toolchain and records a structurally deployable
|
|
67
|
+
runtime artifact. The final release candidate must additionally pass the
|
|
68
|
+
mandatory external Fastly CLI-managed reality lane. Neither result authorizes a
|
|
69
|
+
service deployment or activation.
|
|
70
|
+
|
|
71
|
+
There is no automatic fallback. An operator must select the target through
|
|
72
|
+
project configuration or an explicitly permitted CLI target selection. A
|
|
73
|
+
successful provider-neutral compile does not silently change a
|
|
74
|
+
JavaScript-selected project into a Native one.
|
|
75
|
+
|
|
76
|
+
## Deliberately unsupported
|
|
77
|
+
|
|
78
|
+
- Automatic fallback from Native lowering to JavaScript execution.
|
|
79
|
+
- Declaring general target availability without satisfying every declared
|
|
80
|
+
full-target-support gate.
|
|
81
|
+
- Arbitrary Promise construction, arbitrary library awaits under Native
|
|
82
|
+
selection, JSPI, or Asyncify semantics. Managed `async` wrappers and trusted
|
|
83
|
+
Pulse awaits are supported notation, not a Promise runtime.
|
|
84
|
+
- Ambient `fetch`, environment variables, filesystem, process, sockets, or
|
|
85
|
+
timers.
|
|
86
|
+
- Provider SDK objects or `ctx.fastly` / `ctx.cloudflare` namespaces.
|
|
87
|
+
- Capability enumeration or runtime provider introspection.
|
|
88
|
+
- Automatic discovery of arbitrary TypeScript types.
|
|
89
|
+
- Dynamic schema IDs.
|
|
90
|
+
- Arbitrary binary body inspection or mutation.
|
|
91
|
+
- Userland chunk iteration, transform streams, or manual backpressure.
|
|
92
|
+
- Background tasks and work that outlives the request.
|
|
93
|
+
- Raw TCP or UDP sockets.
|
|
94
|
+
- Dynamic GRIP channel, framing-option, or message shapes under Native
|
|
95
|
+
selection.
|
|
96
|
+
- Onion-style post-`next()` middleware, assigning or awaiting `next()`, Router
|
|
97
|
+
`throw` transfer, realtime hooks, channels, timeout scopes, `ctx.resolve`, or
|
|
98
|
+
`ctx.resolved`.
|
|
99
|
+
- Third-party provider or lowerer self-registration.
|
|
100
|
+
- A public event listener, production event transport, delivery/retry
|
|
101
|
+
guarantee, automatic loopback or reentrancy, generic bus, `ctx.call`, or
|
|
102
|
+
request/reply event routing.
|
|
103
|
+
- Fastly, browser, or ESP32 event ingress/emit realization. Fastly fails closed
|
|
104
|
+
with exact eligibility diagnostics; browser and ESP32 remain unclaimed.
|
|
105
|
+
|
|
106
|
+
## Compatibility authority
|
|
107
|
+
|
|
108
|
+
The single source-form, provider-binding, artifact, and deployment-boundary
|
|
109
|
+
table is [Provider and target compatibility](./reference/compatibility-matrix.md).
|
|
110
|
+
It uses one public target order—Node JavaScript, Fastly JavaScript, Node Native,
|
|
111
|
+
and Fastly Native—and links every row to a focused proof or canonical contract.
|
|
112
|
+
|
|
113
|
+
The exact portable language subset and the JavaScript-only Native eligibility
|
|
114
|
+
boundaries are defined in
|
|
115
|
+
[Managed handler TypeScript and JavaScript](./reference/handler-authoring.md).
|
|
116
|
+
|
|
117
|
+
## Body model
|
|
118
|
+
|
|
119
|
+
If a body is inspected as text or JSON, Pulse treats it as a bounded immutable
|
|
120
|
+
value. If a body is passed through as binary or a stream, it remains an opaque
|
|
121
|
+
host-owned capability handle.
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
inspect it → bounded structured value
|
|
125
|
+
pass it through → opaque handle
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Compatibility and release signals
|
|
129
|
+
|
|
130
|
+
- Documented behavior is intentional and evidence-backed.
|
|
131
|
+
- Unsupported behavior fails explicitly.
|
|
132
|
+
- No execution target silently falls back.
|
|
133
|
+
- Public surfaces may still change deliberately before stable `1.0.0`.
|
|
134
|
+
- Implementation and historical subpaths do not gain accidental compatibility
|
|
135
|
+
guarantees.
|
|
136
|
+
- Package names, release artifacts, and published versions are immutable once
|
|
137
|
+
released.
|
|
138
|
+
|
|
139
|
+
The intended npm dist-tag for the Beta is `beta`. It becomes
|
|
140
|
+
active only through the atomic documentation-release transaction and an
|
|
141
|
+
explicitly authorized publication. The workflow never assigns `latest`
|
|
142
|
+
implicitly.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!-- pulse-doc-meta:start
|
|
2
|
+
owner: docs-platform
|
|
3
|
+
status: active
|
|
4
|
+
last-reviewed: 2026-08-01
|
|
5
|
+
review-by: 2027-02-01
|
|
6
|
+
pulse-doc-meta:end -->
|
|
7
|
+
|
|
8
|
+
# Reference
|
|
9
|
+
|
|
10
|
+
Use this section for exact application, command, configuration, compatibility,
|
|
11
|
+
and diagnostic contracts.
|
|
12
|
+
|
|
13
|
+
- [API reference](../../API.md) — a context-at-a-glance map plus the exact
|
|
14
|
+
Router, request, header, route parameter, state, response, and capability
|
|
15
|
+
surfaces.
|
|
16
|
+
- [Provider and target compatibility](./compatibility-matrix.md) — supported
|
|
17
|
+
behavior across Node and Fastly Native and JavaScript targets.
|
|
18
|
+
- [Managed handler TypeScript and JavaScript](./handler-authoring.md) — the
|
|
19
|
+
accepted authoring language and Native eligibility boundary.
|
|
20
|
+
- [CLI reference](./cli.md) — commands, flags, and machine-readable command
|
|
21
|
+
specification.
|
|
22
|
+
- [Project configuration](./project-config.md) — profiles, providers, targets,
|
|
23
|
+
bindings, and schemas.
|
|
24
|
+
- [Diagnostics and remediation](./diagnostics.md) — stable public diagnostic
|
|
25
|
+
codes and corrective actions.
|
|
26
|
+
- [Environment variables](./environment.md) — supported tooling inputs and
|
|
27
|
+
contributor-only controls.
|
|
28
|
+
- [Shell completion](./shell-completion.md) — Bash, Zsh, and Fish integration.
|
|
29
|
+
|
|
30
|
+
Repository governance, release operations, publication, deployment, and
|
|
31
|
+
evidence procedures are intentionally separated from the application
|
|
32
|
+
reference. Maintainers can enter that narrower surface through the
|
|
33
|
+
[maintainer documentation](../maintainers/).
|