@modernrelay/orbit-omnigraph 0.13.6 → 0.14.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 +37 -39
- package/dist/{chunk-NT5KJVIT.js → chunk-YDRPXYQ7.js} +5 -5
- package/dist/chunk-YDRPXYQ7.js.map +1 -0
- package/dist/codegen-cli.js +14 -14
- package/dist/codegen-cli.js.map +1 -1
- package/dist/index.d.ts +112 -112
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +9 -9
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-NT5KJVIT.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
# @modernrelay/orbit-omnigraph
|
|
2
2
|
|
|
3
|
-
Optional Omnigraph data-source adapter for Orbit
|
|
3
|
+
Optional Omnigraph data-source adapter for Orbit. Framework-agnostic:
|
|
4
4
|
depends only on the framework-free ingestion/error surface of `@modernrelay/orbit-core`
|
|
5
|
-
and the official TypeScript SDK `@modernrelay/omnigraph` (0.
|
|
5
|
+
and the official TypeScript SDK `@modernrelay/omnigraph` (0.9.x) — never on React, and
|
|
6
6
|
core never depends on it.
|
|
7
7
|
|
|
8
|
-
## The v1 rule
|
|
8
|
+
## The v1 rule
|
|
9
9
|
|
|
10
|
-
> **v1 loads graphs via `og.export()`; queries only ever resolve ids**
|
|
11
|
-
> selection
|
|
10
|
+
> **v1 loads graphs via `og.export()`; queries only ever resolve ids** for search and
|
|
11
|
+
> overlay selection. The query path never introduces nodes or
|
|
12
12
|
> edges into the graph.
|
|
13
13
|
|
|
14
14
|
Export is the only complete-graph read: it streams NDJSON with full identity — physical
|
|
15
15
|
edge ids included — so every v1 edge carries an export id and no synthesized-id scheme ever
|
|
16
|
-
mixes in
|
|
17
|
-
|
|
16
|
+
mixes in. Server-backed expansion, query-path loading, and authenticated blob fetches
|
|
17
|
+
remain outside the adapter's v1 scope.
|
|
18
18
|
|
|
19
19
|
## Quick start
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
|
-
// server.ts — the ONLY place authenticated construction lives
|
|
22
|
+
// server.ts — the ONLY place authenticated construction lives
|
|
23
23
|
import { createOmnigraphServerClient } from '@modernrelay/orbit-omnigraph/server';
|
|
24
24
|
|
|
25
25
|
const client = createOmnigraphServerClient({
|
|
@@ -34,12 +34,12 @@ import { createOmnigraphSource } from '@modernrelay/orbit-omnigraph';
|
|
|
34
34
|
import { createGraphInstance } from '@modernrelay/orbit-core';
|
|
35
35
|
|
|
36
36
|
const source = createOmnigraphSource({
|
|
37
|
-
client,
|
|
37
|
+
client, // preconfigured SDK client — no token option here
|
|
38
38
|
graphId: 'demo',
|
|
39
|
-
branch: 'main',
|
|
40
|
-
// typeNames: ['Signal', 'Correlates'],
|
|
41
|
-
// driftPolicy: 'reject',
|
|
42
|
-
// maxPendingBytes:
|
|
39
|
+
branch: 'main', // default
|
|
40
|
+
// typeNames: ['Signal', 'Correlates'], // partial per-type load (wire: type_names)
|
|
41
|
+
// driftPolicy: 'reject', // default; see below
|
|
42
|
+
// maxPendingBytes: 512 * 1024 * 1024, // default whole-load atomic budget
|
|
43
43
|
onProgress: ({ lines, nodes, edges, bytes }) => console.log(lines, nodes, edges, bytes),
|
|
44
44
|
});
|
|
45
45
|
|
|
@@ -50,10 +50,9 @@ const result = await source.load(instance /*, abortSignal */);
|
|
|
50
50
|
|
|
51
51
|
`load()` drives one streamed export pass into a `purpose:'replace'` ingest session
|
|
52
52
|
(`datasetKey` = `og:<graphId>:<branch>`): edge lines arrive first (lexicographic table-key
|
|
53
|
-
order) and pass straight through — core's pending-endpoint index links them as nodes land
|
|
54
|
-
(
|
|
55
|
-
|
|
56
|
-
graph. Ids are namespaced through the B.3 codec, and B.6 wire encodings are normalized to
|
|
53
|
+
order) and pass straight through — core's pending-endpoint index links them as nodes land. Every append is awaited, and the atomic load has a finite whole-export byte budget
|
|
54
|
+
(`maxPendingBytes`, 512 MiB by default); exceeding it aborts without publishing a partial
|
|
55
|
+
graph. Ids are namespaced through the codec, and wire encodings are normalized to
|
|
57
56
|
the query-path string forms. Byte progress and budgets use re-serialized UTF-8 NDJSON size,
|
|
58
57
|
including one line break per export row.
|
|
59
58
|
|
|
@@ -61,7 +60,7 @@ The `target` is structural (`IngestTarget`: `beginIngest` + `getRevisions` +
|
|
|
61
60
|
optional `getDiagnostics`) — deliberately decoupled from `GraphInstance`, which satisfies
|
|
62
61
|
it structurally; so does any recorder or headless pipeline.
|
|
63
62
|
|
|
64
|
-
## `sourceRevision` and drift
|
|
63
|
+
## `sourceRevision` and drift
|
|
65
64
|
|
|
66
65
|
The canonical `sourceRevision` is a hash of
|
|
67
66
|
`{ graphId, branch, headBefore, headAfter, schemaFingerprint }` — but `/export` is
|
|
@@ -81,17 +80,17 @@ until that second head is known, then opens one session under the canonical fina
|
|
|
81
80
|
**both** heads and a warning is added to the result.
|
|
82
81
|
- `'retry-once'` — abort and restart the whole load once; a second drift rejects.
|
|
83
82
|
|
|
84
|
-
This is sound because a replace session is atomic and invisible until commit
|
|
83
|
+
This is sound because a replace session is atomic and invisible until commit:
|
|
85
84
|
nothing publishes under a revision the policy did not explicitly accept, and the decision
|
|
86
85
|
is never hidden — every accepted drift or retry appears in `result.warnings`.
|
|
87
86
|
|
|
88
87
|
A second identical load of a quiescent branch produces the same
|
|
89
|
-
`{datasetKey, sourceRevision}` and replays idempotently — core publishes nothing
|
|
88
|
+
`{datasetKey, sourceRevision}` and replays idempotently — core publishes nothing.
|
|
90
89
|
|
|
91
|
-
## Search: stored-query `SearchService`
|
|
90
|
+
## Search: stored-query `SearchService`
|
|
92
91
|
|
|
93
92
|
`createOmnigraphSearchService` wires a stored server-side search query (BM25 / fuzzy /
|
|
94
|
-
vector / RRF with `order { score desc } limit K`) as a
|
|
93
|
+
vector / RRF with `order { score desc } limit K`) as a core `SearchService` — plug it into
|
|
95
94
|
core as `services.search` and the instance owns `RequestContext` creation, revision-keyed
|
|
96
95
|
caching, supersede cancellation, and stale-result admission. The service declares
|
|
97
96
|
`revisionDependencies: ['source']` and passes `ctx.signal` through SDK `CallOptions`, so a
|
|
@@ -101,13 +100,13 @@ superseded keystroke cancels the in-flight HTTP call.
|
|
|
101
100
|
import { createOmnigraphSearchService } from '@modernrelay/orbit-omnigraph';
|
|
102
101
|
|
|
103
102
|
const search = createOmnigraphSearchService({
|
|
104
|
-
client,
|
|
103
|
+
client, // preconfigured SDK client — same rule as the loader
|
|
105
104
|
graphId: 'demo',
|
|
106
|
-
branch: 'main',
|
|
107
|
-
queryName: 'search-intel',
|
|
108
|
-
// params: (q, limit) => ({ q, limit }),
|
|
109
|
-
typeOf: { $s: 'Signal' },
|
|
110
|
-
// labelColumn: '$s.title',
|
|
105
|
+
branch: 'main', // default
|
|
106
|
+
queryName: 'search-intel', // registry name; invoked as POST /queries/search-intel
|
|
107
|
+
// params: (q, limit) => ({ q, limit }), // default — reshape for your query's params
|
|
108
|
+
typeOf: { $s: 'Signal' }, // REQUIRED: column → node type for the id encoding
|
|
109
|
+
// labelColumn: '$s.title', // default: the first string-valued column per row
|
|
111
110
|
});
|
|
112
111
|
|
|
113
112
|
const instance = createGraphInstance({ engine, services: { search } });
|
|
@@ -128,14 +127,14 @@ Row mapping (override wholesale with `mapRow: (row) => SearchResult | null`, `nu
|
|
|
128
127
|
row key order.
|
|
129
128
|
|
|
130
129
|
Trivial calls (empty query, non-positive limit) resolve `[]` without a network call, and
|
|
131
|
-
results are defensively capped at the requested limit.
|
|
130
|
+
results are defensively capped at the requested limit. SDK typed errors
|
|
132
131
|
rethrow as plain `omnigraph:`-prefixed `Error`s; aborts surface as `AbortError`.
|
|
133
132
|
|
|
134
|
-
> **v1 caveat
|
|
133
|
+
> **v1 caveat:** the stored query searches the WHOLE branch server-side, so against a
|
|
135
134
|
> *partial* export load (`typeNames`) it can return ids outside the loaded set.
|
|
136
|
-
> `activateSearchResult` classifies those as `'not-loaded'`
|
|
135
|
+
> `activateSearchResult` classifies those as `'not-loaded'` — the host may remedy
|
|
137
136
|
> that only by re-running export for the relevant types (query-path single-node fetch is
|
|
138
|
-
>
|
|
137
|
+
> not implemented in v1). Constrain the stored query to the loaded types, or load the
|
|
139
138
|
> full graph, to avoid the mismatch. Discovery via `og.queries.list()` returns only the
|
|
140
139
|
> `mcp.expose == true` registry subset — invoking a known `queryName` works regardless.
|
|
141
140
|
|
|
@@ -143,25 +142,24 @@ rethrow as plain `omnigraph:`-prefixed `Error`s; aborts surface as `AbortError`.
|
|
|
143
142
|
|
|
144
143
|
`@modernrelay/orbit-omnigraph/server` (`createOmnigraphServerClient`) is the only
|
|
145
144
|
authenticated SDK construction and must stay server-side: `omnigraph-server` ships no CORS
|
|
146
|
-
configuration and uses static bearer tokens (secret material)
|
|
145
|
+
configuration and uses static bearer tokens (secret material). Browser deployments
|
|
147
146
|
pass a preconfigured safe same-origin/public client to `createOmnigraphSource` — the
|
|
148
147
|
browser entry deliberately has no `baseUrl`/`token` option — and typically route reads
|
|
149
148
|
through a proxy/BFF. A client-bundle exclusion gate (`scripts/pack-smoke.mjs`,
|
|
150
149
|
`treeshake:omnigraph-client`) asserts the server entry never reaches a client bundle.
|
|
151
150
|
|
|
152
|
-
## Error surface
|
|
151
|
+
## Error surface
|
|
153
152
|
|
|
154
153
|
SDK typed errors (`NetworkError`, `ConflictError`, …) never cross this package's public
|
|
155
154
|
surface — failures rethrow as plain `Error`s with a stable `omnigraph:` message prefix.
|
|
156
155
|
Cancellation (`AbortSignal`) surfaces as an `AbortError`; the session is aborted and the
|
|
157
156
|
graph left untouched. SDK/server `major.minor` version mismatches (`og.health()` vs the
|
|
158
|
-
SDK's pinned `SERVER_VERSION`) surface as a result warning, never a hard failure
|
|
157
|
+
SDK's pinned `SERVER_VERSION`) surface as a result warning, never a hard failure.
|
|
159
158
|
|
|
160
159
|
## Also in the box
|
|
161
160
|
|
|
162
|
-
- `encodeSourceId`/`decodeSourceId`/`encodeSyntheticEdgeId` — the
|
|
161
|
+
- `encodeSourceId`/`decodeSourceId`/`encodeSyntheticEdgeId` — the identity codec
|
|
163
162
|
every adapter path must use.
|
|
164
163
|
- `parsePgSchema`/`edgeEndpointTypes`/`schemaFingerprint`/`bigIntKeyWarnings` — the `.pg`
|
|
165
|
-
schema model
|
|
166
|
-
- `classifyExportLine`/`normalizeNode`/`normalizeEdge` — export-line normalization
|
|
167
|
-
(B.2/B.6).
|
|
164
|
+
schema model: endpoint-type resolution, wire-type knowledge, revision fingerprint.
|
|
165
|
+
- `classifyExportLine`/`normalizeNode`/`normalizeEdge` — export-line normalization.
|
|
@@ -425,7 +425,7 @@ var UnknownEdgeTypeError = class extends Error {
|
|
|
425
425
|
edgeName;
|
|
426
426
|
constructor(edgeName) {
|
|
427
427
|
super(
|
|
428
|
-
`Unknown edge type '${edgeName}': not declared in the graph schema, so its endpoint node types cannot be resolved
|
|
428
|
+
`Unknown edge type '${edgeName}': not declared in the graph schema, so its endpoint node types cannot be resolved.`
|
|
429
429
|
);
|
|
430
430
|
this.edgeName = edgeName;
|
|
431
431
|
}
|
|
@@ -496,7 +496,7 @@ function requireStringId(data, what) {
|
|
|
496
496
|
const id = data["id"];
|
|
497
497
|
if (typeof id !== "string") {
|
|
498
498
|
throw new InvalidExportLineError(
|
|
499
|
-
`${what} export line has ${id === void 0 ? "no" : "a non-string"} 'data.id' \u2014 cannot build a stable orbit id
|
|
499
|
+
`${what} export line has ${id === void 0 ? "no" : "a non-string"} 'data.id' \u2014 cannot build a stable orbit id; data.id must be a string.`
|
|
500
500
|
);
|
|
501
501
|
}
|
|
502
502
|
return id;
|
|
@@ -509,7 +509,7 @@ function normalizeNode(line, schema) {
|
|
|
509
509
|
id,
|
|
510
510
|
// The discriminator is adapter-owned identity metadata. It lands LAST so
|
|
511
511
|
// a forward-compatible export field literally named `orbit:type` cannot
|
|
512
|
-
// forge the value the generated attrs unions promise
|
|
512
|
+
// forge the value the generated attrs unions promise.
|
|
513
513
|
attrs: { ...normalizeData(line.data, propTypeMap(nodeType)), [ORBIT_TYPE_KEY]: line.type }
|
|
514
514
|
};
|
|
515
515
|
}
|
|
@@ -530,5 +530,5 @@ function normalizeEdge(line, schema) {
|
|
|
530
530
|
}
|
|
531
531
|
|
|
532
532
|
export { InvalidExportLineError, ORBIT_TYPE_KEY, UnknownEdgeTypeError, bigIntKeyWarnings, classifyExportLine, decodeSourceId, edgeEndpointTypes, encodeSourceId, encodeSyntheticEdgeId, normalizeEdge, normalizeNode, parsePgSchema, schemaFingerprint };
|
|
533
|
-
//# sourceMappingURL=chunk-
|
|
534
|
-
//# sourceMappingURL=chunk-
|
|
533
|
+
//# sourceMappingURL=chunk-YDRPXYQ7.js.map
|
|
534
|
+
//# sourceMappingURL=chunk-YDRPXYQ7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/idCodec.ts","../src/pgSchema.ts","../src/normalize.ts"],"names":["body","braceIdx","blockEnd"],"mappings":"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","file":"chunk-YDRPXYQ7.js","sourcesContent":["/**\n * Identity codec.\n *\n * Omnigraph node ids are unique **per type only** (derived from the `@key`\n * tuple within each type's table), so unqualified ids are unsound as orbit\n * `NodeId`s. Every adapter path — nodes, edges, search results, view state,\n * services — MUST qualify ids through this one collision-proof tuple codec.\n * `JSON.stringify` of a fixed-arity string tuple is injective over its inputs\n * (quotes, brackets, commas, and unicode in either component are escaped), so\n * no `(kind, sourceId)` pair can collide with a different pair.\n *\n * Human-readable labels stay separate from identity; there is deliberately no\n * `namespaceIds:false` escape hatch.\n */\n\nexport interface DecodedSourceId {\n /** The namespace component: a node type name or an edge type name. */\n kind: string;\n /** The physical Omnigraph id within that type's table. */\n sourceId: string;\n}\n\n/**\n * Encode a `(kind, sourceId)` pair as a collision-proof orbit id.\n *\n * - Nodes: `encodeSourceId(NodeType, data.id)`\n * - Edges: `encodeSourceId(EdgeName, data.id)`; endpoints use\n * `encodeSourceId(endpointType, from|to)`.\n */\nexport function encodeSourceId(kind: string, sourceId: string): string {\n return JSON.stringify([kind, sourceId]);\n}\n\n/**\n * Decode an id produced by {@link encodeSourceId}.\n *\n * Returns `null` for anything that does not conform exactly (non-JSON input,\n * non-array JSON, wrong arity — including synthetic edge ids, which are\n * 4-tuples — or non-string elements). Never throws.\n */\nexport function decodeSourceId(id: string): DecodedSourceId | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(id);\n } catch {\n return null;\n }\n if (!Array.isArray(parsed) || parsed.length !== 2) return null;\n const [kind, sourceId] = parsed as unknown[];\n if (typeof kind !== 'string' || typeof sourceId !== 'string') return null;\n return { kind, sourceId };\n}\n\n/**\n * Synthetic edge id for **query-derived** subgraphs.\n *\n * The GQ grammar has no edge variable, so the query path can never surface\n * physical edge ids; query-derived edges are identified by\n * `['synthetic-edge', EdgeName, source, target]` where `source`/`target` are\n * the already-encoded endpoint node ids.\n *\n * Exported for the future query path.\n * Caveats: parallel edges collapse under this scheme, and a dataset\n * MUST NOT mix synthetic ids with physical `/export` ids for the same edges\n * one scheme per dataset, never both. Because a synthetic id is a 4-tuple,\n * {@link decodeSourceId} rejects it (`null`), keeping the two schemes\n * mechanically un-confusable.\n */\nexport function encodeSyntheticEdgeId(edgeName: string, source: string, target: string): string {\n return JSON.stringify(['synthetic-edge', edgeName, source, target]);\n}\n","/**\n * `.pg` schema model + tolerant parser.\n *\n * The adapter needs three things from the graph schema, all served here:\n * 1. edge endpoint-type resolution (export edge lines carry bare `from`/`to`\n * ids without endpoint types),\n * 2. per-property wire-type knowledge for temporal/blob normalization,\n * 3. a stable schema fingerprint for the export revision stamp.\n *\n * The parser is deliberately tolerant: it extracts the declarations it\n * understands (interfaces, node blocks, edge declarations, properties,\n * constraints) and preserves anything else — unknown annotations survive as\n * raw strings, unknown type spellings become `{ kind: 'unknown' }` — so a\n * newer server grammar degrades gracefully instead of failing the load.\n *\n * Browser-safe: no `node:` imports. The fingerprint is a pure FNV-1a 64-bit\n * hash rather than `node:crypto` sha256 so this module can sit on the\n * browser entry's critical path.\n */\n\n// ---------------------------------------------------------------------------\n// Model\n// ---------------------------------------------------------------------------\n\n/** Closed scalar set per the `.pg` grammar (docs/user/schema). */\nexport type PgScalarName =\n | 'String'\n | 'Blob'\n | 'Bool'\n | 'I32'\n | 'I64'\n | 'U32'\n | 'U64'\n | 'F32'\n | 'F64'\n | 'Date'\n | 'DateTime';\n\nexport type PgType =\n | PgScalarName\n | { kind: 'vector'; dim: number }\n | { kind: 'enum'; values: readonly string[] }\n | { kind: 'list'; element: PgScalarName }\n | { kind: 'unknown'; raw: string };\n\nexport interface PgProperty {\n name: string;\n type: PgType;\n /** `T?` nullability. */\n optional: boolean;\n /** Set by inline `@key` or a body-level `@key(...)` naming this property. */\n key: boolean;\n /** Set by inline `@unique` or a body-level `@unique(...)` naming this property. */\n unique: boolean;\n /** Set by inline `@index` or a body-level `@index(...)` naming this property. */\n index: boolean;\n /** Every annotation as written (`'@key'`, `'@embed(\"body\")'`) — unknown ones preserved verbatim. */\n annotations: readonly string[];\n}\n\nexport interface PgInterfaceType {\n name: string;\n properties: readonly PgProperty[];\n /** Body-level constraint declarations preserved verbatim (e.g. `'@unique(a, b)'`). */\n constraints: readonly string[];\n}\n\nexport interface PgNodeType {\n name: string;\n /** Interface names from the `implements` clause (already expanded into `properties`). */\n implements: readonly string[];\n properties: readonly PgProperty[];\n constraints: readonly string[];\n}\n\nexport interface PgEdgeType {\n name: string;\n /** Source (from) node type name. */\n from: string;\n /** Destination (to) node type name. */\n to: string;\n /** Raw `@card` bounds, e.g. `'1..1'`, `'0..*'`. Absent means the default `0..*`. */\n card?: string;\n /** Header annotations as written (including the `@card(...)` one, if any). */\n annotations: readonly string[];\n properties: readonly PgProperty[];\n constraints: readonly string[];\n}\n\nexport interface PgSchema {\n interfaces: readonly PgInterfaceType[];\n nodes: readonly PgNodeType[];\n edges: readonly PgEdgeType[];\n}\n\nconst SCALARS: ReadonlySet<string> = new Set<PgScalarName>([\n 'String',\n 'Blob',\n 'Bool',\n 'I32',\n 'I64',\n 'U32',\n 'U64',\n 'F32',\n 'F64',\n 'Date',\n 'DateTime',\n]);\n\n// ---------------------------------------------------------------------------\n// Lexical helpers (string-aware; `.pg` strings are double-quoted with `\\` escapes)\n// ---------------------------------------------------------------------------\n\n/** Blank out line and block comments, preserving newlines and string literals. */\nfunction stripComments(src: string): string {\n let out = '';\n let i = 0;\n const n = src.length;\n while (i < n) {\n const ch = src.charAt(i);\n if (ch === '\"') {\n out += ch;\n i++;\n while (i < n) {\n const c = src.charAt(i);\n out += c;\n i++;\n if (c === '\\\\' && i < n) {\n out += src.charAt(i);\n i++;\n } else if (c === '\"') break;\n }\n } else if (ch === '/' && src.charAt(i + 1) === '/') {\n while (i < n && src.charAt(i) !== '\\n') i++;\n } else if (ch === '/' && src.charAt(i + 1) === '*') {\n i += 2;\n while (i < n && !(src.charAt(i) === '*' && src.charAt(i + 1) === '/')) {\n out += src.charAt(i) === '\\n' ? '\\n' : ' ';\n i++;\n }\n i += 2;\n } else {\n out += ch;\n i++;\n }\n }\n return out;\n}\n\n/** Index just past the `}` matching the `{` at `openIdx`, or `src.length` if unbalanced. */\nfunction findBlockEnd(src: string, openIdx: number): number {\n let depth = 0;\n let i = openIdx;\n const n = src.length;\n while (i < n) {\n const ch = src.charAt(i);\n if (ch === '\"') {\n i++;\n while (i < n) {\n const c = src.charAt(i);\n i++;\n if (c === '\\\\') i++;\n else if (c === '\"') break;\n }\n continue;\n }\n if (ch === '{') depth++;\n else if (ch === '}') {\n depth--;\n if (depth === 0) return i + 1;\n }\n i++;\n }\n return n;\n}\n\n/** Split a block body into statements at newlines that sit outside parens/brackets/strings. */\nfunction splitStatements(body: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let current = '';\n let i = 0;\n const n = body.length;\n while (i < n) {\n const ch = body.charAt(i);\n if (ch === '\"') {\n current += ch;\n i++;\n while (i < n) {\n const c = body.charAt(i);\n current += c;\n i++;\n if (c === '\\\\' && i < n) {\n current += body.charAt(i);\n i++;\n } else if (c === '\"') break;\n }\n continue;\n }\n if (ch === '(' || ch === '[') depth++;\n else if (ch === ')' || ch === ']') depth = Math.max(0, depth - 1);\n if (ch === '\\n' && depth === 0) {\n out.push(current);\n current = '';\n } else {\n current += ch;\n }\n i++;\n }\n out.push(current);\n return out.map((s) => s.trim()).filter((s) => s.length > 0);\n}\n\ninterface RawAnnotation {\n name: string;\n args?: string;\n raw: string;\n}\n\n/** Scan a run of `@ident` / `@ident(...)` annotations starting at `start`. */\nfunction scanAnnotations(src: string, start: number): { anns: RawAnnotation[]; end: number } {\n const anns: RawAnnotation[] = [];\n let i = start;\n const n = src.length;\n for (;;) {\n let j = i;\n while (j < n && /\\s/.test(src.charAt(j))) j++;\n if (src.charAt(j) !== '@') break;\n const m = /^@([A-Za-z_]\\w*)/.exec(src.slice(j));\n if (!m || m[1] === undefined) break;\n const name = m[1];\n let end = j + m[0].length;\n let args: string | undefined;\n if (src.charAt(end) === '(') {\n let depth = 0;\n let k = end;\n while (k < n) {\n const ch = src.charAt(k);\n if (ch === '\"') {\n k++;\n while (k < n) {\n const c = src.charAt(k);\n k++;\n if (c === '\\\\') k++;\n else if (c === '\"') break;\n }\n continue;\n }\n if (ch === '(') depth++;\n else if (ch === ')') {\n depth--;\n if (depth === 0) {\n k++;\n break;\n }\n }\n k++;\n }\n args = src.slice(end + 1, k - 1);\n end = k;\n }\n const entry: RawAnnotation = { name, raw: src.slice(j, end) };\n if (args !== undefined) entry.args = args;\n anns.push(entry);\n i = end;\n }\n return { anns, end: i };\n}\n\n/** Split on top-level commas (outside parens/strings), trim, drop empties. */\nfunction splitArgs(args: string): string[] {\n const out: string[] = [];\n let depth = 0;\n let current = '';\n for (let i = 0; i < args.length; i++) {\n const ch = args.charAt(i);\n if (ch === '\"') {\n current += ch;\n i++;\n while (i < args.length) {\n const c = args.charAt(i);\n current += c;\n if (c === '\\\\') {\n i++;\n current += args.charAt(i);\n } else if (c === '\"') break;\n i++;\n }\n continue;\n }\n if (ch === '(' || ch === '[') depth++;\n else if (ch === ')' || ch === ']') depth = Math.max(0, depth - 1);\n if (ch === ',' && depth === 0) {\n out.push(current);\n current = '';\n } else {\n current += ch;\n }\n }\n out.push(current);\n return out.map((s) => s.trim()).filter((s) => s.length > 0);\n}\n\n// ---------------------------------------------------------------------------\n// Statement parsing\n// ---------------------------------------------------------------------------\n\ninterface MutableTypeBody {\n properties: PgProperty[];\n constraints: string[];\n}\n\nfunction parseTypeRef(text: string): { type: PgType; optional: boolean; end: number } {\n let i = 0;\n const n = text.length;\n while (i < n && /\\s/.test(text.charAt(i))) i++;\n let type: PgType;\n if (text.charAt(i) === '[') {\n const m = /^\\[\\s*([A-Za-z_]\\w*)\\s*\\]/.exec(text.slice(i));\n if (m && m[1] !== undefined && SCALARS.has(m[1])) {\n type = { kind: 'list', element: m[1] as PgScalarName };\n i += m[0].length;\n } else {\n const close = text.indexOf(']', i);\n const end = close === -1 ? n : close + 1;\n type = { kind: 'unknown', raw: text.slice(i, end).trim() };\n i = end;\n }\n } else {\n const m = /^([A-Za-z_]\\w*)/.exec(text.slice(i));\n if (!m || m[1] === undefined) {\n return { type: { kind: 'unknown', raw: text.trim() }, optional: false, end: n };\n }\n const ident = m[1];\n i += m[0].length;\n if ((ident === 'enum' || ident === 'Vector') && text.charAt(i) === '(') {\n let depth = 0;\n let k = i;\n while (k < n) {\n const ch = text.charAt(k);\n if (ch === '(') depth++;\n else if (ch === ')') {\n depth--;\n if (depth === 0) {\n k++;\n break;\n }\n }\n k++;\n }\n const inner = text.slice(i + 1, k - 1);\n i = k;\n if (ident === 'enum') {\n const values = splitArgs(inner).map((v) => v.replace(/^\"(.*)\"$/s, '$1'));\n type = { kind: 'enum', values };\n } else {\n const dim = Number.parseInt(inner.trim(), 10);\n type = Number.isFinite(dim)\n ? { kind: 'vector', dim }\n : { kind: 'unknown', raw: `Vector(${inner})` };\n }\n } else if (SCALARS.has(ident)) {\n type = ident as PgScalarName;\n } else {\n type = { kind: 'unknown', raw: ident };\n }\n }\n let optional = false;\n if (text.charAt(i) === '?') {\n optional = true;\n i++;\n }\n return { type, optional, end: i };\n}\n\nfunction parseBody(body: string): MutableTypeBody {\n const properties: PgProperty[] = [];\n const constraints: string[] = [];\n for (const stmt of splitStatements(body)) {\n if (stmt.startsWith('@')) {\n const { anns } = scanAnnotations(stmt, 0);\n for (const a of anns) constraints.push(a.raw);\n continue;\n }\n // A statement may carry SEVERAL whitespace-separated properties\n // (`id: String when: DateTime`); a single parse would keep only the first\n // and silently drop the rest. Loop until the trailer\n // stops looking like another property head; junk trailers stay\n // tolerant-skipped as before.\n let cursor = stmt;\n for (;;) {\n const head = /^([A-Za-z_]\\w*)\\s*:\\s*/.exec(cursor);\n if (!head || head[1] === undefined) break; // tolerant: skip unrecognized statements\n const name = head[1];\n const rest = cursor.slice(head[0].length);\n const { type, optional, end } = parseTypeRef(rest);\n const { anns, end: annsEnd } = scanAnnotations(rest, end);\n properties.push({\n name,\n type,\n optional,\n key: anns.some((a) => a.name === 'key'),\n unique: anns.some((a) => a.name === 'unique'),\n index: anns.some((a) => a.name === 'index'),\n annotations: anns.map((a) => a.raw),\n });\n cursor = rest.slice(annsEnd).trimStart();\n if (cursor === '') break;\n }\n }\n // Body-level @key(a, b) / @unique(a) / @index(a) constraints flag the named properties.\n for (const raw of constraints) {\n const m = /^@(key|unique|index)\\((.*)\\)$/s.exec(raw);\n if (!m || m[1] === undefined || m[2] === undefined) continue;\n const flag = m[1] as 'key' | 'unique' | 'index';\n for (const propName of splitArgs(m[2])) {\n const prop = properties.find((p) => p.name === propName);\n if (prop) prop[flag] = true;\n }\n }\n return { properties, constraints };\n}\n\n// ---------------------------------------------------------------------------\n// Top-level parse\n// ---------------------------------------------------------------------------\n\n/**\n * Parse `.pg` source into a {@link PgSchema}. Tolerant by design: malformed\n * or unrecognized declarations are skipped, not fatal; `implements` clauses\n * are expanded into node properties (node-declared properties win on name\n * collisions, matching the server's table layout).\n */\nexport function parsePgSchema(source: string): PgSchema {\n const src = stripComments(source);\n const interfaces: PgInterfaceType[] = [];\n const nodes: (PgNodeType & { properties: PgProperty[] })[] = [];\n const edges: PgEdgeType[] = [];\n\n const headRe = /\\b(interface|node|edge)\\s+([A-Za-z_]\\w*)/g;\n let m: RegExpExecArray | null;\n while ((m = headRe.exec(src)) !== null) {\n const kw = m[1];\n const name = m[2];\n if (kw === undefined || name === undefined) continue;\n let pos = headRe.lastIndex;\n\n if (kw === 'edge') {\n const em = /^\\s*:\\s*([A-Za-z_]\\w*)\\s*->\\s*([A-Za-z_]\\w*)/.exec(src.slice(pos));\n if (!em || em[1] === undefined || em[2] === undefined) continue; // tolerant skip\n pos += em[0].length;\n const { anns, end } = scanAnnotations(src, pos);\n pos = end;\n let body: MutableTypeBody = { properties: [], constraints: [] };\n let braceIdx = pos;\n while (braceIdx < src.length && /\\s/.test(src.charAt(braceIdx))) braceIdx++;\n if (src.charAt(braceIdx) === '{') {\n const blockEnd = findBlockEnd(src, braceIdx);\n body = parseBody(src.slice(braceIdx + 1, blockEnd - 1));\n pos = blockEnd;\n }\n const card = anns.find((a) => a.name === 'card')?.args?.trim();\n const edge: PgEdgeType = {\n name,\n from: em[1],\n to: em[2],\n annotations: anns.map((a) => a.raw),\n properties: body.properties,\n constraints: body.constraints,\n ...(card !== undefined ? { card } : {}),\n };\n edges.push(edge);\n headRe.lastIndex = pos;\n continue;\n }\n\n // interface / node: optional `implements A, B` (node only), then a block.\n let impls: string[] = [];\n // The grammar carries head annotations (`@card`/`@unique` prove the\n // family). `node Account @rename_from(\"User\") { … }` previously hit the\n // tolerant skip and silently dropped the whole declaration.\n // Annotations are consumed (and ignored — migration metadata) on either\n // side of `implements`, through the SAME scanner the body lane uses. It\n // honors nested parens and escaped quotes; a first-`)` regex would\n // truncate `@rename_from(\"User (legacy)\")` and drop the node.\n const skipAnnotations = (): void => {\n pos = scanAnnotations(src, pos).end;\n };\n skipAnnotations();\n if (kw === 'node') {\n const im = /^\\s*implements\\s+([A-Za-z_]\\w*(?:\\s*,\\s*[A-Za-z_]\\w*)*)/.exec(src.slice(pos));\n if (im && im[1] !== undefined) {\n impls = im[1].split(',').map((s) => s.trim());\n pos += im[0].length;\n }\n skipAnnotations();\n }\n let braceIdx = pos;\n while (braceIdx < src.length && /\\s/.test(src.charAt(braceIdx))) braceIdx++;\n if (src.charAt(braceIdx) !== '{') continue; // tolerant skip\n const blockEnd = findBlockEnd(src, braceIdx);\n const body = parseBody(src.slice(braceIdx + 1, blockEnd - 1));\n headRe.lastIndex = blockEnd;\n if (kw === 'interface') {\n interfaces.push({ name, properties: body.properties, constraints: body.constraints });\n } else {\n nodes.push({\n name,\n implements: impls,\n properties: body.properties,\n constraints: body.constraints,\n });\n }\n }\n\n // Expand implements clauses: interface properties precede the node's own,\n // except where the node re-declares a name (node declaration wins).\n for (const node of nodes) {\n if (node.implements.length === 0) continue;\n const own = new Set(node.properties.map((p) => p.name));\n const inherited: PgProperty[] = [];\n for (const ifaceName of node.implements) {\n const iface = interfaces.find((i) => i.name === ifaceName);\n if (!iface) continue; // tolerant: unknown interface\n for (const p of iface.properties) {\n if (!own.has(p.name) && !inherited.some((q) => q.name === p.name)) inherited.push(p);\n }\n }\n node.properties = [...inherited, ...node.properties];\n }\n\n return { interfaces, nodes, edges };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve an edge type's declared endpoint node types. Export edge\n * lines carry bare `from`/`to` ids, so endpoint types come from here. Edge\n * names match exactly first, then case-insensitively (the server matches edge\n * names case-insensitively). Returns `null` for an unknown edge name.\n */\nexport function edgeEndpointTypes(\n schema: PgSchema,\n edgeName: string,\n): { from: string; to: string } | null {\n const lower = edgeName.toLowerCase();\n const edge =\n schema.edges.find((e) => e.name === edgeName) ??\n schema.edges.find((e) => e.name.toLowerCase() === lower);\n return edge ? { from: edge.from, to: edge.to } : null;\n}\n\n/**\n * Stable fingerprint of `.pg` source for the adapter revision stamp: FNV-1a\n * 64-bit over the UTF-8 bytes of the source, as 16 lowercase hex chars.\n *\n * Pure and browser-safe (no `node:crypto`). Hashes the source **verbatim**:\n * any textual change — including comments or whitespace — changes the\n * fingerprint, which is the conservative choice for drift detection.\n */\nexport function schemaFingerprint(source: string): string {\n const MASK64 = 0xffffffffffffffffn;\n let h = 0xcbf29ce484222325n;\n const bytes = new TextEncoder().encode(source);\n for (const b of bytes) {\n h ^= BigInt(b);\n h = (h * 0x100000001b3n) & MASK64;\n }\n return h.toString(16).padStart(16, '0');\n}\n\nexport interface BigIntKeyWarning {\n /** Node or edge type name. */\n type: string;\n /** The hazardous property. */\n property: string;\n}\n\n/**\n * Find `I64`/`U64` properties used as identity (`@key` or named `id`). The\n * HTTP path emits native JSON numbers even past ±2^53, where `JSON.parse`\n * silently rounds them, so two distinct big-int ids can collapse. Surface\n * these hazards before loading.\n */\nexport function bigIntKeyWarnings(schema: PgSchema): BigIntKeyWarning[] {\n const out: BigIntKeyWarning[] = [];\n for (const t of [...schema.nodes, ...schema.edges]) {\n for (const p of t.properties) {\n if ((p.type === 'I64' || p.type === 'U64') && (p.key || p.name === 'id')) {\n out.push({ type: t.name, property: p.name });\n }\n }\n }\n return out;\n}\n","/**\n * Export-line classification and normalization.\n *\n * `/export` streams NDJSON — one JSON object per line, `data` passed through\n * **verbatim** by the SDK. This module turns those lines into orbit\n * `GraphNode`/`GraphEdge` values:\n *\n * - ids are namespaced through the adapter identity codec (`encodeSourceId`),\n * - the node/edge KIND is injected as {@link ORBIT_TYPE_KEY} — namespaced so\n * a schema's own `type` property passes through as ordinary data,\n * - edge endpoint types are resolved from the `.pg` schema because edge lines\n * carry bare `from`/`to` ids,\n * - attr values are normalized to the query-path string forms so\n * generated types and temporal dimensions see one encoding\n * regardless of read path:\n * * `Date` — export sends **days since Unix epoch** (number) →\n * `'YYYY-MM-DD'` (UTC)\n * * `DateTime` — export sends **epoch milliseconds** (number) →\n * ISO 8601 (`'YYYY-MM-DDTHH:MM:SS.mmmZ'`)\n * * `Blob` — inline internal blobs arrive as `'base64:<data>'` →\n * `'data:application/octet-stream;base64,<data>'`;\n * external-URI refs pass through verbatim\n * * everything else — verbatim.\n *\n * Non-finite float sentinels (`'NaN'`/`'Infinity'`/`'-Infinity'`) are a\n * **query-path-only** encoding: a non-finite stored float aborts `/export`\n * server-side, so export-loaded data never contains the sentinels.\n * This module therefore does NOT special-case them.\n */\n\nimport type { GraphEdge, GraphNode } from '@modernrelay/orbit-core';\nimport { encodeSourceId } from './idCodec';\nimport {\n edgeEndpointTypes,\n type PgEdgeType,\n type PgNodeType,\n type PgProperty,\n type PgSchema,\n type PgType,\n} from './pgSchema';\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/** An edge line names an edge type the `.pg` schema does not declare. */\nexport class UnknownEdgeTypeError extends Error {\n override readonly name = 'UnknownEdgeTypeError';\n readonly edgeName: string;\n constructor(edgeName: string) {\n super(\n `Unknown edge type '${edgeName}': not declared in the graph schema, so its ` +\n `endpoint node types cannot be resolved.`,\n );\n this.edgeName = edgeName;\n }\n}\n\n/** An export line is structurally unusable (e.g. missing/non-string `data.id`). */\nexport class InvalidExportLineError extends Error {\n override readonly name = 'InvalidExportLineError';\n constructor(message: string) {\n super(message);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Classification\n// ---------------------------------------------------------------------------\n\nexport interface NodeExportLine {\n kind: 'node';\n type: string;\n data: Record<string, unknown>;\n}\n\nexport interface EdgeExportLine {\n kind: 'edge';\n edge: string;\n from: string;\n to: string;\n data: Record<string, unknown>;\n}\n\nexport type ClassifiedExportLine = NodeExportLine | EdgeExportLine | { kind: 'unknown' };\n\nfunction isRecord(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n/**\n * Classify one parsed export line using the adapter's wire shapes:\n * - node line: `{\"type\": \"<NodeType>\", \"data\": {\"id\", …props}}`\n * - edge line: `{\"edge\": \"<EdgeName>\", \"from\": <src id>, \"to\": <dst id>, \"data\": {\"id\", …props}}`\n * Anything else is `{ kind: 'unknown' }`.\n */\nexport function classifyExportLine(line: unknown): ClassifiedExportLine {\n if (!isRecord(line) || !isRecord(line['data'])) return { kind: 'unknown' };\n const data = line['data'];\n if (\n typeof line['edge'] === 'string' &&\n typeof line['from'] === 'string' &&\n typeof line['to'] === 'string'\n ) {\n return { kind: 'edge', edge: line['edge'], from: line['from'], to: line['to'], data };\n }\n if (typeof line['type'] === 'string') {\n return { kind: 'node', type: line['type'], data };\n }\n return { kind: 'unknown' };\n}\n\n// ---------------------------------------------------------------------------\n// Value normalization\n// ---------------------------------------------------------------------------\n\nconst MS_PER_DAY = 86_400_000;\n\n/** Format an epoch-day count as `'YYYY-MM-DD'` (UTC). Handles negative days. */\nfunction formatEpochDay(days: number): string {\n const d = new Date(days * MS_PER_DAY);\n const t = d.getTime();\n if (!Number.isFinite(t)) return String(days); // out of Date range — leave a readable value\n const y = d.getUTCFullYear();\n const year =\n y < 0\n ? `-${String(-y).padStart(6, '0')}`\n : y > 9999\n ? `+${String(y).padStart(6, '0')}`\n : String(y).padStart(4, '0');\n const month = String(d.getUTCMonth() + 1).padStart(2, '0');\n const day = String(d.getUTCDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\nfunction normalizeValue(type: PgType | undefined, value: unknown): unknown {\n if (type === undefined || value === null || value === undefined) return value;\n if (type === 'Date' && typeof value === 'number' && Number.isInteger(value)) {\n return formatEpochDay(value);\n }\n if (type === 'DateTime' && typeof value === 'number' && Number.isFinite(value)) {\n const d = new Date(value);\n return Number.isFinite(d.getTime()) ? d.toISOString() : value;\n }\n if (type === 'Blob' && typeof value === 'string' && value.startsWith('base64:')) {\n return `data:application/octet-stream;base64,${value.slice('base64:'.length)}`;\n }\n return value;\n}\n\nfunction propTypeMap(t: PgNodeType | PgEdgeType | undefined): ReadonlyMap<string, PgType> {\n const map = new Map<string, PgType>();\n if (t) for (const p of t.properties as readonly PgProperty[]) map.set(p.name, p.type);\n return map;\n}\n\nfunction normalizeData(\n data: Record<string, unknown>,\n types: ReadonlyMap<string, PgType>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n // Source data can carry '__proto__' as an own key (JSON.parse creates it);\n // defineProperty writes the own property, never the setter.\n for (const [k, v] of Object.entries(data)) {\n Object.defineProperty(out, k, {\n value: normalizeValue(types.get(k), v),\n enumerable: true,\n writable: true,\n configurable: true,\n });\n }\n return out;\n}\n\nfunction requireStringId(data: Record<string, unknown>, what: string): string {\n const id = data['id'];\n if (typeof id !== 'string') {\n throw new InvalidExportLineError(\n `${what} export line has ${id === undefined ? 'no' : 'a non-string'} 'data.id' — ` +\n `cannot build a stable orbit id; data.id must be a string.`,\n );\n }\n return id;\n}\n\n// ---------------------------------------------------------------------------\n// Node / edge normalization\n// ---------------------------------------------------------------------------\n\n/**\n * The adapter's node/edge KIND discriminator key.\n *\n * Namespaced on purpose: the adapter injects this field into someone else's\n * data, so it takes the awkward key and leaves the generic word `type` to the\n * schema author, who means something real by it (`Company.type = investor`).\n * A colon is illegal in `.pg` identifiers, so no schema property can ever\n * claim this key — the collision class is closed by construction, and a\n * source-declared `type` now flows through untouched with no preservation\n * mechanism, no warning, and no schema migration. Same convention as\n * GraphQL's `__typename` / JSON-LD's `@type`.\n */\nexport const ORBIT_TYPE_KEY = 'orbit:type';\n\n/**\n * Normalize a node export line to a `GraphNode`:\n * `id = encodeSourceId(type, data.id)`, `attrs = { …data, 'orbit:type' }`\n * with value normalization driven by the schema's property types. A node type\n * absent from the schema is tolerated — its attrs pass through verbatim\n * (identity never needs the schema on the node path).\n */\nexport function normalizeNode(\n line: { type: string; data: Record<string, unknown> },\n schema: PgSchema,\n): GraphNode {\n const nodeType = schema.nodes.find((n) => n.name === line.type);\n const id = encodeSourceId(line.type, requireStringId(line.data, `Node '${line.type}'`));\n return {\n id,\n // The discriminator is adapter-owned identity metadata. It lands LAST so\n // a forward-compatible export field literally named `orbit:type` cannot\n // forge the value the generated attrs unions promise.\n attrs: { ...normalizeData(line.data, propTypeMap(nodeType)), [ORBIT_TYPE_KEY]: line.type },\n };\n}\n\n/**\n * Normalize an edge export line to a `GraphEdge`:\n * `id = encodeSourceId(edge, data.id)`; `source`/`target` namespace the bare\n * `from`/`to` ids with the endpoint node types resolved from the schema.\n * Throws {@link UnknownEdgeTypeError} when the schema does not declare\n * the edge — endpoint identity cannot be constructed without it.\n */\nexport function normalizeEdge(\n line: { edge: string; from: string; to: string; data: Record<string, unknown> },\n schema: PgSchema,\n): GraphEdge {\n const endpoints = edgeEndpointTypes(schema, line.edge);\n if (endpoints === null) throw new UnknownEdgeTypeError(line.edge);\n const lower = line.edge.toLowerCase();\n const edgeType =\n schema.edges.find((e) => e.name === line.edge) ??\n schema.edges.find((e) => e.name.toLowerCase() === lower);\n const id = encodeSourceId(line.edge, requireStringId(line.data, `Edge '${line.edge}'`));\n return {\n id,\n source: encodeSourceId(endpoints.from, line.from),\n target: encodeSourceId(endpoints.to, line.to),\n // As on nodes, the adapter's resolved edge name lands last and always\n // wins the discriminator key; a source `type` property is ordinary data.\n attrs: { ...normalizeData(line.data, propTypeMap(edgeType)), [ORBIT_TYPE_KEY]: line.edge },\n };\n}\n"]}
|
package/dist/codegen-cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { parsePgSchema, schemaFingerprint, ORBIT_TYPE_KEY } from './chunk-
|
|
2
|
+
import { parsePgSchema, schemaFingerprint, ORBIT_TYPE_KEY } from './chunk-YDRPXYQ7.js';
|
|
3
3
|
import { readFileSync, writeFileSync } from 'fs';
|
|
4
4
|
import process from 'process';
|
|
5
5
|
import { Omnigraph } from '@modernrelay/omnigraph';
|
|
@@ -38,14 +38,14 @@ function wireNote(type) {
|
|
|
38
38
|
if (typeof type === "string") {
|
|
39
39
|
switch (type) {
|
|
40
40
|
case "Date":
|
|
41
|
-
return "`Date` \u2014 normalized to 'YYYY-MM-DD' (UTC) on load
|
|
41
|
+
return "`Date` \u2014 normalized to 'YYYY-MM-DD' (UTC) on load.";
|
|
42
42
|
case "DateTime":
|
|
43
|
-
return "`DateTime` \u2014 normalized to ISO 8601 UTC on load
|
|
43
|
+
return "`DateTime` \u2014 normalized to ISO 8601 UTC on load.";
|
|
44
44
|
case "Blob":
|
|
45
|
-
return "`Blob` \u2014 `data:` URI for inline blobs, stored URI refs verbatim
|
|
45
|
+
return "`Blob` \u2014 `data:` URI for inline blobs, stored URI refs verbatim.";
|
|
46
46
|
case "I64":
|
|
47
47
|
case "U64":
|
|
48
|
-
return `\`${type}\` \u2014 JSON numbers round silently past \xB12^53
|
|
48
|
+
return `\`${type}\` \u2014 JSON numbers round silently past \xB12^53.`;
|
|
49
49
|
default:
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
@@ -70,11 +70,11 @@ function emitProperty(lines, prop) {
|
|
|
70
70
|
lines.push(` ${propertyKey(prop.name)}: ${prop.optional ? `${base} | null` : base};`);
|
|
71
71
|
}
|
|
72
72
|
function emitPropsInterface(lines, interfaceName, kindLabel, typeName, properties) {
|
|
73
|
-
lines.push(`/** Normalized attrs for ${kindLabel} type \`${typeName}
|
|
73
|
+
lines.push(`/** Normalized attrs for ${kindLabel} type \`${typeName}\`. */`);
|
|
74
74
|
lines.push(`export interface ${interfaceName} {`);
|
|
75
75
|
if (!properties.some((p) => p.name === "id")) {
|
|
76
76
|
lines.push(
|
|
77
|
-
` /** Physical Omnigraph id \u2014 injected into every export line's \`data
|
|
77
|
+
` /** Physical Omnigraph id \u2014 injected into every export line's \`data\`; unique per ${kindLabel} type only. */`
|
|
78
78
|
);
|
|
79
79
|
lines.push(" id: string;");
|
|
80
80
|
}
|
|
@@ -103,7 +103,7 @@ function headerBanner(fingerprintLine, extra) {
|
|
|
103
103
|
const lines = [
|
|
104
104
|
"// AUTO-GENERATED \u2014 DO NOT EDIT.",
|
|
105
105
|
"//",
|
|
106
|
-
"// .pg \u2192 TypeScript typed attrs (
|
|
106
|
+
"// .pg \u2192 TypeScript typed attrs (wire-normalized), generated by",
|
|
107
107
|
"// @modernrelay/orbit-omnigraph (`orbit-omnigraph-codegen`).",
|
|
108
108
|
`// ${fingerprintLine}`
|
|
109
109
|
];
|
|
@@ -114,7 +114,7 @@ function headerBanner(fingerprintLine, extra) {
|
|
|
114
114
|
}
|
|
115
115
|
lines.push(
|
|
116
116
|
"//",
|
|
117
|
-
"// Shapes describe attrs AFTER the adapter's
|
|
117
|
+
"// Shapes describe attrs AFTER the adapter's wire normalization (both read",
|
|
118
118
|
"// paths converge on the query-path string encodings):",
|
|
119
119
|
"// Date \u2192 'YYYY-MM-DD' \xB7 DateTime \u2192 ISO 8601 \xB7 enum(...) \u2192 literal union",
|
|
120
120
|
"// I64/U64/F32/F64 \u2192 number \xB7 Vector(n) \u2192 number[] \xB7 T? \u2192 T | null",
|
|
@@ -124,7 +124,7 @@ function headerBanner(fingerprintLine, extra) {
|
|
|
124
124
|
return lines;
|
|
125
125
|
}
|
|
126
126
|
function generateTypes(schema, opts) {
|
|
127
|
-
const fingerprintLine = opts?.fingerprint !== void 0 ? `Schema fingerprint: ${opts.fingerprint}
|
|
127
|
+
const fingerprintLine = opts?.fingerprint !== void 0 ? `Schema fingerprint: ${opts.fingerprint}.` : `Schema fingerprint: ${schemaFingerprint(JSON.stringify(schema))} (parsed model \u2014 regenerate from .pg source for the source fingerprint).`;
|
|
128
128
|
const lines = headerBanner(fingerprintLine, opts?.header);
|
|
129
129
|
const nodeMembers = schema.nodes.map((n) => ({
|
|
130
130
|
typeName: n.name,
|
|
@@ -145,16 +145,16 @@ function generateTypes(schema, opts) {
|
|
|
145
145
|
emitAttrsUnion(
|
|
146
146
|
lines,
|
|
147
147
|
"NodeAttrs",
|
|
148
|
-
"Discriminated union over every node type's normalized attrs \u2014 `'orbit:type'` is injected by the adapter
|
|
148
|
+
"Discriminated union over every node type's normalized attrs \u2014 `'orbit:type'` is injected by the adapter.",
|
|
149
149
|
nodeMembers
|
|
150
150
|
);
|
|
151
151
|
emitAttrsUnion(
|
|
152
152
|
lines,
|
|
153
153
|
"EdgeAttrs",
|
|
154
|
-
"Discriminated union over every edge type's normalized attrs \u2014 `'orbit:type'` is the edge name
|
|
154
|
+
"Discriminated union over every edge type's normalized attrs \u2014 `'orbit:type'` is the edge name.",
|
|
155
155
|
edgeMembers
|
|
156
156
|
);
|
|
157
|
-
lines.push("/** Type-name \u2192 props lookup for both kinds (closed sets from the schema \u2014
|
|
157
|
+
lines.push("/** Type-name \u2192 props lookup for both kinds (closed sets from the schema \u2014 the wire contract). */");
|
|
158
158
|
lines.push("export interface TypeMap {");
|
|
159
159
|
lines.push(" nodes: {");
|
|
160
160
|
for (const m of nodeMembers) lines.push(` ${propertyKey(m.typeName)}: ${m.interfaceName};`);
|
|
@@ -181,7 +181,7 @@ var USAGE = `Usage:
|
|
|
181
181
|
orbit-omnigraph-codegen <schema.pg> [-o <out.ts>]
|
|
182
182
|
orbit-omnigraph-codegen --from-server <baseUrl> --graph <id> [-o <out.ts>]
|
|
183
183
|
|
|
184
|
-
Generates TypeScript typed attrs
|
|
184
|
+
Generates TypeScript typed attrs from a .pg schema \u2014 read from a
|
|
185
185
|
file, or fetched from a running omnigraph-server (unauthenticated client).
|
|
186
186
|
Writes to stdout unless -o is given.
|
|
187
187
|
`;
|
package/dist/codegen-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/codegen.ts","../src/codegen-cli.ts"],"names":[],"mappings":"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","file":"codegen-cli.js","sourcesContent":["/**\n * `.pg` → TypeScript codegen (spec Appendix B.6).\n *\n * The `.pg` scalar set is closed, so typed attrs for the §5 `N`/`E` generics\n * generate mechanically: one interface per node/edge type, a `NodeAttrs` /\n * `EdgeAttrs` discriminated union on the adapter-injected `'orbit:type'`\n * field (B.3 — namespaced so a schema's own `type` property emits as an\n * ordinary member), and a `TypeMap` lookup interface.\n *\n * Generated shapes describe attrs **after** the adapter's B.6 normalization\n * (the v1 loader rewrites export-path wire values to the query-path string\n * forms before populating attrs — see `normalize.ts`), so one encoding holds\n * regardless of read path:\n *\n * `Date` → `string` (`'YYYY-MM-DD'`)\n * `DateTime` → `string` (ISO 8601, `'YYYY-MM-DDTHH:MM:SS.mmmZ'`)\n * `enum(...)` → string-literal union\n * `I64`/`U64` → `number` (beware silent rounding past ±2^53 — B.6)\n * `F32`/`F64` → `number`\n * `Vector(n)` → `number[]`\n * `Blob` → `string` (`data:` URI for inline blobs, stored URI refs verbatim)\n * `T?` → `T | null`\n *\n * Output is a self-contained module (no imports), safe under the strictest\n * tsconfig (`strict`, `exactOptionalPropertyTypes`, `verbatimModuleSyntax`,\n * `isolatedModules`). The file carries a DO-NOT-EDIT header with the B.2\n * schema fingerprint. Generation is deterministic — no timestamps — so the\n * output is committable and diff-stable.\n *\n * Browser-safe: no `node:` imports (the CLI wrapper in `codegen-cli.ts` owns\n * file I/O).\n */\n\nimport { ORBIT_TYPE_KEY } from './normalize';\nimport {\n parsePgSchema,\n schemaFingerprint,\n type PgProperty,\n type PgScalarName,\n type PgSchema,\n type PgType,\n} from './pgSchema';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface GenerateTypesOptions {\n /**\n * Extra provenance lines for the DO-NOT-EDIT banner (e.g. the schema file\n * path or server URL). May be multi-line; lines are comment-prefixed as\n * needed.\n */\n header?: string;\n /**\n * The B.2 schema fingerprint of the `.pg` **source** (from\n * {@link schemaFingerprint}). When omitted, a fingerprint of the canonical\n * parsed model is used instead and labelled as such — prefer\n * {@link generateTypesFromPgSource}, which always stamps the source\n * fingerprint.\n */\n fingerprint?: string;\n}\n\n// ---------------------------------------------------------------------------\n// B.6 wire → TS mapping (post-normalization)\n// ---------------------------------------------------------------------------\n\nconst SCALAR_TS: Record<PgScalarName, string> = {\n String: 'string',\n Blob: 'string',\n Bool: 'boolean',\n I32: 'number',\n I64: 'number',\n U32: 'number',\n U64: 'number',\n F32: 'number',\n F64: 'number',\n Date: 'string',\n DateTime: 'string',\n};\n\n/** Single-quoted TS string literal with escapes. */\nfunction tsStringLiteral(value: string): string {\n return `'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\").replace(/\\r/g, '\\\\r').replace(/\\n/g, '\\\\n')}'`;\n}\n\nfunction tsType(type: PgType): string {\n if (typeof type === 'string') return SCALAR_TS[type];\n switch (type.kind) {\n case 'vector':\n return 'number[]';\n case 'enum':\n return type.values.length === 0 ? 'string' : type.values.map(tsStringLiteral).join(' | ');\n case 'list':\n return `${SCALAR_TS[type.element]}[]`;\n case 'unknown':\n return 'unknown';\n }\n}\n\n/** One-line doc note for types whose TS shape hides a wire subtlety (B.6). */\nfunction wireNote(type: PgType): string | null {\n if (typeof type === 'string') {\n switch (type) {\n case 'Date':\n return \"`Date` — normalized to 'YYYY-MM-DD' (UTC) on load (B.6).\";\n case 'DateTime':\n return '`DateTime` — normalized to ISO 8601 UTC on load (B.6).';\n case 'Blob':\n return \"`Blob` — `data:` URI for inline blobs, stored URI refs verbatim (B.6/B.10).\";\n case 'I64':\n case 'U64':\n return `\\`${type}\\` — JSON numbers round silently past ±2^53 (B.6).`;\n default:\n return null;\n }\n }\n switch (type.kind) {\n case 'vector':\n return `\\`Vector(${type.dim})\\`.`;\n case 'unknown':\n return `Unrecognized \\`.pg\\` type \\`${type.raw}\\` — value passes through verbatim.`;\n default:\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Emission helpers\n// ---------------------------------------------------------------------------\n\nconst IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nfunction propertyKey(name: string): string {\n return IDENT_RE.test(name) ? name : tsStringLiteral(name);\n}\n\nfunction emitProperty(lines: string[], prop: PgProperty): void {\n const note = wireNote(prop.type);\n if (note !== null) lines.push(` /** ${note} */`);\n const base = tsType(prop.type);\n lines.push(` ${propertyKey(prop.name)}: ${prop.optional ? `${base} | null` : base};`);\n}\n\nfunction emitPropsInterface(\n lines: string[],\n interfaceName: string,\n kindLabel: 'node' | 'edge',\n typeName: string,\n properties: readonly PgProperty[],\n): void {\n lines.push(`/** Normalized attrs for ${kindLabel} type \\`${typeName}\\` (B.6). */`);\n lines.push(`export interface ${interfaceName} {`);\n if (!properties.some((p) => p.name === 'id')) {\n lines.push(\n ` /** Physical Omnigraph id — injected into every export line's \\`data\\` (B.2); unique per ${kindLabel} type only (B.3). */`,\n );\n lines.push(' id: string;');\n }\n for (const prop of properties) {\n // Every schema property emits normally — including one named `type`: the\n // adapter's discriminator lives at the namespaced ORBIT_TYPE_KEY, so\n // there is nothing to shadow (B.3/B.6).\n emitProperty(lines, prop);\n }\n lines.push('}');\n lines.push('');\n}\n\nfunction emitAttrsUnion(\n lines: string[],\n unionName: string,\n doc: string,\n members: ReadonlyArray<{ typeName: string; interfaceName: string }>,\n): void {\n lines.push(`/** ${doc} */`);\n if (members.length === 0) {\n lines.push(`export type ${unionName} = never;`);\n } else {\n lines.push(`export type ${unionName} =`);\n members.forEach(({ typeName, interfaceName }, i) => {\n const tail = i === members.length - 1 ? ';' : '';\n lines.push(\n ` | ({ ${tsStringLiteral(ORBIT_TYPE_KEY)}: ${tsStringLiteral(typeName)} } & ${interfaceName})${tail}`,\n );\n });\n }\n lines.push('');\n}\n\nfunction headerBanner(fingerprintLine: string, extra: string | undefined): string[] {\n const lines = [\n '// AUTO-GENERATED — DO NOT EDIT.',\n '//',\n '// .pg → TypeScript typed attrs (orbit spec Appendix B.6), generated by',\n '// @modernrelay/orbit-omnigraph (`orbit-omnigraph-codegen`).',\n `// ${fingerprintLine}`,\n ];\n if (extra !== undefined && extra.length > 0) {\n for (const raw of extra.split('\\n')) {\n lines.push(raw.startsWith('//') ? raw : `// ${raw}`.trimEnd());\n }\n }\n lines.push(\n '//',\n \"// Shapes describe attrs AFTER the adapter's B.6 normalization (both read\",\n '// paths converge on the query-path string encodings):',\n \"// Date → 'YYYY-MM-DD' · DateTime → ISO 8601 · enum(...) → literal union\",\n '// I64/U64/F32/F64 → number · Vector(n) → number[] · T? → T | null',\n \"// Blob → string ('data:' URI for inline blobs, stored URI for external)\",\n '',\n );\n return lines;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a self-contained TypeScript module of typed attrs from a parsed\n * `.pg` schema (B.6): one `<Name>Props` interface per node type, one\n * `<Name>EdgeProps` per edge type (suffixed so a node and an edge sharing a\n * name cannot collide), `NodeAttrs`/`EdgeAttrs` discriminated unions on the\n * adapter-injected `'orbit:type'` field, and a `TypeMap` lookup interface with\n * `NodeTypeName`/`EdgeTypeName` key unions.\n *\n * Deterministic: identical input (schema + options) yields identical output.\n */\nexport function generateTypes(schema: PgSchema, opts?: GenerateTypesOptions): string {\n const fingerprintLine =\n opts?.fingerprint !== undefined\n ? `Schema fingerprint: ${opts.fingerprint} (B.2).`\n : `Schema fingerprint: ${schemaFingerprint(JSON.stringify(schema))} (parsed model — regenerate from .pg source for the B.2 source fingerprint).`;\n const lines = headerBanner(fingerprintLine, opts?.header);\n\n const nodeMembers = schema.nodes.map((n) => ({\n typeName: n.name,\n interfaceName: `${n.name}Props`,\n }));\n const edgeMembers = schema.edges.map((e) => ({\n typeName: e.name,\n interfaceName: `${e.name}EdgeProps`,\n }));\n\n schema.nodes.forEach((n, i) => {\n const member = nodeMembers[i];\n if (member) emitPropsInterface(lines, member.interfaceName, 'node', n.name, n.properties);\n });\n schema.edges.forEach((e, i) => {\n const member = edgeMembers[i];\n if (member) emitPropsInterface(lines, member.interfaceName, 'edge', e.name, e.properties);\n });\n\n emitAttrsUnion(\n lines,\n 'NodeAttrs',\n \"Discriminated union over every node type's normalized attrs — `'orbit:type'` is injected by the adapter (B.3).\",\n nodeMembers,\n );\n emitAttrsUnion(\n lines,\n 'EdgeAttrs',\n \"Discriminated union over every edge type's normalized attrs — `'orbit:type'` is the edge name (B.3).\",\n edgeMembers,\n );\n\n lines.push('/** Type-name → props lookup for both kinds (closed sets from the schema — B.3). */');\n lines.push('export interface TypeMap {');\n lines.push(' nodes: {');\n for (const m of nodeMembers) lines.push(` ${propertyKey(m.typeName)}: ${m.interfaceName};`);\n lines.push(' };');\n lines.push(' edges: {');\n for (const m of edgeMembers) lines.push(` ${propertyKey(m.typeName)}: ${m.interfaceName};`);\n lines.push(' };');\n lines.push('}');\n lines.push('');\n lines.push(\"export type NodeTypeName = keyof TypeMap['nodes'];\");\n lines.push(\"export type EdgeTypeName = keyof TypeMap['edges'];\");\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Parse `.pg` source and generate typed attrs (see {@link generateTypes}),\n * stamping the header with the B.2 source fingerprint\n * ({@link schemaFingerprint} over the verbatim source).\n */\nexport function generateTypesFromPgSource(\n source: string,\n opts?: Omit<GenerateTypesOptions, 'fingerprint'>,\n): string {\n const schema = parsePgSchema(source);\n const options: GenerateTypesOptions = { fingerprint: schemaFingerprint(source) };\n if (opts?.header !== undefined) options.header = opts.header;\n return generateTypes(schema, options);\n}\n","#!/usr/bin/env node\n/**\n * `orbit-omnigraph-codegen` — minimal `.pg` → TypeScript codegen CLI (spec B.6).\n *\n * orbit-omnigraph-codegen <schema.pg> [-o out.ts]\n * orbit-omnigraph-codegen --from-server <baseUrl> --graph <id> [-o out.ts]\n *\n * The first form reads a `.pg` file; the second fetches the active schema\n * from a running omnigraph-server via a plain **unauthenticated** SDK client\n * (`og.schema.get()` returns the raw `.pg` source — B.6). Authenticated\n * client construction stays exclusively in the `/server` entry (B.1); point\n * this tool at an `--unauthenticated` server or a same-origin proxy.\n *\n * Without `-o`, the generated module goes to stdout.\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport process from 'node:process';\nimport { Omnigraph } from '@modernrelay/omnigraph';\nimport { generateTypesFromPgSource } from './codegen';\n\nconst USAGE = `Usage:\n orbit-omnigraph-codegen <schema.pg> [-o <out.ts>]\n orbit-omnigraph-codegen --from-server <baseUrl> --graph <id> [-o <out.ts>]\n\nGenerates TypeScript typed attrs (spec B.6) from a .pg schema — read from a\nfile, or fetched from a running omnigraph-server (unauthenticated client).\nWrites to stdout unless -o is given.\n`;\n\ninterface CliArgs {\n schemaPath?: string;\n out?: string;\n fromServer?: string;\n graph?: string;\n}\n\nfunction parseArgs(argv: readonly string[]): CliArgs | string {\n const args: CliArgs = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === undefined) continue;\n switch (arg) {\n case '-h':\n case '--help':\n return 'help';\n case '-o':\n case '--out': {\n const v = argv[++i];\n if (v === undefined) return `missing value for ${arg}`;\n args.out = v;\n break;\n }\n case '--from-server': {\n const v = argv[++i];\n if (v === undefined) return 'missing value for --from-server';\n args.fromServer = v;\n break;\n }\n case '--graph': {\n const v = argv[++i];\n if (v === undefined) return 'missing value for --graph';\n args.graph = v;\n break;\n }\n default:\n if (arg.startsWith('-')) return `unknown option '${arg}'`;\n if (args.schemaPath !== undefined) return `unexpected argument '${arg}'`;\n args.schemaPath = arg;\n }\n }\n if (args.fromServer !== undefined && args.schemaPath !== undefined) {\n return 'pass a schema file OR --from-server, not both';\n }\n if (args.fromServer !== undefined && args.graph === undefined) {\n return '--from-server requires --graph <id> (schema reads are graph-scoped)';\n }\n if (args.fromServer === undefined && args.schemaPath === undefined) {\n return 'no schema given';\n }\n return args;\n}\n\nasync function main(argv: readonly string[]): Promise<number> {\n const parsed = parseArgs(argv);\n if (parsed === 'help') {\n process.stdout.write(USAGE);\n return 0;\n }\n if (typeof parsed === 'string') {\n process.stderr.write(`orbit-omnigraph-codegen: ${parsed}\\n\\n${USAGE}`);\n return 2;\n }\n\n let source: string;\n let provenance: string;\n if (parsed.fromServer !== undefined && parsed.graph !== undefined) {\n const og = new Omnigraph({ baseUrl: parsed.fromServer, graphId: parsed.graph });\n const schema = await og.schema.get();\n source = schema.schemaSource;\n provenance = `Source: ${parsed.fromServer} (graph '${parsed.graph}', GET /schema)`;\n } else if (parsed.schemaPath !== undefined) {\n source = readFileSync(parsed.schemaPath, 'utf8');\n provenance = `Source: ${parsed.schemaPath}`;\n } else {\n // Unreachable: parseArgs guarantees one of the two.\n return 2;\n }\n\n const output = generateTypesFromPgSource(source, { header: provenance });\n if (parsed.out !== undefined) {\n writeFileSync(parsed.out, output);\n process.stderr.write(`orbit-omnigraph-codegen: wrote ${parsed.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\nmain(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`orbit-omnigraph-codegen: ${message}\\n`);\n process.exitCode = 1;\n },\n);\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/codegen.ts","../src/codegen-cli.ts"],"names":[],"mappings":"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","file":"codegen-cli.js","sourcesContent":["/**\n * `.pg` → TypeScript code generation.\n *\n * The `.pg` scalar set is closed, so typed attrs for the `N`/`E` generics\n * generate mechanically: one interface per node/edge type, a `NodeAttrs` /\n * `EdgeAttrs` discriminated union on the adapter-injected `'orbit:type'`\n * field (namespaced so a schema's own `type` property emits as an ordinary\n * member), and a `TypeMap` lookup interface.\n *\n * Generated shapes describe attrs **after** the adapter's wire normalization\n * (the v1 loader rewrites export-path wire values to the query-path string\n * forms before populating attrs — see `normalize.ts`), so one encoding holds\n * regardless of read path:\n *\n * `Date` → `string` (`'YYYY-MM-DD'`)\n * `DateTime` → `string` (ISO 8601, `'YYYY-MM-DDTHH:MM:SS.mmmZ'`)\n * `enum(...)` → string-literal union\n * `I64`/`U64` → `number` (beware silent rounding past ±2^53)\n * `F32`/`F64` → `number`\n * `Vector(n)` → `number[]`\n * `Blob` → `string` (`data:` URI for inline blobs, stored URI refs verbatim)\n * `T?` → `T | null`\n *\n * Output is a self-contained module (no imports), safe under the strictest\n * tsconfig (`strict`, `exactOptionalPropertyTypes`, `verbatimModuleSyntax`,\n * `isolatedModules`). The file carries a DO-NOT-EDIT header with the\n * schema fingerprint. Generation is deterministic — no timestamps — so the\n * output is committable and diff-stable.\n *\n * Browser-safe: no `node:` imports (the CLI wrapper in `codegen-cli.ts` owns\n * file I/O).\n */\n\nimport { ORBIT_TYPE_KEY } from './normalize';\nimport {\n parsePgSchema,\n schemaFingerprint,\n type PgProperty,\n type PgScalarName,\n type PgSchema,\n type PgType,\n} from './pgSchema';\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\nexport interface GenerateTypesOptions {\n /**\n * Extra provenance lines for the DO-NOT-EDIT banner (e.g. the schema file\n * path or server URL). May be multi-line; lines are comment-prefixed as\n * needed.\n */\n header?: string;\n /**\n * The schema fingerprint of the `.pg` **source** (from\n * {@link schemaFingerprint}). When omitted, a fingerprint of the canonical\n * parsed model is used instead and labelled as such — prefer\n * {@link generateTypesFromPgSource}, which always stamps the source\n * fingerprint.\n */\n fingerprint?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Wire value → TypeScript mapping (post-normalization)\n// ---------------------------------------------------------------------------\n\nconst SCALAR_TS: Record<PgScalarName, string> = {\n String: 'string',\n Blob: 'string',\n Bool: 'boolean',\n I32: 'number',\n I64: 'number',\n U32: 'number',\n U64: 'number',\n F32: 'number',\n F64: 'number',\n Date: 'string',\n DateTime: 'string',\n};\n\n/** Single-quoted TS string literal with escapes. */\nfunction tsStringLiteral(value: string): string {\n return `'${value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\").replace(/\\r/g, '\\\\r').replace(/\\n/g, '\\\\n')}'`;\n}\n\nfunction tsType(type: PgType): string {\n if (typeof type === 'string') return SCALAR_TS[type];\n switch (type.kind) {\n case 'vector':\n return 'number[]';\n case 'enum':\n return type.values.length === 0 ? 'string' : type.values.map(tsStringLiteral).join(' | ');\n case 'list':\n return `${SCALAR_TS[type.element]}[]`;\n case 'unknown':\n return 'unknown';\n }\n}\n\n/** One-line doc note for types whose TS shape hides a wire subtlety. */\nfunction wireNote(type: PgType): string | null {\n if (typeof type === 'string') {\n switch (type) {\n case 'Date':\n return \"`Date` — normalized to 'YYYY-MM-DD' (UTC) on load.\";\n case 'DateTime':\n return '`DateTime` — normalized to ISO 8601 UTC on load.';\n case 'Blob':\n return \"`Blob` — `data:` URI for inline blobs, stored URI refs verbatim.\";\n case 'I64':\n case 'U64':\n return `\\`${type}\\` — JSON numbers round silently past ±2^53.`;\n default:\n return null;\n }\n }\n switch (type.kind) {\n case 'vector':\n return `\\`Vector(${type.dim})\\`.`;\n case 'unknown':\n return `Unrecognized \\`.pg\\` type \\`${type.raw}\\` — value passes through verbatim.`;\n default:\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Emission helpers\n// ---------------------------------------------------------------------------\n\nconst IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nfunction propertyKey(name: string): string {\n return IDENT_RE.test(name) ? name : tsStringLiteral(name);\n}\n\nfunction emitProperty(lines: string[], prop: PgProperty): void {\n const note = wireNote(prop.type);\n if (note !== null) lines.push(` /** ${note} */`);\n const base = tsType(prop.type);\n lines.push(` ${propertyKey(prop.name)}: ${prop.optional ? `${base} | null` : base};`);\n}\n\nfunction emitPropsInterface(\n lines: string[],\n interfaceName: string,\n kindLabel: 'node' | 'edge',\n typeName: string,\n properties: readonly PgProperty[],\n): void {\n lines.push(`/** Normalized attrs for ${kindLabel} type \\`${typeName}\\`. */`);\n lines.push(`export interface ${interfaceName} {`);\n if (!properties.some((p) => p.name === 'id')) {\n lines.push(\n ` /** Physical Omnigraph id — injected into every export line's \\`data\\`; unique per ${kindLabel} type only. */`,\n );\n lines.push(' id: string;');\n }\n for (const prop of properties) {\n // Every schema property emits normally — including one named `type`: the\n // adapter's discriminator lives at the namespaced ORBIT_TYPE_KEY, so\n // there is nothing to shadow.\n emitProperty(lines, prop);\n }\n lines.push('}');\n lines.push('');\n}\n\nfunction emitAttrsUnion(\n lines: string[],\n unionName: string,\n doc: string,\n members: ReadonlyArray<{ typeName: string; interfaceName: string }>,\n): void {\n lines.push(`/** ${doc} */`);\n if (members.length === 0) {\n lines.push(`export type ${unionName} = never;`);\n } else {\n lines.push(`export type ${unionName} =`);\n members.forEach(({ typeName, interfaceName }, i) => {\n const tail = i === members.length - 1 ? ';' : '';\n lines.push(\n ` | ({ ${tsStringLiteral(ORBIT_TYPE_KEY)}: ${tsStringLiteral(typeName)} } & ${interfaceName})${tail}`,\n );\n });\n }\n lines.push('');\n}\n\nfunction headerBanner(fingerprintLine: string, extra: string | undefined): string[] {\n const lines = [\n '// AUTO-GENERATED — DO NOT EDIT.',\n '//',\n '// .pg → TypeScript typed attrs (wire-normalized), generated by',\n '// @modernrelay/orbit-omnigraph (`orbit-omnigraph-codegen`).',\n `// ${fingerprintLine}`,\n ];\n if (extra !== undefined && extra.length > 0) {\n for (const raw of extra.split('\\n')) {\n lines.push(raw.startsWith('//') ? raw : `// ${raw}`.trimEnd());\n }\n }\n lines.push(\n '//',\n \"// Shapes describe attrs AFTER the adapter's wire normalization (both read\",\n '// paths converge on the query-path string encodings):',\n \"// Date → 'YYYY-MM-DD' · DateTime → ISO 8601 · enum(...) → literal union\",\n '// I64/U64/F32/F64 → number · Vector(n) → number[] · T? → T | null',\n \"// Blob → string ('data:' URI for inline blobs, stored URI for external)\",\n '',\n );\n return lines;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a self-contained TypeScript module of typed attrs from a parsed\n * `.pg` schema: one `<Name>Props` interface per node type, one\n * `<Name>EdgeProps` per edge type (suffixed so a node and an edge sharing a\n * name cannot collide), `NodeAttrs`/`EdgeAttrs` discriminated unions on the\n * adapter-injected `'orbit:type'` field, and a `TypeMap` lookup interface with\n * `NodeTypeName`/`EdgeTypeName` key unions.\n *\n * Deterministic: identical input (schema + options) yields identical output.\n */\nexport function generateTypes(schema: PgSchema, opts?: GenerateTypesOptions): string {\n const fingerprintLine =\n opts?.fingerprint !== undefined\n ? `Schema fingerprint: ${opts.fingerprint}.`\n : `Schema fingerprint: ${schemaFingerprint(JSON.stringify(schema))} (parsed model — regenerate from .pg source for the source fingerprint).`;\n const lines = headerBanner(fingerprintLine, opts?.header);\n\n const nodeMembers = schema.nodes.map((n) => ({\n typeName: n.name,\n interfaceName: `${n.name}Props`,\n }));\n const edgeMembers = schema.edges.map((e) => ({\n typeName: e.name,\n interfaceName: `${e.name}EdgeProps`,\n }));\n\n schema.nodes.forEach((n, i) => {\n const member = nodeMembers[i];\n if (member) emitPropsInterface(lines, member.interfaceName, 'node', n.name, n.properties);\n });\n schema.edges.forEach((e, i) => {\n const member = edgeMembers[i];\n if (member) emitPropsInterface(lines, member.interfaceName, 'edge', e.name, e.properties);\n });\n\n emitAttrsUnion(\n lines,\n 'NodeAttrs',\n \"Discriminated union over every node type's normalized attrs — `'orbit:type'` is injected by the adapter.\",\n nodeMembers,\n );\n emitAttrsUnion(\n lines,\n 'EdgeAttrs',\n \"Discriminated union over every edge type's normalized attrs — `'orbit:type'` is the edge name.\",\n edgeMembers,\n );\n\n lines.push('/** Type-name → props lookup for both kinds (closed sets from the schema — the wire contract). */');\n lines.push('export interface TypeMap {');\n lines.push(' nodes: {');\n for (const m of nodeMembers) lines.push(` ${propertyKey(m.typeName)}: ${m.interfaceName};`);\n lines.push(' };');\n lines.push(' edges: {');\n for (const m of edgeMembers) lines.push(` ${propertyKey(m.typeName)}: ${m.interfaceName};`);\n lines.push(' };');\n lines.push('}');\n lines.push('');\n lines.push(\"export type NodeTypeName = keyof TypeMap['nodes'];\");\n lines.push(\"export type EdgeTypeName = keyof TypeMap['edges'];\");\n lines.push('');\n return lines.join('\\n');\n}\n\n/**\n * Parse `.pg` source and generate typed attrs (see {@link generateTypes}),\n * stamping the header with the source fingerprint\n * ({@link schemaFingerprint} over the verbatim source).\n */\nexport function generateTypesFromPgSource(\n source: string,\n opts?: Omit<GenerateTypesOptions, 'fingerprint'>,\n): string {\n const schema = parsePgSchema(source);\n const options: GenerateTypesOptions = { fingerprint: schemaFingerprint(source) };\n if (opts?.header !== undefined) options.header = opts.header;\n return generateTypes(schema, options);\n}\n","#!/usr/bin/env node\n/**\n * `orbit-omnigraph-codegen` — minimal `.pg` → TypeScript codegen CLI.\n *\n * orbit-omnigraph-codegen <schema.pg> [-o out.ts]\n * orbit-omnigraph-codegen --from-server <baseUrl> --graph <id> [-o out.ts]\n *\n * The first form reads a `.pg` file; the second fetches the active schema\n * from a running omnigraph-server via a plain **unauthenticated** SDK client\n * (`og.schema.get()` returns the raw `.pg` source). Authenticated client\n * construction stays exclusively in the `/server` entry; point\n * this tool at an `--unauthenticated` server or a same-origin proxy.\n *\n * Without `-o`, the generated module goes to stdout.\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport process from 'node:process';\nimport { Omnigraph } from '@modernrelay/omnigraph';\nimport { generateTypesFromPgSource } from './codegen';\n\nconst USAGE = `Usage:\n orbit-omnigraph-codegen <schema.pg> [-o <out.ts>]\n orbit-omnigraph-codegen --from-server <baseUrl> --graph <id> [-o <out.ts>]\n\nGenerates TypeScript typed attrs from a .pg schema — read from a\nfile, or fetched from a running omnigraph-server (unauthenticated client).\nWrites to stdout unless -o is given.\n`;\n\ninterface CliArgs {\n schemaPath?: string;\n out?: string;\n fromServer?: string;\n graph?: string;\n}\n\nfunction parseArgs(argv: readonly string[]): CliArgs | string {\n const args: CliArgs = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === undefined) continue;\n switch (arg) {\n case '-h':\n case '--help':\n return 'help';\n case '-o':\n case '--out': {\n const v = argv[++i];\n if (v === undefined) return `missing value for ${arg}`;\n args.out = v;\n break;\n }\n case '--from-server': {\n const v = argv[++i];\n if (v === undefined) return 'missing value for --from-server';\n args.fromServer = v;\n break;\n }\n case '--graph': {\n const v = argv[++i];\n if (v === undefined) return 'missing value for --graph';\n args.graph = v;\n break;\n }\n default:\n if (arg.startsWith('-')) return `unknown option '${arg}'`;\n if (args.schemaPath !== undefined) return `unexpected argument '${arg}'`;\n args.schemaPath = arg;\n }\n }\n if (args.fromServer !== undefined && args.schemaPath !== undefined) {\n return 'pass a schema file OR --from-server, not both';\n }\n if (args.fromServer !== undefined && args.graph === undefined) {\n return '--from-server requires --graph <id> (schema reads are graph-scoped)';\n }\n if (args.fromServer === undefined && args.schemaPath === undefined) {\n return 'no schema given';\n }\n return args;\n}\n\nasync function main(argv: readonly string[]): Promise<number> {\n const parsed = parseArgs(argv);\n if (parsed === 'help') {\n process.stdout.write(USAGE);\n return 0;\n }\n if (typeof parsed === 'string') {\n process.stderr.write(`orbit-omnigraph-codegen: ${parsed}\\n\\n${USAGE}`);\n return 2;\n }\n\n let source: string;\n let provenance: string;\n if (parsed.fromServer !== undefined && parsed.graph !== undefined) {\n const og = new Omnigraph({ baseUrl: parsed.fromServer, graphId: parsed.graph });\n const schema = await og.schema.get();\n source = schema.schemaSource;\n provenance = `Source: ${parsed.fromServer} (graph '${parsed.graph}', GET /schema)`;\n } else if (parsed.schemaPath !== undefined) {\n source = readFileSync(parsed.schemaPath, 'utf8');\n provenance = `Source: ${parsed.schemaPath}`;\n } else {\n // Unreachable: parseArgs guarantees one of the two.\n return 2;\n }\n\n const output = generateTypesFromPgSource(source, { header: provenance });\n if (parsed.out !== undefined) {\n writeFileSync(parsed.out, output);\n process.stderr.write(`orbit-omnigraph-codegen: wrote ${parsed.out}\\n`);\n } else {\n process.stdout.write(output);\n }\n return 0;\n}\n\nmain(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`orbit-omnigraph-codegen: ${message}\\n`);\n process.exitCode = 1;\n },\n);\n"]}
|