@crvouga/mockingbird-service-plane 2.1.0 → 2.3.0

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.
@@ -3,7 +3,7 @@ import {
3
3
  createRuntime,
4
4
  parseDuration,
5
5
  resolveAdminPrefix
6
- } from "./chunk-NSDJM2TL.js";
6
+ } from "./chunk-7ZEMJWNY.js";
7
7
 
8
8
  // ../../adapters/node/dist/cli.js
9
9
  import { readFile as readFile2 } from "node:fs/promises";
@@ -843,4 +843,4 @@ export {
843
843
  createServer2 as createServer,
844
844
  serveTarget
845
845
  };
846
- //# sourceMappingURL=chunk-4RCG3YYZ.js.map
846
+ //# sourceMappingURL=chunk-IBJ4UB3V.js.map
package/dist/cli.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  runCli,
4
4
  serveCommand,
5
5
  serveTarget
6
- } from "./chunk-4RCG3YYZ.js";
7
- import "./chunk-NSDJM2TL.js";
6
+ } from "./chunk-IBJ4UB3V.js";
7
+ import "./chunk-7ZEMJWNY.js";
8
8
 
9
9
  // src/cli.ts
10
10
  var code = await runCli(
package/dist/index.d.ts CHANGED
@@ -10,36 +10,6 @@ interface FetchAPI$1 {
10
10
  fetch(request: Request): Promise<Response>;
11
11
  }
12
12
 
13
- /**
14
- * The single source of time for a service.
15
- *
16
- * Every timestamp a mock writes reads from here, so a suite moves time instead of
17
- * sleeping: appointment windows, result delays and expiries become reachable in
18
- * milliseconds. A frozen clock also makes timestamps reproducible from a seed.
19
- */
20
- type ClockState = {
21
- /** Current epoch milliseconds. */
22
- now: number;
23
- /** True while time does not advance on its own. */
24
- frozen: boolean;
25
- /** Milliseconds this clock adds to its underlying source. */
26
- offsetMs: number;
27
- };
28
- type Clock = {
29
- now(): number;
30
- /** Pin the clock to an exact instant, keeping it frozen if it already was. */
31
- set(epochMs: number): void;
32
- /** Move the clock forward, or back with a negative delta. */
33
- advance(deltaMs: number): void;
34
- /** Stop time at the current instant. */
35
- freeze(): void;
36
- /** Resume from the current instant. */
37
- unfreeze(): void;
38
- /** Drop back to the underlying source, live. */
39
- reset(): void;
40
- state(): ClockState;
41
- };
42
-
43
13
  /** Bind values accepted by Mockingbird's SQLite port (matches sqlite-mem / better-sqlite3). */
44
14
  type SqliteValue$1 = null | number | bigint | string | Uint8Array | boolean;
45
15
  /** Mutation counters returned by {@link SqliteStatement.run}. */
@@ -111,6 +81,139 @@ declare class Collection<T> {
111
81
  }>;
112
82
  }
113
83
 
