mapples 0.2.0-beta.1 → 0.2.0-beta.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.
Files changed (171) hide show
  1. package/README.md +133 -22
  2. package/dist/adopt/scan.d.ts +8 -2
  3. package/dist/adopt/scan.js +31 -13
  4. package/dist/adopt/scan.js.map +1 -1
  5. package/dist/api/agent.d.ts +85 -0
  6. package/dist/api/agent.js +92 -0
  7. package/dist/api/agent.js.map +1 -0
  8. package/dist/api/client.d.ts +12 -1
  9. package/dist/api/client.js +23 -2
  10. package/dist/api/client.js.map +1 -1
  11. package/dist/api/commit.d.ts +9 -0
  12. package/dist/api/commit.js +51 -2
  13. package/dist/api/commit.js.map +1 -1
  14. package/dist/api/errors.d.ts +1 -1
  15. package/dist/api/errors.js +15 -2
  16. package/dist/api/errors.js.map +1 -1
  17. package/dist/api/objects.d.ts +39 -6
  18. package/dist/api/objects.js +204 -11
  19. package/dist/api/objects.js.map +1 -1
  20. package/dist/api/poll.d.ts +5 -3
  21. package/dist/api/poll.js +17 -6
  22. package/dist/api/poll.js.map +1 -1
  23. package/dist/api/txPlan.d.ts +15 -0
  24. package/dist/api/txPlan.js +196 -0
  25. package/dist/api/txPlan.js.map +1 -0
  26. package/dist/assets/assets.d.ts +21 -0
  27. package/dist/assets/assets.js +62 -4
  28. package/dist/assets/assets.js.map +1 -1
  29. package/dist/codegen/emit.d.ts +4 -7
  30. package/dist/codegen/emit.js +10 -29
  31. package/dist/codegen/emit.js.map +1 -1
  32. package/dist/codegen/imports.d.ts +8 -15
  33. package/dist/codegen/imports.js +27 -72
  34. package/dist/codegen/imports.js.map +1 -1
  35. package/dist/codegen/instances.d.ts +5 -0
  36. package/dist/codegen/instances.js +30 -0
  37. package/dist/codegen/instances.js.map +1 -0
  38. package/dist/codegen/styles.d.ts +1 -0
  39. package/dist/codegen/styles.js +3 -0
  40. package/dist/codegen/styles.js.map +1 -0
  41. package/dist/commands/agent.d.ts +2 -0
  42. package/dist/commands/agent.js +87 -0
  43. package/dist/commands/agent.js.map +1 -0
  44. package/dist/commands/create.js +1 -0
  45. package/dist/commands/create.js.map +1 -1
  46. package/dist/commands/impl/adoptImpl.js +3 -0
  47. package/dist/commands/impl/adoptImpl.js.map +1 -1
  48. package/dist/commands/impl/agentImpl.d.ts +23 -0
  49. package/dist/commands/impl/agentImpl.js +426 -0
  50. package/dist/commands/impl/agentImpl.js.map +1 -0
  51. package/dist/commands/impl/createImpl.js +31 -4
  52. package/dist/commands/impl/createImpl.js.map +1 -1
  53. package/dist/commands/impl/initImpl.js +35 -5
  54. package/dist/commands/impl/initImpl.js.map +1 -1
  55. package/dist/commands/impl/syncImpl.js +30 -5
  56. package/dist/commands/impl/syncImpl.js.map +1 -1
  57. package/dist/commands/init.js +1 -0
  58. package/dist/commands/init.js.map +1 -1
  59. package/dist/index.js +12 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/merge/applyOps.d.ts +5 -2
  62. package/dist/merge/applyOps.js +75 -32
  63. package/dist/merge/applyOps.js.map +1 -1
  64. package/dist/merge/childrenOrder.d.ts +13 -0
  65. package/dist/merge/childrenOrder.js +51 -0
  66. package/dist/merge/childrenOrder.js.map +1 -0
  67. package/dist/merge/diff.d.ts +20 -1
  68. package/dist/merge/diff.js +77 -17
  69. package/dist/merge/diff.js.map +1 -1
  70. package/dist/merge/threeWay.d.ts +2 -2
  71. package/dist/merge/threeWay.js +74 -10
  72. package/dist/merge/threeWay.js.map +1 -1
  73. package/dist/merge/toEdits.d.ts +1 -3
  74. package/dist/merge/toEdits.js +3 -91
  75. package/dist/merge/toEdits.js.map +1 -1
  76. package/dist/nav/navigatorTree.d.ts +78 -0
  77. package/dist/nav/navigatorTree.js +419 -0
  78. package/dist/nav/navigatorTree.js.map +1 -0
  79. package/dist/nav/placement.d.ts +53 -0
  80. package/dist/nav/placement.js +260 -0
  81. package/dist/nav/placement.js.map +1 -0
  82. package/dist/nav/routeTree.d.ts +8 -2
  83. package/dist/nav/routeTree.js +85 -152
  84. package/dist/nav/routeTree.js.map +1 -1
  85. package/dist/nav/screenOptions.d.ts +15 -0
  86. package/dist/nav/screenOptions.js +213 -0
  87. package/dist/nav/screenOptions.js.map +1 -0
  88. package/dist/project/agentState.d.ts +30 -0
  89. package/dist/project/agentState.js +42 -0
  90. package/dist/project/agentState.js.map +1 -0
  91. package/dist/project/baseStore.d.ts +19 -1
  92. package/dist/project/baseStore.js +28 -0
  93. package/dist/project/baseStore.js.map +1 -1
  94. package/dist/project/componentsMap.d.ts +7 -0
  95. package/dist/project/componentsMap.js +21 -0
  96. package/dist/project/componentsMap.js.map +1 -0
  97. package/dist/project/config.d.ts +12 -3
  98. package/dist/project/config.js +11 -2
  99. package/dist/project/config.js.map +1 -1
  100. package/dist/project/env.d.ts +10 -3
  101. package/dist/project/env.js +23 -5
  102. package/dist/project/env.js.map +1 -1
  103. package/dist/project/pagesMap.d.ts +2 -0
  104. package/dist/project/pagesMap.js.map +1 -1
  105. package/dist/project/secret.d.ts +6 -2
  106. package/dist/project/secret.js +11 -5
  107. package/dist/project/secret.js.map +1 -1
  108. package/dist/services/adoptService.d.ts +3 -0
  109. package/dist/services/adoptService.js +357 -38
  110. package/dist/services/adoptService.js.map +1 -1
  111. package/dist/services/agentInstall.d.ts +80 -0
  112. package/dist/services/agentInstall.js +309 -0
  113. package/dist/services/agentInstall.js.map +1 -0
  114. package/dist/services/agentLease.d.ts +2 -0
  115. package/dist/services/agentLease.js +32 -0
  116. package/dist/services/agentLease.js.map +1 -0
  117. package/dist/services/clientFactory.d.ts +2 -0
  118. package/dist/services/clientFactory.js +20 -3
  119. package/dist/services/clientFactory.js.map +1 -1
  120. package/dist/services/doctorService.js +77 -66
  121. package/dist/services/doctorService.js.map +1 -1
  122. package/dist/services/scaffold.d.ts +3 -0
  123. package/dist/services/scaffold.js +16 -0
  124. package/dist/services/scaffold.js.map +1 -1
  125. package/dist/services/syncEngine.d.ts +7 -0
  126. package/dist/services/syncEngine.js +766 -306
  127. package/dist/services/syncEngine.js.map +1 -1
  128. package/dist/style/theme.js +17 -1
  129. package/dist/style/theme.js.map +1 -1
  130. package/dist/types.d.ts +55 -2
  131. package/dist/types.js +25 -0
  132. package/dist/types.js.map +1 -1
  133. package/dist/ui/report.d.ts +15 -0
  134. package/dist/ui/report.js +30 -0
  135. package/dist/ui/report.js.map +1 -1
  136. package/package.json +4 -2
  137. package/templates/agent/agents-md/AGENTS.md +8 -0
  138. package/templates/agent/claude/CLAUDE.md +7 -0
  139. package/templates/agent/claude/mcp.json +11 -0
  140. package/templates/agent/claude/settings.json +26 -0
  141. package/templates/agent/codex/config.toml +6 -0
  142. package/templates/agent/codex/hooks.json +26 -0
  143. package/templates/agent/cursor/hooks.json +9 -0
  144. package/templates/agent/cursor/mcp.json +10 -0
  145. package/templates/agent/mapples.md +124 -0
  146. package/templates/agent/skills/mapples-conventions/SKILL.md +137 -0
  147. package/templates/agent/skills/mapples-design/SKILL.md +235 -0
  148. package/templates/agent/skills/mapples-design/reference/component-library.md +128 -0
  149. package/templates/agent/skills/mapples-design/reference/design-tokens.md +132 -0
  150. package/templates/agent/skills/mapples-design/reference/layout-contract.md +227 -0
  151. package/templates/agent/skills/mapples-design/reference/lint-checklist.md +51 -0
  152. package/templates/agent/skills/mapples-design/reference/plan.md +95 -0
  153. package/templates/agent/skills/mapples-design/reference/playbooks/empty-states.md +14 -0
  154. package/templates/agent/skills/mapples-design/reference/playbooks/forms-and-auth.md +22 -0
  155. package/templates/agent/skills/mapples-design/reference/playbooks/home-dashboard.md +14 -0
  156. package/templates/agent/skills/mapples-design/reference/playbooks/list-and-detail.md +18 -0
  157. package/templates/agent/skills/mapples-design/reference/playbooks/microcopy.md +20 -0
  158. package/templates/agent/skills/mapples-design/reference/playbooks/navigation-chrome.md +21 -0
  159. package/templates/agent/skills/mapples-design/reference/playbooks/onboarding-flow.md +15 -0
  160. package/templates/agent/skills/mapples-design/reference/playbooks/screen-flow-wiring.md +37 -0
  161. package/templates/agent/skills/mapples-design/reference/playbooks/settings-profile.md +16 -0
  162. package/templates/agent/skills/mapples-design/reference/playbooks/stats-and-progress.md +17 -0
  163. package/templates/agent/skills/mapples-design/reference/playbooks/visual-hierarchy.md +18 -0
  164. package/templates/agent/skills/mapples-design/reference/style-guides.md +92 -0
  165. package/templates/agent/skills/mapples-sync/SKILL.md +93 -0
  166. package/templates/app/_layout.tsx +9 -1
  167. package/templates/app.json +0 -1
  168. package/templates/gitignore +2 -0
  169. package/templates/mapples/sid.d.ts +6 -0
  170. package/templates/metro.config.js +11 -0
  171. package/templates/package.json +13 -10
