@ontrails/core 1.0.0-beta.14 → 1.0.0-beta.16

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 (314) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +73 -24
  3. package/package.json +11 -4
  4. package/src/activation-provenance.ts +111 -0
  5. package/src/activation-source-compatibility.ts +430 -0
  6. package/src/activation-source-projection.ts +221 -0
  7. package/src/activation-source.ts +91 -0
  8. package/src/blob-ref.ts +51 -0
  9. package/src/branded.ts +1 -1
  10. package/src/context.ts +28 -4
  11. package/src/contour.ts +344 -0
  12. package/src/cross-batch.ts +69 -0
  13. package/src/cross-schema.ts +36 -0
  14. package/src/detours.ts +8 -0
  15. package/src/draft.ts +60 -52
  16. package/src/error-projection.ts +51 -0
  17. package/src/errors.ts +245 -48
  18. package/src/execute.ts +1250 -40
  19. package/src/fire.ts +1169 -0
  20. package/src/index.ts +383 -49
  21. package/src/internal/fork-ctx.ts +69 -0
  22. package/src/layer-projection.ts +192 -0
  23. package/src/layer.ts +81 -0
  24. package/src/observe.ts +361 -0
  25. package/src/path-security.ts +1 -1
  26. package/src/permits.ts +12 -0
  27. package/src/redaction/patterns.ts +6 -3
  28. package/src/resilience.ts +11 -11
  29. package/src/resource-config.ts +792 -0
  30. package/src/resource.ts +175 -0
  31. package/src/result.ts +18 -0
  32. package/src/run.ts +7 -6
  33. package/src/schedule-runtime.ts +689 -0
  34. package/src/schedule.ts +324 -0
  35. package/src/serialization.ts +90 -55
  36. package/src/signal-diagnostics.ts +633 -0
  37. package/src/signal-ref.ts +87 -0
  38. package/src/signal.ts +37 -0
  39. package/src/store/accessor-protocol.ts +56 -0
  40. package/src/store/index.ts +4 -0
  41. package/src/structured-examples.ts +245 -0
  42. package/src/surface-derivation.ts +91 -0
  43. package/src/surface-filter.ts +176 -0
  44. package/src/topo.ts +710 -59
  45. package/src/tracing.ts +345 -0
  46. package/src/trail.ts +347 -33
  47. package/src/trails/derive-trail.ts +842 -0
  48. package/src/trails/index.ts +9 -0
  49. package/src/trails/ingest.ts +138 -0
  50. package/src/{internal/trails-db.ts → trails-db.ts} +50 -31
  51. package/src/transport-error-map.ts +174 -0
  52. package/src/type-utils.ts +17 -2
  53. package/src/types.ts +208 -17
  54. package/src/validate-established-topo.ts +8 -2
  55. package/src/validate-topo.ts +244 -13
  56. package/src/validation.ts +58 -1
  57. package/src/webhook.ts +276 -0
  58. package/src/workspace.ts +1 -1
  59. package/src/zod-wrappers.ts +72 -0
  60. package/.turbo/turbo-build.log +0 -1
  61. package/.turbo/turbo-lint.log +0 -3
  62. package/.turbo/turbo-typecheck.log +0 -1
  63. package/dist/adapters.d.ts +0 -39
  64. package/dist/adapters.d.ts.map +0 -1
  65. package/dist/adapters.js +0 -2
  66. package/dist/adapters.js.map +0 -1
  67. package/dist/blob-ref.d.ts +0 -20
  68. package/dist/blob-ref.d.ts.map +0 -1
  69. package/dist/blob-ref.js +0 -22
  70. package/dist/blob-ref.js.map +0 -1
  71. package/dist/branded.d.ts +0 -36
  72. package/dist/branded.d.ts.map +0 -1
  73. package/dist/branded.js +0 -89
  74. package/dist/branded.js.map +0 -1
  75. package/dist/collections.d.ts +0 -31
  76. package/dist/collections.d.ts.map +0 -1
  77. package/dist/collections.js +0 -60
  78. package/dist/collections.js.map +0 -1
  79. package/dist/context.d.ts +0 -10
  80. package/dist/context.d.ts.map +0 -1
  81. package/dist/context.js +0 -21
  82. package/dist/context.js.map +0 -1
  83. package/dist/derive.d.ts +0 -44
  84. package/dist/derive.d.ts.map +0 -1
  85. package/dist/derive.js +0 -149
  86. package/dist/derive.js.map +0 -1
  87. package/dist/dispatch.d.ts +0 -27
  88. package/dist/dispatch.d.ts.map +0 -1
  89. package/dist/dispatch.js +0 -34
  90. package/dist/dispatch.js.map +0 -1
  91. package/dist/draft.d.ts +0 -28
  92. package/dist/draft.d.ts.map +0 -1
  93. package/dist/draft.js +0 -156
  94. package/dist/draft.js.map +0 -1
  95. package/dist/errors.d.ts +0 -83
  96. package/dist/errors.d.ts.map +0 -1
  97. package/dist/errors.js +0 -142
  98. package/dist/errors.js.map +0 -1
  99. package/dist/event.d.ts +0 -8
  100. package/dist/event.d.ts.map +0 -1
  101. package/dist/event.js +0 -7
  102. package/dist/event.js.map +0 -1
  103. package/dist/execute.d.ts +0 -35
  104. package/dist/execute.d.ts.map +0 -1
  105. package/dist/execute.js +0 -90
  106. package/dist/execute.js.map +0 -1
  107. package/dist/fetch.d.ts +0 -15
  108. package/dist/fetch.d.ts.map +0 -1
  109. package/dist/fetch.js +0 -102
  110. package/dist/fetch.js.map +0 -1
  111. package/dist/gate.d.ts +0 -17
  112. package/dist/gate.d.ts.map +0 -1
  113. package/dist/gate.js +0 -21
  114. package/dist/gate.js.map +0 -1
  115. package/dist/guards.d.ts +0 -17
  116. package/dist/guards.d.ts.map +0 -1
  117. package/dist/guards.js +0 -25
  118. package/dist/guards.js.map +0 -1
  119. package/dist/health.d.ts +0 -18
  120. package/dist/health.d.ts.map +0 -1
  121. package/dist/health.js +0 -5
  122. package/dist/health.js.map +0 -1
  123. package/dist/index.d.ts +0 -48
  124. package/dist/index.d.ts.map +0 -1
  125. package/dist/index.js +0 -51
  126. package/dist/index.js.map +0 -1
  127. package/dist/internal/topo-saves.d.ts +0 -47
  128. package/dist/internal/topo-saves.d.ts.map +0 -1
  129. package/dist/internal/topo-saves.js +0 -310
  130. package/dist/internal/topo-saves.js.map +0 -1
  131. package/dist/internal/topo-store-read.d.ts +0 -67
  132. package/dist/internal/topo-store-read.d.ts.map +0 -1
  133. package/dist/internal/topo-store-read.js +0 -222
  134. package/dist/internal/topo-store-read.js.map +0 -1
  135. package/dist/internal/topo-store.d.ts +0 -12
  136. package/dist/internal/topo-store.d.ts.map +0 -1
  137. package/dist/internal/topo-store.js +0 -571
  138. package/dist/internal/topo-store.js.map +0 -1
  139. package/dist/internal/trails-db.d.ts +0 -16
  140. package/dist/internal/trails-db.d.ts.map +0 -1
  141. package/dist/internal/trails-db.js +0 -118
  142. package/dist/internal/trails-db.js.map +0 -1
  143. package/dist/job.d.ts +0 -24
  144. package/dist/job.d.ts.map +0 -1
  145. package/dist/job.js +0 -17
  146. package/dist/job.js.map +0 -1
  147. package/dist/layer.d.ts +0 -6
  148. package/dist/layer.d.ts.map +0 -1
  149. package/dist/layer.js +0 -4
  150. package/dist/layer.js.map +0 -1
  151. package/dist/path-security.d.ts +0 -28
  152. package/dist/path-security.d.ts.map +0 -1
  153. package/dist/path-security.js +0 -63
  154. package/dist/path-security.js.map +0 -1
  155. package/dist/patterns/bulk.d.ts +0 -15
  156. package/dist/patterns/bulk.d.ts.map +0 -1
  157. package/dist/patterns/bulk.js +0 -14
  158. package/dist/patterns/bulk.js.map +0 -1
  159. package/dist/patterns/change.d.ts +0 -10
  160. package/dist/patterns/change.d.ts.map +0 -1
  161. package/dist/patterns/change.js +0 -10
  162. package/dist/patterns/change.js.map +0 -1
  163. package/dist/patterns/date-range.d.ts +0 -10
  164. package/dist/patterns/date-range.d.ts.map +0 -1
  165. package/dist/patterns/date-range.js +0 -10
  166. package/dist/patterns/date-range.js.map +0 -1
  167. package/dist/patterns/index.d.ts +0 -9
  168. package/dist/patterns/index.d.ts.map +0 -1
  169. package/dist/patterns/index.js +0 -9
  170. package/dist/patterns/index.js.map +0 -1
  171. package/dist/patterns/pagination.d.ts +0 -18
  172. package/dist/patterns/pagination.d.ts.map +0 -1
  173. package/dist/patterns/pagination.js +0 -18
  174. package/dist/patterns/pagination.js.map +0 -1
  175. package/dist/patterns/progress.d.ts +0 -11
  176. package/dist/patterns/progress.d.ts.map +0 -1
  177. package/dist/patterns/progress.js +0 -11
  178. package/dist/patterns/progress.js.map +0 -1
  179. package/dist/patterns/sorting.d.ts +0 -13
  180. package/dist/patterns/sorting.d.ts.map +0 -1
  181. package/dist/patterns/sorting.js +0 -10
  182. package/dist/patterns/sorting.js.map +0 -1
  183. package/dist/patterns/status.d.ts +0 -15
  184. package/dist/patterns/status.d.ts.map +0 -1
  185. package/dist/patterns/status.js +0 -9
  186. package/dist/patterns/status.js.map +0 -1
  187. package/dist/patterns/timestamps.d.ts +0 -10
  188. package/dist/patterns/timestamps.d.ts.map +0 -1
  189. package/dist/patterns/timestamps.js +0 -10
  190. package/dist/patterns/timestamps.js.map +0 -1
  191. package/dist/provision-config.d.ts +0 -22
  192. package/dist/provision-config.d.ts.map +0 -1
  193. package/dist/provision-config.js +0 -210
  194. package/dist/provision-config.js.map +0 -1
  195. package/dist/provision.d.ts +0 -71
  196. package/dist/provision.d.ts.map +0 -1
  197. package/dist/provision.js +0 -56
  198. package/dist/provision.js.map +0 -1
  199. package/dist/redaction/index.d.ts +0 -4
  200. package/dist/redaction/index.d.ts.map +0 -1
  201. package/dist/redaction/index.js +0 -3
  202. package/dist/redaction/index.js.map +0 -1
  203. package/dist/redaction/patterns.d.ts +0 -9
  204. package/dist/redaction/patterns.d.ts.map +0 -1
  205. package/dist/redaction/patterns.js +0 -39
  206. package/dist/redaction/patterns.js.map +0 -1
  207. package/dist/redaction/redactor.d.ts +0 -27
  208. package/dist/redaction/redactor.d.ts.map +0 -1
  209. package/dist/redaction/redactor.js +0 -89
  210. package/dist/redaction/redactor.js.map +0 -1
  211. package/dist/resilience.d.ts +0 -34
  212. package/dist/resilience.d.ts.map +0 -1
  213. package/dist/resilience.js +0 -164
  214. package/dist/resilience.js.map +0 -1
  215. package/dist/result.d.ts +0 -57
  216. package/dist/result.d.ts.map +0 -1
  217. package/dist/result.js +0 -156
  218. package/dist/result.js.map +0 -1
  219. package/dist/run.d.ts +0 -27
  220. package/dist/run.d.ts.map +0 -1
  221. package/dist/run.js +0 -34
  222. package/dist/run.js.map +0 -1
  223. package/dist/serialization.d.ts +0 -27
  224. package/dist/serialization.d.ts.map +0 -1
  225. package/dist/serialization.js +0 -153
  226. package/dist/serialization.js.map +0 -1
  227. package/dist/service-config.d.ts +0 -22
  228. package/dist/service-config.d.ts.map +0 -1
  229. package/dist/service-config.js +0 -210
  230. package/dist/service-config.js.map +0 -1
  231. package/dist/service.d.ts +0 -71
  232. package/dist/service.d.ts.map +0 -1
  233. package/dist/service.js +0 -56
  234. package/dist/service.js.map +0 -1
  235. package/dist/signal.d.ts +0 -33
  236. package/dist/signal.d.ts.map +0 -1
  237. package/dist/signal.js +0 -17
  238. package/dist/signal.js.map +0 -1
  239. package/dist/topo-store.d.ts +0 -48
  240. package/dist/topo-store.d.ts.map +0 -1
  241. package/dist/topo-store.js +0 -175
  242. package/dist/topo-store.js.map +0 -1
  243. package/dist/topo.d.ts +0 -25
  244. package/dist/topo.d.ts.map +0 -1
  245. package/dist/topo.js +0 -112
  246. package/dist/topo.js.map +0 -1
  247. package/dist/trail.d.ts +0 -96
  248. package/dist/trail.d.ts.map +0 -1
  249. package/dist/trail.js +0 -20
  250. package/dist/trail.js.map +0 -1
  251. package/dist/type-utils.d.ts +0 -24
  252. package/dist/type-utils.d.ts.map +0 -1
  253. package/dist/type-utils.js +0 -12
  254. package/dist/type-utils.js.map +0 -1
  255. package/dist/types.d.ts +0 -71
  256. package/dist/types.d.ts.map +0 -1
  257. package/dist/types.js +0 -3
  258. package/dist/types.js.map +0 -1
  259. package/dist/validate-established-topo.d.ts +0 -76
  260. package/dist/validate-established-topo.d.ts.map +0 -1
  261. package/dist/validate-established-topo.js +0 -43
  262. package/dist/validate-established-topo.js.map +0 -1
  263. package/dist/validate-topo.d.ts +0 -24
  264. package/dist/validate-topo.d.ts.map +0 -1
  265. package/dist/validate-topo.js +0 -176
  266. package/dist/validate-topo.js.map +0 -1
  267. package/dist/validation.d.ts +0 -27
  268. package/dist/validation.d.ts.map +0 -1
  269. package/dist/validation.js +0 -165
  270. package/dist/validation.js.map +0 -1
  271. package/dist/workspace.d.ts +0 -25
  272. package/dist/workspace.d.ts.map +0 -1
  273. package/dist/workspace.js +0 -57
  274. package/dist/workspace.js.map +0 -1
  275. package/src/__tests__/blob-ref.test.ts +0 -103
  276. package/src/__tests__/branded.test.ts +0 -148
  277. package/src/__tests__/collections.test.ts +0 -126
  278. package/src/__tests__/context.test.ts +0 -77
  279. package/src/__tests__/derive.test.ts +0 -260
  280. package/src/__tests__/errors.test.ts +0 -309
  281. package/src/__tests__/execute.test.ts +0 -525
  282. package/src/__tests__/fetch.test.ts +0 -217
  283. package/src/__tests__/gate.test.ts +0 -125
  284. package/src/__tests__/guards.test.ts +0 -102
  285. package/src/__tests__/path-security.test.ts +0 -114
  286. package/src/__tests__/patterns.test.ts +0 -273
  287. package/src/__tests__/redaction.test.ts +0 -244
  288. package/src/__tests__/resilience.test.ts +0 -246
  289. package/src/__tests__/result.test.ts +0 -155
  290. package/src/__tests__/run.test.ts +0 -181
  291. package/src/__tests__/serialization.test.ts +0 -401
  292. package/src/__tests__/service-config.test.ts +0 -228
  293. package/src/__tests__/service.test.ts +0 -197
  294. package/src/__tests__/signal.test.ts +0 -82
  295. package/src/__tests__/topo-store-read.test.ts +0 -251
  296. package/src/__tests__/topo-store.test.ts +0 -469
  297. package/src/__tests__/topo.test.ts +0 -277
  298. package/src/__tests__/trail-permit.test.ts +0 -60
  299. package/src/__tests__/trail.test.ts +0 -261
  300. package/src/__tests__/trails-db.test.ts +0 -191
  301. package/src/__tests__/type-utils.test.ts +0 -90
  302. package/src/__tests__/validate-topo.test.ts +0 -489
  303. package/src/__tests__/validation.test.ts +0 -336
  304. package/src/__tests__/workspace.test.ts +0 -183
  305. package/src/event.ts +0 -15
  306. package/src/gate.ts +0 -44
  307. package/src/internal/topo-saves.ts +0 -429
  308. package/src/internal/topo-store-read.ts +0 -473
  309. package/src/internal/topo-store.ts +0 -1087
  310. package/src/provision-config.ts +0 -373
  311. package/src/provision.ts +0 -148
  312. package/src/topo-store.ts +0 -301
  313. package/tsconfig.json +0 -9
  314. package/tsconfig.tsbuildinfo +0 -1