84
+ /** A stable identifier for a point in a {@link Timeline}. */
85
+ type CheckpointId = string;
86
+ /** An immutable node in a timeline's checkpoint DAG. */
87
+ type Checkpoint<T> = Readonly<{
88
+ id: CheckpointId;
89
+ branch: string;
90
+ parent: CheckpointId | null;
91
+ /** Logical time supplied by the timeline's injected clock. */
92
+ at: number;
93
+ value: T;
94
+ }>;
95
+ type TimelineOptions = {
96
+ /** Logical clock used to stamp checkpoints. Defaults to a deterministic counter. */
97
+ now?: () => number;
98
+ /** Maximum retained checkpoints. Branch heads are never collected. Default 1,000. */
99
+ maxCheckpoints?: number;
100
+ /** Customize deterministic checkpoint IDs. */
101
+ id?: (sequence: number) => CheckpointId;
102
+ };
103
+ type CommitOptions = {
104
+ branch?: string;
105
+ /** Parent checkpoint. Defaults to the selected branch's current head. */
106
+ parent?: CheckpointId | null;
107
+ };
108
+ type ForkOptions = {
109
+ /** Checkpoint to fork from. Defaults to the main branch's head. */
110
+ from?: CheckpointId;
111
+ };
112
+ /**
113
+ * Small, storage-agnostic checkpoint DAG shared by service runtimes. Its values may be immutable
114
+ * records, namespace images, or copy-on-write SQL engine snapshots.
115
+ *
116
+ * Values are retained by reference. Engines can therefore use persistent/COW snapshots while
117
+ * simpler services can use immutable values. IDs and GC order are deterministic, and all IO
118
+ * (the logical clock) is injected.
119
+ */
120
+ declare class Timeline<T> {
121
+ readonly maxCheckpoints: number;
122
+ private readonly now;
123
+ private readonly makeId;
124
+ private readonly nodes;
125
+ private readonly heads;
126
+ /** Unreferenced nodes in the exact order they became collectible. */
127
+ private readonly evictable;
128
+ /** Branch heads plus explicit retainers. Absent means zero. */
129
+ private readonly references;
130
+ private readonly explicitPins;
131
+ private sequence;
132
+ constructor(options?: TimelineOptions);
133
+ /** Capture a new immutable value and move `branch` to it. */
134
+ commit(value: T, options?: CommitOptions): Checkpoint<T>;
135
+ /** Create a branch pointer without copying its checkpoint value. */
136
+ fork(branch: string, options?: ForkOptions): Checkpoint<T> | undefined;
137
+ /** Move a branch pointer to an existing checkpoint. */
138
+ checkout(branch: string, id: CheckpointId): Checkpoint<T>;
139
+ get(id: CheckpointId): Checkpoint<T>;
140
+ head(branch?: string): Checkpoint<T> | undefined;
141
+ hasBranch(branch: string): boolean;
142
+ branches(): Readonly<Record<string, CheckpointId>>;
143
+ checkpoints(): readonly Checkpoint<T>[];
144
+ /** Number of retained checkpoints without allocating an array. */
145
+ get size(): number;
146
+ /** Pin a checkpoint independently of branch heads (used by compatibility snapshot handles). */
147
+ retain(id: CheckpointId): Checkpoint<T>;
148
+ /** Release one explicit pin. Branch heads remain pinned until moved or deleted. */
149
+ release(id: CheckpointId): boolean;
150
+ deleteBranch(branch: string): boolean;
151
+ /**
152
+ * Deterministically discard oldest unpinned checkpoints. Collection is O(number removed):
153
+ * commits never scan pinned nodes or the retained history. Parents are metadata rather than a
154
+ * storage dependency, so a retained node remains usable after pruning.
155
+ */
156
+ gc(max?: number): CheckpointId[];
157
+ private collect;
158
+ private moveHead;
159
+ private addReference;
160
+ private removeReference;
161
+ private assertBranch;
162
+ }
163
+
164
+ /**
165
+ * Anything that can answer a Fetch `Request` with a `Response`.
166
+ *
167
+ * Every Mockingbird service implements this, and every runtime adapter consumes it.
168
+ * It is the only contract shared across the whole graph.
169
+ */
170
+ interface FetchAPI {
171
+ fetch(request: Request): Promise<Response>;
172
+ }
173
+
174
+ /** Options every provider constructor accepts. */
175
+ type APIOptions = {
176
+ /** Sync SQLite client. Defaults to `@crvouga/mockingbird-service-sqlite`. */
177
+ sqlite?: SqliteClient$1;
178
+ /** Clock used for `created`-style fields. Default `Date.now`. */
179
+ now?: () => number;
180
+ /**
181
+ * Storage namespace for this instance's records. Instances sharing one SQLite
182
+ * client stay isolated when their namespaces differ. Defaults to the service name.
183
+ */
184
+ namespace?: string;
185
+ };
186
+
187
+ /**
188
+ * The single source of time for a service.
189
+ *
190
+ * Every timestamp a mock writes reads from here, so a suite moves time instead of
191
+ * sleeping: appointment windows, result delays and expiries become reachable in
192
+ * milliseconds. A frozen clock also makes timestamps reproducible from a seed.
193
+ */
194
+ type ClockState = {
195
+ /** Current epoch milliseconds. */
196
+ now: number;
197
+ /** True while time does not advance on its own. */
198
+ frozen: boolean;
199
+ /** Milliseconds this clock adds to its underlying source. */
200
+ offsetMs: number;
201
+ };
202
+ type Clock = {
203
+ now(): number;
204
+ /** Pin the clock to an exact instant, keeping it frozen if it already was. */
205
+ set(epochMs: number): void;
206
+ /** Move the clock forward, or back with a negative delta. */
207
+ advance(deltaMs: number): void;
208
+ /** Stop time at the current instant. */
209
+ freeze(): void;
210
+ /** Resume from the current instant. */
211
+ unfreeze(): void;
212
+ /** Drop back to the underlying source, live. */
213
+ reset(): void;
214
+ state(): ClockState;
215
+ };
216
+
114
217
  /**
115
218
  * Seeded pseudo-random numbers, so anything a mock invents — ids, jitter, which
116
219
  * request a percentage fault hits — is reproducible from a seed.
@@ -251,109 +354,6 @@ type FaultRegistry = {
251
354
  take(candidate: FaultCandidate): Promise<FaultHit[]>;
252
355
  };
253
356
 
254
- /** A stable identifier for a point in a {@link Timeline}. */
255
- type CheckpointId = string;
256
- /** An immutable node in a timeline's checkpoint DAG. */
257
- type Checkpoint<T> = Readonly<{
258
- id: CheckpointId;
259
- branch: string;
260
- parent: CheckpointId | null;
261
- /** Logical time supplied by the timeline's injected clock. */
262
- at: number;
263
- value: T;
264
- }>;
265
- type TimelineOptions = {
266
- /** Logical clock used to stamp checkpoints. Defaults to a deterministic counter. */
267
- now?: () => number;
268
- /** Maximum retained checkpoints. Branch heads are never collected. Default 1,000. */
269
- maxCheckpoints?: number;
270
- /** Customize deterministic checkpoint IDs. */
271
- id?: (sequence: number) => CheckpointId;
272
- };
273
- type CommitOptions = {
274
- branch?: string;
275
- /** Parent checkpoint. Defaults to the selected branch's current head. */
276
- parent?: CheckpointId | null;
277
- };
278
- type ForkOptions = {
279
- /** Checkpoint to fork from. Defaults to the main branch's head. */
280
- from?: CheckpointId;
281
- };
282
- /**
283
- * Small, storage-agnostic checkpoint DAG shared by service runtimes. Its values may be immutable
284
- * records, namespace images, or copy-on-write SQL engine snapshots.
285
- *
286
- * Values are retained by reference. Engines can therefore use persistent/COW snapshots while
287
- * simpler services can use immutable values. IDs and GC order are deterministic, and all IO
288
- * (the logical clock) is injected.
289
- */
290
- declare class Timeline<T> {
291
- readonly maxCheckpoints: number;
292
- private readonly now;
293
- private readonly makeId;
294
- private readonly nodes;
295
- private readonly heads;
296
- /** Unreferenced nodes in the exact order they became collectible. */
297
- private readonly evictable;
298
- /** Branch heads plus explicit retainers. Absent means zero. */
299
- private readonly references;
300
- private readonly explicitPins;
301
- private sequence;
302
- constructor(options?: TimelineOptions);
303
- /** Capture a new immutable value and move `branch` to it. */
304
- commit(value: T, options?: CommitOptions): Checkpoint<T>;
305
- /** Create a branch pointer without copying its checkpoint value. */
306
- fork(branch: string, options?: ForkOptions): Checkpoint<T> | undefined;
307
- /** Move a branch pointer to an existing checkpoint. */
308
- checkout(branch: string, id: CheckpointId): Checkpoint<T>;
309
- get(id: CheckpointId): Checkpoint<T>;
310
- head(branch?: string): Checkpoint<T> | undefined;
311
- hasBranch(branch: string): boolean;
312
- branches(): Readonly<Record<string, CheckpointId>>;
313
- checkpoints(): readonly Checkpoint<T>[];
314
- /** Number of retained checkpoints without allocating an array. */
315
- get size(): number;
316
- /** Pin a checkpoint independently of branch heads (used by compatibility snapshot handles). */
317
- retain(id: CheckpointId): Checkpoint<T>;
318
- /** Release one explicit pin. Branch heads remain pinned until moved or deleted. */
319
- release(id: CheckpointId): boolean;
320
- deleteBranch(branch: string): boolean;
321
- /**
322
- * Deterministically discard oldest unpinned checkpoints. Collection is O(number removed):
323
- * commits never scan pinned nodes or the retained history. Parents are metadata rather than a
324
- * storage dependency, so a retained node remains usable after pruning.
325
- */
326
- gc(max?: number): CheckpointId[];
327
- private collect;
328
- private moveHead;
329
- private addReference;
330
- private removeReference;
331
- private assertBranch;
332
- }
333
-
334
- /**
335
- * Anything that can answer a Fetch `Request` with a `Response`.
336
- *
337
- * Every Mockingbird service implements this, and every runtime adapter consumes it.
338
- * It is the only contract shared across the whole graph.
339
- */
340
- interface FetchAPI {
341
- fetch(request: Request): Promise<Response>;
342
- }
343
-
344
- /** Options every provider constructor accepts. */
345
- type APIOptions = {
346
- /** Sync SQLite client. Defaults to `@crvouga/mockingbird-service-sqlite`. */
347
- sqlite?: SqliteClient$1;
348
- /** Clock used for `created`-style fields. Default `Date.now`. */
349
- now?: () => number;
350
- /**
351
- * Storage namespace for this instance's records. Instances sharing one SQLite
352
- * client stay isolated when their namespaces differ. Defaults to the service name.
353
- */
354
- namespace?: string;
355
- };
356
-
357
357
  /**
358
358
  * One problem with a request body, at a dotted path (`patient.address.city`, `items.0.sku`).
359
359
  * `kind` is `media_type` when the body is present but its media type is not one the operation
@@ -395,6 +395,10 @@ type RequestLog = {
395
395
  ids?: Record<string, string>;
396
396
  /** Set when the service created a resource the request referred to but that did not exist. */
