@pulse-compute/grip 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/README.md CHANGED
@@ -1,3 +1,45 @@
1
1
  # @pulse-compute/grip
2
2
 
3
- This is an inert namespace-bootstrap package. It contains no executable code.
3
+ <!-- pulse-package-status:start -->
4
+ > **Support tier:** Supported provider/extension surface<br>
5
+ > **Audience:** Applications using stateless GRIP/Fanout HTTP framing and request-bound broadcast behavior.<br>
6
+ > **Install directly:** Yes, only when the application uses GRIP/Fanout behavior.<br>
7
+ > **Supported entry points:** `@pulse-compute/grip`<br>
8
+ > **Stability:** The package root has bounded JavaScript and Native HTTP-framing realization plus configured Node/Fastly broadcast; /pulsewasm remains compatibility-only.<br>
9
+ > **Canonical documentation:** [Package guide](https://pulsecompute.io/v1.0.0-beta.1/packages/grip/)
10
+ >
11
+ > This release-status block is generated from the synchronized `Pulse 1.0.0-beta.1` package policy.
12
+ <!-- pulse-package-status:end -->
13
+
14
+ The normal package root provides stateless GRIP/Fanout HTTP framing:
15
+
16
+ ```ts
17
+ import { grip } from '@pulse-compute/grip'
18
+
19
+ if (grip.isWebSocket(ctx.req)) {
20
+ return grip.handoff({ channel: 'events:demo' })
21
+ }
22
+
23
+ return grip.subscribe(new Response(null), {
24
+ channel: 'events:demo',
25
+ mode: 'stream',
26
+ })
27
+ ```
28
+
29
+ Outbound publication is the package's request-bound broadcast API and effect:
30
+
31
+ ```ts
32
+ await grip.broadcast(ctx, {
33
+ channel: 'events:demo',
34
+ data: { type: 'message', value: 'hello' },
35
+ })
36
+ ```
37
+
38
+ Pulse owns no WebSocket object or connection lifecycle. An external gateway owns connections, fan-out, backpressure, and reconnection. Cross-target conformance covers the bounded JavaScript/Native framing surface and configured Node/Fastly broadcast providers. Native lowering requires supported static options and messages; unsupported expressions fail without target fallback.
39
+
40
+ `@pulse-compute/grip/pulsewasm` remains a compatibility Native facade for
41
+ existing fixtures and is not recommended for new applications. Migration
42
+ guidance is published at
43
+ <https://pulsecompute.io/v1.0.0-beta.1/guides/compatibility-imports/>.
44
+
45
+ Broadcast configuration is provider-owned. It requires an explicit publish/control endpoint and may name a bearer-token secret reference; it never discovers an ambient endpoint or credential. Public gateway URLs and ingress routes are separate concerns. This bounded realization is included in both generally available JavaScript targets.
package/as/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # @pulse-compute/grip PulseWasm sidecar
2
+
3
+ This directory contains the package-owned AssemblyScript sidecar symbols used by
4
+ supported package-root Native lowering. The older
5
+ `@pulse-compute/grip/pulsewasm` surface remains compatibility-only.
6
+
7
+ The GRIP package owns its manifest, compiler builder, and sidecar declaration.
8
+ Canonical TypeScript lowering now emits provider-neutral GRIP effects and the
9
+ Fastly provider realizes them. These AssemblyScript symbols remain the focused
10
+ compiled-sidecar boundary rather than a userland stream API.
package/as/index.as.ts ADDED
@@ -0,0 +1,28 @@
1
+ // Package-owned AssemblyScript sidecar declaration for @pulse-compute/grip.
2
+ //
3
+ // These exports intentionally expose only the static ABI symbols declared by
4
+ // pulsewasm.manifest.cjs for this first-party lowerable package. Provider and
5
+ // runtime GRIP behavior remains outside this sidecar declaration.
6
+
7
+ export function pulse_grip_hold(modePtr: usize, modeLen: i32, optionsRef: i32): i32 {
8
+ void modePtr;
9
+ void modeLen;
10
+ void optionsRef;
11
+ return 0;
12
+ }
13
+
14
+ export function pulse_grip_channel(channelPtr: usize, channelLen: i32, optionsRef: i32): i32 {
15
+ void channelPtr;
16
+ void channelLen;
17
+ void optionsRef;
18
+ return 0;
19
+ }
20
+
21
+ export function pulse_grip_publish(channelPtr: usize, channelLen: i32, messagePtr: usize, messageLen: i32, optionsRef: i32): i32 {
22
+ void channelPtr;
23
+ void channelLen;
24
+ void messagePtr;
25
+ void messageLen;
26
+ void optionsRef;
27
+ return 0;
28
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "version": "pulse.package-conformance-fixture.v1",
3
+ "contractId": "pulse.grip",
4
+ "target": "native",
5
+ "status": "target-overlap",
6
+ "canonicalRoot": "@pulse-compute/grip",
7
+ "compatibilityRoot": "@pulse-compute/grip/pulsewasm",
8
+ "cases": [
9
+ "grip.isWebSocket",
10
+ "grip.subscribe",
11
+ "grip.handoff",
12
+ "grip.broadcast"
13
+ ],
14
+ "nativeRestrictions": {
15
+ "options": "static",
16
+ "messages": "static",
17
+ "dynamicInputs": "fail-at-exact-expression",
18
+ "trialLowering": false,
19
+ "automaticFallback": false
20
+ },
21
+ "evidence": "wasm/test/contracts/assert-grip-cross-target-conformance.cjs"
22
+ }
@@ -0,0 +1,45 @@
1
+ import type { PulseContext, PulseParallelEffect } from '@pulse-compute/runtime';
2
+ export type GripRequestLike = Request | {
3
+ readonly method?: string;
4
+ readonly headers?: Headers | Readonly<Record<string, string | undefined>> | readonly (readonly [string, string])[];
5
+ header?(name: string): string | undefined;
6
+ };
7
+ export type GripSubscribeMode = 'stream' | 'response';
8
+ export interface GripSubscriptionOptions {
9
+ readonly channel?: string;
10
+ readonly channels?: readonly string[];
11
+ readonly mode?: GripSubscribeMode;
12
+ readonly timeoutMs?: number;
13
+ }
14
+ export interface GripHandoffOptions extends GripSubscriptionOptions {
15
+ readonly status?: number;
16
+ readonly headers?: HeadersInit;
17
+ readonly body?: BodyInit | null;
18
+ }
19
+ export interface GripBroadcastMessage {
20
+ readonly channel: string;
21
+ readonly data: unknown;
22
+ readonly event?: string;
23
+ readonly id?: string;
24
+ }
25
+ export interface GripBroadcastAck {
26
+ readonly accepted: boolean;
27
+ readonly status?: number;
28
+ readonly messageId?: string;
29
+ }
30
+ /** Pure classification. Pulse never creates or owns a WebSocket object. */
31
+ export declare function isWebSocket(request: GripRequestLike): boolean;
32
+ /** Pure response decoration. The external GRIP gateway owns the held connection. */
33
+ export declare function subscribe(response: Response, options: GripSubscriptionOptions): Response;
34
+ /** Pure HTTP handoff framing for websocket-over-HTTP requests. */
35
+ export declare function handoff(options: GripHandoffOptions): Response;
36
+ /** The only request-bound I/O operation in the bounded GRIP API. */
37
+ export declare function broadcast(ctx: PulseContext, message: GripBroadcastMessage): PulseParallelEffect<GripBroadcastAck>;
38
+ export declare const grip: Readonly<{
39
+ isWebSocket: typeof isWebSocket;
40
+ subscribe: typeof subscribe;
41
+ handoff: typeof handoff;
42
+ broadcast: typeof broadcast;
43
+ }>;
44
+ export default grip;
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAGhF,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IACnH,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AA2DD,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAQ7D;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,uBAAuB,GAAG,QAAQ,CAQxF;AAED,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,QAAQ,CAQ7D;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CACvB,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CAAC,gBAAgB,CAAC,CA6BvC;AAED,eAAO,MAAM,IAAI;;;;;EAKf,CAAC;AAEH,eAAe,IAAI,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,135 @@
1
+ import packageRuntime from '@pulse-compute/runtime/package';
2
+ const gripRuntime = packageRuntime.createPackageRuntime({
3
+ package: '@pulse-compute/grip',
4
+ contractId: 'pulse.grip',
5
+ providerKind: 'grip',
6
+ operations: {
7
+ broadcast: {
8
+ kind: 'grip.broadcast',
9
+ capability: 'grip.broadcast',
10
+ result: 'ack',
11
+ },
12
+ },
13
+ });
14
+ function headerValue(request, name) {
15
+ if ('header' in request && typeof request.header === 'function')
16
+ return request.header(name);
17
+ const headers = request.headers;
18
+ if (!headers)
19
+ return undefined;
20
+ if (headers instanceof Headers)
21
+ return headers.get(name) ?? undefined;
22
+ if (Array.isArray(headers)) {
23
+ const values = headers
24
+ .filter(([key]) => String(key).toLowerCase() === name.toLowerCase())
25
+ .map(([, value]) => String(value));
26
+ return values.length > 0 ? values.join(', ') : undefined;
27
+ }
28
+ for (const [key, value] of Object.entries(headers)) {
29
+ if (key.toLowerCase() === name.toLowerCase() && value !== undefined)
30
+ return String(value);
31
+ }
32
+ return undefined;
33
+ }
34
+ function normalizeChannels(options) {
35
+ const input = options.channels ?? (options.channel === undefined ? [] : [options.channel]);
36
+ if (!Array.isArray(input) || input.length === 0)
37
+ throw new TypeError('GRIP subscription requires at least one channel.');
38
+ const channels = input.map((value) => {
39
+ const channelName = String(value).trim();
40
+ if (!channelName)
41
+ throw new TypeError('GRIP channel names must be non-empty strings.');
42
+ if (/[,\r\n]/.test(channelName))
43
+ throw new TypeError('GRIP channel names may not contain commas or line breaks.');
44
+ return channelName;
45
+ });
46
+ return Object.freeze(channels);
47
+ }
48
+ function applySubscriptionHeaders(headers, options) {
49
+ const mode = options.mode ?? 'stream';
50
+ if (mode !== 'stream' && mode !== 'response')
51
+ throw new TypeError('GRIP subscription mode must be stream or response.');
52
+ headers.set('Grip-Hold', mode);
53
+ headers.delete('Grip-Channel');
54
+ headers.delete('Grip-Timeout');
55
+ for (const channelName of normalizeChannels(options))
56
+ headers.append('Grip-Channel', channelName);
57
+ if (options.timeoutMs !== undefined) {
58
+ const timeoutMs = Number(options.timeoutMs);
59
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 0)
60
+ throw new TypeError('GRIP timeoutMs must be a non-negative safe integer.');
61
+ headers.set('Grip-Timeout', String(timeoutMs));
62
+ }
63
+ return headers;
64
+ }
65
+ /** Pure classification. Pulse never creates or owns a WebSocket object. */
66
+ export function isWebSocket(request) {
67
+ const contentType = (headerValue(request, 'content-type') || '').toLowerCase();
68
+ const accept = (headerValue(request, 'accept') || '').toLowerCase();
69
+ const upgrade = (headerValue(request, 'upgrade') || '').toLowerCase();
70
+ const connection = (headerValue(request, 'connection') || '').toLowerCase();
71
+ return contentType.includes('application/websocket-events')
72
+ || accept.includes('application/websocket-events')
73
+ || (upgrade === 'websocket' && connection.split(',').some((value) => value.trim() === 'upgrade'));
74
+ }
75
+ /** Pure response decoration. The external GRIP gateway owns the held connection. */
76
+ export function subscribe(response, options) {
77
+ if (!(response instanceof Response))
78
+ throw new TypeError('grip.subscribe requires a Web Response.');
79
+ const headers = applySubscriptionHeaders(new Headers(response.headers), options);
80
+ return new Response(response.body, {
81
+ status: response.status,
82
+ statusText: response.statusText,
83
+ headers,
84
+ });
85
+ }
86
+ /** Pure HTTP handoff framing for websocket-over-HTTP requests. */
87
+ export function handoff(options) {
88
+ const headers = new Headers(options.headers);
89
+ if (!headers.has('content-type'))
90
+ headers.set('Content-Type', 'application/websocket-events');
91
+ applySubscriptionHeaders(headers, options);
92
+ return new Response(options.body ?? null, {
93
+ status: options.status ?? 200,
94
+ headers,
95
+ });
96
+ }
97
+ /** The only request-bound I/O operation in the bounded GRIP API. */
98
+ export function broadcast(ctx, message) {
99
+ if (!message || typeof message !== 'object' || Array.isArray(message)) {
100
+ throw new TypeError('grip.broadcast requires a structured message.');
101
+ }
102
+ const channelName = String(message.channel || '').trim();
103
+ if (!channelName || /[,\r\n]/.test(channelName)) {
104
+ throw new TypeError('grip.broadcast channel must be non-empty and may not contain commas or line breaks.');
105
+ }
106
+ if (!Object.prototype.hasOwnProperty.call(message, 'data') || message.data === undefined) {
107
+ throw new TypeError('grip.broadcast requires a JSON-compatible data value.');
108
+ }
109
+ return gripRuntime.effect(ctx, 'broadcast', {
110
+ channel: channelName,
111
+ data: message.data,
112
+ ...(message.event === undefined ? {} : { event: String(message.event) }),
113
+ ...(message.id === undefined ? {} : { id: String(message.id) }),
114
+ }, (value) => {
115
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
116
+ const record = value;
117
+ const status = record.status === undefined ? undefined : Number(record.status);
118
+ const messageId = record.messageId === undefined ? undefined : String(record.messageId);
119
+ return Object.freeze({
120
+ accepted: record.accepted !== false,
121
+ ...(Number.isSafeInteger(status) ? { status } : {}),
122
+ ...(messageId === undefined ? {} : { messageId }),
123
+ });
124
+ }
125
+ return Object.freeze({ accepted: value !== false });
126
+ });
127
+ }
128
+ export const grip = Object.freeze({
129
+ isWebSocket,
130
+ subscribe,
131
+ handoff,
132
+ broadcast,
133
+ });
134
+ export default grip;
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * PulseWasm lowerable facade for @pulse-compute/grip.
3
+ *
4
+ * This module is the public package-owned lowering facade. PulseWasm compilers may recognize these
5
+ * symbols statically and lower them to the internal `pulse.grip` library
6
+ * contract. They are not a JavaScript GRIP runtime.
7
+ */
8
+ export type GripHoldMode = 'stream' | 'response';
9
+ export type GripHoldOptions = {
10
+ readonly channels?: readonly string[] | undefined;
11
+ readonly timeoutMs?: number | undefined;
12
+ readonly headers?: HeadersInit | undefined;
13
+ };
14
+ export type GripChannelOptions = {
15
+ readonly prefix?: string | undefined;
16
+ readonly fanout?: boolean | undefined;
17
+ };
18
+ export type GripPublishOptions = {
19
+ readonly event?: string | undefined;
20
+ readonly id?: string | undefined;
21
+ };
22
+ import type { PulseEffect, PulseResult } from '@pulse-compute/runtime';
23
+ export type GripHold = PulseEffect<PulseResult> & {
24
+ readonly kind: 'pulse.grip.hold';
25
+ readonly mode: GripHoldMode;
26
+ readonly options?: GripHoldOptions | undefined;
27
+ };
28
+ export type GripChannel = PulseEffect<void> & {
29
+ readonly kind: 'pulse.grip.channel';
30
+ readonly channel: string;
31
+ readonly options?: GripChannelOptions | undefined;
32
+ };
33
+ export type GripPublish = PulseEffect<PulseResult> & {
34
+ readonly kind: 'pulse.grip.publish';
35
+ readonly channel: string;
36
+ readonly message: string;
37
+ readonly options?: GripPublishOptions | undefined;
38
+ };
39
+ export declare class PulseWasmGripLoweringError extends Error {
40
+ constructor(symbol: string);
41
+ }
42
+ export declare function hold(mode: GripHoldMode, options?: GripHoldOptions): GripHold;
43
+ export declare function channel(channelName: string, options?: GripChannelOptions): GripChannel;
44
+ export declare function publish(channelName: string, message: string, options?: GripPublishOptions): GripPublish;
45
+ export declare const grip: Readonly<{
46
+ hold: typeof hold;
47
+ channel: typeof channel;
48
+ publish: typeof publish;
49
+ }>;
50
+ export default grip;
51
+ //# sourceMappingURL=pulsewasm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulsewasm.d.ts","sourceRoot":"","sources":["../src/pulsewasm.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEvE,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG;IAChD,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG;IAC5C,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,GAAG;IACnD,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACnD,CAAC;AAEF,qBAAa,0BAA2B,SAAQ,KAAK;gBACvC,MAAM,EAAE,MAAM;CAM3B;AAMD,wBAAgB,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,QAAQ,CAI5E;AAED,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAItF;AAED,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,WAAW,CAKvG;AAED,eAAO,MAAM,IAAI;;;;EAIf,CAAC;AAEH,eAAe,IAAI,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * PulseWasm lowerable facade for @pulse-compute/grip.
3
+ *
4
+ * This module is the public package-owned lowering facade. PulseWasm compilers may recognize these
5
+ * symbols statically and lower them to the internal `pulse.grip` library
6
+ * contract. They are not a JavaScript GRIP runtime.
7
+ */
8
+ export class PulseWasmGripLoweringError extends Error {
9
+ constructor(symbol) {
10
+ super(`${symbol} is a PulseWasm lowerable facade and cannot run directly in JavaScript. Select a supported compiler/provider target; no direct JavaScript GRIP runtime is exported by this package.`);
11
+ this.name = 'PulseWasmGripLoweringError';
12
+ }
13
+ }
14
+ function lowerableOnly(symbol) {
15
+ throw new PulseWasmGripLoweringError(symbol);
16
+ }
17
+ export function hold(mode, options) {
18
+ void mode;
19
+ void options;
20
+ return lowerableOnly('grip.hold');
21
+ }
22
+ export function channel(channelName, options) {
23
+ void channelName;
24
+ void options;
25
+ return lowerableOnly('grip.channel');
26
+ }
27
+ export function publish(channelName, message, options) {
28
+ void channelName;
29
+ void message;
30
+ void options;
31
+ return lowerableOnly('grip.publish');
32
+ }
33
+ export const grip = Object.freeze({
34
+ hold,
35
+ channel,
36
+ publish,
37
+ });
38
+ export default grip;
39
+ //# sourceMappingURL=pulsewasm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pulsewasm.js","sourceRoot":"","sources":["../src/pulsewasm.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyCH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAY,MAAc;QACxB,KAAK,CACH,GAAG,MAAM,qLAAqL,CAC/L,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED,SAAS,aAAa,CAAC,MAAqD;IAC1E,MAAM,IAAI,0BAA0B,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAkB,EAAE,OAAyB;IAChE,KAAK,IAAI,CAAC;IACV,KAAK,OAAO,CAAC;IACb,OAAO,aAAa,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,WAAmB,EAAE,OAA4B;IACvE,KAAK,WAAW,CAAC;IACjB,KAAK,OAAO,CAAC;IACb,OAAO,aAAa,CAAC,cAAc,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,WAAmB,EAAE,OAAe,EAAE,OAA4B;IACxF,KAAK,WAAW,CAAC;IACjB,KAAK,OAAO,CAAC;IACb,KAAK,OAAO,CAAC;IACb,OAAO,aAAa,CAAC,cAAc,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;IAChC,IAAI;IACJ,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAEH,eAAe,IAAI,CAAC"}
@@ -0,0 +1,76 @@
1
+ {
2
+ "version": "pulse.grip-framing-contract.v1",
3
+ "contractId": "pulse.grip",
4
+ "ownership": {
5
+ "connectionOwner": "external-grip-gateway",
6
+ "pulseState": "request-only",
7
+ "providerEffect": "grip.broadcast",
8
+ "automaticFallback": false
9
+ },
10
+ "classification": {
11
+ "mediaType": "application/websocket-events",
12
+ "upgradeToken": "websocket",
13
+ "connectionToken": "upgrade",
14
+ "headerNamesCaseInsensitive": true,
15
+ "connectionTokensCaseInsensitive": true
16
+ },
17
+ "subscription": {
18
+ "modes": ["stream", "response"],
19
+ "channels": {
20
+ "minimum": 1,
21
+ "trim": true,
22
+ "ordered": true,
23
+ "repeatedHeader": "Grip-Channel",
24
+ "forbidden": ["empty", "comma", "carriage-return", "line-feed"]
25
+ },
26
+ "timeoutMs": {
27
+ "requiredType": "non-negative-safe-integer",
28
+ "header": "Grip-Timeout"
29
+ },
30
+ "holdHeader": "Grip-Hold",
31
+ "preserve": ["status", "statusText", "body", "headers"]
32
+ },
33
+ "handoff": {
34
+ "defaultStatus": 200,
35
+ "defaultContentType": "application/websocket-events",
36
+ "bodyOwnership": "caller-owned-exact-text"
37
+ },
38
+ "broadcast": {
39
+ "message": {
40
+ "required": ["channel", "data"],
41
+ "optional": ["event", "id"]
42
+ },
43
+ "acknowledgement": {
44
+ "required": ["accepted"],
45
+ "optional": ["status", "messageId"]
46
+ },
47
+ "requestOwned": true,
48
+ "cancellable": true,
49
+ "boundedRequest": true,
50
+ "boundedResponse": true,
51
+ "authentication": "named-secret-reference",
52
+ "ambientEndpoint": false,
53
+ "ambientCredentials": false
54
+ },
55
+ "stableFailureCodes": [
56
+ "PULSE_GRIP_BROADCAST_ABORTED",
57
+ "PULSE_GRIP_BROADCAST_AUTH_SCHEME_UNSUPPORTED",
58
+ "PULSE_GRIP_BROADCAST_CAPABILITY_REQUIRED",
59
+ "PULSE_GRIP_BROADCAST_CHANNEL_INVALID",
60
+ "PULSE_GRIP_BROADCAST_ENDPOINT_INVALID",
61
+ "PULSE_GRIP_BROADCAST_MESSAGE_INVALID",
62
+ "PULSE_GRIP_BROADCAST_NETWORK",
63
+ "PULSE_GRIP_BROADCAST_REJECTED",
64
+ "PULSE_GRIP_BROADCAST_REQUEST_TOO_LARGE",
65
+ "PULSE_GRIP_BROADCAST_RESPONSE_INVALID",
66
+ "PULSE_GRIP_BROADCAST_RESPONSE_TOO_LARGE",
67
+ "PULSE_GRIP_BROADCAST_SECRET_REFERENCE_REQUIRED",
68
+ "PULSE_GRIP_BROADCAST_SECRET_REQUIRED"
69
+ ],
70
+ "redaction": {
71
+ "safeFields": ["operation", "status", "secretRef", "maxRequestBytes", "maxResponseBytes"],
72
+ "secretValues": "never-recorded",
73
+ "authorizationHeaders": "never-recorded",
74
+ "providerBodies": "never-recorded-on-error"
75
+ }
76
+ }
package/package.json CHANGED
@@ -1,15 +1,70 @@
1
1
  {
2
2
  "name": "@pulse-compute/grip",
3
- "version": "0.0.0",
4
- "description": "Inert namespace bootstrap for Pulse.",
3
+ "version": "1.0.0-beta.1",
5
4
  "license": "Apache-2.0",
5
+ "engines": {
6
+ "node": "^22.14.0 || ^24.0.0"
7
+ },
8
+ "description": "Package-owned GRIP/Fanout lowering facade and compiler integration for Pulse.",
9
+ "type": "module",
10
+ "exports": {
11
+ "./pulsewasm": {
12
+ "types": "./dist/pulsewasm.d.ts",
13
+ "import": "./dist/pulsewasm.js"
14
+ },
15
+ "./pulsewasm/manifest": {
16
+ "require": "./pulsewasm.manifest.cjs",
17
+ "default": "./pulsewasm.manifest.cjs"
18
+ },
19
+ "./pulsewasm/compiler": {
20
+ "require": "./pulsewasm.compiler.cjs",
21
+ "default": "./pulsewasm.compiler.cjs"
22
+ },
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "default": "./dist/index.js"
27
+ }
28
+ },
29
+ "sideEffects": false,
6
30
  "files": [
31
+ "dist",
7
32
  "README.md",
33
+ "pulse.package.json",
34
+ "grip.framing-contract.json",
35
+ "pulsewasm.manifest.cjs",
36
+ "pulsewasm.compiler.cjs",
37
+ "as",
38
+ "conformance",
8
39
  "LICENSE",
9
40
  "NOTICE"
10
41
  ],
