@ontrails/core 1.0.0-beta.2 → 1.0.0-beta.21

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 (245) hide show
  1. package/CHANGELOG.md +283 -5
  2. package/README.md +113 -33
  3. package/package.json +11 -1
  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/compose-batch.ts +69 -0
  11. package/src/compose-schema.ts +36 -0
  12. package/src/context.ts +44 -10
  13. package/src/contour.ts +346 -0
  14. package/src/derive.ts +59 -18
  15. package/src/detours.ts +8 -0
  16. package/src/draft.ts +342 -0
  17. package/src/error-projection.ts +51 -0
  18. package/src/errors.ts +309 -48
  19. package/src/execute.ts +1577 -0
  20. package/src/fire.ts +1169 -0
  21. package/src/index.ts +477 -32
  22. package/src/internal/fork-ctx.ts +69 -0
  23. package/src/layer-projection.ts +193 -0
  24. package/src/layer.ts +43 -6
  25. package/src/observe.ts +361 -0
  26. package/src/path-security.ts +1 -1
  27. package/src/permits.ts +12 -0
  28. package/src/redaction/patterns.ts +6 -3
  29. package/src/resilience.ts +11 -11
  30. package/src/resource-config.ts +792 -0
  31. package/src/resource.ts +194 -0
  32. package/src/result.ts +36 -4
  33. package/src/run.ts +76 -0
  34. package/src/schedule-runtime.ts +689 -0
  35. package/src/schedule.ts +326 -0
  36. package/src/serialization.ts +119 -39
  37. package/src/signal-diagnostics.ts +633 -0
  38. package/src/signal-ref.ts +87 -0
  39. package/src/signal.ts +104 -0
  40. package/src/store/accessor-protocol.ts +56 -0
  41. package/src/store/index.ts +4 -0
  42. package/src/structured-examples.ts +248 -0
  43. package/src/surface-derivation.ts +91 -0
  44. package/src/surface-filter.ts +176 -0
  45. package/src/surface-versioning.ts +42 -0
  46. package/src/topo.ts +769 -57
  47. package/src/tracing.ts +345 -0
  48. package/src/trail.ts +1161 -29
  49. package/src/trails/derive-trail.ts +842 -0
  50. package/src/trails/index.ts +9 -0
  51. package/src/trails/ingest.ts +139 -0
  52. package/src/trails-db.ts +208 -0
  53. package/src/transport-error-map.ts +174 -0
  54. package/src/type-utils.ts +87 -0
  55. package/src/types.ts +254 -12
  56. package/src/validate-established-topo.ts +69 -0
  57. package/src/validate-topo.ts +442 -35
  58. package/src/validation.ts +152 -4
  59. package/src/version-marker.ts +716 -0
  60. package/src/version-resolution.ts +308 -0
  61. package/src/version-runtime.ts +120 -0
  62. package/src/webhook.ts +278 -0
  63. package/src/workspace.ts +1 -1
  64. package/src/zod-wrappers.ts +72 -0
  65. package/.turbo/turbo-build.log +0 -1
  66. package/.turbo/turbo-lint.log +0 -3
  67. package/.turbo/turbo-typecheck.log +0 -1
  68. package/dist/adapters.d.ts +0 -39
  69. package/dist/adapters.d.ts.map +0 -1
  70. package/dist/adapters.js +0 -2
  71. package/dist/adapters.js.map +0 -1
  72. package/dist/blob-ref.d.ts +0 -20
  73. package/dist/blob-ref.d.ts.map +0 -1
  74. package/dist/blob-ref.js +0 -22
  75. package/dist/blob-ref.js.map +0 -1
  76. package/dist/branded.d.ts +0 -36
  77. package/dist/branded.d.ts.map +0 -1
  78. package/dist/branded.js +0 -89
  79. package/dist/branded.js.map +0 -1
  80. package/dist/collections.d.ts +0 -31
  81. package/dist/collections.d.ts.map +0 -1
  82. package/dist/collections.js +0 -60
  83. package/dist/collections.js.map +0 -1
  84. package/dist/context.d.ts +0 -10
  85. package/dist/context.d.ts.map +0 -1
  86. package/dist/context.js +0 -15
  87. package/dist/context.js.map +0 -1
  88. package/dist/derive.d.ts +0 -33
  89. package/dist/derive.d.ts.map +0 -1
  90. package/dist/derive.js +0 -122
  91. package/dist/derive.js.map +0 -1
  92. package/dist/errors.d.ts +0 -83
  93. package/dist/errors.d.ts.map +0 -1
  94. package/dist/errors.js +0 -142
  95. package/dist/errors.js.map +0 -1
  96. package/dist/event.d.ts +0 -45
  97. package/dist/event.d.ts.map +0 -1
  98. package/dist/event.js +0 -17
  99. package/dist/event.js.map +0 -1
  100. package/dist/fetch.d.ts +0 -15
  101. package/dist/fetch.d.ts.map +0 -1
  102. package/dist/fetch.js +0 -102
  103. package/dist/fetch.js.map +0 -1
  104. package/dist/guards.d.ts +0 -17
  105. package/dist/guards.d.ts.map +0 -1
  106. package/dist/guards.js +0 -25
  107. package/dist/guards.js.map +0 -1
  108. package/dist/health.d.ts +0 -18
  109. package/dist/health.d.ts.map +0 -1
  110. package/dist/health.js +0 -5
  111. package/dist/health.js.map +0 -1
  112. package/dist/hike.d.ts +0 -36
  113. package/dist/hike.d.ts.map +0 -1
  114. package/dist/hike.js +0 -20
  115. package/dist/hike.js.map +0 -1
  116. package/dist/index.d.ts +0 -34
  117. package/dist/index.d.ts.map +0 -1
  118. package/dist/index.js +0 -38
  119. package/dist/index.js.map +0 -1
  120. package/dist/job.d.ts +0 -24
  121. package/dist/job.d.ts.map +0 -1
  122. package/dist/job.js +0 -17
  123. package/dist/job.js.map +0 -1
  124. package/dist/layer.d.ts +0 -17
  125. package/dist/layer.d.ts.map +0 -1
  126. package/dist/layer.js +0 -21
  127. package/dist/layer.js.map +0 -1
  128. package/dist/path-security.d.ts +0 -28
  129. package/dist/path-security.d.ts.map +0 -1
  130. package/dist/path-security.js +0 -63
  131. package/dist/path-security.js.map +0 -1
  132. package/dist/patterns/bulk.d.ts +0 -15
  133. package/dist/patterns/bulk.d.ts.map +0 -1
  134. package/dist/patterns/bulk.js +0 -14
  135. package/dist/patterns/bulk.js.map +0 -1
  136. package/dist/patterns/change.d.ts +0 -10
  137. package/dist/patterns/change.d.ts.map +0 -1
  138. package/dist/patterns/change.js +0 -10
  139. package/dist/patterns/change.js.map +0 -1
  140. package/dist/patterns/date-range.d.ts +0 -10
  141. package/dist/patterns/date-range.d.ts.map +0 -1
  142. package/dist/patterns/date-range.js +0 -10
  143. package/dist/patterns/date-range.js.map +0 -1
  144. package/dist/patterns/index.d.ts +0 -9
  145. package/dist/patterns/index.d.ts.map +0 -1
  146. package/dist/patterns/index.js +0 -9
  147. package/dist/patterns/index.js.map +0 -1
  148. package/dist/patterns/pagination.d.ts +0 -18
  149. package/dist/patterns/pagination.d.ts.map +0 -1
  150. package/dist/patterns/pagination.js +0 -18
  151. package/dist/patterns/pagination.js.map +0 -1
  152. package/dist/patterns/progress.d.ts +0 -11
  153. package/dist/patterns/progress.d.ts.map +0 -1
  154. package/dist/patterns/progress.js +0 -11
  155. package/dist/patterns/progress.js.map +0 -1
  156. package/dist/patterns/sorting.d.ts +0 -13
  157. package/dist/patterns/sorting.d.ts.map +0 -1
  158. package/dist/patterns/sorting.js +0 -10
  159. package/dist/patterns/sorting.js.map +0 -1
  160. package/dist/patterns/status.d.ts +0 -15
  161. package/dist/patterns/status.d.ts.map +0 -1
  162. package/dist/patterns/status.js +0 -9
  163. package/dist/patterns/status.js.map +0 -1
  164. package/dist/patterns/timestamps.d.ts +0 -10
  165. package/dist/patterns/timestamps.d.ts.map +0 -1
  166. package/dist/patterns/timestamps.js +0 -10
  167. package/dist/patterns/timestamps.js.map +0 -1
  168. package/dist/redaction/index.d.ts +0 -4
  169. package/dist/redaction/index.d.ts.map +0 -1
  170. package/dist/redaction/index.js +0 -3
  171. package/dist/redaction/index.js.map +0 -1
  172. package/dist/redaction/patterns.d.ts +0 -9
  173. package/dist/redaction/patterns.d.ts.map +0 -1
  174. package/dist/redaction/patterns.js +0 -39
  175. package/dist/redaction/patterns.js.map +0 -1
  176. package/dist/redaction/redactor.d.ts +0 -27
  177. package/dist/redaction/redactor.d.ts.map +0 -1
  178. package/dist/redaction/redactor.js +0 -89
  179. package/dist/redaction/redactor.js.map +0 -1
  180. package/dist/resilience.d.ts +0 -34
  181. package/dist/resilience.d.ts.map +0 -1
  182. package/dist/resilience.js +0 -164
  183. package/dist/resilience.js.map +0 -1
  184. package/dist/result.d.ts +0 -57
  185. package/dist/result.d.ts.map +0 -1
  186. package/dist/result.js +0 -145
  187. package/dist/result.js.map +0 -1
  188. package/dist/serialization.d.ts +0 -27
  189. package/dist/serialization.d.ts.map +0 -1
  190. package/dist/serialization.js +0 -115
  191. package/dist/serialization.js.map +0 -1
  192. package/dist/topo.d.ts +0 -18
  193. package/dist/topo.d.ts.map +0 -1
  194. package/dist/topo.js +0 -74
  195. package/dist/topo.js.map +0 -1
  196. package/dist/trail.d.ts +0 -83
  197. package/dist/trail.d.ts.map +0 -1
  198. package/dist/trail.js +0 -16
  199. package/dist/trail.js.map +0 -1
  200. package/dist/types.d.ts +0 -46
  201. package/dist/types.d.ts.map +0 -1
  202. package/dist/types.js +0 -2
  203. package/dist/types.js.map +0 -1
  204. package/dist/validate-topo.d.ts +0 -24
  205. package/dist/validate-topo.d.ts.map +0 -1
  206. package/dist/validate-topo.js +0 -108
  207. package/dist/validate-topo.js.map +0 -1
  208. package/dist/validation.d.ts +0 -27
  209. package/dist/validation.d.ts.map +0 -1
  210. package/dist/validation.js +0 -134
  211. package/dist/validation.js.map +0 -1
  212. package/dist/workspace.d.ts +0 -25
  213. package/dist/workspace.d.ts.map +0 -1
  214. package/dist/workspace.js +0 -57
  215. package/dist/workspace.js.map +0 -1
  216. package/src/__tests__/blob-ref.test.ts +0 -103
  217. package/src/__tests__/branded.test.ts +0 -148
  218. package/src/__tests__/collections.test.ts +0 -126
  219. package/src/__tests__/context.test.ts +0 -66
  220. package/src/__tests__/derive.test.ts +0 -159
  221. package/src/__tests__/errors.test.ts +0 -309
  222. package/src/__tests__/event.test.ts +0 -82
  223. package/src/__tests__/fetch.test.ts +0 -217
  224. package/src/__tests__/guards.test.ts +0 -102
  225. package/src/__tests__/hike.test.ts +0 -117
  226. package/src/__tests__/job.test.ts +0 -98
  227. package/src/__tests__/layer.test.ts +0 -224
  228. package/src/__tests__/path-security.test.ts +0 -114
  229. package/src/__tests__/patterns.test.ts +0 -273
  230. package/src/__tests__/redaction.test.ts +0 -244
  231. package/src/__tests__/resilience.test.ts +0 -246
  232. package/src/__tests__/result.test.ts +0 -155
  233. package/src/__tests__/serialization.test.ts +0 -236
  234. package/src/__tests__/topo.test.ts +0 -184
  235. package/src/__tests__/trail.test.ts +0 -179
  236. package/src/__tests__/validate-topo.test.ts +0 -201
  237. package/src/__tests__/validation.test.ts +0 -283
  238. package/src/__tests__/workspace.test.ts +0 -183
  239. package/src/adapters.ts +0 -68
  240. package/src/event.ts +0 -77
  241. package/src/health.ts +0 -23
  242. package/src/hike.ts +0 -77
  243. package/src/job.ts +0 -20
  244. package/tsconfig.json +0 -9
  245. package/tsconfig.tsbuildinfo +0 -1