397
397
  adopted?: boolean;
398
+ /** Explicit durable acceptance, independent of response delivery. */
399
+ accepted?: boolean;
400
+ /** Checkpoint captured at explicit acceptance. */
401
+ checkpoint?: string;
398
402
  /** Set on a rejection (status ≥ 400) the mock produced itself, never on a scripted fault. */
399
403
  request?: RejectedRequest;
400
404
  /** The validation issues behind a rejection, when the service found any. */
@@ -715,6 +719,8 @@ type PlaneWorkItemRecord = {
715
719
  description_stripped: string | null;
716
720
  priority: "urgent" | "high" | "medium" | "low" | "none";
717
721
  state: string;
722
+ type_id: string | null;
723
+ type: string | null;
718
724
  labels: string[];
719
725
  assignees: string[];
720
726
  parent: string | null;
@@ -754,6 +760,52 @@ type PlaneLinkRecord = {
754
760
  created_at: string;
755
761
  updated_at: string;
756
762
  };
763
+ type PlaneCycleRecord = {
764
+ id: string;
765
+ name: string;
766
+ description: string;
767
+ start_date: string | null;
768
+ end_date: string | null;
769
+ owned_by: string | null;
770
+ timezone: string;
771
+ external_source: string | null;
772
+ external_id: string | null;
773
+ project: string;
774
+ workspace: string;
775
+ created_at: string;
776
+ updated_at: string;
777
+ archived_at: string | null;
778
+ deleted_at: string | null;
779
+ };
780
+ type PlaneCycleMembership = {
781
+ id: string;
782
+ cycle: string;
783
+ issue: string;
784
+ project: string;
785
+ workspace: string;
786
+ created_at: string;
787
+ updated_at: string;
788
+ deleted_at: string | null;
789
+ };
790
+ type PlaneWorkItemType = {
791
+ id: string;
792
+ name: string;
793
+ description: string;
794
+ project_ids: string[];
795
+ logo_props: Record<string, unknown>;
796
+ is_epic: boolean;
797
+ is_default: boolean;
798
+ is_active: boolean;
799
+ level: number;
800
+ created_at: string;
801
+ updated_at: string;
802
+ deleted_at: string | null;
803
+ };
804
+ type WorkItemTypeSeed = {
805
+ name: string;
806
+ description?: string;
807
+ is_default?: boolean;
808
+ };
757
809
  /** One project: its workspace slug and the per-project work-item sequence. */
758
810
  type ProjectRecord = {
759
811
  id: string;
@@ -786,6 +838,9 @@ declare class PlaneState {
786
838
  readonly items: Collection<PlaneWorkItemRecord>;
787
839
  readonly comments: Collection<PlaneCommentRecord>;
788
840
  readonly links: Collection<PlaneLinkRecord>;
841
+ readonly cycles: Collection<PlaneCycleRecord>;
842
+ readonly memberships: Collection<PlaneCycleMembership>;
843
+ readonly types: Collection<PlaneWorkItemType>;
789
844
  readonly settings: Collection<Settings>;
790
845
  readonly rateLimits: Collection<number>;
791
846
  private readonly ids;
@@ -963,10 +1018,10 @@ type OpenAPIDocument = {
963
1018
  };
964
1019
 
965
1020
  declare const document: OpenAPIDocument;
966
- type OperationId = "ListWorkItems" | "CreateWorkItem" | "GetWorkItem" | "UpdateWorkItem" | "ListComments" | "CreateComment" | "ListLinks" | "CreateLink" | "ListStates" | "ListLabels" | "CreateLabel";
967
- type SupportedOperationId = "ListWorkItems" | "CreateWorkItem" | "GetWorkItem" | "UpdateWorkItem" | "ListComments" | "CreateComment" | "ListLinks" | "CreateLink" | "ListStates" | "ListLabels" | "CreateLabel";
968
- declare const operationIds: readonly ["ListWorkItems", "CreateWorkItem", "GetWorkItem", "UpdateWorkItem", "ListComments", "CreateComment", "ListLinks", "CreateLink", "ListStates", "ListLabels", "CreateLabel"];
969
- declare const supportedOperationIds: readonly ["ListWorkItems", "CreateWorkItem", "GetWorkItem", "UpdateWorkItem", "ListComments", "CreateComment", "ListLinks", "CreateLink", "ListStates", "ListLabels", "CreateLabel"];
1021
+ type OperationId = "ListWorkItems" | "CreateWorkItem" | "GetWorkItem" | "UpdateWorkItem" | "ListComments" | "CreateComment" | "ListLinks" | "CreateLink" | "ListStates" | "ListLabels" | "CreateLabel" | "ListCycles" | "CreateCycle" | "ListCycleWorkItems" | "AddCycleWorkItems" | "ListWorkItemTypes";
1022
+ type SupportedOperationId = "ListWorkItems" | "CreateWorkItem" | "GetWorkItem" | "UpdateWorkItem" | "ListComments" | "CreateComment" | "ListLinks" | "CreateLink" | "ListStates" | "ListLabels" | "CreateLabel" | "ListCycles" | "CreateCycle" | "ListCycleWorkItems" | "AddCycleWorkItems" | "ListWorkItemTypes";
1023
+ declare const operationIds: readonly ["ListWorkItems", "CreateWorkItem", "GetWorkItem", "UpdateWorkItem", "ListComments", "CreateComment", "ListLinks", "CreateLink", "ListStates", "ListLabels", "CreateLabel", "ListCycles", "CreateCycle", "ListCycleWorkItems", "AddCycleWorkItems", "ListWorkItemTypes"];
1024
+ declare const supportedOperationIds: readonly ["ListWorkItems", "CreateWorkItem", "GetWorkItem", "UpdateWorkItem", "ListComments", "CreateComment", "ListLinks", "CreateLink", "ListStates", "ListLabels", "CreateLabel", "ListCycles", "CreateCycle", "ListCycleWorkItems", "AddCycleWorkItems", "ListWorkItemTypes"];
970
1025
 
971
1026
  /**
972
1027
  * Every named Plane misbehaviour our bug-report client branches on, switched on with
@@ -1020,11 +1075,20 @@ declare class PlaneAPI implements FetchAPI$1 {
1020
1075
  private item;
1021
1076
  statesOf(projectId: string): PlaneStateRecord[];
1022
1077
  labelsOf(projectId: string): PlaneLabelRecord[];
1078
+ typesOf(projectId: string): PlaneWorkItemType[];
1079
+ /** Idempotent fixture provisioning; type IDs remain stable when metadata is reseeded. */
1080
+ seedWorkItemTypes(workspace: string, projectId: string, types: WorkItemTypeSeed[]): PlaneWorkItemType[] | undefined;
1023
1081
  /** Plane's cursor paginator: `cursor=<per_page>:<page>:<is_prev>`, offset = page × per_page. */
1024
1082
  private paginate;
1025
1083
  private listWorkItems;
1084
+ private cycle;
1085
+ private cycleView;
1086
+ private listCycles;
1087
+ private createCycle;
1088
+ private listCycleWorkItems;
1089
+ private addCycleWorkItems;
1026
1090
  private body;
1027
- /** Validate `state` / `labels` references against the project, DRF-style. */
1091
+ /** Validate workflow references before any part of a write is persisted, DRF-style. */
1028
1092
  private references;
1029
1093
  private createWorkItem;
1030
1094
  private updateWorkItem;
@@ -1042,4 +1106,4 @@ declare class PlaneAPI implements FetchAPI$1 {
1042
1106
  }
1043
1107
 
1044
1108
  export { DEFAULT_STATES, PLANE_NAMESPACE, PLANE_PRESETS, PlaneAPI, apiKeyCredential, createRuntime, document, operationIds, supportedOperationIds, uuidFrom };
1045
- export type { FetchAPI$1 as FetchAPI, OperationId, PlaneAPIOptions, PlaneCommentRecord, PlaneLabelRecord, PlaneLinkRecord, PlaneRuntime, PlaneRuntimeOptions, PlaneStateRecord, PlaneWorkItemRecord, ProjectRecord, Settings, SqliteClient, StateGroup, SupportedOperationId };
1109
+ export type { FetchAPI$1 as FetchAPI, OperationId, PlaneAPIOptions, PlaneCommentRecord, PlaneCycleMembership, PlaneCycleRecord, PlaneLabelRecord, PlaneLinkRecord, PlaneRuntime, PlaneRuntimeOptions, PlaneStateRecord, PlaneWorkItemRecord, PlaneWorkItemType, ProjectRecord, Settings, SqliteClient, StateGroup, SupportedOperationId, WorkItemTypeSeed };
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  operationIds,
10
10
  supportedOperationIds,
11
11
  uuidFrom
12
- } from "./chunk-NSDJM2TL.js";
12
+ } from "./chunk-7ZEMJWNY.js";
13
13
  export {
14
14
  DEFAULT_STATES,
15
15
  PLANE_NAMESPACE,