@@ -1,191 +0,0 @@
1
- import { afterEach, describe, expect, test } from 'bun:test';
2
- import { existsSync, mkdtempSync, rmSync } from 'node:fs';
3
- import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
5
-
6
- import {
7
- ensureSubsystemSchema,
8
- openReadTrailsDb,
9
- openWriteTrailsDb,
10
- resolveTrailsDbPath,
11
- } from '../internal/trails-db.js';
12
- import {
13
- createTopoSave,
14
- ensureTopoHistorySchema,
15
- listTopoPins,
16
- listTopoSaves,
17
- pinTopoSave,
18
- pruneUnpinnedTopoSaves,
19
- } from '../internal/topo-saves.js';
20
-
21
- describe('trails db foundation', () => {
22
- let tmpRoot: string | undefined;
23
-
24
- afterEach(() => {
25
- if (tmpRoot) {
26
- rmSync(tmpRoot, { force: true, recursive: true });
27
- tmpRoot = undefined;
28
- }
29
- });
30
-
31
- const makeRoot = (): string => {
32
- tmpRoot = mkdtempSync(join(tmpdir(), 'trails-db-'));
33
- return tmpRoot;
34
- };
35
-
36
- const expectWorkspaceLayout = (rootDir: string): void => {
37
- expect(existsSync(join(rootDir, '.trails', '.gitignore'))).toBe(true);
38
- expect(existsSync(join(rootDir, '.trails', 'config'))).toBe(true);
39
- expect(existsSync(join(rootDir, '.trails', 'dev'))).toBe(true);
40
- expect(existsSync(join(rootDir, '.trails', 'generated'))).toBe(true);
41
- };
42
-
43
- test('resolveTrailsDbPath places the database in .trails/trails.db', () => {
44
- const rootDir = '/tmp/example-app';
45
- expect(resolveTrailsDbPath({ rootDir })).toBe(
46
- '/tmp/example-app/.trails/trails.db'
47
- );
48
- });
49
-
50
- test('openWriteTrailsDb creates the database with WAL and NORMAL defaults', () => {
51
- const rootDir = makeRoot();
52
- const db = openWriteTrailsDb({ rootDir });
53
-
54
- try {
55
- expect(existsSync(resolveTrailsDbPath({ rootDir }))).toBe(true);
56
- expectWorkspaceLayout(rootDir);
57
-
58
- const journal = db
59
- .query<{ journal_mode: string }, []>('PRAGMA journal_mode')
60
- .get();
61
- const synchronous = db
62
- .query<{ synchronous: number }, []>('PRAGMA synchronous')
63
- .get();
64
-
65
- expect(journal?.journal_mode.toLowerCase()).toBe('wal');
66
- expect(synchronous?.synchronous).toBe(1);
67
- } finally {
68
- db.close();
69
- }
70
- });
71
-
72
- test('openReadTrailsDb blocks writes at the SQLite connection level', () => {
73
- const rootDir = makeRoot();
74
- const writer = openWriteTrailsDb({ rootDir });
75
- writer.close();
76
-
77
- const reader = openReadTrailsDb({ rootDir });
78
-
79
- try {
80
- expect(() => reader.run('CREATE TABLE readonly_probe (id TEXT)')).toThrow(
81
- /readonly|read-only/i
82
- );
83
- } finally {
84
- reader.close();
85
- }
86
- });
87
-
88
- test('ensureSubsystemSchema only migrates when the subsystem version changes', () => {
89
- const rootDir = makeRoot();
90
- const db = openWriteTrailsDb({ rootDir });
91
- let calls = 0;
92
-
93
- try {
94
- ensureSubsystemSchema(db, {
95
- migrate: () => {
96
- calls += 1;
97
- db.run(
98
- 'CREATE TABLE IF NOT EXISTS track_records (id TEXT PRIMARY KEY)'
99
- );
100
- },
101
- subsystem: 'track',
102
- version: 1,
103
- });
104
-
105
- ensureSubsystemSchema(db, {
106
- migrate: () => {
107
- calls += 1;
108
- },
109
- subsystem: 'track',
110
- version: 1,
111
- });
112
-
113
- ensureSubsystemSchema(db, {
114
- migrate: (currentVersion) => {
115
- calls += 1;
116
- expect(currentVersion).toBe(1);
117
- db.run('ALTER TABLE track_records ADD COLUMN status TEXT');
118
- },
119
- subsystem: 'track',
120
- version: 2,
121
- });
122
-
123
- expect(calls).toBe(2);
124
- } finally {
125
- db.close();
126
- }
127
- });
128
- });
129
-
130
- describe('topo save primitives', () => {
131
- let tmpRoot: string | undefined;
132
-
133
- afterEach(() => {
134
- if (tmpRoot) {
135
- rmSync(tmpRoot, { force: true, recursive: true });
136
- tmpRoot = undefined;
137
- }
138
- });
139
-
140
- const makeRoot = (): string => {
141
- tmpRoot = mkdtempSync(join(tmpdir(), 'topo-saves-'));
142
- return tmpRoot;
143
- };
144
-
145
- const seedHistory = (db: ReturnType<typeof openWriteTrailsDb>) => {
146
- ensureTopoHistorySchema(db);
147
-
148
- const pinned = createTopoSave(db, {
149
- createdAt: '2026-04-01T00:00:00.000Z',
150
- gitDirty: false,
151
- gitSha: 'abc123',
152
- provisionCount: 2,
153
- signalCount: 1,
154
- trailCount: 3,
155
- });
156
- const disposable = createTopoSave(db, {
157
- createdAt: '2026-04-02T00:00:00.000Z',
158
- gitDirty: true,
159
- gitSha: 'def456',
160
- provisionCount: 3,
161
- signalCount: 2,
162
- trailCount: 4,
163
- });
164
-
165
- return {
166
- disposable,
167
- pin: pinTopoSave(db, { name: 'before-auth', saveId: pinned.id }),
168
- pinned,
169
- };
170
- };
171
-
172
- test('creates saves, pins them, and prunes only unpinned history', () => {
173
- const rootDir = makeRoot();
174
- const db = openWriteTrailsDb({ rootDir });
175
-
176
- try {
177
- const { disposable, pin, pinned } = seedHistory(db);
178
-
179
- expect(listTopoPins(db)).toEqual([pin]);
180
- expect(listTopoSaves(db).map((save) => save.id)).toEqual([
181
- disposable.id,
182
- pinned.id,
183
- ]);
184
-
185
- expect(pruneUnpinnedTopoSaves(db, { keep: 0 })).toBe(1);
186
- expect(listTopoSaves(db).map((save) => save.id)).toEqual([pinned.id]);
187
- } finally {
188
- db.close();
189
- }
190
- });
191
- });
@@ -1,90 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import { z } from 'zod';
4
-
5
- import { Result } from '../result';
6
- import { trail } from '../trail';
7
- import type { TrailInput, TrailOutput, TrailResult } from '../type-utils';
8
- import { inputOf, outputOf } from '../type-utils';
9
-
10
- const greetTrail = trail('greet', {
11
- blaze: (input) => Result.ok({ message: `Hello, ${input.name}!` }),
12
- input: z.object({ name: z.string() }),
13
- output: z.object({ message: z.string() }),
14
- });
15
-
16
- const noOutputTrail = trail('ping', {
17
- blaze: () => Result.ok(),
18
- input: z.object({}),
19
- });
20
-
21
- describe('type-utils', () => {
22
- describe('inputOf', () => {
23
- test('returns the Zod input schema and can parse valid input', () => {
24
- const schema = inputOf(greetTrail);
25
- const result = schema.safeParse({ name: 'Alice' });
26
- expect(result.success).toBe(true);
27
- expect(
28
- (result as { success: true; data: { name: string } }).data
29
- ).toEqual({
30
- name: 'Alice',
31
- });
32
- });
33
-
34
- test('preserves specific schema type so .shape is accessible', () => {
35
- const schema = inputOf(greetTrail);
36
- // .shape is only available on z.ZodObject, not the broader z.ZodType
37
- expect(schema.shape).toBeDefined();
38
- expect(schema.shape.name).toBeDefined();
39
- });
40
- });
41
-
42
- describe('outputOf', () => {
43
- test('returns the Zod output schema when defined', () => {
44
- const schema = outputOf(greetTrail);
45
- expect(schema).toBeDefined();
46
- // oxlint-disable-next-line no-non-null-assertion -- guarded by toBeDefined() above
47
- const result = schema!.safeParse({ message: 'hello' });
48
- expect(result.success).toBe(true);
49
- });
50
-
51
- test('returns undefined when no output schema', () => {
52
- const schema = outputOf(noOutputTrail);
53
- expect(schema).toBeUndefined();
54
- });
55
- });
56
-
57
- describe('type-level checks', () => {
58
- test('TrailInput matches expected shape', () => {
59
- // If this compiles, the type is correct
60
- const _input: TrailInput<typeof greetTrail> = { name: 'test' };
61
- expect(_input.name).toBe('test');
62
- });
63
-
64
- test('TrailOutput matches expected shape', () => {
65
- // If this compiles, the type is correct
66
- const _output: TrailOutput<typeof greetTrail> = { message: 'hello' };
67
- expect(_output.message).toBe('hello');
68
- });
69
- });
70
-
71
- describe('TrailResult', () => {
72
- test('extracts Result<Output, Error> from a trail', () => {
73
- const t = trail('test.result', {
74
- blaze: (input) => Result.ok({ answer: input.q }),
75
- input: z.object({ q: z.string() }),
76
- output: z.object({ answer: z.string() }),
77
- });
78
-
79
- type Expected = Result<{ answer: string }, Error>;
80
- type Actual = TrailResult<typeof t>;
81
-
82
- // Compile-time check: assignment works in both directions
83
- const _check1: Expected = {} as Actual;
84
- const _check2: Actual = {} as Expected;
85
-
86
- // Runtime: type exists and is usable
87
- expect(true).toBe(true);
88
- });
89
- });
90
- });