package/src/validation.ts CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import type { z } from 'zod';
9
9
 
10
+ import { BLOB_REF_SCHEMA_META_KEY, blobRefJsonSchema } from './blob-ref.js';
10
11
  import { ValidationError } from './errors.js';
11
12
  import { Result } from './result.js';
12
13
 
@@ -31,10 +32,66 @@ type JsonSchemaConverter = (schema: z.ZodType) => JsonSchema;
31
32
  // ---------------------------------------------------------------------------
32
33
 
33
34
  const isOptionalLike = (s: ZodInternals): boolean => {
34
- const defType = s._zod.def['type'] as string;
35
+ let current = s;
36
+ const seen = new Set<ZodInternals>();
37
+ while (
38
+ current._zod.def['type'] === 'readonly' &&
39
+ !seen.has(current) &&
40
+ current._zod.def['innerType'] !== undefined
41
+ ) {
42
+ seen.add(current);
43
+ current = current._zod.def['innerType'] as ZodInternals;
44
+ }
45
+ const defType = current._zod.def['type'] as string;
35
46
  return defType === 'optional' || defType === 'default';
36
47
  };
37
48
 
49
+ const getSchemaMeta = (
50
+ schema: z.ZodType
51
+ ): Readonly<Record<string, unknown>> | undefined => {
52
+ const maybeMeta = (schema as unknown as { meta?: () => unknown }).meta;
53
+ if (typeof maybeMeta !== 'function') {
54
+ return undefined;
55
+ }
56
+ const meta = maybeMeta.call(schema);
57
+ return typeof meta === 'object' && meta !== null
58
+ ? (meta as Readonly<Record<string, unknown>>)
59
+ : undefined;
60
+ };
61
+
62
+ const getSchemaJsonSchemaOverride = (
63
+ schema: z.ZodType
64
+ ): JsonSchema | undefined => {
65
+ const meta = getSchemaMeta(schema);
66
+ if (meta?.[BLOB_REF_SCHEMA_META_KEY] === true) {
67
+ const override: JsonSchema = {
68
+ properties: Object.fromEntries(
69
+ Object.entries(blobRefJsonSchema.properties).map(([key, value]) => [
70
+ key,
71
+ { ...value },
72
+ ])
73
+ ),
74
+ required: [...blobRefJsonSchema.required],
75
+ type: blobRefJsonSchema.type,
76
+ };
77
+ const { description } = schema as unknown as ZodInternals;
78
+ if (description) {
79
+ override['description'] = description;
80
+ }
81
+ return override;
82
+ }
83
+ return undefined;
84
+ };
85
+
86
+ /**
87
+ * Whether a schema has a deterministic JSON-schema override projection (for
88
+ * example `blobRefSchema`, a `z.custom(...)` carrying the descriptor metadata).
89
+ * Such schemas project to a canonical descriptor regardless of their underlying
90
+ * Zod internals, so marker derivation can treat them as supported.
91
+ */
92
+ export const schemaHasJsonSchemaOverride = (schema: z.ZodType): boolean =>
93
+ getSchemaJsonSchemaOverride(schema) !== undefined;
94
+
38
95
  // ---------------------------------------------------------------------------
