@jigs.design/client 0.1.1 → 0.2.0
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 +5 -5
- package/dist/client.d.ts +5 -5
- package/dist/client.js +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/transport.d.ts +7 -7
- package/dist/transport.js +4 -4
- package/dist/view/controller.d.ts +4 -3
- package/dist/view/controller.js +5 -4
- package/dist/view/frame-check.js +1 -1
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# @jigs.design/client
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`createJigsClient` is the browser's connection to a Jigs server: the transport and the query cache, on TanStack Query Core. `createViewController` is the framework-free half of the view: it owns the sandbox frame, keeps the tree and routes the program's queries, mutations and actions through the client, so a renderer for any framework builds on it as `JigsView` does. The package has no React and no schema library.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import {
|
|
6
|
+
import { createJigsClient } from "@jigs.design/client";
|
|
7
7
|
|
|
8
|
-
export const client =
|
|
8
|
+
export const client = createJigsClient({ endpoint: "/api/jigs" });
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
Create one client per app, in its own module. Every view and session that imports it shares one query cache, so two views reading the same query make one request, and a mutation's invalidations reach both. The client retries network failures, aborts a query's request when nothing reads it any more, and refreshes the queries a mutation invalidates.
|
|
@@ -14,7 +14,7 @@ Create one client per app, in its own module. Every view and session that import
|
|
|
14
14
|
|
|
15
15
|
| Export | What it is |
|
|
16
16
|
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
17
|
-
| `
|
|
17
|
+
| `createJigsClient` | The client, with `observe`, `mutate`, `invalidate` and `session` |
|
|
18
18
|
| `httpTransport`, `Transport` | The default HTTP transport, and the type to implement your own |
|
|
19
19
|
| `TransportError` | What a transport rejects with: `{ code, message }` |
|
|
20
20
|
| `createViewController`, `ViewController` | One view's page side: `start`, `load`, `subscribe`, `store`, `drawnProps`, `call`, `stop`, and the handlers for issues, actions and confirmation |
|
|
@@ -26,7 +26,7 @@ The view calls `observe` and `mutate`; app code calls `invalidate`. `mutate(name
|
|
|
26
26
|
|
|
27
27
|
The controller trusts the program it loaded and nothing the worker says: it checks each read and mutation against the program's procedure table, has the tree store check each op against the program's prop schemas, and enforces the budgets on the page again. `drawnProps` turns a node's props into what a component takes, reading each prop's kind from the schema, never from the value.
|
|
28
28
|
|
|
29
|
-
It re-exports the shared types from `@jigs.design/
|
|
29
|
+
It re-exports the shared types from `@jigs.design/protocol`.
|
|
30
30
|
|
|
31
31
|
## Source
|
|
32
32
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HeadersOption, Transport } from "./transport.js";
|
|
2
|
-
import { Message, MutationResult, QueryResult, SessionEvent, SessionOptions } from "@jigs.design/
|
|
2
|
+
import { Message, MutationResult, QueryResult, SessionEvent, SessionOptions } from "@jigs.design/protocol";
|
|
3
3
|
//#region src/client.d.ts
|
|
4
4
|
interface CacheOptions {
|
|
5
5
|
/**
|
|
@@ -28,7 +28,7 @@ interface ConfirmOptions {
|
|
|
28
28
|
/**
|
|
29
29
|
* Asks the user to approve a mutation whose policy is "confirm", in the
|
|
30
30
|
* page's own UI, outside the sandbox. Without it, or when it resolves
|
|
31
|
-
* false or throws, the mutation fails with `DECLINED`. A `
|
|
31
|
+
* false or throws, the mutation fails with `DECLINED`. A `JigsView`'s
|
|
32
32
|
* `onConfirm` takes its place for that view.
|
|
33
33
|
*/
|
|
34
34
|
confirm?: ConfirmFunction;
|
|
@@ -46,7 +46,7 @@ export type ClientOptions = CacheOptions & ConfirmOptions & ({
|
|
|
46
46
|
headers?: never;
|
|
47
47
|
transport: Transport;
|
|
48
48
|
});
|
|
49
|
-
export interface
|
|
49
|
+
export interface JigsClient {
|
|
50
50
|
/** URL of the sandbox frame document. */
|
|
51
51
|
readonly frame: string;
|
|
52
52
|
/** Refetches every query with this name, for every input. */
|
|
@@ -83,10 +83,10 @@ export interface PickleClient {
|
|
|
83
83
|
}) => AsyncIterable<SessionEvent>;
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
|
-
* The browser's connection to a
|
|
86
|
+
* The browser's connection to a Jigs server. Create one per app, in its
|
|
87
87
|
* own module: each client has its own query cache, so two clients share no
|
|
88
88
|
* requests and no invalidations.
|
|
89
89
|
*/
|
|
90
|
-
export declare function
|
|
90
|
+
export declare function createJigsClient(options: ClientOptions): JigsClient;
|
|
91
91
|
//#endregion
|
|
92
92
|
export {};
|
package/dist/client.js
CHANGED
|
@@ -23,11 +23,11 @@ function toQueryResult(result) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* The browser's connection to a
|
|
26
|
+
* The browser's connection to a Jigs server. Create one per app, in its
|
|
27
27
|
* own module: each client has its own query cache, so two clients share no
|
|
28
28
|
* requests and no invalidations.
|
|
29
29
|
*/
|
|
30
|
-
function
|
|
30
|
+
function createJigsClient(options) {
|
|
31
31
|
const transport = options.transport === void 0 ? httpTransport(httpOptions(options)) : options.transport;
|
|
32
32
|
const queries = new QueryClient({ defaultOptions: {
|
|
33
33
|
mutations: { retry: false },
|
|
@@ -156,4 +156,4 @@ function httpOptions(options) {
|
|
|
156
156
|
return http;
|
|
157
157
|
}
|
|
158
158
|
//#endregion
|
|
159
|
-
export {
|
|
159
|
+
export { createJigsClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CallReply, HeadersOption, HttpTransportOptions, Transport, TransportError, httpTransport } from "./transport.js";
|
|
2
|
-
import { ClientOptions, ConfirmFunction,
|
|
2
|
+
import { ClientOptions, ConfirmFunction, JigsClient, createJigsClient } from "./client.js";
|
|
3
3
|
import { ActionCall, ActionHandler, ViewController, ViewIssue, ViewStatus, createViewController, missingComponents } from "./view/controller.js";
|
|
4
|
-
import { Diagnostic, Invalidation,
|
|
5
|
-
export { type ActionCall, type ActionHandler, type CallReply, type ClientOptions, type ConfirmFunction, type Diagnostic, type HeadersOption, type HttpTransportOptions, type Invalidation, type
|
|
4
|
+
import { Diagnostic, Invalidation, JigsErrorCode, JigsErrorData, Message, Program, SessionEvent, Severity, Span } from "@jigs.design/protocol";
|
|
5
|
+
export { type ActionCall, type ActionHandler, type CallReply, type ClientOptions, type ConfirmFunction, type Diagnostic, type HeadersOption, type HttpTransportOptions, type Invalidation, type JigsClient, type JigsErrorCode, type JigsErrorData, type Message, type Program, type SessionEvent, type Severity, type Span, type Transport, TransportError, type ViewController, type ViewIssue, type ViewStatus, createJigsClient, createViewController, httpTransport, missingComponents };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { TransportError, httpTransport } from "./transport.js";
|
|
2
|
-
import {
|
|
2
|
+
import { createJigsClient } from "./client.js";
|
|
3
3
|
import { createViewController, missingComponents } from "./view/controller.js";
|
|
4
|
-
export { TransportError,
|
|
4
|
+
export { TransportError, createJigsClient, createViewController, httpTransport, missingComponents };
|
package/dist/transport.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Invalidation,
|
|
1
|
+
import { Invalidation, JigsErrorCode, JigsErrorData, Message, ProcedureKind, SessionEvent, SessionOptions } from "@jigs.design/protocol";
|
|
2
2
|
//#region src/transport.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* A call's reply: the procedure's data and, for a mutation, the queries the
|
|
@@ -16,7 +16,7 @@ export type CallReply = {
|
|
|
16
16
|
token: string;
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
|
-
/** How the browser reaches the server. Implement it to host
|
|
19
|
+
/** How the browser reaches the server. Implement it to host Jigs behind another router. */
|
|
20
20
|
export interface Transport {
|
|
21
21
|
/**
|
|
22
22
|
* Resolves with the reply, or rejects with a `TransportError`. `kind` is
|
|
@@ -43,18 +43,18 @@ export interface Transport {
|
|
|
43
43
|
}) => AsyncIterable<SessionEvent>;
|
|
44
44
|
}
|
|
45
45
|
/** A failure with a code the spec can read. */
|
|
46
|
-
export declare class TransportError extends Error implements
|
|
47
|
-
readonly code:
|
|
48
|
-
constructor(data:
|
|
46
|
+
export declare class TransportError extends Error implements JigsErrorData {
|
|
47
|
+
readonly code: JigsErrorCode;
|
|
48
|
+
constructor(data: JigsErrorData);
|
|
49
49
|
}
|
|
50
50
|
export type HeadersOption = HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
|
|
51
51
|
export interface HttpTransportOptions {
|
|
52
52
|
credentials?: RequestCredentials;
|
|
53
|
-
/** Path or URL where `
|
|
53
|
+
/** Path or URL where `jigs.handler` is mounted. */
|
|
54
54
|
endpoint: string;
|
|
55
55
|
fetch?: typeof fetch;
|
|
56
56
|
headers?: HeadersOption;
|
|
57
57
|
}
|
|
58
|
-
/** The default transport: `fetch` against `
|
|
58
|
+
/** The default transport: `fetch` against `jigs.handler`. */
|
|
59
59
|
export declare function httpTransport(options: HttpTransportOptions): Transport;
|
|
60
60
|
//#endregion
|
package/dist/transport.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseErrorData, parseInvalidations, parseSessionEvent } from "@jigs.design/
|
|
1
|
+
import { parseErrorData, parseInvalidations, parseSessionEvent } from "@jigs.design/protocol";
|
|
2
2
|
//#region src/transport.ts
|
|
3
3
|
/** A failure with a code the spec can read. */
|
|
4
4
|
var TransportError = class extends Error {
|
|
@@ -9,7 +9,7 @@ var TransportError = class extends Error {
|
|
|
9
9
|
this.name = "TransportError";
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
|
-
const VERSION_HEADER = "
|
|
12
|
+
const VERSION_HEADER = "jigs-version";
|
|
13
13
|
const GATEWAY_STATUSES = /* @__PURE__ */ new Set([
|
|
14
14
|
502,
|
|
15
15
|
503,
|
|
@@ -23,7 +23,7 @@ const network = {
|
|
|
23
23
|
code: "NETWORK",
|
|
24
24
|
message: "Could not reach the server."
|
|
25
25
|
};
|
|
26
|
-
/** The error a reply carries, or `UNAVAILABLE` when the reply is not one of
|
|
26
|
+
/** The error a reply carries, or `UNAVAILABLE` when the reply is not one of Jigs's. */
|
|
27
27
|
async function replyError(response) {
|
|
28
28
|
if (GATEWAY_STATUSES.has(response.status) || !response.headers.has(VERSION_HEADER)) return unavailable;
|
|
29
29
|
try {
|
|
@@ -40,7 +40,7 @@ function headersError(cause) {
|
|
|
40
40
|
message: `The request headers could not be built: ${cause instanceof Error ? cause.message : String(cause)}`
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
/** The default transport: `fetch` against `
|
|
43
|
+
/** The default transport: `fetch` against `jigs.handler`. */
|
|
44
44
|
function httpTransport(options) {
|
|
45
45
|
const fetcher = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
46
46
|
const credentials = options.credentials ?? "same-origin";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { ConfirmFunction,
|
|
2
|
-
import { Program, PropSchema, RuntimeError,
|
|
1
|
+
import { ConfirmFunction, JigsClient } from "../client.js";
|
|
2
|
+
import { Program, PropSchema, RuntimeError, WireArg } from "@jigs.design/protocol";
|
|
3
|
+
import { TreeNode, TreeStore } from "@jigs.design/runtime";
|
|
3
4
|
//#region src/view/controller.d.ts
|
|
4
5
|
/** What the view shows beside the tree: a snapshot, replaced on each change. */
|
|
5
6
|
export interface ViewStatus {
|
|
@@ -128,5 +129,5 @@ export declare function missingComponents(program: Program, registered: Readonly
|
|
|
128
129
|
* procedure in the program, since the worker shares its realm with the
|
|
129
130
|
* program and is not trusted either.
|
|
130
131
|
*/
|
|
131
|
-
export declare function createViewController(client:
|
|
132
|
+
export declare function createViewController(client: JigsClient): ViewController;
|
|
132
133
|
//#endregion
|
package/dist/view/controller.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { frameProblem, unprotectedProblem } from "./frame-check.js";
|
|
2
|
-
import {
|
|
2
|
+
import { parseErrorData, parseProgram } from "@jigs.design/protocol";
|
|
3
|
+
import { createTreeStore } from "@jigs.design/runtime";
|
|
3
4
|
//#region src/view/controller.ts
|
|
4
5
|
const WATCHDOG_NOTICE = "Program stopped: it did not answer within a second. The sandbox was restarted.";
|
|
5
6
|
const GAVE_UP_NOTICE = "Program stopped: it did not answer within a second, again after a restart. It will not run until a new program is loaded.";
|
|
@@ -163,7 +164,7 @@ function createViewController(client) {
|
|
|
163
164
|
clearStartup();
|
|
164
165
|
if (reported) return;
|
|
165
166
|
reported = true;
|
|
166
|
-
console.error(`
|
|
167
|
+
console.error(`Jigs: ${problem}`);
|
|
167
168
|
setStatus({
|
|
168
169
|
...status,
|
|
169
170
|
notice: problem
|
|
@@ -184,7 +185,7 @@ function createViewController(client) {
|
|
|
184
185
|
} catch {
|
|
185
186
|
if (!warnedClone) {
|
|
186
187
|
warnedClone = true;
|
|
187
|
-
console.warn("
|
|
188
|
+
console.warn("Jigs: an onAction handler returned a value structuredClone cannot copy (a function, a DOM node, a class with private fields), so the program's handle got null as its data.");
|
|
188
189
|
}
|
|
189
190
|
return null;
|
|
190
191
|
}
|
|
@@ -398,7 +399,7 @@ function createViewController(client) {
|
|
|
398
399
|
if (culprit !== null) {
|
|
399
400
|
const before = hangs.get(culprit) ?? 0;
|
|
400
401
|
hangs.set(culprit, failed === void 0 ? before + 1 : 2);
|
|
401
|
-
if (before === 0) console.warn(`
|
|
402
|
+
if (before === 0) console.warn(`Jigs: ${WATCHDOG_NOTICE}`);
|
|
402
403
|
}
|
|
403
404
|
const usable = (candidate) => candidate !== null && (hangs.get(candidate) ?? 0) < 2;
|
|
404
405
|
let recovery = null;
|
package/dist/view/frame-check.js
CHANGED
|
@@ -22,7 +22,7 @@ function frameProblem(frame, response, pageOrigin) {
|
|
|
22
22
|
if ((URL.canParse(frame, pageOrigin) ? new URL(frame, pageOrigin).origin : pageOrigin) !== pageOrigin) return `The sandbox frame at ${frame} did not start, and its response could not be read to say why. It is on another origin: check that the server's \`allowedOrigins\` lists ${pageOrigin}, which its frame-ancestors and CORS headers both need, and that nothing replaces the Content-Security-Policy it sends.`;
|
|
23
23
|
return `The sandbox frame at ${frame} did not start, and its response could not be read to say why. Check that nothing replaces the Content-Security-Policy it sends.`;
|
|
24
24
|
}
|
|
25
|
-
if (response.status !== 200) return `The sandbox frame at ${frame} answered ${response.status}, so the view cannot start. Check that the route hands GET requests to \`
|
|
25
|
+
if (response.status !== 200) return `The sandbox frame at ${frame} answered ${response.status}, so the view cannot start. Check that the route hands GET requests to \`jigs.handler\`.`;
|
|
26
26
|
const policies = (response.headers.get("content-security-policy") ?? "").split(",").map((policy) => policy.trim()).filter((policy) => policy !== "");
|
|
27
27
|
if (!policies.some((policy) => policy.startsWith(frameSecurityPolicy))) return `The page's Content-Security-Policy replaced the sandbox frame's on ${frame}, so the sandbox will not run. ${ADVICE}`;
|
|
28
28
|
if (policies.length > 1) return `A second Content-Security-Policy is added to the sandbox frame's response on ${frame}, and it stops the frame from starting. ${ADVICE}`;
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jigs.design/client",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "createJigsClient: the browser's transport and query cache. No React.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/yoamomonstruos/
|
|
8
|
+
"url": "git+https://github.com/yoamomonstruos/jigs.git",
|
|
9
9
|
"directory": "packages/client"
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@tanstack/query-core": "5.104.4",
|
|
29
|
-
"@jigs.design/
|
|
29
|
+
"@jigs.design/protocol": "0.2.0",
|
|
30
|
+
"@jigs.design/runtime": "0.2.0"
|
|
30
31
|
}
|
|
31
32
|
}
|