@@ -1,3 +1,4 @@
1
+ import { mapAddedLines } from '@mapples/textpatch';
1
2
  import { ulid } from 'ulid';
2
3
  import { isNetworkError } from './client.js';
3
4
  import { JpatchError } from './errors.js';
@@ -7,6 +8,50 @@ export function mintTxId() {
7
8
  export function mintCid() {
8
9
  return `c_${ulid()}`;
9
10
  }
11
+ /**
12
+ * Rewrite every cid that an earlier transaction already resolved (its `idMap`)
13
+ * to the server id, wherever it appears in `ops` — `id`, `data.parent`,
14
+ * children refs, props that point at sibling nodes. cids are transaction-scoped
15
+ * (RFC-0001 §5.2, invariant 5): once the create that minted one has committed,
16
+ * a later transaction must reference the DB id or the server answers
17
+ * CID_UNRESOLVED. Returns new objects; `ops` is left untouched.
18
+ */
19
+ export function resolveCids(ops, idMap) {
20
+ if (!Object.keys(idMap).some((k) => k.startsWith('c_')))
21
+ return ops;
22
+ const walk = (value) => {
23
+ if (typeof value === 'string') {
24
+ return value.startsWith('c_') && idMap[value] !== undefined ? idMap[value] : value;
25
+ }
26
+ if (Array.isArray(value))
27
+ return value.map(walk);
28
+ if (value !== null && typeof value === 'object') {
29
+ const out = {};
30
+ for (const [k, v] of Object.entries(value))
31
+ out[k] = walk(v);
32
+ return out;
33
+ }
34
+ return value;
35
+ };
36
+ // Source text carries cid tokens inside a longer string (`$sid="c_…"`):
37
+ // whole-string matching never reaches them. Same boundary rule as the
38
+ // server (A12); a directive's added lines are the only place hunks hold one (A13).
39
+ const rewriteTokens = (text) => text.replace(CID_TOKEN_RE, (match, boundary, cid) => idMap[cid] === undefined ? match : boundary + idMap[cid]);
40
+ return ops.map((op) => {
41
+ const next = walk(op);
42
+ if (next.entity !== 'Source')
43
+ return next;
44
+ if (next.data && typeof next.data.text === 'string') {
45
+ next.data = { ...next.data, text: rewriteTokens(next.data.text) };
46
+ }
47
+ if (next.text) {
48
+ next.text = { ...next.text, hunks: mapAddedLines(next.text.hunks, rewriteTokens) };
49
+ }
50
+ return next;
51
+ });
52
+ }
53
+ /** A cid token inside Source text, bounded by non-identifier characters (server's `_CID_TOKEN_RE`). */
54
+ const CID_TOKEN_RE = /(^|[^0-9A-Za-z_])(c_[0-9A-HJKMNP-TV-Z]{26})(?![0-9A-Za-z_])/g;
10
55
  export function buildEnvelope(client, params) {
11
56
  const envelope = {
12
57
  protocol: 'jpatch/1',
@@ -17,6 +62,7 @@ export function buildEnvelope(client, params) {
17
62
  meta: {
18
63
  ...(client.actor ? { actor: client.actor } : {}),
19
64
  ...(client.origin ? { origin: client.origin } : {}),
65
+ ...(client.summary ? { summary: client.summary } : {}),
20
66
  ts: new Date().toISOString(),
21
67
  },
22
68
  };
@@ -38,8 +84,11 @@ export async function commitWithTransportRetry(client, envelope, maxAttempts = 5
38
84
  }
39
85
  catch (err) {
40
86
  if (err instanceof JpatchError && err.code === 'FORBIDDEN') {
41
- // RFC-0003: read-scoped keys can pull but not push.
42
- throw new Error('push rejected: this API key is read-scoped — generate a read & write key in Creator (Project → Settings) and re-run `mapples init --secret <key>`');
87
+ // RFC-0003: read-scoped keys can pull but not push. Prefer the
88
+ // server's own guidance when it sends one.
89
+ const detail = err.message.replace(/^FORBIDDEN:\s*/, '');
90
+ throw new Error(`push rejected: ${detail ||
91
+ 'this API key is read-scoped — generate a read & write key in Creator (Project → Settings)'} (then re-run \`mapples init --secret <key>\`)`);
43
92
  }
44
93
  if (!isNetworkError(err))
45
94
  throw err;
@@ -1 +1 @@
1
- {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/api/commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,UAAU,QAAQ;IACtB,OAAO,MAAM,IAAI,EAAE,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,KAAK,IAAI,EAAE,EAAE,CAAC;AACvB,CAAC;AASD,MAAM,UAAU,aAAa,CAAC,MAAoB,EAAE,MAAoB;IACtE,MAAM,QAAQ,GAAa;QACzB,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,QAAQ,EAAE;QAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,IAAI,EAAE;YACJ,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAC7B;KACF,CAAC;IACF,IAAI,MAAM,CAAC,QAAQ,KAAK,SAAS;QAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACvE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAoB,EACpB,QAAkB,EAClB,WAAW,GAAG,CAAC;IAEf,IAAI,OAAgB,CAAC;IACrB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,WAAW,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAC3D,oDAAoD;gBACpD,MAAM,IAAI,KAAK,CACb,mJAAmJ,CACpJ,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YACpC,OAAO,GAAG,GAAG,CAAC;YACd,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,MAAM,OAAO,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"commit.js","sourceRoot":"","sources":["../../src/api/commit.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { Delta, JpatchOp } from '../types.js';
2
- export type JpatchErrorCode = 'HEAD_MISMATCH' | 'HASH_MISMATCH' | 'CID_UNRESOLVED' | 'UNKNOWN_ENTITY' | 'PATCH_INVALID' | 'CHILDREN_PRESENT' | 'OBJECT_MISSING' | 'TX_TOO_LARGE' | 'PROJECT_LOCKED' | 'FORBIDDEN' | 'SNAPSHOT_REQUIRED';
2
+ export type JpatchErrorCode = 'HEAD_MISMATCH' | 'HASH_MISMATCH' | 'CID_UNRESOLVED' | 'UNKNOWN_ENTITY' | 'PATCH_INVALID' | 'SOURCE_INVALID' | 'SOURCE_BASE_MISMATCH' | 'SOURCE_PATCH_INVALID' | 'CHILDREN_PRESENT' | 'OBJECT_MISSING' | 'TX_TOO_LARGE' | 'PROJECT_LOCKED' | 'FORBIDDEN' | 'SNAPSHOT_REQUIRED';
3
3
  export declare class JpatchError extends Error {
4
4
  readonly code: JpatchErrorCode;
5
5
  readonly http: number;
@@ -6,6 +6,9 @@ const HTTP_BY_CODE = {
6
6
  CID_UNRESOLVED: 422,
7
7
  UNKNOWN_ENTITY: 422,
8
8
  PATCH_INVALID: 422,
9
+ SOURCE_INVALID: 422,
10
+ SOURCE_BASE_MISMATCH: 409,
11
+ SOURCE_PATCH_INVALID: 422,
9
12
  CHILDREN_PRESENT: 409,
10
13
  OBJECT_MISSING: 424,
11
14
  TX_TOO_LARGE: 413,
@@ -60,14 +63,24 @@ export class UnexpectedResponseError extends Error {
60
63
  }
61
64
  }
62
65
  export function errorFromBody(status, body) {
66
+ // The real backend's auth denials carry {detail} without a code field.
67
+ if (status === 403 &&
68
+ typeof body === 'object' &&
69
+ body !== null &&
70
+ !('code' in body) &&
71
+ typeof body.detail === 'string') {
72
+ return new JpatchError('FORBIDDEN', body.detail);
73
+ }
63
74
  if (isJpatchErrorBody(body)) {
64
- const { code, message, ...rest } = body;
75
+ // The real server words its errors as `detail`; the mock as `message`.
76
+ const { code, message, detail, ...rest } = body;
65
77
  if (code === 'HEAD_MISMATCH') {
66
78
  const head = rest.head;
67
79
  const delta = rest.delta;
68
80
  return new HeadMismatchError(head, delta);
69
81
  }
70
- return new JpatchError(code, typeof message === 'string' ? message : '', rest);
82
+ const text = typeof message === 'string' ? message : typeof detail === 'string' ? detail : '';
83
+ return new JpatchError(code, text, rest);
71
84
  }
72
85
  return new UnexpectedResponseError(status, body);
73
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/api/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/api/errors.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,39 @@
1
- import type { Bootstrap, RenderDomNode } from '../types.js';
1
+ import { type Bootstrap, type RenderDomNode, type SourceEntity } from '../types.js';
2
2
  import type { JpatchClient } from './client.js';
3
+ /**
4
+ * A container's render states by key — what a node's `style::<key>` variant
5
+ * renders under (RFC-0001 §4.1 `state`). The file owns the states its prop
6
+ * tests declare (`props.*` conditions); the Creator owns the rest.
7
+ */
8
+ export type EntityStates = Record<string, {
9
+ name: string;
10
+ condition: string;
11
+ id?: string;
12
+ }>;
3
13
  export interface PageEntity {
4
14
  id: string;
5
15
  name: string;
6
16
  route: string;
7
17
  root: RenderDomNode;
18
+ /** Creator page uuid — navigator route targets reference pages by this. */
19
+ uuid?: string;
20
+ state?: EntityStates;
8
21
  }
9
22
  export interface ComponentEntity {
10
23
  id: string;
11
24
  name: string;
12
25
  root: RenderDomNode;
26
+ /** Creator component uuid — a page's `ComponentInstance` nodes link to it. */
27
+ uuid?: string;
28
+ state?: EntityStates;
13
29
  }
14
30
  export interface NavigationDocument {
15
- routes: NavigationRoute[];
16
- layouts: Record<string, unknown>;
31
+ /** Legacy/CLI route list. The real backend serves a navigator document
32
+ * (`data.navigators`) without this field — then route-tree codegen is
33
+ * skipped with a visible note; the raw doc is preserved in base. */
34
+ routes?: NavigationRoute[];
35
+ layouts?: Record<string, unknown>;
36
+ [k: string]: unknown;
17
37
  }
18
38
  export interface NavigationRoute {
19
39
  id: string;
@@ -28,11 +48,18 @@ export interface StyleConfig {
28
48
  sizing: Record<string, unknown>;
29
49
  }
30
50
  export type AssetIndex = Record<string, {
31
- sha256: string;
32
- mime: string;
51
+ sha256?: string;
52
+ mime?: string;
33
53
  w?: number;
34
54
  h?: number;
35
55
  name?: string;
56
+ /** Real backend fields (dev): server-relative body URL + file metadata. */
57
+ link?: string;
58
+ file_name?: string;
59
+ extension?: string;
60
+ type?: string;
61
+ uuid?: string;
62
+ [k: string]: unknown;
36
63
  }>;
37
64
  export interface ProjectState {
38
65
  head: string;
@@ -42,9 +69,15 @@ export interface ProjectState {
42
69
  navigation: NavigationDocument;
43
70
  style: StyleConfig;
44
71
  assets: AssetIndex;
72
+ /** Stored source text per page/component id — only containers that have one. */
73
+ sources: Map<string, SourceEntity>;
45
74
  }
75
+ /** Pages on the real backend carry no route; derive a stable one from the name. */
76
+ export declare function deriveRoute(name: string): string;
46
77
  /** Cold bootstrap: walk the manifest and fetch every blob (RFC-0001 §6). */
47
- export declare function fetchProjectState(client: JpatchClient, boot: Bootstrap): Promise<ProjectState>;
78
+ export declare function fetchProjectState(client: JpatchClient, boot: Bootstrap,
79
+ /** Source texts already held (the base): a blob whose hash they reproduce is not fetched again. */
80
+ knownSources?: Map<string, SourceEntity>): Promise<ProjectState>;
48
81
  /**
49
82
  * Upload binary asset bodies: `objects/have` filters to genuinely missing
50
83
  * hashes, then PUT bytes to each signed URL (RFC-0001 §6, binary assets).
@@ -1,24 +1,217 @@
1
1
  import axios from 'axios';
2
+ import { sidecarOf, } from '../types.js';
3
+ import { contentHash } from './canonical.js';
4
+ // ---- Hash-linked blob resolution (RFC-0001 §4.1) ----
5
+ // The real backend embeds children as hash STRINGS, never inlined: a page blob
6
+ // is {id, name, root: "b3:…"} and a node blob is {id, key?, type, props,
7
+ // children: ["b3:…"], _canvasProps?}. The mock server may still serve
8
+ // materialized trees; both shapes resolve through the same walker.
9
+ const isHashRef = (v) => typeof v === 'string' && v.startsWith('b3:');
10
+ /** Editor-internal node fields that never enter the CLI's RenderDom model. */
11
+ const NODE_META_FIELDS = new Set([
12
+ 'id',
13
+ 'sid',
14
+ 'key',
15
+ 'type',
16
+ 'props',
17
+ 'children',
18
+ 'refProps',
19
+ 'dataProps',
20
+ 'actionProps',
21
+ '_canvasProps',
22
+ 'uuid',
23
+ ]);
24
+ async function fetchObjects(client, hashes) {
25
+ const out = new Map();
26
+ for (let i = 0; i < hashes.length; i += 100) {
27
+ const chunk = hashes.slice(i, i + 100);
28
+ const objects = await client.objectsGet(chunk);
29
+ for (const h of chunk) {
30
+ if (!(h in objects))
31
+ throw new Error(`objects/get did not return blob ${h}`);
32
+ out.set(h, objects[h]);
33
+ }
34
+ }
35
+ return out;
36
+ }
37
+ /** Resolve a root ref (hash or inline tree) into a materialized RenderDomNode. */
38
+ async function materializeTree(client, rootRef) {
39
+ // Breadth-first: collect unresolved hashes level by level, batch-fetch them.
40
+ const blobCache = new Map();
41
+ const collectHashes = (ref, acc) => {
42
+ if (isHashRef(ref)) {
43
+ if (!blobCache.has(ref))
44
+ acc.add(ref);
45
+ return;
46
+ }
47
+ const node = ref;
48
+ for (const child of node.children ?? [])
49
+ collectHashes(child, acc);
50
+ };
51
+ let frontier = [rootRef];
52
+ for (let depth = 0; depth < 100 && frontier.length > 0; depth++) {
53
+ const wanted = new Set();
54
+ for (const ref of frontier)
55
+ collectHashes(ref, wanted);
56
+ if (wanted.size === 0)
57
+ break;
58
+ const fetched = await fetchObjects(client, [...wanted]);
59
+ for (const [h, blob] of fetched)
60
+ blobCache.set(h, blob);
61
+ frontier = [...fetched.values()];
62
+ }
63
+ const build = (ref, trail) => {
64
+ let blob = ref;
65
+ if (isHashRef(ref)) {
66
+ if (trail.has(ref))
67
+ throw new Error(`cycle in canvas blobs at ${ref}`);
68
+ trail = new Set(trail).add(ref);
69
+ blob = blobCache.get(ref);
70
+ if (blob === undefined)
71
+ throw new Error(`unresolved canvas blob ${ref}`);
72
+ }
73
+ const node = blob;
74
+ const sid = (node.id ?? node.sid);
75
+ if (typeof sid !== 'string' || typeof node.type !== 'string') {
76
+ throw new Error(`canvas node blob is missing id/type: ${JSON.stringify(node).slice(0, 120)}`);
77
+ }
78
+ // Anything beyond the known meta fields is unexpected — keep it visible.
79
+ for (const k of Object.keys(node)) {
80
+ if (!NODE_META_FIELDS.has(k)) {
81
+ throw new Error(`canvas node ${sid} has unknown field \`${k}\` — schema drift, update the CLI`);
82
+ }
83
+ }
84
+ return {
85
+ sid,
86
+ type: node.type,
87
+ props: node.props ?? {},
88
+ children: (node.children ?? []).map((c) => build(c, trail)),
89
+ ...sidecarOf(node),
90
+ };
91
+ };
92
+ return build(rootRef, new Set());
93
+ }
94
+ /** Pages on the real backend carry no route; derive a stable one from the name. */
95
+ export function deriveRoute(name) {
96
+ const slug = name
97
+ .trim()
98
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
99
+ .replace(/[^A-Za-z0-9]+/g, '-')
100
+ .replace(/^-+|-+$/g, '')
101
+ .toLowerCase();
102
+ return slug === '' || slug === 'home' || slug === 'index' ? '/' : `/${slug}`;
103
+ }
104
+ /** A style-blob section may be inline, hash-linked, or a {id, data} document. */
105
+ async function resolveStyleSection(client, value) {
106
+ let section = value;
107
+ if (isHashRef(section)) {
108
+ const fetched = await fetchObjects(client, [section]);
109
+ section = fetched.get(section);
110
+ }
111
+ if (typeof section !== 'object' || section === null)
112
+ return {};
113
+ const doc = section;
114
+ if (typeof doc.data === 'object' && doc.data !== null)
115
+ return doc.data;
116
+ return doc;
117
+ }
2
118
  /** Cold bootstrap: walk the manifest and fetch every blob (RFC-0001 §6). */
3
- export async function fetchProjectState(client, boot) {
4
- const [pagesIndex, componentsIndex, navigation, style, assets] = await Promise.all([
119
+ export async function fetchProjectState(client, boot,
120
+ /** Source texts already held (the base): a blob whose hash they reproduce is not fetched again. */
121
+ knownSources = new Map()) {
122
+ const [pagesIndex, componentsIndex, navigationBlob, styleBlob, assets] = await Promise.all([
5
123
  client.getObject(boot.manifest.pages),
6
124
  client.getObject(boot.manifest.components),
7
125
  client.getObject(boot.manifest.navigation),
8
126
  client.getObject(boot.manifest.style),
9
127
  client.getObject(boot.manifest.assets),
10
128
  ]);
129
+ const pageBlobs = await fetchObjects(client, Object.values(pagesIndex));
11
130
  const pages = new Map();
12
- await Promise.all(Object.entries(pagesIndex).map(async ([id, hash]) => {
13
- const blob = (await client.getObject(hash));
14
- pages.set(id, { id, ...blob });
15
- }));
131
+ for (const [indexId, hash] of Object.entries(pagesIndex)) {
132
+ const blob = pageBlobs.get(hash);
133
+ pages.set(indexId, {
134
+ id: blob.id ?? indexId,
135
+ name: blob.name,
136
+ route: blob.route ?? deriveRoute(blob.name),
137
+ root: await materializeTree(client, blob.root),
138
+ ...(blob.uuid ? { uuid: blob.uuid } : {}),
139
+ ...(blob.state ? { state: blob.state } : {}),
140
+ });
141
+ }
142
+ const componentBlobs = await fetchObjects(client, Object.values(componentsIndex));
16
143
  const components = new Map();
17
- await Promise.all(Object.entries(componentsIndex).map(async ([id, hash]) => {
18
- const blob = (await client.getObject(hash));
19
- components.set(id, { id, ...blob });
20
- }));
21
- return { head: boot.head, seq: boot.seq, pages, components, navigation, style, assets };
144
+ for (const [indexId, hash] of Object.entries(componentsIndex)) {
145
+ const blob = componentBlobs.get(hash);
146
+ components.set(indexId, {
147
+ id: blob.id ?? indexId,
148
+ name: blob.name,
149
+ root: await materializeTree(client, blob.root),
150
+ ...(blob.uuid ? { uuid: blob.uuid } : {}),
151
+ ...(blob.state ? { state: blob.state } : {}),
152
+ });
153
+ }
154
+ const style = {
155
+ theme: await resolveStyleSection(client, styleBlob.theme),
156
+ typography: await resolveStyleSection(client, styleBlob.typography),
157
+ sizing: await resolveStyleSection(client, styleBlob.sizing),
158
+ };
159
+ return {
160
+ head: boot.head,
161
+ seq: boot.seq,
162
+ pages,
163
+ components,
164
+ navigation: navigationBlob,
165
+ style,
166
+ assets,
167
+ sources: await fetchSources(client, boot, knownSources),
168
+ };
169
+ }
170
+ /** The Source blob exactly as the server stores it, so its hash can be recomputed. */
171
+ function sourceBlobOf(source) {
172
+ return {
173
+ id: source.id,
174
+ of: source.of,
175
+ lang: source.lang,
176
+ text: source.text,
177
+ ...(source.docHash !== undefined ? { docHash: source.docHash } : {}),
178
+ };
179
+ }
180
+ /** The `sources` index (RFC-0001 A12), keyed by container id; empty when the manifest has none. */
181
+ async function fetchSources(client, boot, known) {
182
+ const sources = new Map();
183
+ if (boot.manifest.sources === undefined)
184
+ return sources;
185
+ const index = (await client.getObject(boot.manifest.sources));
186
+ // Blobs are content-addressed: a known text that hashes to the index entry
187
+ // IS the server's blob, so only changed Sources travel (A13).
188
+ const missing = [];
189
+ for (const [indexId, hash] of Object.entries(index)) {
190
+ const held = known.get(indexId.replace(/^src_/, ''));
191
+ if (held !== undefined && contentHash(sourceBlobOf(held)) === hash) {
192
+ sources.set(held.of, { ...held, id: held.id || indexId });
193
+ }
194
+ else {
195
+ missing.push(hash);
196
+ }
197
+ }
198
+ const blobs = await fetchObjects(client, missing);
199
+ for (const [indexId, hash] of Object.entries(index)) {
200
+ if (!blobs.has(hash))
201
+ continue;
202
+ const blob = blobs.get(hash);
203
+ if (typeof blob.of !== 'string' || typeof blob.text !== 'string') {
204
+ throw new Error(`source blob ${indexId} is missing of/text — schema drift, update the CLI`);
205
+ }
206
+ sources.set(blob.of, {
207
+ id: blob.id ?? indexId,
208
+ of: blob.of,
209
+ lang: typeof blob.lang === 'string' ? blob.lang : 'tsx',
210
+ text: blob.text,
211
+ ...(typeof blob.docHash === 'string' ? { docHash: blob.docHash } : {}),
212
+ });
213
+ }
214
+ return sources;
22
215
  }
23
216
  /**
24
217
  * Upload binary asset bodies: `objects/have` filters to genuinely missing
@@ -1 +1 @@
1
- {"version":3,"file":"objects.js","sourceRoot":"","sources":["../../src/api/objects.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"objects.js","sourceRoot":"","sources":["../../src/api/objects.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,9 @@ export declare class SnapshotRequired extends Error {
4
4
  constructor();
5
5
  }
6
6
  /**
7
- * Pull the full delta since `head`, following `truncated: true` pages until
8
- * exhausted (RFC-0001 §6). Throws SnapshotRequired when the server signals it.
7
+ * Pull the full delta since `sinceSeq`, following `truncated: true` pages via
8
+ * `lastSeq` until exhausted. The real backend signals "cold-bootstrap instead"
9
+ * with a 200 `snapshotRequired: true` body; older servers/mocks may use a
10
+ * SNAPSHOT_REQUIRED error — both raise SnapshotRequired.
9
11
  */
10
- export declare function pullDelta(client: JpatchClient, since: string): Promise<Delta>;
12
+ export declare function pullDelta(client: JpatchClient, sinceSeq: number): Promise<Delta>;
package/dist/api/poll.js CHANGED
@@ -6,13 +6,15 @@ export class SnapshotRequired extends Error {
6
6
  }
7
7
  }
8
8
  /**
9
- * Pull the full delta since `head`, following `truncated: true` pages until
10
- * exhausted (RFC-0001 §6). Throws SnapshotRequired when the server signals it.
9
+ * Pull the full delta since `sinceSeq`, following `truncated: true` pages via
10
+ * `lastSeq` until exhausted. The real backend signals "cold-bootstrap instead"
11
+ * with a 200 `snapshotRequired: true` body; older servers/mocks may use a
12
+ * SNAPSHOT_REQUIRED error — both raise SnapshotRequired.
11
13
  */
12
- export async function pullDelta(client, since) {
14
+ export async function pullDelta(client, sinceSeq) {
13
15
  const ops = [];
14
- let cursor = since;
15
- for (;;) {
16
+ let cursor = sinceSeq;
17
+ for (let page_n = 0; page_n < 1000; page_n++) {
16
18
  let page;
17
19
  try {
18
20
  page = await client.pullOnce(cursor);
@@ -23,11 +25,20 @@ export async function pullDelta(client, since) {
23
25
  }
24
26
  throw err;
25
27
  }
28
+ if (page.snapshotRequired)
29
+ throw new SnapshotRequired();
30
+ if (!Array.isArray(page.ops)) {
31
+ throw new Error(`delta response has no ops array (head ${page.head}) — server/CLI contract drift`);
32
+ }
26
33
  ops.push(...page.ops);
27
34
  if (!page.truncated) {
28
35
  return { ops, head: page.head, seq: page.seq, truncated: false };
29
36
  }
30
- cursor = page.head;
37
+ if (typeof page.lastSeq !== 'number' || page.lastSeq <= cursor) {
38
+ throw new Error('truncated delta without an advancing lastSeq cursor');
39
+ }
40
+ cursor = page.lastSeq;
31
41
  }
42
+ throw new Error('delta paging did not converge after 1000 pages');
32
43
  }
33
44
  //# sourceMappingURL=poll.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/api/poll.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC;QACE,KAAK,CAAC,qEAAqE,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAoB,EAAE,KAAa;IACjE,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,SAAS,CAAC;QACR,IAAI,IAAW,CAAC;QAChB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,WAAW,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACnE,MAAM,IAAI,gBAAgB,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACnE,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/api/poll.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC;QACE,KAAK,CAAC,qEAAqE,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAoB,EAAE,QAAgB;IACpE,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,IAAI,MAAM,GAAG,QAAQ,CAAC;IACtB,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;QAC7C,IAAI,IAAW,CAAC;QAChB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,WAAW,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACnE,MAAM,IAAI,gBAAgB,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB;YAAE,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,yCAAyC,IAAI,CAAC,IAAI,+BAA+B,CAClF,CAAC;QACJ,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACnE,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,OAAO,IAAI,MAAM,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;IACxB,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { JpatchOp } from '../types.js';
2
+ export declare const MAX_OPS_PER_TX = 200;
3
+ /** A placement group larger than one transaction: the push stops, nothing is sent. */
4
+ export declare class PushGroupTooLargeError extends Error {
5
+ readonly size: number;
6
+ readonly limit: number;
7
+ readonly sample: JpatchOp[];
8
+ constructor(size: number, limit: number, sample: JpatchOp[]);
9
+ }
10
+ /**
11
+ * Plan `ops` as sequential transactions, each at most `limit` ops. Flattening
12
+ * the result gives the order the ops are sent in; a caller that tracks how
13
+ * many ops committed must count against that flattened order.
14
+ */
15
+ export declare function planTransactions(ops: JpatchOp[], limit?: number): JpatchOp[][];