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

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 (56) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +34 -0
  3. package/README.md +8 -11
  4. package/dist/derive.d.ts +1 -1
  5. package/dist/derive.d.ts.map +1 -1
  6. package/dist/derive.js +4 -1
  7. package/dist/derive.js.map +1 -1
  8. package/dist/event.d.ts +2 -2
  9. package/dist/event.d.ts.map +1 -1
  10. package/dist/event.js +1 -1
  11. package/dist/event.js.map +1 -1
  12. package/dist/index.d.ts +3 -3
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -2
  15. package/dist/index.js.map +1 -1
  16. package/dist/result.d.ts.map +1 -1
  17. package/dist/result.js +15 -4
  18. package/dist/result.js.map +1 -1
  19. package/dist/serialization.d.ts.map +1 -1
  20. package/dist/serialization.js +45 -7
  21. package/dist/serialization.js.map +1 -1
  22. package/dist/topo.d.ts +2 -4
  23. package/dist/topo.d.ts.map +1 -1
  24. package/dist/topo.js +8 -16
  25. package/dist/topo.js.map +1 -1
  26. package/dist/trail.d.ts +16 -10
  27. package/dist/trail.d.ts.map +1 -1
  28. package/dist/trail.js +4 -2
  29. package/dist/trail.js.map +1 -1
  30. package/dist/validate-topo.d.ts +2 -2
  31. package/dist/validate-topo.d.ts.map +1 -1
  32. package/dist/validate-topo.js +59 -9
  33. package/dist/validate-topo.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/__tests__/derive.test.ts +44 -0
  36. package/src/__tests__/event.test.ts +5 -5
  37. package/src/__tests__/layer.test.ts +10 -22
  38. package/src/__tests__/serialization.test.ts +166 -1
  39. package/src/__tests__/topo.test.ts +78 -81
  40. package/src/__tests__/trail.test.ts +73 -35
  41. package/src/__tests__/validate-topo.test.ts +97 -20
  42. package/src/derive.ts +12 -2
  43. package/src/event.ts +3 -3
  44. package/src/index.ts +11 -5
  45. package/src/result.ts +18 -4
  46. package/src/serialization.ts +56 -11
  47. package/src/topo.ts +11 -23
  48. package/src/trail.ts +24 -13
  49. package/src/validate-topo.ts +70 -10
  50. package/tsconfig.tsbuildinfo +1 -1
  51. package/dist/hike.d.ts +0 -36
  52. package/dist/hike.d.ts.map +0 -1
  53. package/dist/hike.js +0 -20
  54. package/dist/hike.js.map +0 -1
  55. package/src/__tests__/hike.test.ts +0 -117
  56. package/src/hike.ts +0 -77
package/src/index.ts CHANGED
@@ -42,11 +42,13 @@ export { createTrailContext } from './context.js';
42
42
 
43
43
  // Trail
44
44
  export { trail } from './trail.js';
45
- export type { AnyTrail, Trail, TrailSpec, TrailExample } from './trail.js';
46
-
47
- // Hike
48
- export { hike } from './hike.js';
49
- export type { AnyHike, Hike, HikeSpec } from './hike.js';
45
+ export type {
46
+ AnyTrail,
47
+ Intent,
48
+ Trail,
49
+ TrailSpec,
50
+ TrailExample,
51
+ } from './trail.js';
50
52
 
51
53
  // Event
52
54
  export { event } from './event.js';
@@ -133,6 +135,10 @@ export {
133
135
  getRelativePath,
134
136
  } from './workspace.js';
135
137
 
138
+ // Blob
139
+ export { createBlobRef, isBlobRef } from './blob-ref.js';
140
+ export type { BlobRef } from './blob-ref.js';
141
+
136
142
  // Guards