39
96
  // Issue formatting
40
97
  // ---------------------------------------------------------------------------
@@ -94,6 +151,86 @@ export const validateOutput = <T>(
94
151
  // Zod → JSON Schema (public API)
95
152
  // ---------------------------------------------------------------------------
96
153
 
154
+ /**
155
+ * Sentinel indicating a dynamic default that should be omitted from schema
156
+ * exports. Zod v4 wraps all defaults in getters; dynamic ones (functions)
157
+ * produce new values on each access. We detect this by reading the getter
158
+ * twice and comparing with `Object.is`. If values differ, the default is
159
+ * dynamic and we cache this sentinel to skip it in future calls.
160
+ */
161
+ const DYNAMIC_DEFAULT = Symbol('DYNAMIC_DEFAULT');
162
+ const defaultValueCache = new WeakMap<object, unknown>();
163
+
164
+ const defaultsMatch = (left: unknown, right: unknown): boolean => {
165
+ if (Object.is(left, right)) {
166
+ return true;
167
+ }
168
+ try {
169
+ return JSON.stringify(left) === JSON.stringify(right);
170
+ } catch {
171
+ return false;
172
+ }
173
+ };
174
+
175
+ const waitForClockAdvance = (): void => {
176
+ const wallStart = Date.now();
177
+ const monotonicStart = performance.now();
178
+ while (Date.now() === wallStart && performance.now() - monotonicStart < 4) {
179
+ // Zod hides default factories behind a getter. A bounded sync wait lets
180
+ // Date.now()-style factories reveal themselves without making the API async.
181
+ }
182
+ };
183
+
184
+ const readDefaultWithDateNowOffset = (
185
+ def: Record<string, unknown>
186
+ ): unknown => {
187
+ const originalDateNow = Date.now;
188
+ try {
189
+ Date.now = () => originalDateNow() + 86_400_000;
190
+ return def['defaultValue'];
191
+ } finally {
192
+ Date.now = originalDateNow;
193
+ }
194
+ };
195
+
196
+ /**
197
+ * Read a Zod v4 default getter and decide if it is stable.
198
+ *
199
+ * Uses Object.is for primitives and JSON.stringify for objects/arrays. A delayed
200
+ * third read catches default factories such as `() => Date.now()` that can return
201
+ * equal values for immediate back-to-back reads. A Date.now() probe catches
202
+ * coarser clock factories without requiring marker derivation to wait for the
203
+ * next second/day boundary.
204
+ */
205
+ const resolveDefault = (def: Record<string, unknown>): unknown => {
206
+ try {
207
+ const a = def['defaultValue'];
208
+ const b = def['defaultValue'];
209
+ if (!defaultsMatch(a, b)) {
210
+ return DYNAMIC_DEFAULT;
211
+ }
212
+ waitForClockAdvance();
213
+ const c = def['defaultValue'];
214
+ if (!defaultsMatch(a, c)) {
215
+ return DYNAMIC_DEFAULT;
216
+ }
217
+ const d = readDefaultWithDateNowOffset(def);
218
+ return defaultsMatch(a, d) ? a : DYNAMIC_DEFAULT;
219
+ } catch {
220
+ // BigInt, circular refs, or other non-serializable defaults
221
+ return DYNAMIC_DEFAULT;
222
+ }
223
+ };
224
+
225
+ export const zodDefaultValueIsDynamic = (
226
+ def: Record<string, unknown>
227
+ ): boolean => {
228
+ if (!defaultValueCache.has(def)) {
229
+ defaultValueCache.set(def, resolveDefault(def));
230
+ }
231
+ return defaultValueCache.get(def) === DYNAMIC_DEFAULT;
232
+ };
233
+
97
234
  /**
98
235
  * Convert common Zod types to a JSON Schema object.
99
236
  *
@@ -104,6 +241,11 @@ export const validateOutput = <T>(
104
241
  export const zodToJsonSchema: JsonSchemaConverter = (
105
242
  schema: z.ZodType
106
243
  ): JsonSchema => {
244
+ const jsonSchemaOverride = getSchemaJsonSchemaOverride(schema);
245
+ if (jsonSchemaOverride !== undefined) {
246
+ return jsonSchemaOverride;
247
+ }
248
+
107
249
  const s = schema as unknown as ZodInternals;
108
250
 
109
251
  const collectObjectFields = (shape: Record<string, ZodInternals>) => {
@@ -142,9 +284,11 @@ export const zodToJsonSchema: JsonSchemaConverter = (
142
284
  default: (value) => {
143
285
  const inner = value._zod.def['innerType'] as unknown as z.ZodType;
144
286
  const innerSchema = zodToJsonSchema(inner);
145
- const rawDefault = value._zod.def['defaultValue'];
146
- innerSchema['default'] =
147
- typeof rawDefault === 'function' ? rawDefault() : rawDefault;
287
+ zodDefaultValueIsDynamic(value._zod.def);
288
+ const cached = defaultValueCache.get(value._zod.def);
289
+ if (cached !== DYNAMIC_DEFAULT) {
290
+ innerSchema['default'] = cached;
291
+ }
148
292
  return innerSchema;
149
293
  },
150
294
  enum: (value) => {
@@ -165,6 +309,10 @@ export const zodToJsonSchema: JsonSchemaConverter = (
165
309
  const inner = value._zod.def['innerType'] as unknown as z.ZodType;
166
310
  return zodToJsonSchema(inner);
167
311
  },
312
+ readonly: (value) => {
313
+ const inner = value._zod.def['innerType'] as unknown as z.ZodType;
314
+ return zodToJsonSchema(inner);
315
+ },
168
316
  string: () => ({ type: 'string' }),
169
317
  union: (value) => {
170
318
  const options = value._zod.def['options'] as unknown as z.ZodType[];