@xanots/sdk 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +48 -5
- package/dist/.build-fingerprint +1 -1
- package/dist/{agent-file-refresh-QNKN5RYD.js → agent-file-refresh-GQWAAOBV.js} +4 -4
- package/dist/bin.js +12 -11
- package/dist/{branch-commands-2BLOC2GR.js → branch-commands-5KMPAAZV.js} +7 -7
- package/dist/bundle.d.ts +218 -0
- package/dist/bundle.js +143 -0
- package/dist/{capture-4WVJY4DQ.js → capture-YLUVAITI.js} +2 -2
- package/dist/chunk-2VTJSI6X.js +192 -0
- package/dist/{chunk-5XZ744TS.js → chunk-2ZCUO2UG.js} +1 -1
- package/dist/{chunk-OYMR5AMJ.js → chunk-3LQGF2WS.js} +2 -2
- package/dist/{chunk-WP4OZZV4.js → chunk-3VFCKHOB.js} +2 -2
- package/dist/{chunk-XHEXOES3.js → chunk-5YDINUAP.js} +1 -1
- package/dist/{chunk-LU7TRWMC.js → chunk-6VNRMKFJ.js} +2 -2
- package/dist/{chunk-CTD5ZCV6.js → chunk-7WRJPKGK.js} +2 -2
- package/dist/{chunk-3INK4Y4E.js → chunk-AE3PDSDS.js} +1 -1
- package/dist/{chunk-5YCQ2QHH.js → chunk-AG5GCZDD.js} +2 -2
- package/dist/{chunk-DBFU47BJ.js → chunk-AOFFKSJC.js} +2 -2
- package/dist/{chunk-TCFIPDB3.js → chunk-AVGDL6RB.js} +1 -1
- package/dist/{chunk-4BXJGVZ3.js → chunk-DCMANKMX.js} +2 -69
- package/dist/{chunk-WHOJWOSV.js → chunk-EETVJZAZ.js} +1 -1
- package/dist/chunk-EHP3WPEG.js +21 -0
- package/dist/{chunk-W24FJHPD.js → chunk-ELK7UALJ.js} +3 -3
- package/dist/{chunk-VNQM3V2C.js → chunk-EXENFOWE.js} +2 -2
- package/dist/{chunk-P6TAVLOX.js → chunk-GSP2BY4F.js} +17 -10
- package/dist/{chunk-AIZKXUNP.js → chunk-IMLYGQK6.js} +2 -2
- package/dist/{chunk-LBYWGMOA.js → chunk-N74KDCBD.js} +176 -42
- package/dist/{chunk-3IGNIP6R.js → chunk-NDP7OUPS.js} +1 -1
- package/dist/chunk-OHX6MIUZ.js +184 -0
- package/dist/{chunk-EQW3YT5U.js → chunk-P6PVBQL6.js} +2 -2
- package/dist/{chunk-I7DQDJAM.js → chunk-PLE5QQOZ.js} +55 -56
- package/dist/chunk-PR7OXHGZ.js +70 -0
- package/dist/{chunk-VKSOTZK3.js → chunk-QYSQ3UDO.js} +160 -8
- package/dist/{chunk-ZQ2PKR6R.js → chunk-RQ3FXV4K.js} +2 -2
- package/dist/{chunk-Q77KNEUL.js → chunk-RQNMTDXD.js} +1703 -2
- package/dist/{chunk-QKM4U5UK.js → chunk-TJS2AF5Y.js} +2 -2
- package/dist/{chunk-DIA7CT7J.js → chunk-V5Y7D4LH.js} +11 -2
- package/dist/{chunk-KA6G2L7U.js → chunk-VK26K7AY.js} +3 -3
- package/dist/{chunk-YYFXVYPX.js → chunk-VPAWRBK5.js} +12 -16
- package/dist/{chunk-5R73LFWK.js → chunk-VRNZ2NVV.js} +7 -7
- package/dist/{chunk-ACCBOMCB.js → chunk-XT3XQ4PF.js} +32 -27
- package/dist/{chunk-7JDT4PBU.js → chunk-XWFRNJMQ.js} +5 -179
- package/dist/{chunk-7ZYW652H.js → chunk-YHS6VVLJ.js} +2 -2
- package/dist/{chunk-75Z74TA7.js → chunk-YX22LKQE.js} +2 -2
- package/dist/{chunk-F6CYJ7TN.js → chunk-Z2ZIE5CO.js} +2 -2
- package/dist/cli.d.ts +13 -6
- package/dist/cli.js +11 -10
- package/dist/codegen-command-Y2SPMAUW.js +47 -0
- package/dist/codegen.d.ts +5 -4
- package/dist/codegen.js +2 -2
- package/dist/{completion-WF46272M.js → completion-HJU5QEFB.js} +2 -2
- package/dist/{deploy-command-QTIVA22A.js → deploy-command-XHS5PKPV.js} +20 -19
- package/dist/{ephemeral-command-U4AQ3TXX.js → ephemeral-command-2NKPEXUU.js} +8 -8
- package/dist/index.d.ts +88 -102
- package/dist/index.js +13 -12
- package/dist/init-command-23FFNUFT.js +32 -0
- package/dist/internal.d.ts +10 -16
- package/dist/internal.js +76 -54
- package/dist/io-UBDMMDH6.js +12 -0
- package/dist/{live-diff-IXKBVG4K.js → live-diff-HCOTN5WC.js} +3 -3
- package/dist/{lock-GFXD6G2E.js → lock-HQ4KARU2.js} +3 -2
- package/dist/{lock-commands-DQ7CUMIV.js → lock-commands-WCRC56ME.js} +12 -11
- package/dist/{login-command-Z6CHTA57.js → login-command-P7LXD5TE.js} +6 -6
- package/dist/{loop-D5NPL4VH.js → loop-IC5ISSYB.js} +3 -3
- package/dist/{marketplace-command-P4IPLJ6J.js → marketplace-command-T6JCHW7J.js} +4 -4
- package/dist/{meta-client-K2J4XH64.js → meta-client-LKRKR3L2.js} +4 -4
- package/dist/node.d.ts +6 -5
- package/dist/node.js +18 -17
- package/dist/{preflight-command-GZ2GE5RN.js → preflight-command-TZWPHBXY.js} +17 -16
- package/dist/{profile-command-LJSBDV2L.js → profile-command-WBNSMQSI.js} +3 -3
- package/dist/{release-command-YUBTNHVX.js → release-command-WEFYRTCI.js} +27 -26
- package/dist/response-D6xGLEIn.d.ts +839 -0
- package/dist/{routes-manifest-PWZHDOI5.js → routes-manifest-5ZFKUQWA.js} +2 -2
- package/dist/{runtime-V4C3AC3A.js → runtime-LSLIDALK.js} +1 -1
- package/dist/scaffold.d.ts +16 -8
- package/dist/scaffold.js +7 -11
- package/dist/{static-host-3WMV7IZO.js → static-host-4JDQCHUW.js} +1 -1
- package/dist/{status-command-AL47VG7H.js → status-command-VARULAR5.js} +4 -4
- package/dist/{store-BG1UPZ3Z.d.ts → store-DAnUIi1T.d.ts} +95 -87
- package/dist/{test-command-YAZLKLGQ.js → test-command-YCAR4O35.js} +7 -7
- package/dist/{upgrade-command-FB5QJ363.js → upgrade-command-GYEIMJBG.js} +16 -16
- package/dist/{workspace-2COHDBM3.js → workspace-33KHFLX3.js} +2 -2
- package/dist/{workspace-command-43P42FBP.js → workspace-command-2ZTGT26W.js} +28 -27
- package/dist/{workspace-export-DURY5WYL.js → workspace-export-MLYTYZS5.js} +3 -3
- package/dist/{response-CVAE2kMj.d.ts → xdo-ODuJklk6.d.ts} +28 -860
- package/guides/authoring.md +11 -2
- package/guides/typed-frontend.md +5 -5
- package/llms/filters.md +11 -10
- package/llms/kinds-core.md +1 -1
- package/llms/statements-data.md +6 -3
- package/llms/values.md +1 -1
- package/llms-full.txt +53 -42
- package/llms.txt +34 -27
- package/manifest.json +6 -2
- package/package.json +7 -2
- package/dist/chunk-ANUDXFEX.js +0 -881
- package/dist/chunk-JGCWTCA7.js +0 -95
- package/dist/chunk-YBC3IKMF.js +0 -845
- package/dist/codegen-command-GB3H2KQ7.js +0 -46
- package/dist/init-command-MAXULNAD.js +0 -33
- package/dist/io-M7XZEMK7.js +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,39 @@ listed here.
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## 0.0.11 — The silent-success pass
|
|
15
|
+
|
|
16
|
+
_2026-08-31_ · [release notes](https://github.com/xanots/sdk/releases/tag/v0.0.11)
|
|
17
|
+
|
|
18
|
+
This release adds one new entry point and closes a set of shapes that compiled clean and then went wrong at request time — a regex pair that answered `false` for every input, a read addressed by query string instead of by path, a column name the engine reserves, and a `0` id that fails a whole request. Most land as warnings, so an ordinary build is unaffected; `export --strict` promotes them, so a strict build that passed on 0.0.10 can newly fail. It also corrects one piece of published advice: a physical table name is not stable across deploys, and the old atomic-counter guidance said to hardcode it.
|
|
19
|
+
|
|
20
|
+
- `@xanots/sdk/bundle` reads a compiled bundle without reimplementing the SDK
|
|
21
|
+
- ⚠️ A reversed regex operand pair is refused instead of answering `false` forever
|
|
22
|
+
- ⚠️ An addressing input missing from a query's path now warns
|
|
23
|
+
- ⚠️ A reserved `run` column and a `get_by_id` id that can be `0` now warn
|
|
24
|
+
- `obj()` accepts `c.obj` and `c.array` members
|
|
25
|
+
- `./manifest.json` is exported from the package
|
|
26
|
+
- Corrected: a physical table name is not stable across deploys
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 0.0.10 — The CLI surface pass
|
|
31
|
+
|
|
32
|
+
_2026-08-31_ · [release notes](https://github.com/xanots/sdk/releases/tag/v0.0.10)
|
|
33
|
+
|
|
34
|
+
This release is a CLI surface pass, and it is breaking throughout. Six ways to start a project collapse to `init` plus two flags, the sandbox environment is gone with every surface that named it, and a run of commands and flags were renamed to say what they actually do — including three that each carried two or three unrelated meanings. One command is new: `xanots status` answers where you stand in a single read.
|
|
35
|
+
|
|
36
|
+
- ⚠️ Project creation is one command: `init`, with `--from` and `--web`
|
|
37
|
+
- ⚠️ The sandbox environment is gone
|
|
38
|
+
- ⚠️ `deploy` takes no environment flag
|
|
39
|
+
- `xanots status` — who, where, and which environment
|
|
40
|
+
- ⚠️ `validate` is now `preflight`, and `lock adopt` is now `lock import`
|
|
41
|
+
- ⚠️ `--dest` is now `--env`, and names environments the way `--from` does
|
|
42
|
+
- ⚠️ Flags that carried several meanings were split apart
|
|
43
|
+
- `routes` and `whoami` are the canonical spellings
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
14
47
|
## 0.0.9 — Eight reports from real use
|
|
15
48
|
|
|
16
49
|
_2026-08-31_ · [release notes](https://github.com/xanots/sdk/releases/tag/v0.0.9)
|
package/README.md
CHANGED
|
@@ -173,8 +173,10 @@ const HOST = (typeof window !== "undefined" && window.XANO_HOST) || import.meta.
|
|
|
173
173
|
|
|
174
174
|
**Prefer to wire it by hand?** Skip `init` — `npm install @xanots/sdk`, write your workspace
|
|
175
175
|
in `xano/index.ts`, and steps 1 and 4 are unchanged. The entry must be an ES module (XanoTS
|
|
176
|
-
defs are ESM-only)
|
|
177
|
-
|
|
176
|
+
defs are ESM-only), and a TypeScript entry wants [`tsx`](https://tsx.is) installed
|
|
177
|
+
(`npm i -D tsx`) — the CLI picks it up automatically. Node's own type stripping is not
|
|
178
|
+
enough on its own: it loads a `.ts` file but does not remap the `./x.js` specifiers a
|
|
179
|
+
workspace uses to import its own modules, so anything past a single file fails to resolve.
|
|
178
180
|
|
|
179
181
|
---
|
|
180
182
|
|
|
@@ -228,8 +230,9 @@ export default workspace("blog")
|
|
|
228
230
|
Tab-complete `s.` to discover the entire statement catalog — `s.db.*`, `s.math.*`,
|
|
229
231
|
`s.array.*`, `s.text.*`, `s.storage.*`, `s.api.*`, `s.cloud.*`, control flow, AI agent runs,
|
|
230
232
|
and more. **All 214 engine statement surfaces are authorable** — every field name matches
|
|
231
|
-
the Xano engine, and the
|
|
232
|
-
|
|
233
|
+
the Xano engine, and the emitted shape is checked against bytes a real engine stored. Where
|
|
234
|
+
a surface has no stored instance behind it yet, it is built from the engine's own schema;
|
|
235
|
+
[Coverage](https://github.com/xanots/sdk/blob/main/guides/coverage.md) says which is which.
|
|
233
236
|
|
|
234
237
|
Give a table a `seed` array and those rows ship into the database on deploy, so a fresh
|
|
235
238
|
environment comes up with its lookup tables and fixtures already in place.
|
|
@@ -288,7 +291,7 @@ remember the environment's name; it is tracked with the project.
|
|
|
288
291
|
|
|
289
292
|
Every flag, the `--prune` rules, the identity model, and headless CI runs are in
|
|
290
293
|
[Signing in & deploying](https://github.com/xanots/sdk/blob/main/guides/deploying.md). Environment management is
|
|
291
|
-
`xanots ephemeral <list|get|delete|export>`.
|
|
294
|
+
`xanots ephemeral <list|get|delete|export|impersonate>`.
|
|
292
295
|
|
|
293
296
|
### Testing
|
|
294
297
|
|
|
@@ -414,6 +417,46 @@ reference, the guides carry the shape of a project and the behavior that will bi
|
|
|
414
417
|
| [Pulling an existing workspace](https://github.com/xanots/sdk/blob/main/guides/codegen.md) | What `xanots init --from` writes, how faithful it is, and how to read its report |
|
|
415
418
|
| [Coverage & agent grounding](https://github.com/xanots/sdk/blob/main/guides/coverage.md) | What is covered, what is out of scope, and the files agents read |
|
|
416
419
|
|
|
420
|
+
### Reading a compiled bundle
|
|
421
|
+
|
|
422
|
+
`@xanots/sdk` writes a bundle; `@xanots/sdk/bundle` reads one back. It is the surface for
|
|
423
|
+
tools that take compiled JSON as input — a graph view, a diff, a linter, a docs generator —
|
|
424
|
+
so none of them has to reverse-engineer the storage shape and then go quietly wrong when the
|
|
425
|
+
engine grows a new one.
|
|
426
|
+
|
|
427
|
+
```ts
|
|
428
|
+
import { statementCatalog, walk } from "@xanots/sdk/bundle";
|
|
429
|
+
|
|
430
|
+
const bundle = JSON.parse(await readFile("bundle.json", "utf8"));
|
|
431
|
+
const catalog = statementCatalog();
|
|
432
|
+
|
|
433
|
+
for (const { raw, path, depth } of walk(bundle.payload.query[0].run)) {
|
|
434
|
+
console.log(`${" ".repeat(depth)}${path} ${catalog.get(raw.name)?.sPath ?? raw.name}`);
|
|
435
|
+
}
|
|
436
|
+
// 0 db.query
|
|
437
|
+
// 1 conditional
|
|
438
|
+
// 1.if.0 db.add
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
- **`walk(run)`** → every statement in the tree, each with a `path` and a `depth`. The path
|
|
442
|
+
format (`2.if.0`) is the shared address: a lint finding, a review comment and a runtime
|
|
443
|
+
error written by three different tools all name the same node.
|
|
444
|
+
- **`subStacks(raw)`** → the nested stacks a statement carries, keyed by where they are
|
|
445
|
+
stored and labelled by what they mean — a try/catch and a conditional share the same three
|
|
446
|
+
storage keys. Found by shape, so a nesting form added later is still walked.
|
|
447
|
+
- **`statementCatalog()`** → the stored `mvp:*` name to its authoring path, minus the
|
|
448
|
+
namespace (`mvp:dbo_view` → `db.query`, the `sPath` you write after `s.`) — which is
|
|
449
|
+
the point: the stored name is often not the one you'd guess.
|
|
450
|
+
- **`structuralHash(raw)`** → a diff key for a statement and everything under it, with
|
|
451
|
+
engine-filled operands excluded. Without that exclusion, adding one column to a table
|
|
452
|
+
reports every statement that writes it as changed.
|
|
453
|
+
- **`tableRefOf(column)` / `linkedTableOf(column)`** → the table a column points at.
|
|
454
|
+
- **`normalize(value)`** → the normalizer `xanots preflight` compares with, for diffing a
|
|
455
|
+
stored workspace against a compiled one.
|
|
456
|
+
|
|
457
|
+
Everything on the entry is pure — no filesystem, no network, no Node built-ins — so it runs
|
|
458
|
+
in a browser or a worker.
|
|
459
|
+
|
|
417
460
|
The package also ships two machine-readable descriptions of the same surface, generated from
|
|
418
461
|
the SDK's own sources so they cannot drift from it: `llms.txt` (the router — the mental model
|
|
419
462
|
and the gotchas, plus a map of the `llms/*.md` topic files) and `manifest.json` (per-entry
|
package/dist/.build-fingerprint
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
7189e90fd30c05ded87b682caf1b483465145a88a8373b654ad8f94fb6812b79
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
codingAgentDetected,
|
|
4
4
|
isCI,
|
|
5
5
|
refreshAgentFiles
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-2VTJSI6X.js";
|
|
7
|
+
import "./chunk-VK26K7AY.js";
|
|
8
8
|
import "./chunk-ZSYZTGJH.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-RQNMTDXD.js";
|
|
10
10
|
import "./chunk-EZG76F7R.js";
|
|
11
11
|
export {
|
|
12
12
|
CI_ENV_VARS,
|
|
@@ -14,4 +14,4 @@ export {
|
|
|
14
14
|
isCI,
|
|
15
15
|
refreshAgentFiles
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=agent-file-refresh-
|
|
17
|
+
//# sourceMappingURL=agent-file-refresh-GQWAAOBV.js.map
|
package/dist/bin.js
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
maybeNotifyUpdate
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-AG5GCZDD.js";
|
|
5
5
|
import {
|
|
6
6
|
readVersion,
|
|
7
7
|
run
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-XT3XQ4PF.js";
|
|
9
|
+
import "./chunk-7WRJPKGK.js";
|
|
10
|
+
import "./chunk-3LQGF2WS.js";
|
|
11
11
|
import {
|
|
12
12
|
exitCodeOf,
|
|
13
13
|
reportFailure
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-Z2ZIE5CO.js";
|
|
15
15
|
import "./chunk-GNPVYOPB.js";
|
|
16
16
|
import {
|
|
17
17
|
clearProgress,
|
|
18
18
|
error
|
|
19
19
|
} from "./chunk-EZG76F7R.js";
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-QYSQ3UDO.js";
|
|
21
|
+
import "./chunk-V5Y7D4LH.js";
|
|
22
|
+
import "./chunk-N74KDCBD.js";
|
|
23
|
+
import "./chunk-EETVJZAZ.js";
|
|
24
|
+
import "./chunk-XWFRNJMQ.js";
|
|
25
|
+
import "./chunk-2ZCUO2UG.js";
|
|
26
|
+
import "./chunk-OHX6MIUZ.js";
|
|
26
27
|
|
|
27
28
|
// src/emit/interrupt.ts
|
|
28
29
|
var EXIT_SIGINT = 130;
|
|
@@ -3,23 +3,23 @@ import {
|
|
|
3
3
|
listBranches,
|
|
4
4
|
requireBranch,
|
|
5
5
|
setLiveBranch
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-P6PVBQL6.js";
|
|
7
7
|
import {
|
|
8
8
|
confirm
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-IMLYGQK6.js";
|
|
10
10
|
import {
|
|
11
11
|
isMachineOutput,
|
|
12
12
|
writeJson
|
|
13
13
|
} from "./chunk-NUQCEOKA.js";
|
|
14
14
|
import {
|
|
15
15
|
getAccessToken
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TJS2AF5Y.js";
|
|
17
17
|
import "./chunk-FE5I6S6N.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-NDP7OUPS.js";
|
|
19
19
|
import {
|
|
20
20
|
UsageError,
|
|
21
21
|
assertNoForce
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-Z2ZIE5CO.js";
|
|
23
23
|
import "./chunk-GNPVYOPB.js";
|
|
24
24
|
import {
|
|
25
25
|
blank,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
success,
|
|
30
30
|
warn
|
|
31
31
|
} from "./chunk-EZG76F7R.js";
|
|
32
|
-
import "./chunk-
|
|
32
|
+
import "./chunk-V5Y7D4LH.js";
|
|
33
33
|
|
|
34
34
|
// src/emit/branch-commands.ts
|
|
35
35
|
var VERBS = ["list", "set-live", "delete"];
|
|
@@ -133,4 +133,4 @@ Promote another branch first (\`xanots workspace branch set-live <other>\`), the
|
|
|
133
133
|
export {
|
|
134
134
|
runBranchCommand
|
|
135
135
|
};
|
|
136
|
-
//# sourceMappingURL=branch-commands-
|
|
136
|
+
//# sourceMappingURL=branch-commands-5KMPAAZV.js.map
|
package/dist/bundle.d.ts
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { S as StackItemXdo, g as FieldXdo } from './xdo-ODuJklk6.js';
|
|
2
|
+
export { b as ConditionalContext, c as ConditionalElifContext, E as ExprGroup, d as ExprNode, e as ExprOperand, f as ExprStatement, h as FilterXdo, I as InputXdo, M as MethodXdo, k as ResultItemXdo, l as StatementInputXdo, o as TaggedValue } from './xdo-ODuJklk6.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The statement catalog, keyed the way a bundle reader needs it.
|
|
6
|
+
*
|
|
7
|
+
* A compiled statement identifies itself by its STORED name (`mvp:dbo_view`);
|
|
8
|
+
* everything a person reads — a docs link, a lint message, a graph node label —
|
|
9
|
+
* wants the authoring path (`s.db.query`). The mapping is SDK metadata, so a
|
|
10
|
+
* third-party tool must not have to keep its own copy: a new statement kind
|
|
11
|
+
* would then need a release in every tool before it stopped rendering as an
|
|
12
|
+
* unknown node.
|
|
13
|
+
*/
|
|
14
|
+
/** One stored statement name and the authoring surface(s) that compile to it. */
|
|
15
|
+
interface StatementCatalogEntry {
|
|
16
|
+
/** The stored `mvp:` name, as it appears on a compiled statement's `name`. */
|
|
17
|
+
readonly storedName: string;
|
|
18
|
+
/** The primary surface key — the engine's own schema name, e.g. `db.query`. */
|
|
19
|
+
readonly surface: string;
|
|
20
|
+
/** The dotted accessor under `s.`, e.g. `db.query` is reachable as `s.db.query`. */
|
|
21
|
+
readonly sPath: string;
|
|
22
|
+
/**
|
|
23
|
+
* Every surface key stored under this name, in catalog order. Almost always
|
|
24
|
+
* one; the mapping is NOT injective (`util.get_raw_input` and `util.get_input`
|
|
25
|
+
* both store `mvp:get_input`), so a reader that must not lose a surface reads
|
|
26
|
+
* this rather than {@link StatementCatalogEntry.surface}.
|
|
27
|
+
*/
|
|
28
|
+
readonly surfaces: readonly string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Every stored statement name the SDK knows, mapped to its authoring surface.
|
|
32
|
+
*
|
|
33
|
+
* Built once and shared — the returned map is frozen in the sense that it is the
|
|
34
|
+
* same instance on every call, so a caller must not mutate it.
|
|
35
|
+
*
|
|
36
|
+
* `raw()` is deliberately absent: it is the passthrough for stored statements
|
|
37
|
+
* the catalog cannot model, so a `name` that misses here is exactly the set a
|
|
38
|
+
* tool should render as opaque.
|
|
39
|
+
*/
|
|
40
|
+
declare function statementCatalog(): ReadonlyMap<string, StatementCatalogEntry>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Statement-tree traversal for a compiled bundle.
|
|
44
|
+
*
|
|
45
|
+
* A stack is a `run[]` of {@link StackItemXdo} envelopes, and a statement that
|
|
46
|
+
* nests carries its children under `context` — never under a single key. A
|
|
47
|
+
* conditional stores `if.run` / `elif.run` / `else.run`, a try/catch reuses the
|
|
48
|
+
* same three keys for `try` / `catch` / `finally`, a switch stores its cases
|
|
49
|
+
* under `elif.run` and its default under `else.run`, and every loop, group and
|
|
50
|
+
* transaction stores a bare `context.run`.
|
|
51
|
+
*
|
|
52
|
+
* A tool that hardcodes that key set drops a subtree silently the day the engine
|
|
53
|
+
* adds a nesting shape, so {@link subStacks} does not hardcode it: it finds a
|
|
54
|
+
* sub-stack by SHAPE — any `context` member that is a `{run: [...]}` object,
|
|
55
|
+
* plus `context.run` itself. {@link SUB_STACK_KEYS} is exported as the set known
|
|
56
|
+
* today, and it fixes the ORDER discovery reports; a key outside it is still
|
|
57
|
+
* found, reported after the known ones, in `context` order.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The `context` keys that hold a nested stack today, in the order
|
|
62
|
+
* {@link subStacks} reports them. The order is the authoring order for every
|
|
63
|
+
* statement that nests: `if` before `elif` before `else` for a conditional,
|
|
64
|
+
* try before catch before finally for a try/catch, cases before default for a
|
|
65
|
+
* switch.
|
|
66
|
+
*
|
|
67
|
+
* This is a reference set, not a filter — see the module note.
|
|
68
|
+
*/
|
|
69
|
+
declare const SUB_STACK_KEYS: readonly string[];
|
|
70
|
+
/** One nested stack hanging off a statement's `context`. */
|
|
71
|
+
interface SubStack {
|
|
72
|
+
/** The `context` key the stack is stored under (`if`, `elif`, `else`, `then`, `run`). */
|
|
73
|
+
readonly key: string;
|
|
74
|
+
/**
|
|
75
|
+
* What the branch means at the authoring surface — `try`/`catch`/`finally` for
|
|
76
|
+
* a try/catch, `cases`/`default` for a switch, `body` for a loop. Falls back
|
|
77
|
+
* to the key for a statement with no recorded mapping.
|
|
78
|
+
*/
|
|
79
|
+
readonly label: string;
|
|
80
|
+
/** The nested statements, in run order. */
|
|
81
|
+
readonly run: readonly StackItemXdo[];
|
|
82
|
+
}
|
|
83
|
+
/** A statement reached by {@link walk}, with its address and nesting depth. */
|
|
84
|
+
interface WalkedStatement {
|
|
85
|
+
/** The statement envelope, by reference — not a copy. */
|
|
86
|
+
readonly raw: StackItemXdo;
|
|
87
|
+
/**
|
|
88
|
+
* The statement's address within the stack it was walked from — see
|
|
89
|
+
* {@link statementPath}. `"2"` is the third top-level statement; `"2.if.0"` is
|
|
90
|
+
* the first statement of its `if` branch.
|
|
91
|
+
*/
|
|
92
|
+
readonly path: string;
|
|
93
|
+
/** Nesting depth: `0` for a top-level statement, `1` inside one sub-stack, and so on. */
|
|
94
|
+
readonly depth: number;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Every nested stack a statement carries, in canonical order.
|
|
98
|
+
*
|
|
99
|
+
* Returns an empty array for a leaf statement. A sub-stack stored empty
|
|
100
|
+
* (`elif: {run: []}`, which the engine always persists on a conditional) is
|
|
101
|
+
* REPORTED with an empty `run` rather than skipped — the branch exists in the
|
|
102
|
+
* bytes, and a tool that renders branches wants to know the difference between
|
|
103
|
+
* "no elif" and "an elif that does nothing".
|
|
104
|
+
*/
|
|
105
|
+
declare function subStacks(raw: StackItemXdo): SubStack[];
|
|
106
|
+
/**
|
|
107
|
+
* Join path segments into a statement path.
|
|
108
|
+
*
|
|
109
|
+
* The format is dot-separated, alternating an index with the `context` key that
|
|
110
|
+
* contains the next level: `2` is the third top-level statement, `2.if.0` is the
|
|
111
|
+
* first statement of its `if` branch, `2.elif.0.if.1` is the second statement of
|
|
112
|
+
* its first elif branch. The KEY is used, not the label, so the path addresses
|
|
113
|
+
* the stored bytes and stays stable if an authoring name changes.
|
|
114
|
+
*
|
|
115
|
+
* One shared address is the point: a lint finding, a review comment and a
|
|
116
|
+
* runtime error written by three different tools all name the same node.
|
|
117
|
+
*/
|
|
118
|
+
declare function statementPath(segments: readonly (string | number)[]): string;
|
|
119
|
+
/**
|
|
120
|
+
* Walk a stack depth-first in pre-order — every statement, then its sub-stacks
|
|
121
|
+
* in {@link subStacks} order.
|
|
122
|
+
*
|
|
123
|
+
* A statement that is itself a branch carrier (`mvp:conditional_elif`,
|
|
124
|
+
* `mvp:switch_case`) is a stack item like any other, so it is VISITED and then
|
|
125
|
+
* descended into. A tool counting statements should filter those out; a tool
|
|
126
|
+
* addressing nodes wants them present.
|
|
127
|
+
*
|
|
128
|
+
* Iterative rather than recursive: a generated stack can nest deep enough to
|
|
129
|
+
* blow the call stack, and a bundle reader must not be the thing that crashes.
|
|
130
|
+
*/
|
|
131
|
+
declare function walk(run: readonly StackItemXdo[]): WalkedStatement[];
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A structural fingerprint for a compiled statement — the thing a diff, a cache
|
|
135
|
+
* key or a "did this change" check wants, and the thing a byte comparison is
|
|
136
|
+
* not.
|
|
137
|
+
*
|
|
138
|
+
* Two reductions run before the hash:
|
|
139
|
+
*
|
|
140
|
+
* 1. {@link normalize}, the same normalizer the SDK uses for fixture comparison
|
|
141
|
+
* and for the `xanots preflight` round-trip diff. It strips server-assigned
|
|
142
|
+
* identity (`_xsid`, `id`, timestamps, `market_item`) and canonicalizes the
|
|
143
|
+
* spellings the engine persists two ways.
|
|
144
|
+
* 2. Engine-filled `input[]` slots — the entries carrying `ignore: true`.
|
|
145
|
+
*
|
|
146
|
+
* The second one is the whole reason this is not just `sha1(normalize(x))`. A
|
|
147
|
+
* "full" statement (`db.add`, `db.edit`, `api.request`) persists one `input[]`
|
|
148
|
+
* entry per column of the table it writes, and the ones the author did not set
|
|
149
|
+
* carry `ignore: true`. Add a column to a table and EVERY statement that writes
|
|
150
|
+
* it gains an entry — so an unfiltered diff reports that every one of them
|
|
151
|
+
* changed, when what changed was the table. Filtered, the same diff reports the
|
|
152
|
+
* one object that actually changed.
|
|
153
|
+
*
|
|
154
|
+
* The normalizer deliberately KEEPS `ignore: true` (it is meaningful bytes on a
|
|
155
|
+
* system column, and the normalizer's job is byte fidelity — it must not drop
|
|
156
|
+
* what it cannot prove inert). That is not a contradiction: byte fidelity and
|
|
157
|
+
* structural identity are different questions, so they get different reductions.
|
|
158
|
+
* If you need the byte-level answer, hash `normalize()` yourself.
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* JSON with every object's keys sorted — so two statements that differ only in
|
|
163
|
+
* the order the engine happened to serialize their members hash the same.
|
|
164
|
+
*/
|
|
165
|
+
declare function canonicalJson(value: unknown): string;
|
|
166
|
+
/**
|
|
167
|
+
* A stable hex fingerprint of a statement AND everything nested under it.
|
|
168
|
+
*
|
|
169
|
+
* Equal hashes mean the two statements do the same thing; different hashes mean
|
|
170
|
+
* something an author wrote differs. The value is stable across SDK versions
|
|
171
|
+
* only as far as the normalizer is — treat it as a comparison key computed in
|
|
172
|
+
* one pass over both sides, not as a value to persist and compare next year.
|
|
173
|
+
*/
|
|
174
|
+
declare function structuralHash(raw: StackItemXdo): string;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Reading table relationships out of a stored column.
|
|
178
|
+
*
|
|
179
|
+
* Both are storage details a schema view needs and nothing else states, so they
|
|
180
|
+
* have been reverse-engineered once per tool up to now.
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The table a foreign-key column points at, as a guid — or `null` if the column
|
|
185
|
+
* is not a reference.
|
|
186
|
+
*
|
|
187
|
+
* A reference is an `int` or `uuid` column whose LAST method is `@` with a
|
|
188
|
+
* single `dbo=<guid>` argument. The position matters: `@` is an annotation the
|
|
189
|
+
* engine appends, and reading any `@` in the list would misread a column that
|
|
190
|
+
* carries one for another reason.
|
|
191
|
+
*
|
|
192
|
+
* A bare `dbo=` returns `null`. That is what the editor writes when a reference
|
|
193
|
+
* is CLEARED — an FK annotation pointing at nothing, which is not a reference.
|
|
194
|
+
*/
|
|
195
|
+
declare function tableRefOf(column: FieldXdo): string | null;
|
|
196
|
+
/**
|
|
197
|
+
* The table a db-link column expands, as a guid — or `null` if the column is not
|
|
198
|
+
* one.
|
|
199
|
+
*
|
|
200
|
+
* The other table relationship, and a different shape entirely: the column's
|
|
201
|
+
* TYPE is the table's identity with `_mvpschema` appended, and the engine
|
|
202
|
+
* expands the link into one input per column of the named table. A schema view
|
|
203
|
+
* that only reads {@link tableRefOf} misses these edges.
|
|
204
|
+
*/
|
|
205
|
+
declare function linkedTableOf(column: FieldXdo): string | null;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Structural deep-equal for comparing an engine-default subtree to a frozen
|
|
209
|
+
* default — and, exported, for comparing two normalized objects.
|
|
210
|
+
*
|
|
211
|
+
* Exported so a caller that has already normalized both sides does not carry its
|
|
212
|
+
* own copy of the same walk; a second implementation is a second set of rules
|
|
213
|
+
* about what "equal" means.
|
|
214
|
+
*/
|
|
215
|
+
declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
216
|
+
declare function normalize<T>(value: T): T;
|
|
217
|
+
|
|
218
|
+
export { FieldXdo, SUB_STACK_KEYS, StackItemXdo, type StatementCatalogEntry, type SubStack, type WalkedStatement, canonicalJson, deepEqual, linkedTableOf, normalize, statementCatalog, statementPath, structuralHash, subStacks, tableRefOf, walk };
|
package/dist/bundle.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
linkedTableOf,
|
|
3
|
+
tableRefOf
|
|
4
|
+
} from "./chunk-EHP3WPEG.js";
|
|
5
|
+
import {
|
|
6
|
+
deepEqual,
|
|
7
|
+
normalize
|
|
8
|
+
} from "./chunk-AE3PDSDS.js";
|
|
9
|
+
import {
|
|
10
|
+
STATEMENT_SURFACES,
|
|
11
|
+
sPathOf
|
|
12
|
+
} from "./chunk-DCMANKMX.js";
|
|
13
|
+
import {
|
|
14
|
+
sha1Bytes
|
|
15
|
+
} from "./chunk-OHX6MIUZ.js";
|
|
16
|
+
|
|
17
|
+
// src/bundle/catalog.ts
|
|
18
|
+
var cached;
|
|
19
|
+
function statementCatalog() {
|
|
20
|
+
if (cached) return cached;
|
|
21
|
+
const map = /* @__PURE__ */ new Map();
|
|
22
|
+
for (const [surface, storedName] of STATEMENT_SURFACES) {
|
|
23
|
+
const existing = map.get(storedName);
|
|
24
|
+
if (existing) {
|
|
25
|
+
map.set(storedName, { ...existing, surfaces: [...existing.surfaces, surface] });
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
map.set(storedName, {
|
|
29
|
+
storedName,
|
|
30
|
+
surface,
|
|
31
|
+
sPath: sPathOf(surface),
|
|
32
|
+
surfaces: [surface]
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
cached = map;
|
|
36
|
+
return map;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/bundle/walk.ts
|
|
40
|
+
var SUB_STACK_KEYS = ["if", "elif", "else", "then", "run"];
|
|
41
|
+
var SUB_STACK_LABELS = {
|
|
42
|
+
"mvp:conditional": { if: "then", elif: "elif", else: "else" },
|
|
43
|
+
"mvp:conditional_elif": { if: "then" },
|
|
44
|
+
"mvp:switch": { elif: "cases", else: "default" },
|
|
45
|
+
"mvp:switch_case": { if: "body" },
|
|
46
|
+
"mvp:try_catch": { if: "try", else: "catch", then: "finally" }
|
|
47
|
+
};
|
|
48
|
+
var isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
49
|
+
function runOf(value) {
|
|
50
|
+
if (!isRecord(value)) return null;
|
|
51
|
+
const run = value.run;
|
|
52
|
+
return Array.isArray(run) ? run : null;
|
|
53
|
+
}
|
|
54
|
+
function subStacks(raw) {
|
|
55
|
+
const context = raw?.context;
|
|
56
|
+
if (!isRecord(context)) return [];
|
|
57
|
+
const labels = SUB_STACK_LABELS[raw.name] ?? {};
|
|
58
|
+
const found = [];
|
|
59
|
+
const push = (key, value) => {
|
|
60
|
+
const run = key === "run" ? Array.isArray(value) ? value : null : runOf(value);
|
|
61
|
+
if (!run) return;
|
|
62
|
+
found.push({ key, label: labels[key] ?? (key === "run" ? "body" : key), run });
|
|
63
|
+
};
|
|
64
|
+
for (const key of SUB_STACK_KEYS) {
|
|
65
|
+
if (Object.hasOwn(context, key)) push(key, context[key]);
|
|
66
|
+
}
|
|
67
|
+
for (const key of Object.keys(context)) {
|
|
68
|
+
if (!SUB_STACK_KEYS.includes(key)) push(key, context[key]);
|
|
69
|
+
}
|
|
70
|
+
return found;
|
|
71
|
+
}
|
|
72
|
+
function statementPath(segments) {
|
|
73
|
+
return segments.join(".");
|
|
74
|
+
}
|
|
75
|
+
function walk(run) {
|
|
76
|
+
const out = [];
|
|
77
|
+
const pending = [];
|
|
78
|
+
for (let i = run.length - 1; i >= 0; i--) {
|
|
79
|
+
pending.push({ raw: run[i], path: statementPath([i]), depth: 0 });
|
|
80
|
+
}
|
|
81
|
+
while (pending.length > 0) {
|
|
82
|
+
const frame = pending.pop();
|
|
83
|
+
out.push(frame);
|
|
84
|
+
const children = [];
|
|
85
|
+
for (const sub of subStacks(frame.raw)) {
|
|
86
|
+
for (let i = 0; i < sub.run.length; i++) {
|
|
87
|
+
children.push({
|
|
88
|
+
raw: sub.run[i],
|
|
89
|
+
path: statementPath([frame.path, sub.key, i]),
|
|
90
|
+
depth: frame.depth + 1
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
for (let i = children.length - 1; i >= 0; i--) pending.push(children[i]);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/bundle/hash.ts
|
|
100
|
+
var isRecord2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
101
|
+
function withoutIgnoredInputs(value) {
|
|
102
|
+
if (Array.isArray(value)) return value.map(withoutIgnoredInputs);
|
|
103
|
+
if (!isRecord2(value)) return value;
|
|
104
|
+
const out = {};
|
|
105
|
+
for (const [key, member] of Object.entries(value)) {
|
|
106
|
+
if (key === "input" && Array.isArray(member)) {
|
|
107
|
+
out[key] = member.filter((entry) => !(isRecord2(entry) && entry.ignore === true)).map(withoutIgnoredInputs);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
out[key] = withoutIgnoredInputs(member);
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
function canonicalJson(value) {
|
|
115
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
116
|
+
if (isRecord2(value)) {
|
|
117
|
+
const parts = Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`);
|
|
118
|
+
return `{${parts.join(",")}}`;
|
|
119
|
+
}
|
|
120
|
+
return value === void 0 ? "null" : JSON.stringify(value);
|
|
121
|
+
}
|
|
122
|
+
var HEX = "0123456789abcdef";
|
|
123
|
+
function structuralHash(raw) {
|
|
124
|
+
const reduced = withoutIgnoredInputs(normalize(raw));
|
|
125
|
+
const bytes = sha1Bytes(canonicalJson(reduced));
|
|
126
|
+
let hex = "";
|
|
127
|
+
for (const byte of bytes) hex += HEX[byte >> 4] + HEX[byte & 15];
|
|
128
|
+
return hex;
|
|
129
|
+
}
|
|
130
|
+
export {
|
|
131
|
+
SUB_STACK_KEYS,
|
|
132
|
+
canonicalJson,
|
|
133
|
+
deepEqual,
|
|
134
|
+
linkedTableOf,
|
|
135
|
+
normalize,
|
|
136
|
+
statementCatalog,
|
|
137
|
+
statementPath,
|
|
138
|
+
structuralHash,
|
|
139
|
+
subStacks,
|
|
140
|
+
tableRefOf,
|
|
141
|
+
walk
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fixtureDirForKind
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AVGDL6RB.js";
|
|
4
4
|
|
|
5
5
|
// src/validate/capture.ts
|
|
6
6
|
import { mkdirSync, writeFileSync } from "fs";
|
|
@@ -29,4 +29,4 @@ function safeName(name) {
|
|
|
29
29
|
export {
|
|
30
30
|
captureFixtures
|
|
31
31
|
};
|
|
32
|
-
//# sourceMappingURL=capture-
|
|
32
|
+
//# sourceMappingURL=capture-YLUVAITI.js.map
|