137
143
  export {
138
144
  isDefined,
package/src/result.ts CHANGED
@@ -151,16 +151,30 @@ export const Result = {
151
151
  */
152
152
  toJson(value: unknown): Result<string, InternalError> {
153
153
  try {
154
- const seen = new WeakSet();
155
- const json = JSON.stringify(value, (_key, val: unknown) => {
154
+ // Track the current ancestor chain, not every object ever visited.
155
+ // This allows shared references in a DAG while still detecting cycles.
156
+ const stack: unknown[] = [];
157
+ const keys: string[] = [];
158
+
159
+ const json = JSON.stringify(value, function json(key, val: unknown) {
160
+ if (stack.length > 0) {
161
+ // `this` is the object that contains `key`. Trim the stack back
162
+ // to `this` so we only track the current ancestor path.
163
+ const thisIndex = stack.lastIndexOf(this as unknown);
164
+ stack.splice(thisIndex + 1);
165
+ keys.splice(thisIndex);
166
+ }
167
+
156
168
  if (typeof val === 'object' && val !== null) {
157
- if (seen.has(val)) {
169
+ if (stack.includes(val)) {
158
170
  return '[Circular]';
159
171
  }
160
- seen.add(val);
172
+ stack.push(val);
173
+ keys.push(key);
161
174
  }
162
175
  return val;
163
176
  });
177
+
164
178
  if (json === undefined) {
165
179
  return new Err(
166
180
  new InternalError('Value is not JSON-serializable', {
@@ -8,7 +8,10 @@
8
8
  import type { ErrorCategory, TrailsError } from './errors.js';
9
9
  import {
10
10
  ValidationError,
11
+ AmbiguousError,
12
+ AssertionError,
11
13
  NotFoundError,
14
+ AlreadyExistsError,
12
15
  ConflictError,
13
16
  PermissionError,
14
17
  TimeoutError,
@@ -89,6 +92,31 @@ const createErrorByCategory = (
89
92
  return factory(message, opts, retryAfter);
90
93
  };
91
94
 
95
+ /** Map error class names to their constructors for precise round-tripping. */
96
+ const errorConstructorsByName: Record<string, ErrorFactory> = {
97
+ AlreadyExistsError: (msg, opts) => new AlreadyExistsError(msg, opts),
98
+ AmbiguousError: (msg, opts) => new AmbiguousError(msg, opts),
99
+ AssertionError: (msg, opts) => new AssertionError(msg, opts),
100
+ AuthError: (msg, opts) => new AuthError(msg, opts),
101
+ CancelledError: (msg, opts) => new CancelledError(msg, opts),
102
+ ConflictError: (msg, opts) => new ConflictError(msg, opts),
103
+ InternalError: (msg, opts) => new InternalError(msg, opts),
104
+ NetworkError: (msg, opts) => new NetworkError(msg, opts),
105
+ NotFoundError: (msg, opts) => new NotFoundError(msg, opts),
106
+ PermissionError: (msg, opts) => new PermissionError(msg, opts),
107
+ RateLimitError: (msg, opts, retryAfter) => {
108
+ const rlOpts: { context?: Record<string, unknown>; retryAfter?: number } = {
109
+ ...opts,
110
+ };
111
+ if (retryAfter !== undefined) {
112
+ rlOpts.retryAfter = retryAfter;
113
+ }
114
+ return new RateLimitError(msg, rlOpts);
115
+ },
116
+ TimeoutError: (msg, opts) => new TimeoutError(msg, opts),
117
+ ValidationError: (msg, opts) => new ValidationError(msg, opts),
118
+ };
119
+
92
120
  // ---------------------------------------------------------------------------
93
121
  // Error serialization
94
122
  // ---------------------------------------------------------------------------
@@ -117,13 +145,17 @@ export const serializeError = (error: Error): SerializedError => {
117
145
 
118
146
  /** Reconstruct a TrailsError from serialized data. */
119
147
  export const deserializeError = (data: SerializedError): TrailsError => {
120
- const category = data.category ?? 'internal';
121
- const error = createErrorByCategory(
122
- category,
123
- data.message,
124
- data.context,
125
- data.retryAfter
126
- );
148
+ const opts = buildOpts(data.context);
149
+ const nameFactory = errorConstructorsByName[data.name];
150
+
151
+ const error = nameFactory
152
+ ? nameFactory(data.message, opts, data.retryAfter)
153
+ : createErrorByCategory(
154
+ data.category ?? 'internal',
155
+ data.message,
156
+ data.context,
157
+ data.retryAfter
158
+ );
127
159
 
128
160
  if (data.stack) {
129
161
  error.stack = data.stack;
@@ -155,13 +187,26 @@ export const safeStringify = (
155
187
  value: unknown
156
188
  ): Result<string, InternalError> => {
157
189
  try {
158
- const seen = new WeakSet();
159
- const json = JSON.stringify(value, (_key, val: unknown) => {
190
+ // Track the current ancestor chain, not every object ever visited.
191
+ // This allows shared references in a DAG while still detecting cycles.
192
+ const stack: unknown[] = [];
193
+ const keys: string[] = [];
194
+
195
+ const json = JSON.stringify(value, function json(key, val: unknown) {
196
+ if (stack.length > 0) {
197
+ // `this` is the object that contains `key`. Trim the stack back
198
+ // to `this` so we only track the current ancestor path.
199
+ const thisIndex = stack.lastIndexOf(this as unknown);
200
+ stack.splice(thisIndex + 1);
201
+ keys.splice(thisIndex);
202
+ }
203
+
160
204
  if (typeof val === 'object' && val !== null) {
161
- if (seen.has(val)) {
205
+ if (stack.includes(val)) {
162
206
  return '[Circular]';
163
207
  }
164
- seen.add(val);
208
+ stack.push(val);
209
+ keys.push(key);
165
210
  }
166
211
  return val;
167
212
  });
package/src/topo.ts CHANGED
@@ -4,7 +4,6 @@
4
4
 
5
5
  import { ValidationError } from './errors.js';
6
6
  import type { AnyEvent } from './event.js';
7
- import type { AnyHike } from './hike.js';
8
7
  import type { AnyTrail } from './trail.js';
9
8
 
10
9
  // ---------------------------------------------------------------------------
@@ -14,11 +13,10 @@ import type { AnyTrail } from './trail.js';
14
13
  export interface Topo {
15
14
  readonly name: string;
16
15
  readonly trails: ReadonlyMap<string, AnyTrail>;
17
- readonly hikes: ReadonlyMap<string, AnyHike>;
18
16
  readonly events: ReadonlyMap<string, AnyEvent>;
19
- get(id: string): AnyTrail | AnyHike | undefined;
17
+ get(id: string): AnyTrail | undefined;
20
18
  has(id: string): boolean;
21
- list(): (AnyTrail | AnyHike)[];
19
+ list(): AnyTrail[];
22
20
  listEvents(): AnyEvent[];
23
21
  }
24
22
 
@@ -26,14 +24,14 @@ export interface Topo {
26
24
  // Kind discriminant check
27
25
  // ---------------------------------------------------------------------------
28
26
 
29
- type Registrable = AnyTrail | AnyHike | AnyEvent;
27
+ type Registrable = AnyTrail | AnyEvent;
30
28
 
31
29
  const isRegistrable = (value: unknown): value is Registrable => {
32
30
  if (typeof value !== 'object' || value === null) {
33
31
  return false;
34
32
  }
35
33
  const { kind } = value as Record<string, unknown>;
36
- return kind === 'trail' || kind === 'hike' || kind === 'event';
34
+ return kind === 'trail' || kind === 'event';
37
35
  };
38
36
 
39
37
  // ---------------------------------------------------------------------------
@@ -43,20 +41,18 @@ const isRegistrable = (value: unknown): value is Registrable => {
43
41
  const createTopo = (
44
42
  name: string,
45
43
  trails: ReadonlyMap<string, AnyTrail>,
46
- hikes: ReadonlyMap<string, AnyHike>,
47
44
  events: ReadonlyMap<string, AnyEvent>
48
45
  ): Topo => ({
49
46
  events,
50
- get(id: string): AnyTrail | AnyHike | undefined {
51
- return trails.get(id) ?? hikes.get(id);
47
+ get(id: string): AnyTrail | undefined {
48
+ return trails.get(id);
52
49
  },
53
50
  has(id: string): boolean {
54
- return trails.has(id) || hikes.has(id);
51
+ return trails.has(id);
55
52
  },
56
- hikes,
57
53
 
58
- list(): (AnyTrail | AnyHike)[] {
59
- return [...trails.values(), ...hikes.values()];
54
+ list(): AnyTrail[] {
55
+ return [...trails.values()];
60
56
  },
61
57
 
62
58
  listEvents(): AnyEvent[] {
@@ -76,7 +72,6 @@ const createTopo = (
76
72
  const register = (
77
73
  value: Registrable,
78
74
  trails: Map<string, AnyTrail>,
79
- hikes: Map<string, AnyHike>,
80
75
  events: Map<string, AnyEvent>
81
76
  ): void => {
82
77
  const { id } = value as { id: string };
@@ -87,12 +82,6 @@ const register = (
87
82
  }
88
83
  events.set(id, value as AnyEvent);
89
84
  },
90
- hike: () => {
91
- if (hikes.has(id)) {
92
- throw new ValidationError(`Duplicate hike ID: "${id}"`);
93
- }
94
- hikes.set(id, value as AnyHike);
95
- },
96
85
  trail: () => {
97
86
  if (trails.has(id)) {
98
87
  throw new ValidationError(`Duplicate trail ID: "${id}"`);
@@ -108,16 +97,15 @@ export const topo = (
108
97
  ...modules: Record<string, unknown>[]
109
98
  ): Topo => {
110
99
  const trails = new Map<string, AnyTrail>();
111
- const hikes = new Map<string, AnyHike>();
112
100
  const events = new Map<string, AnyEvent>();
113
101
 
114
102
  for (const mod of modules) {
115
103
  for (const value of Object.values(mod)) {
116
104
  if (isRegistrable(value)) {
117
- register(value, trails, hikes, events);
105
+ register(value, trails, events);
118
106
  }
119
107
  }
120
108
  }
121
109
 
122
- return createTopo(name, trails, hikes, events);
110
+ return createTopo(name, trails, events);
123
111
  };
package/src/trail.ts CHANGED
@@ -39,34 +39,44 @@ export interface TrailSpec<I, O> {
39
39
  /** Zod schema for validating output (optional — some trails are fire-and-forget) */
40
40
  readonly output?: z.ZodType<O> | undefined;
41
41
  /** The pure function that does the work (sync or async authoring) */
42
- readonly implementation: Implementation<I, O>;
42
+ readonly run: Implementation<I, O>;
43
43
  /** Human-readable description */
44
44
  readonly description?: string | undefined;
45
45
  /** Named examples for docs and testing */
46
46
  readonly examples?: readonly TrailExample<I, O>[] | undefined;
47
- /** Trail is read-only (no side effects) */
48
- readonly readOnly?: boolean | undefined;
49
- /** Trail is destructive (deletes or overwrites data) */
50
- readonly destructive?: boolean | undefined;
47
+ /** What this trail does to the world: read, write (default), or destroy */
48
+ readonly intent?: 'read' | 'write' | 'destroy' | undefined;
51
49
  /** Trail is idempotent (safe to retry) */
52
50
  readonly idempotent?: boolean | undefined;
53
51
  /** Arbitrary metadata for tooling and filtering */
54
- readonly markers?: Readonly<Record<string, unknown>> | undefined;
52
+ readonly metadata?: Readonly<Record<string, unknown>> | undefined;
55
53
  /** Named sets of downstream trail IDs that may be invoked */
56
54
  readonly detours?: Readonly<Record<string, readonly string[]>> | undefined;
57
55
  /** Per-field overrides for deriveFields() (labels, hints, options) */
58
56
  readonly fields?: Readonly<Record<string, FieldOverride>> | undefined;
57
+ /** IDs of downstream trails this trail may invoke via ctx.follow() */
58
+ readonly follow?: readonly string[] | undefined;
59
59
  }
60
60
 
61
61
  // ---------------------------------------------------------------------------
62
62
  // Trail (the frozen runtime object)
63
63
  // ---------------------------------------------------------------------------
64
64
 
65
+ /** Intent describes what a trail does to the world */
66
+ export type Intent = 'read' | 'write' | 'destroy';
67
+
65
68
  /** A fully-defined trail — the unit of work in the Trails system */
66
- export interface Trail<I, O> extends Omit<TrailSpec<I, O>, 'implementation'> {
69
+ export interface Trail<I, O> extends Omit<
70
+ TrailSpec<I, O>,
71
+ 'run' | 'follow' | 'intent'
72
+ > {
67
73
  readonly kind: 'trail';
68
74
  readonly id: string;
69
- readonly implementation: Implementation<I, O>;
75
+ readonly run: Implementation<I, O>;
76
+ /** IDs of downstream trails this trail may invoke via ctx.follow() (always present, default []) */
77
+ readonly follow: readonly string[];
78
+ /** What this trail does to the world (always present, default 'write') */
79
+ readonly intent: Intent;
70
80
  }
71
81
 
72
82
  // ---------------------------------------------------------------------------
@@ -84,14 +94,14 @@ export interface Trail<I, O> extends Omit<TrailSpec<I, O>, 'implementation'> {
84
94
  * // ID as first argument (recommended for human authoring)
85
95
  * const show = trail("entity.show", {
86
96
  * input: z.object({ name: z.string() }),
87
- * implementation: (input) => Result.ok(entity),
97
+ * run: (input) => Result.ok(entity),
88
98
  * });
89
99
  *
90
100
  * // Full spec object (for programmatic generation)
91
101
  * const show = trail({
92
102
  * id: "entity.show",
93
103
  * input: z.object({ name: z.string() }),
94
- * implementation: (input) => Result.ok(entity),
104
+ * run: (input) => Result.ok(entity),
95
105
  * });
96
106
  * ```
97
107
  */
@@ -112,14 +122,15 @@ export function trail<I, O>(
112
122
  throw new TypeError('trail() requires a spec when an id is provided');
113
123
  }
114
124
 
115
- const { implementation, ...spec } = resolved.spec;
125
+ const { run, follow: rawFollow, intent: rawIntent, ...spec } = resolved.spec;
116
126
 
117
127
  return Object.freeze({
118
128
  ...spec,
129
+ follow: Object.freeze([...(rawFollow ?? [])]),
119
130
  id: resolved.id,
120
- implementation: async (input: I, ctx: TrailContext) =>
121
- await implementation(input, ctx),
131
+ intent: rawIntent ?? 'write',
122
132
  kind: 'trail' as const,
133
+ run: async (input: I, ctx: TrailContext) => await run(input, ctx),
123
134
  });
124
135
  }
125
136
 
@@ -1,14 +1,13 @@
1
1
  /**
2
2
  * Structural validation for a Topo graph.
3
3
  *
4
- * Checks hike follows references, example input validity, event origin
4
+ * Checks trail follow references, example input validity, event origin
5
5
  * references, and output schema completeness. Returns a Result with all
6
6
  * issues collected into a single ValidationError.
7
7
  */
8
8
 
9
9
  import { ValidationError } from './errors.js';
10
10
  import type { AnyEvent } from './event.js';
11
- import type { AnyHike } from './hike.js';
12
11
  import { Result } from './result.js';
13
12
  import type { Topo } from './topo.js';
14
13
  import type { AnyTrail } from './trail.js';
@@ -28,28 +27,89 @@ export interface TopoIssue {
28
27
  // Validators
29
28
  // ---------------------------------------------------------------------------
30
29
 
30
+ const WHITE = 0;
31
+ const GRAY = 1;
32
+ const BLACK = 2;
33
+
34
+ /** Build an adjacency list and initial color map from trails with follow. */
35
+ const buildFollowGraph = (
36
+ trails: ReadonlyMap<string, AnyTrail>
37
+ ): {
38
+ graph: Map<string, readonly string[]>;
39
+ color: Map<string, number>;
40
+ } => {
41
+ const graph = new Map<string, readonly string[]>();
42
+ for (const [id, t] of trails) {
43
+ if (t.follow.length > 0) {
44
+ graph.set(id, t.follow);
45
+ }
46
+ }
47
+ const color = new Map<string, number>();
48
+ for (const id of graph.keys()) {
49
+ color.set(id, WHITE);
50
+ }
51
+ return { color, graph };
52
+ };
53
+
54
+ /** Detect multi-node cycles in the trail follow graph via DFS. */
55
+ const detectFollowCycles = (
56
+ trails: ReadonlyMap<string, AnyTrail>
57
+ ): TopoIssue[] => {
58
+ const issues: TopoIssue[] = [];
59
+ const { color, graph } = buildFollowGraph(trails);
60
+
61
+ const dfs = (node: string, path: string[]): void => {
62
+ color.set(node, GRAY);
63
+ for (const next of graph.get(node) ?? []) {
64
+ if (!graph.has(next)) {
65
+ continue;
66
+ }
67
+ const c = color.get(next) ?? WHITE;
68
+ if (c === GRAY) {
69
+ const cycle = [...path.slice(path.indexOf(next)), next];
70
+ issues.push({
71
+ message: `Cycle detected: ${cycle.join(' → ')}`,
72
+ rule: 'follow-cycle',
73
+ trailId: next,
74
+ });
75
+ } else if (c === WHITE) {
76
+ dfs(next, [...path, next]);
77
+ }
78
+ }
79
+ color.set(node, BLACK);
80
+ };
81
+
82
+ for (const id of graph.keys()) {
83
+ if (color.get(id) === WHITE) {
84
+ dfs(id, [id]);
85
+ }
86
+ }
87
+ return issues;
88
+ };
89
+
31
90
  const checkFollows = (
32
- hikes: ReadonlyMap<string, AnyHike>,
91
+ trails: ReadonlyMap<string, AnyTrail>,
33
92
  topo: Topo
34
93
  ): TopoIssue[] => {
35
94
  const issues: TopoIssue[] = [];
36
- for (const [id, hike] of hikes) {
37
- for (const followId of hike.follows) {
95
+ for (const [id, trail] of trails) {
96
+ for (const followId of trail.follow) {
38
97
  if (followId === id) {
39
98
  issues.push({
40
- message: `Hike follows itself`,
99
+ message: `Trail follows itself`,
41
100
  rule: 'no-self-follow',
42
101
  trailId: id,
43
102
  });
44
103
  } else if (!topo.has(followId)) {
45
104
  issues.push({
46
105
  message: `Follows "${followId}" which is not in the topo`,
47
- rule: 'follows-exist',
106
+ rule: 'follow-exists',
48
107
  trailId: id,
49
108
  });
50
109
  }
51
110
  }
52
111
  }
112
+ issues.push(...detectFollowCycles(trails));
53
113
  return issues;
54
114
  };
55
115
 
@@ -66,7 +126,7 @@ const checkOneExample = (
66
126
  ): TopoIssue[] => {
67
127
  const issues: TopoIssue[] = [];
68
128
  const result = validateInput(inputSchema as AnyTrail['input'], example.input);
69
- if (result.isErr() && example.error === undefined) {
129
+ if (result.isErr() && example.error !== 'ValidationError') {
70
130
  issues.push({
71
131
  message: `Example "${example.name}" input does not parse against schema`,
72
132
  rule: 'example-input-valid',
@@ -125,13 +185,13 @@ const checkEventOrigins = (
125
185
  /**
126
186
  * Validate the structural integrity of a Topo graph.
127
187
  *
128
- * Checks follows references, example inputs, event origins, and output
188
+ * Checks follow references, example inputs, event origins, and output
129
189
  * schema presence. Returns `Result.ok()` when no issues are found, or
130
190
  * `Result.err(ValidationError)` with all issues in the error context.
131
191
  */
132
192
  export const validateTopo = (topo: Topo): Result<void, ValidationError> => {
133
193
  const issues = [
134
- ...checkFollows(topo.hikes, topo),
194
+ ...checkFollows(topo.trails, topo),
135
195
  ...checkExamples(topo.trails),
136
196
  ...checkEventOrigins(topo.events, topo),
137
197
  ];
@@ -1 +1 @@
1
- {"root":["./src/adapters.ts","./src/blob-ref.ts","./src/branded.ts","./src/collections.ts","./src/context.ts","./src/derive.ts","./src/errors.ts","./src/event.ts","./src/fetch.ts","./src/guards.ts","./src/health.ts","./src/hike.ts","./src/index.ts","./src/job.ts","./src/layer.ts","./src/path-security.ts","./src/resilience.ts","./src/result.ts","./src/serialization.ts","./src/topo.ts","./src/trail.ts","./src/types.ts","./src/validate-topo.ts","./src/validation.ts","./src/workspace.ts","./src/patterns/bulk.ts","./src/patterns/change.ts","./src/patterns/date-range.ts","./src/patterns/index.ts","./src/patterns/pagination.ts","./src/patterns/progress.ts","./src/patterns/sorting.ts","./src/patterns/status.ts","./src/patterns/timestamps.ts","./src/redaction/index.ts","./src/redaction/patterns.ts","./src/redaction/redactor.ts"],"version":"5.9.3"}
1
+ {"root":["./src/adapters.ts","./src/blob-ref.ts","./src/branded.ts","./src/collections.ts","./src/context.ts","./src/derive.ts","./src/errors.ts","./src/event.ts","./src/fetch.ts","./src/guards.ts","./src/health.ts","./src/index.ts","./src/job.ts","./src/layer.ts","./src/path-security.ts","./src/resilience.ts","./src/result.ts","./src/serialization.ts","./src/topo.ts","./src/trail.ts","./src/types.ts","./src/validate-topo.ts","./src/validation.ts","./src/workspace.ts","./src/patterns/bulk.ts","./src/patterns/change.ts","./src/patterns/date-range.ts","./src/patterns/index.ts","./src/patterns/pagination.ts","./src/patterns/progress.ts","./src/patterns/sorting.ts","./src/patterns/status.ts","./src/patterns/timestamps.ts","./src/redaction/index.ts","./src/redaction/patterns.ts","./src/redaction/redactor.ts"],"version":"5.9.3"}
package/dist/hike.d.ts DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * Hike — a composition that follows trails.
3
- */
4
- import type { Trail, TrailSpec } from './trail.js';
5
- export interface HikeSpec<I, O> extends TrailSpec<I, O> {
6
- readonly follows: readonly string[];
7
- }
8
- export interface Hike<I, O> extends Omit<Trail<I, O>, 'kind'> {
9
- readonly kind: 'hike';
10
- readonly follows: readonly string[];
11
- }
12
- /**
13
- * Create a hike definition.
14
- *
15
- * A hike is a composition that declares which trails it follows.
16
- * Returns a frozen object with `kind: "hike"` and all spec fields.
17
- *
18
- * @example
19
- * ```typescript
20
- * // ID as first argument
21
- * const onboard = hike("entity.onboard", {
22
- * follows: ["entity.add", "entity.relate"],
23
- * input: z.object({ name: z.string() }),
24
- * implementation: (input, ctx) => Result.ok(...),
25
- * });
26
- *
27
- * // Full spec object (programmatic)
28
- * const onboard = hike({ id: "entity.onboard", follows: [...], ... });
29
- * ```
30
- */
31
- export declare function hike<I, O>(id: string, spec: HikeSpec<I, O>): Hike<I, O>;
32
- export declare function hike<I, O>(spec: HikeSpec<I, O> & {
33
- readonly id: string;
34
- }): Hike<I, O>;
35
- export type AnyHike = Hike<any, any>;
36
- //# sourceMappingURL=hike.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hike.d.ts","sourceRoot":"","sources":["../src/hike.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAOnD,MAAM,WAAW,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAMD,MAAM,WAAW,IAAI,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,wBAAgB,IAAI,CAAC,CAAC,EAAE,CAAC,EACvB,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC7C,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AA0Bd,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC"}
package/dist/hike.js DELETED
@@ -1,20 +0,0 @@
1
- /**
2
- * Hike — a composition that follows trails.
3
- */
4
- export function hike(idOrSpec, maybeSpec) {
5
- const resolved = typeof idOrSpec === 'string'
6
- ? { id: idOrSpec, spec: maybeSpec }
7
- : { id: idOrSpec.id, spec: idOrSpec };
8
- if (!resolved.spec) {
9
- throw new TypeError('hike() requires a spec when an id is provided');
10
- }
11
- const { follows, implementation, ...rest } = resolved.spec;
12
- return Object.freeze({
13
- ...rest,
14
- follows: Object.freeze([...follows]),
15
- id: resolved.id,
16
- implementation: async (input, ctx) => await implementation(input, ctx),
17
- kind: 'hike',
18
- });
19
- }
20
- //# sourceMappingURL=hike.js.map
package/dist/hike.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"hike.js","sourceRoot":"","sources":["../src/hike.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiDH,MAAM,UAAU,IAAI,CAClB,QAA6D,EAC7D,SAA0B;IAE1B,MAAM,QAAQ,GACZ,OAAO,QAAQ,KAAK,QAAQ;QAC1B,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;QACnC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAE1C,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3D,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,IAAI;QACP,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC;QACpC,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,cAAc,EAAE,KAAK,EAAE,KAAQ,EAAE,GAAiB,EAAE,EAAE,CACpD,MAAM,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC;QAClC,IAAI,EAAE,MAAe;KACtB,CAAC,CAAC;AACL,CAAC"}