42
+ "pulsewasm": {
43
+ "manifest": "./pulsewasm.manifest.cjs"
44
+ },
11
45
  "publishConfig": {
12
- "access": "public",
13
- "tag": "bootstrap"
46
+ "access": "public"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/pulse-compute/pulse.git",
51
+ "directory": "packages/grip"
52
+ },
53
+ "homepage": "https://pulsecompute.io/v1.0.0-beta.1/packages/grip/",
54
+ "bugs": {
55
+ "url": "https://github.com/pulse-compute/pulse/issues"
56
+ },
57
+ "dependencies": {
58
+ "@pulse-compute/runtime": "1.0.0-beta.1",
59
+ "@pulse-compute/wasm-contracts": "1.0.0-beta.1"
60
+ },
61
+ "pulse": {
62
+ "contract": "./pulse.package.json"
63
+ },
64
+ "main": "./dist/index.js",
65
+ "types": "./dist/index.d.ts",
66
+ "scripts": {
67
+ "build": "tsc -b",
68
+ "test": "vitest run --root ../.. --config ../../vitest.config.ts packages/grip/test/**/*.test.ts"
14
69
  }
15
- }
70
+ }
@@ -0,0 +1,73 @@
1
+ {
2
+ "version": "pulse.package-contract.v1",
3
+ "kind": "pulse.package-contract",
4
+ "contractId": "pulse.grip",
5
+ "npmPackage": "@pulse-compute/grip",
6
+ "description": "Stateless GRIP/Fanout HTTP framing and request-bound broadcast package.",
7
+ "authoring": {
8
+ "namespace": "grip",
9
+ "import": "@pulse-compute/grip",
10
+ "symbols": [
11
+ "broadcast",
12
+ "handoff",
13
+ "isWebSocket",
14
+ "subscribe"
15
+ ]
16
+ },
17
+ "ownership": {
18
+ "profileFragment": "grip",
19
+ "helperImports": [],
20
+ "reExportImports": []
21
+ },
22
+ "composition": {
23
+ "status": "reserved",
24
+ "helperSymbol": "grip",
25
+ "profileToken": "opaque-direct-use",
26
+ "reasonCode": "PULSE_PACKAGE_COMPOSITION_HELPER_NOT_REALIZED"
27
+ },
28
+ "targets": {
29
+ "native": {
30
+ "status": "provider-dependent",
31
+ "realization": "canonical-package-lowering",
32
+ "lowerableSubpath": "@pulse-compute/grip",
33
+ "providerRequirements": [
34
+ "broadcaster",
35
+ "channel",
36
+ "clock",
37
+ "headers"
38
+ ],
39
+ "reasonCode": "PULSE_GRIP_PROVIDER_CONFIGURATION_REQUIRED"
40
+ },
41
+ "javascript": {
42
+ "status": "supported",
43
+ "realization": "javascript-package-runtime",
44
+ "entry": "./dist/index.js",
45
+ "providerRequirements": [
46
+ "grip.broadcast"
47
+ ]
48
+ }
49
+ },
50
+ "lowering": {
51
+ "manifest": "./pulsewasm.manifest.cjs",
52
+ "trust": "first-party",
53
+ "canonicalOperationVersion": "pulse.canonical-package-operation.v1",
54
+ "bundleVersion": "pulse.package-lowering-bundle.v1",
55
+ "providerRequirementVersion": "pulse.provider-requirement-record.v1"
56
+ },
57
+ "conformance": {
58
+ "status": "target-overlap",
59
+ "fixtureRoots": [
60
+ "./conformance"
61
+ ],
62
+ "semanticCases": [
63
+ "grip.broadcast",
64
+ "grip.handoff",
65
+ "grip.isWebSocket",
66
+ "grip.subscribe"
67
+ ]
68
+ },
69
+ "docs": {
70
+ "readme": "./README.md",
71
+ "contract": "./pulse.package.json"
72
+ }
73
+ }