@useairfoil/producer-linear 0.0.1 → 0.0.3

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 (51) hide show
  1. package/LICENSE.txt +201 -0
  2. package/README.md +71 -0
  3. package/dist/index.d.mts +4027 -0
  4. package/dist/index.mjs +3 -0
  5. package/dist/main.d.mts +1 -0
  6. package/dist/main.mjs +1305 -0
  7. package/dist/main.mjs.map +1 -0
  8. package/dist/manifest.d.mts +114 -0
  9. package/dist/manifest.mjs +161 -0
  10. package/dist/manifest.mjs.map +1 -0
  11. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  12. package/dist/src-BbzySPR7.mjs +1688 -0
  13. package/dist/src-BbzySPR7.mjs.map +1 -0
  14. package/package.json +46 -8
  15. package/src/client/client.ts +200 -0
  16. package/src/connector.ts +151 -0
  17. package/src/create-table.ts +10 -0
  18. package/src/demo/index.ts +137 -0
  19. package/src/demo/initiatives.ts +116 -0
  20. package/src/demo/issues.ts +320 -0
  21. package/src/demo/projects.ts +215 -0
  22. package/src/demo/setup.ts +151 -0
  23. package/src/demo/shared.ts +122 -0
  24. package/src/demo/teams.ts +173 -0
  25. package/src/index.ts +83 -0
  26. package/src/main.ts +28 -0
  27. package/src/manifest.ts +58 -0
  28. package/src/resources/comments.ts +32 -0
  29. package/src/resources/customers.ts +105 -0
  30. package/src/resources/documents.ts +31 -0
  31. package/src/resources/initiatives.ts +136 -0
  32. package/src/resources/issue-history.ts +119 -0
  33. package/src/resources/issues.ts +131 -0
  34. package/src/resources/pages.ts +264 -0
  35. package/src/resources/projects.ts +161 -0
  36. package/src/resources/releases.ts +114 -0
  37. package/src/resources/teams.ts +140 -0
  38. package/src/sandbox.ts +35 -0
  39. package/src/schemas/comments.ts +52 -0
  40. package/src/schemas/customers.ts +96 -0
  41. package/src/schemas/documents.ts +40 -0
  42. package/src/schemas/initiatives.ts +155 -0
  43. package/src/schemas/issues.ts +262 -0
  44. package/src/schemas/projects.ts +210 -0
  45. package/src/schemas/releases.ts +132 -0
  46. package/src/schemas/shared.ts +68 -0
  47. package/src/schemas/teams.ts +177 -0
  48. package/src/start.ts +47 -0
  49. package/src/tables.ts +83 -0
  50. package/src/webhook/route.ts +50 -0
  51. package/src/webhook/signature.ts +28 -0
package/dist/main.mjs ADDED
@@ -0,0 +1,1305 @@
1
+ #!/usr/bin/env node
2
+ import { LinearConfigDef } from "./manifest.mjs";
3
+ import { A as InitiativeToProjectSchema, C as IssueHistorySchema, D as InitiativeLabelSchema, E as IssueSchema, F as CustomerStatusSchema, I as CustomerTierSchema, L as CommentSchema, M as DocumentSchema, N as CustomerNeedSchema, O as InitiativeRelationSchema, P as CustomerSchema, S as AttachmentSchema, T as IssueRelationSchema, _ as ProjectMilestoneSchema, a as CycleSchema, b as ProjectStatusSchema, c as TeamSchema, d as IssueToReleaseSchema, f as ReleaseNoteSchema, g as ProjectLabelSchema, h as ReleaseStageSchema, j as InitiativeUpdateSchema, k as InitiativeSchema, l as UserSchema, m as ReleaseSchema, o as ExternalUserSchema, p as ReleasePipelineSchema, r as layerConfig, s as TeamMembershipSchema, t as LinearConnector, u as WorkflowStateSchema, v as ProjectRelationSchema, w as IssueLabelSchema, x as ProjectUpdateSchema, y as ProjectSchema } from "./src-BbzySPR7.mjs";
4
+ import { ConnectorApp, Demo, Ingestor, RuntimeConfig, StateStore, Telemetry } from "@useairfoil/connector-kit";
5
+ import { Config, DateTime, Duration, Effect, Layer, Logger, Schema } from "effect";
6
+ import { FetchHttpClient } from "effect/http";
7
+ import { NodeRuntime, NodeServices } from "@effect/platform-node";
8
+ import { Command } from "effect/cli";
9
+ import { PgClient } from "@effect/sql-pg";
10
+ //#region package.json
11
+ var version = "0.0.3";
12
+ //#endregion
13
+ //#region src/tables.ts
14
+ const tableSchemas = {
15
+ issues: IssueSchema,
16
+ issue_history: IssueHistorySchema,
17
+ comments: CommentSchema,
18
+ issue_relations: IssueRelationSchema,
19
+ attachments: AttachmentSchema,
20
+ issue_labels: IssueLabelSchema,
21
+ workflow_states: WorkflowStateSchema,
22
+ teams: TeamSchema,
23
+ team_memberships: TeamMembershipSchema,
24
+ users: UserSchema,
25
+ external_users: ExternalUserSchema,
26
+ cycles: CycleSchema,
27
+ projects: ProjectSchema,
28
+ project_milestones: ProjectMilestoneSchema,
29
+ project_updates: ProjectUpdateSchema,
30
+ project_statuses: ProjectStatusSchema,
31
+ project_labels: ProjectLabelSchema,
32
+ project_relations: ProjectRelationSchema,
33
+ initiatives: InitiativeSchema,
34
+ initiative_updates: InitiativeUpdateSchema,
35
+ initiative_labels: InitiativeLabelSchema,
36
+ initiative_relations: InitiativeRelationSchema,
37
+ initiative_to_projects: InitiativeToProjectSchema,
38
+ documents: DocumentSchema,
39
+ customers: CustomerSchema,
40
+ customer_needs: CustomerNeedSchema,
41
+ customer_statuses: CustomerStatusSchema,
42
+ customer_tiers: CustomerTierSchema,
43
+ releases: ReleaseSchema,
44
+ release_notes: ReleaseNoteSchema,
45
+ release_pipelines: ReleasePipelineSchema,
46
+ release_stages: ReleaseStageSchema,
47
+ issue_to_releases: IssueToReleaseSchema
48
+ };
49
+ //#endregion
50
+ //#region src/create-table.ts
51
+ const createTableCommand = ConnectorApp.makeCreateTableCommand(tableSchemas);
52
+ const setupCommand = ConnectorApp.makeSetupCommand(tableSchemas).pipe(Command.provide(RuntimeConfig.layerHosted()));
53
+ //#endregion
54
+ //#region src/demo/shared.ts
55
+ const hour = Duration.toMillis(Duration.hours(1));
56
+ const day = Duration.toMillis(Duration.days(1));
57
+ const workspace = "https://linear.app/acme";
58
+ const uuid = (kind, index, part = 0) => `${kind.toString(16).padStart(8, "0")}-${part.toString(16).padStart(4, "0")}-4000-8000-${index.toString(16).padStart(12, "0")}`;
59
+ const dateOnly = (date) => DateTime.formatIsoDateUtc(DateTime.fromDateUnsafe(date));
60
+ const teams = [
61
+ {
62
+ key: "ENG",
63
+ name: "Engineering",
64
+ cycles: true,
65
+ triage: false
66
+ },
67
+ {
68
+ key: "DES",
69
+ name: "Design",
70
+ cycles: true,
71
+ triage: false
72
+ },
73
+ {
74
+ key: "PRD",
75
+ name: "Product",
76
+ cycles: false,
77
+ triage: false
78
+ },
79
+ {
80
+ key: "SUP",
81
+ name: "Support",
82
+ cycles: false,
83
+ triage: true
84
+ }
85
+ ];
86
+ const states = [
87
+ {
88
+ name: "Triage",
89
+ type: "triage",
90
+ color: "#FC7840"
91
+ },
92
+ {
93
+ name: "Backlog",
94
+ type: "backlog",
95
+ color: "#BEC2C8"
96
+ },
97
+ {
98
+ name: "Todo",
99
+ type: "unstarted",
100
+ color: "#E2E2E2"
101
+ },
102
+ {
103
+ name: "In Progress",
104
+ type: "started",
105
+ color: "#F2C94C"
106
+ },
107
+ {
108
+ name: "In Review",
109
+ type: "started",
110
+ color: "#0F783C"
111
+ },
112
+ {
113
+ name: "Done",
114
+ type: "completed",
115
+ color: "#5E6AD2"
116
+ },
117
+ {
118
+ name: "Canceled",
119
+ type: "canceled",
120
+ color: "#95A2B3"
121
+ }
122
+ ];
123
+ const issueLabels = [
124
+ {
125
+ name: "Bug",
126
+ color: "#EB5757"
127
+ },
128
+ {
129
+ name: "Feature",
130
+ color: "#BB87FC"
131
+ },
132
+ {
133
+ name: "Improvement",
134
+ color: "#4EA7FC"
135
+ },
136
+ {
137
+ name: "Docs",
138
+ color: "#4CB782"
139
+ }
140
+ ];
141
+ const projectStatuses = [
142
+ {
143
+ name: "Backlog",
144
+ type: "backlog",
145
+ color: "#bec2c8"
146
+ },
147
+ {
148
+ name: "Planned",
149
+ type: "planned",
150
+ color: "#e2e2e2"
151
+ },
152
+ {
153
+ name: "In Progress",
154
+ type: "started",
155
+ color: "#f2c94c"
156
+ },
157
+ {
158
+ name: "Paused",
159
+ type: "paused",
160
+ color: "#95a2b3"
161
+ },
162
+ {
163
+ name: "Completed",
164
+ type: "completed",
165
+ color: "#5e6ad2"
166
+ },
167
+ {
168
+ name: "Canceled",
169
+ type: "canceled",
170
+ color: "#95a2b3"
171
+ }
172
+ ];
173
+ const projects = [
174
+ "Onboarding revamp",
175
+ "Billing v2",
176
+ "Mobile offline mode",
177
+ "Search relevance",
178
+ "SSO for enterprise",
179
+ "Design system 2.0",
180
+ "Usage analytics",
181
+ "API rate limits"
182
+ ];
183
+ const priorities = [
184
+ "No priority",
185
+ "Urgent",
186
+ "High",
187
+ "Medium",
188
+ "Low"
189
+ ];
190
+ const teamId = (t) => uuid(1, t);
191
+ const stateId = (t, s) => uuid(2, t, s);
192
+ const userId = (u) => uuid(3, u);
193
+ const labelId = (l) => uuid(4, l);
194
+ const projectId = (p) => uuid(5, p);
195
+ const milestoneId = (p, m) => uuid(6, p, m);
196
+ const cycleId = (t, n) => uuid(7, t, n);
197
+ const customerId = (c) => uuid(8, c);
198
+ const pipelineId = uuid(9, 0);
199
+ const releaseId = (m) => uuid(10, m);
200
+ const initiativeId = (i) => uuid(11, i);
201
+ const issueId = (index) => uuid(12, index);
202
+ const cycleStart = (now, n) => /* @__PURE__ */ new Date(now.getTime() - (26 - n) * 2 * 7 * day);
203
+ const stamp = (created, updated) => ({
204
+ version: updated,
205
+ created_at: created,
206
+ updated_at: updated,
207
+ archived_at: null
208
+ });
209
+ const nameFor = (faker) => {
210
+ const first = faker.person.firstName();
211
+ const last = faker.person.lastName();
212
+ return {
213
+ first,
214
+ last,
215
+ name: `${first} ${last}`
216
+ };
217
+ };
218
+ /** Date helpers for one run. `at` keeps a time from going past now. */
219
+ const clock = ({ faker, now }) => {
220
+ const at = (time) => new Date(Math.min(time, now.getTime()));
221
+ const later = (from, min, max) => at(from.getTime() + faker.number.int({
222
+ min,
223
+ max
224
+ }));
225
+ return {
226
+ at,
227
+ later
228
+ };
229
+ };
230
+ const verbs = [
231
+ "Fix",
232
+ "Add",
233
+ "Improve",
234
+ "Update",
235
+ "Remove",
236
+ "Support"
237
+ ];
238
+ //#endregion
239
+ //#region src/demo/issues.ts
240
+ /** One group is one issue, with its history, comments, and links. */
241
+ const issueRows = (index, context) => {
242
+ const { faker, now } = context;
243
+ const { at, later } = clock(context);
244
+ const rows = {
245
+ issues: [],
246
+ issue_history: [],
247
+ comments: [],
248
+ issue_relations: [],
249
+ attachments: [],
250
+ customer_needs: [],
251
+ issue_to_releases: []
252
+ };
253
+ const t = index % teams.length;
254
+ const team = teams[t] ?? teams[0];
255
+ const number = Math.floor(index / teams.length) + 1;
256
+ const identifier = `${team.key}-${number}`;
257
+ const id = issueId(index);
258
+ const title = `${faker.helpers.arrayElement(verbs)} ${faker.hacker.adjective()} ${faker.hacker.noun()}`;
259
+ const slug = title.toLowerCase().replaceAll(" ", "-");
260
+ const url = `${workspace}/issue/${identifier}/${slug}`;
261
+ const creator = faker.number.int({ max: 15 });
262
+ const assignee = faker.helpers.maybe(() => faker.number.int({ max: 15 }), { probability: .85 });
263
+ const created = at(now.getTime() - faker.number.int({
264
+ min: day,
265
+ max: 360 * day
266
+ }));
267
+ const outcome = faker.helpers.weightedArrayElement([
268
+ {
269
+ weight: 55,
270
+ value: "Done"
271
+ },
272
+ {
273
+ weight: 8,
274
+ value: "Canceled"
275
+ },
276
+ {
277
+ weight: 12,
278
+ value: "In Progress"
279
+ },
280
+ {
281
+ weight: 5,
282
+ value: "In Review"
283
+ },
284
+ {
285
+ weight: 10,
286
+ value: "Todo"
287
+ },
288
+ {
289
+ weight: 10,
290
+ value: "Backlog"
291
+ }
292
+ ]);
293
+ const started = outcome === "Done" || outcome === "In Progress" || outcome === "In Review" ? later(created, hour, 20 * day) : null;
294
+ const completed = outcome === "Done" && started ? later(started, hour, 14 * day) : null;
295
+ const canceled = outcome === "Canceled" ? later(created, day, 30 * day) : null;
296
+ const triaged = team.triage ? later(created, 6e4, day) : null;
297
+ const project = faker.helpers.maybe(() => faker.number.int({ max: projects.length - 1 }), { probability: .6 });
298
+ const cycleNumber = team.cycles && started ? Math.max(0, Math.min(26, 26 - Math.ceil((now.getTime() - started.getTime()) / (14 * day)))) : null;
299
+ const label = faker.number.int({ max: issueLabels.length - 1 });
300
+ const priority = faker.helpers.weightedArrayElement([
301
+ {
302
+ weight: 10,
303
+ value: 0
304
+ },
305
+ {
306
+ weight: 5,
307
+ value: 1
308
+ },
309
+ {
310
+ weight: 25,
311
+ value: 2
312
+ },
313
+ {
314
+ weight: 40,
315
+ value: 3
316
+ },
317
+ {
318
+ weight: 20,
319
+ value: 4
320
+ }
321
+ ]);
322
+ const estimate = team.key === "ENG" ? faker.helpers.arrayElement([
323
+ 1,
324
+ 2,
325
+ 3,
326
+ 5,
327
+ 8
328
+ ]) : null;
329
+ const stateIndex = states.findIndex((state) => state.name === outcome);
330
+ const changes = [{
331
+ at: created,
332
+ from: null,
333
+ to: team.triage ? 0 : 1
334
+ }];
335
+ if (triaged) changes.push({
336
+ at: triaged,
337
+ from: 0,
338
+ to: 1
339
+ });
340
+ if (started) changes.push({
341
+ at: started,
342
+ from: 1,
343
+ to: 3
344
+ });
345
+ if (outcome === "In Review" && started) changes.push({
346
+ at: later(started, day, 5 * day),
347
+ from: 3,
348
+ to: 4
349
+ });
350
+ if (completed) changes.push({
351
+ at: completed,
352
+ from: 3,
353
+ to: 5
354
+ });
355
+ if (canceled) changes.push({
356
+ at: canceled,
357
+ from: 1,
358
+ to: 6
359
+ });
360
+ if (outcome === "Todo") changes.push({
361
+ at: later(created, 6e4, 3 * day),
362
+ from: 1,
363
+ to: 2
364
+ });
365
+ changes.forEach((change, h) => {
366
+ rows.issue_history.push({
367
+ id: uuid(30, index, h),
368
+ ...stamp(change.at, change.at),
369
+ issue_id: id,
370
+ actor_id: userId(h === 0 ? creator : assignee ?? creator),
371
+ from_state_id: change.from === null ? null : stateId(t, change.from),
372
+ to_state_id: stateId(t, change.to),
373
+ from_assignee_id: null,
374
+ to_assignee_id: h === 0 && assignee !== void 0 ? userId(assignee) : null,
375
+ from_cycle_id: null,
376
+ to_cycle_id: change.to === 3 && cycleNumber !== null ? cycleId(t, cycleNumber) : null,
377
+ from_project_id: null,
378
+ to_project_id: h === 0 && project !== void 0 ? projectId(project) : null,
379
+ from_parent_id: null,
380
+ to_parent_id: null,
381
+ from_team_id: null,
382
+ to_team_id: null,
383
+ from_priority: null,
384
+ to_priority: h === 0 ? priority : null,
385
+ from_estimate: null,
386
+ to_estimate: h === 0 ? estimate : null,
387
+ from_due_date: null,
388
+ to_due_date: null,
389
+ from_title: null,
390
+ to_title: null,
391
+ added_label_ids: h === 0 ? [labelId(label)] : null,
392
+ removed_label_ids: null,
393
+ attachment_id: null,
394
+ customer_need_id: null,
395
+ to_converted_project_id: null,
396
+ updated_description: null,
397
+ archived: null,
398
+ trashed: null,
399
+ auto_archived: null,
400
+ auto_closed: null
401
+ });
402
+ });
403
+ const comments = Array.from({ length: faker.number.int({ max: 3 }) }, (_, c) => {
404
+ const posted = later(created, 6e4, 10 * day);
405
+ return {
406
+ id: uuid(31, index, c),
407
+ ...stamp(posted, posted),
408
+ _deleted: false,
409
+ body: faker.helpers.arrayElement([
410
+ "I can reproduce this on staging.",
411
+ "Picking this up now.",
412
+ "Added a fix behind a feature flag.",
413
+ "Can we pair on this tomorrow?",
414
+ "Customer confirmed it works now."
415
+ ]),
416
+ user_id: userId(faker.number.int({ max: 15 })),
417
+ external_user_id: null,
418
+ issue_id: id,
419
+ project_id: null,
420
+ project_update_id: null,
421
+ initiative_id: null,
422
+ initiative_update_id: null,
423
+ document_content_id: null,
424
+ parent_id: null,
425
+ quoted_text: null,
426
+ edited_at: null,
427
+ resolved_at: null,
428
+ resolving_user_id: null,
429
+ url: `${url}#comment-${uuid(31, index, c).slice(-8)}`
430
+ };
431
+ });
432
+ rows.comments.push(...comments);
433
+ if (index >= teams.length && faker.datatype.boolean({ probability: .1 })) rows.issue_relations.push({
434
+ id: uuid(32, index),
435
+ ...stamp(created, created),
436
+ issue_id: id,
437
+ related_issue_id: issueId(index - teams.length),
438
+ type: faker.helpers.arrayElement([
439
+ "blocks",
440
+ "related",
441
+ "duplicate"
442
+ ])
443
+ });
444
+ if (team.key === "ENG" && started) {
445
+ const prNumber = 1e3 + index;
446
+ rows.attachments.push({
447
+ id: uuid(33, index),
448
+ ...stamp(started, completed ?? started),
449
+ _deleted: false,
450
+ issue_id: id,
451
+ creator_id: assignee === void 0 ? null : userId(assignee),
452
+ external_user_creator_id: null,
453
+ title: `${title} #${prNumber}`,
454
+ subtitle: completed ? "Merged" : "Open",
455
+ url: `https://github.com/acme-labs/web/pull/${prNumber}`,
456
+ source_type: "github"
457
+ });
458
+ }
459
+ if (faker.datatype.boolean({ probability: .15 })) {
460
+ const asked = later(created, 0, 5 * day);
461
+ rows.customer_needs.push({
462
+ id: uuid(34, index),
463
+ ...stamp(asked, asked),
464
+ _deleted: false,
465
+ customer_id: customerId(faker.number.int({ max: 11 })),
466
+ issue_id: id,
467
+ project_id: null,
468
+ original_issue_id: id,
469
+ comment_id: null,
470
+ attachment_id: null,
471
+ creator_id: userId(creator),
472
+ body: "Their team asked for this on the last call.",
473
+ priority: faker.helpers.arrayElement([
474
+ 0,
475
+ 0,
476
+ 1
477
+ ]),
478
+ url: null
479
+ });
480
+ }
481
+ if (team.key === "ENG" && completed) {
482
+ const month = Math.floor((now.getTime() - completed.getTime()) / (30 * day));
483
+ if (month < 12) rows.issue_to_releases.push({
484
+ id: uuid(35, index),
485
+ ...stamp(completed, completed),
486
+ issue_id: id,
487
+ release_id: releaseId(month)
488
+ });
489
+ }
490
+ const updated = new Date(Math.max(...changes.map((change) => change.at.getTime()), ...comments.map((row) => row.created_at.getTime())));
491
+ rows.issues.push({
492
+ id,
493
+ ...stamp(created, updated),
494
+ _deleted: false,
495
+ identifier,
496
+ number,
497
+ title,
498
+ description: `${faker.hacker.phrase()}\n\n**Steps**\n\n1. Open the page\n2. Try the action\n3. See the error`,
499
+ url,
500
+ branch_name: `${identifier.toLowerCase()}-${slug}`,
501
+ priority,
502
+ priority_label: priorities[priority] ?? "No priority",
503
+ estimate,
504
+ due_date: priority === 1 ? dateOnly(new Date(created.getTime() + 7 * day)) : null,
505
+ creator_id: userId(creator),
506
+ assignee_id: assignee === void 0 ? null : userId(assignee),
507
+ delegate_id: null,
508
+ snoozed_by_id: null,
509
+ state_id: stateId(t, stateIndex),
510
+ team_id: teamId(t),
511
+ project_id: project === void 0 ? null : projectId(project),
512
+ project_milestone_id: project === void 0 ? null : milestoneId(project, faker.number.int({ max: 2 })),
513
+ cycle_id: cycleNumber === null ? null : cycleId(t, cycleNumber),
514
+ parent_id: null,
515
+ source_comment_id: null,
516
+ external_user_creator_id: null,
517
+ label_ids: [labelId(label)],
518
+ previous_identifiers: [],
519
+ started_at: started,
520
+ completed_at: completed,
521
+ canceled_at: canceled,
522
+ started_triage_at: team.triage ? created : null,
523
+ triaged_at: triaged,
524
+ auto_closed_at: null,
525
+ auto_archived_at: null,
526
+ added_to_cycle_at: cycleNumber === null ? null : started,
527
+ added_to_project_at: project === void 0 ? null : created,
528
+ added_to_team_at: created,
529
+ snoozed_until_at: null,
530
+ sla_type: null,
531
+ sla_started_at: null,
532
+ sla_breaches_at: null,
533
+ customer_ticket_count: BigInt(rows.customer_needs.length),
534
+ integration_source_type: null,
535
+ trashed: false
536
+ });
537
+ return rows;
538
+ };
539
+ //#endregion
540
+ //#region src/demo/initiatives.ts
541
+ /** Initiatives with their labels, updates, relations, and projects. */
542
+ const initiativeTables = ({ now }, founded) => {
543
+ const set = stamp(founded, founded);
544
+ const initiatives = [
545
+ "Enterprise readiness",
546
+ "Self-serve growth",
547
+ "Platform reliability"
548
+ ];
549
+ return {
550
+ initiatives: initiatives.map((name, i) => ({
551
+ id: initiativeId(i),
552
+ ...stamp(founded, now),
553
+ _deleted: false,
554
+ name,
555
+ description: `${name} for this year`,
556
+ content: null,
557
+ url: `${workspace}/initiative/${name.toLowerCase().replaceAll(" ", "-")}`,
558
+ icon: null,
559
+ color: null,
560
+ status: "Active",
561
+ health: "onTrack",
562
+ health_updated_at: /* @__PURE__ */ new Date(now.getTime() - 7 * day),
563
+ priority: BigInt(i + 1),
564
+ owner_id: userId(i),
565
+ creator_id: userId(0),
566
+ parent_initiative_id: null,
567
+ target_date: dateOnly(new Date(now.getTime() + 90 * day)),
568
+ started_at: founded,
569
+ completed_at: null,
570
+ canceled_at: null,
571
+ label_ids: [uuid(20, i % 2)],
572
+ visibility: "workspace",
573
+ trashed: false
574
+ })),
575
+ initiative_labels: ["Company goal", "Team goal"].map((name, l) => ({
576
+ id: uuid(20, l),
577
+ ...set,
578
+ name,
579
+ description: null,
580
+ color: "#5E6AD2",
581
+ is_group: false,
582
+ parent_id: null,
583
+ creator_id: userId(0),
584
+ retired_at: null
585
+ })),
586
+ initiative_updates: initiatives.flatMap((_, i) => Array.from({ length: 6 }, (_, k) => {
587
+ const posted = /* @__PURE__ */ new Date(now.getTime() - (6 - k) * 30 * day);
588
+ return {
589
+ id: uuid(21, i, k),
590
+ ...stamp(posted, posted),
591
+ _deleted: false,
592
+ initiative_id: initiativeId(i),
593
+ user_id: userId(i),
594
+ body: "Monthly check-in: projects are moving and the main risks are covered.",
595
+ health: "onTrack",
596
+ url: `${workspace}/initiative/${i}/updates#${k}`,
597
+ edited_at: null,
598
+ comment_count: 0n
599
+ };
600
+ })),
601
+ initiative_relations: [{
602
+ id: uuid(22, 0),
603
+ ...set,
604
+ initiative_id: initiativeId(0),
605
+ related_initiative_id: initiativeId(2),
606
+ sort_order: 0,
607
+ user_id: userId(0)
608
+ }],
609
+ initiative_to_projects: projects.map((_, p) => ({
610
+ id: uuid(23, p),
611
+ ...set,
612
+ initiative_id: initiativeId(p % initiatives.length),
613
+ project_id: projectId(p),
614
+ sort_order: String(p)
615
+ }))
616
+ };
617
+ };
618
+ //#endregion
619
+ //#region src/demo/projects.ts
620
+ /** Projects with their milestones, updates, specs, and relations. */
621
+ const projectTables = ({ faker, now }, founded) => {
622
+ const set = stamp(founded, founded);
623
+ const statusRows = projectStatuses.map((status, s) => ({
624
+ id: uuid(15, s),
625
+ ...set,
626
+ name: status.name,
627
+ type: status.type,
628
+ color: status.color,
629
+ description: null,
630
+ position: s
631
+ }));
632
+ const projectLabels = [
633
+ "Q1",
634
+ "Q2",
635
+ "Customer request",
636
+ "Tech debt"
637
+ ].map((name, l) => ({
638
+ id: uuid(16, l),
639
+ ...set,
640
+ _deleted: false,
641
+ name,
642
+ description: null,
643
+ color: faker.color.rgb({ casing: "upper" }),
644
+ is_group: false,
645
+ parent_id: null,
646
+ creator_id: userId(1),
647
+ retired_at: null
648
+ }));
649
+ const projectRows = [];
650
+ const milestones = [];
651
+ const updates = [];
652
+ const documents = [];
653
+ projects.forEach((name, p) => {
654
+ const started = /* @__PURE__ */ new Date(now.getTime() - (360 - p * 40) * day);
655
+ const target = new Date(started.getTime() + 120 * day);
656
+ const completed = target < now;
657
+ const status = completed ? 4 : p % 3 === 2 ? 1 : 2;
658
+ const lead = p * 3 % 16;
659
+ const health = completed ? null : faker.helpers.arrayElement([
660
+ "onTrack",
661
+ "onTrack",
662
+ "atRisk",
663
+ "offTrack"
664
+ ]);
665
+ const updated = completed ? target : now;
666
+ const slug = name.toLowerCase().replaceAll(" ", "-");
667
+ projectRows.push({
668
+ id: projectId(p),
669
+ ...stamp(started, updated),
670
+ _deleted: false,
671
+ name,
672
+ description: `${name} for the ${teams[p % teams.length]?.name ?? "Engineering"} team`,
673
+ content: `## Goal\n\nShip ${name.toLowerCase()} by ${dateOnly(target)}.`,
674
+ url: `${workspace}/project/${slug}-${p.toString(16).padStart(12, "0")}`,
675
+ icon: null,
676
+ color: faker.color.rgb({ casing: "upper" }),
677
+ status_id: uuid(15, status),
678
+ priority: BigInt(1 + p % 4),
679
+ priority_label: priorities[1 + p % 4] ?? "Medium",
680
+ health,
681
+ health_updated_at: health ? /* @__PURE__ */ new Date(now.getTime() - 3 * day) : null,
682
+ progress: completed ? 1 : faker.number.float({
683
+ min: .1,
684
+ max: .8,
685
+ fractionDigits: 2
686
+ }),
687
+ scope: faker.number.int({
688
+ min: 20,
689
+ max: 80
690
+ }),
691
+ lead_id: userId(lead),
692
+ creator_id: userId(lead),
693
+ converted_from_issue_id: null,
694
+ start_date: dateOnly(started),
695
+ target_date: dateOnly(target),
696
+ started_at: status === 1 ? null : started,
697
+ completed_at: completed ? target : null,
698
+ canceled_at: null,
699
+ auto_archived_at: null,
700
+ label_ids: [uuid(16, p % 4)],
701
+ team_ids: [teamId(p % teams.length)],
702
+ member_ids: [userId(lead), userId((lead + 1) % 16)],
703
+ trashed: false
704
+ });
705
+ [
706
+ "Alpha",
707
+ "Beta",
708
+ "GA"
709
+ ].forEach((stage, m) => {
710
+ const milestoneTarget = new Date(started.getTime() + (m + 1) * 40 * day);
711
+ milestones.push({
712
+ id: milestoneId(p, m),
713
+ ...stamp(started, started),
714
+ name: stage,
715
+ description: null,
716
+ project_id: projectId(p),
717
+ target_date: dateOnly(milestoneTarget),
718
+ status: milestoneTarget <= now ? "done" : m === 0 || milestoneTarget.getTime() - now.getTime() < 40 * day ? "next" : "unstarted",
719
+ progress: milestoneTarget <= now ? 1 : 0,
720
+ sort_order: m
721
+ });
722
+ });
723
+ for (let week = started.getTime() + 7 * day; week <= Math.min(updated.getTime(), now.getTime()); week += 7 * day) {
724
+ const posted = new Date(week);
725
+ updates.push({
726
+ id: uuid(17, p, updates.length),
727
+ ...stamp(posted, posted),
728
+ _deleted: false,
729
+ project_id: projectId(p),
730
+ user_id: userId(lead),
731
+ body: faker.helpers.arrayElement([
732
+ "Good week. The main flows are done and we're testing edge cases.",
733
+ "We hit a snag with the migration. It may slip a few days.",
734
+ "On track. Design review is done and we start the rollout next week."
735
+ ]),
736
+ health: faker.helpers.arrayElement([
737
+ "onTrack",
738
+ "onTrack",
739
+ "atRisk"
740
+ ]),
741
+ url: `${workspace}/project/${slug}/updates#${updates.length}`,
742
+ edited_at: null,
743
+ comment_count: 0n
744
+ });
745
+ }
746
+ documents.push({
747
+ id: uuid(18, p),
748
+ ...stamp(started, started),
749
+ _deleted: false,
750
+ title: `${name} spec`,
751
+ content: `# ${name}\n\n## Problem\n\nCustomers asked for this.\n\n## Plan\n\nShip it in three milestones.`,
752
+ url: `${workspace}/document/${slug}-spec-${p.toString(16).padStart(12, "0")}`,
753
+ icon: null,
754
+ color: null,
755
+ creator_id: userId(lead),
756
+ updated_by_id: userId(lead),
757
+ project_id: projectId(p),
758
+ initiative_id: null,
759
+ issue_id: null,
760
+ cycle_id: null,
761
+ team_id: null,
762
+ parent_document_id: null,
763
+ hidden_at: null,
764
+ trashed: false
765
+ });
766
+ });
767
+ return {
768
+ project_statuses: statusRows,
769
+ project_labels: projectLabels,
770
+ projects: projectRows,
771
+ project_milestones: milestones,
772
+ project_updates: updates,
773
+ project_relations: [{
774
+ id: uuid(19, 0),
775
+ ...set,
776
+ type: "dependency",
777
+ project_id: projectId(4),
778
+ project_milestone_id: null,
779
+ anchor_type: "start",
780
+ related_project_id: projectId(1),
781
+ related_project_milestone_id: null,
782
+ related_anchor_type: "end",
783
+ user_id: userId(0)
784
+ }, {
785
+ id: uuid(19, 1),
786
+ ...set,
787
+ type: "dependency",
788
+ project_id: projectId(6),
789
+ project_milestone_id: null,
790
+ anchor_type: "start",
791
+ related_project_id: projectId(3),
792
+ related_project_milestone_id: null,
793
+ related_anchor_type: "end",
794
+ user_id: userId(1)
795
+ }],
796
+ documents
797
+ };
798
+ };
799
+ //#endregion
800
+ //#region src/demo/teams.ts
801
+ /** Teams with their workflow states, users, labels, and cycles. */
802
+ const teamTables = ({ faker, now }, founded) => {
803
+ const set = stamp(founded, founded);
804
+ const teamRows = teams.map((team, t) => ({
805
+ id: teamId(t),
806
+ ...set,
807
+ name: team.name,
808
+ key: team.key,
809
+ display_name: team.name,
810
+ description: null,
811
+ visibility: "public",
812
+ parent_id: null,
813
+ timezone: "America/New_York",
814
+ cycles_enabled: team.cycles,
815
+ cycle_duration: 2,
816
+ cycle_cooldown_time: 0,
817
+ cycle_start_day: 1,
818
+ triage_enabled: team.triage,
819
+ issue_estimation_type: team.key === "ENG" ? "fibonacci" : "notUsed",
820
+ default_issue_estimate: team.key === "ENG" ? 1 : 0,
821
+ auto_archive_period: 6,
822
+ auto_close_period: 6,
823
+ retired_at: null
824
+ }));
825
+ const stateRows = teams.flatMap((team, t) => states.filter((state) => state.type !== "triage" || team.triage).map((state, s) => ({
826
+ id: stateId(t, states.indexOf(state)),
827
+ ...set,
828
+ name: state.name,
829
+ type: state.type,
830
+ color: state.color,
831
+ description: null,
832
+ position: s,
833
+ team_id: teamId(t)
834
+ })));
835
+ const users = Array.from({ length: 16 }, (_, u) => {
836
+ const person = nameFor(faker);
837
+ const joined = new Date(founded.getTime() + u * 20 * day);
838
+ return {
839
+ id: userId(u),
840
+ ...stamp(joined, joined),
841
+ _deleted: false,
842
+ name: person.name,
843
+ display_name: person.first.toLowerCase(),
844
+ email: faker.internet.exampleEmail({
845
+ firstName: person.first,
846
+ lastName: person.last
847
+ }).toLowerCase(),
848
+ avatar_url: null,
849
+ title: faker.person.jobTitle(),
850
+ timezone: faker.helpers.arrayElement([
851
+ "America/New_York",
852
+ "Europe/London",
853
+ "Europe/Berlin"
854
+ ]),
855
+ active: true,
856
+ admin: u < 2,
857
+ owner: u === 0,
858
+ guest: false,
859
+ app: false,
860
+ last_seen: new Date(now.getTime() - faker.number.int({
861
+ min: 6e4,
862
+ max: 3 * day
863
+ })),
864
+ url: `${workspace}/profiles/${person.first.toLowerCase()}`
865
+ };
866
+ });
867
+ return {
868
+ teams: teamRows,
869
+ workflow_states: stateRows,
870
+ users,
871
+ team_memberships: users.map((user, u) => ({
872
+ id: uuid(13, u),
873
+ ...stamp(user.created_at, user.created_at),
874
+ team_id: teamId(u % teams.length),
875
+ user_id: user.id,
876
+ owner: u < teams.length
877
+ })),
878
+ external_users: [
879
+ "Slack",
880
+ "Intercom",
881
+ "Zendesk"
882
+ ].map((source, e) => {
883
+ const person = nameFor(faker);
884
+ return {
885
+ id: uuid(14, e),
886
+ ...set,
887
+ name: person.name,
888
+ display_name: `${person.name} (${source})`,
889
+ email: faker.internet.exampleEmail({
890
+ firstName: person.first,
891
+ lastName: person.last
892
+ }).toLowerCase(),
893
+ avatar_url: null,
894
+ last_seen: new Date(now.getTime() - faker.number.int({
895
+ min: day,
896
+ max: 30 * day
897
+ }))
898
+ };
899
+ }),
900
+ issue_labels: issueLabels.map((label, l) => ({
901
+ id: labelId(l),
902
+ ...set,
903
+ _deleted: false,
904
+ name: label.name,
905
+ description: null,
906
+ color: label.color,
907
+ is_group: false,
908
+ parent_id: null,
909
+ team_id: null,
910
+ creator_id: userId(0),
911
+ retired_at: null
912
+ })),
913
+ cycles: teams.flatMap((team, t) => team.cycles ? Array.from({ length: 27 }, (_, n) => {
914
+ const starts = cycleStart(now, n);
915
+ const ends = new Date(starts.getTime() + 14 * day);
916
+ const done = ends <= now;
917
+ return {
918
+ id: cycleId(t, n),
919
+ ...stamp(starts, done ? ends : now),
920
+ _deleted: false,
921
+ number: n + 1,
922
+ name: null,
923
+ description: null,
924
+ team_id: teamId(t),
925
+ starts_at: starts,
926
+ ends_at: ends,
927
+ completed_at: done ? ends : null,
928
+ auto_archived_at: null,
929
+ progress: done ? 1 : .4
930
+ };
931
+ }) : [])
932
+ };
933
+ };
934
+ //#endregion
935
+ //#region src/demo/setup.ts
936
+ /** The workspace, written once before any issue. */
937
+ const setupRows = (context) => {
938
+ const { faker, now } = context;
939
+ const founded = /* @__PURE__ */ new Date(now.getTime() - 900 * day);
940
+ const set = stamp(founded, founded);
941
+ const teamSetup = teamTables(context, founded);
942
+ const projectSetup = projectTables(context, founded);
943
+ const initiativeSetup = initiativeTables(context, founded);
944
+ const customerStatuses = [
945
+ "Active",
946
+ "Trial",
947
+ "Churned"
948
+ ].map((name, s) => ({
949
+ id: uuid(24, s),
950
+ ...set,
951
+ name: name.toLowerCase(),
952
+ display_name: name,
953
+ description: null,
954
+ color: [
955
+ "#4CB782",
956
+ "#F2C94C",
957
+ "#95A2B3"
958
+ ][s] ?? "#95A2B3",
959
+ position: s
960
+ }));
961
+ const customerTiers = [
962
+ "Enterprise",
963
+ "Growth",
964
+ "Starter"
965
+ ].map((name, s) => ({
966
+ id: uuid(25, s),
967
+ ...set,
968
+ name: name.toLowerCase(),
969
+ display_name: name,
970
+ description: null,
971
+ color: [
972
+ "#5E6AD2",
973
+ "#4EA7FC",
974
+ "#BEC2C8"
975
+ ][s] ?? "#BEC2C8",
976
+ position: s
977
+ }));
978
+ const customers = Array.from({ length: 12 }, (_, c) => {
979
+ const name = faker.company.name();
980
+ const domain = `${name.toLowerCase().replaceAll(/[^a-z]+/g, "")}.example.com`;
981
+ const tier = c % 3;
982
+ return {
983
+ id: customerId(c),
984
+ ...stamp(founded, now),
985
+ _deleted: false,
986
+ name,
987
+ domains: [domain],
988
+ external_ids: [],
989
+ logo_url: null,
990
+ owner_id: userId(c % 16),
991
+ status_id: uuid(24, c === 11 ? 2 : c % 5 === 4 ? 1 : 0),
992
+ tier_id: uuid(25, tier),
993
+ revenue: BigInt([
994
+ 25e4,
995
+ 6e4,
996
+ 12e3
997
+ ][tier] ?? 12e3),
998
+ size: [
999
+ 2e3,
1000
+ 300,
1001
+ 40
1002
+ ][tier] ?? 40,
1003
+ approximate_need_count: 0,
1004
+ url: `${workspace}/customer/${name.toLowerCase().replaceAll(/[^a-z]+/g, "-")}`
1005
+ };
1006
+ });
1007
+ const pipeline = [{
1008
+ id: pipelineId,
1009
+ ...set,
1010
+ name: "Web app",
1011
+ type: "scheduled",
1012
+ is_production: true,
1013
+ url: `${workspace}/releases/web-app`,
1014
+ include_path_patterns: ["apps/web/**"],
1015
+ approximate_release_count: BigInt(12),
1016
+ trashed: false
1017
+ }];
1018
+ const stages = [
1019
+ "Planned",
1020
+ "In progress",
1021
+ "Released"
1022
+ ].map((name, s) => ({
1023
+ id: uuid(26, s),
1024
+ ...set,
1025
+ name,
1026
+ type: [
1027
+ "planned",
1028
+ "started",
1029
+ "completed"
1030
+ ][s] ?? "completed",
1031
+ color: [
1032
+ "#BEC2C8",
1033
+ "#F2C94C",
1034
+ "#5E6AD2"
1035
+ ][s] ?? "#5E6AD2",
1036
+ position: s,
1037
+ frozen: false,
1038
+ pipeline_id: pipelineId
1039
+ }));
1040
+ const releases = Array.from({ length: 12 }, (_, m) => {
1041
+ const released = /* @__PURE__ */ new Date(now.getTime() - m * 30 * day);
1042
+ const current = m === 0;
1043
+ return {
1044
+ id: releaseId(m),
1045
+ ...stamp(/* @__PURE__ */ new Date(released.getTime() - 30 * day), current ? now : released),
1046
+ name: `Release 2.${12 - m}.0`,
1047
+ description: null,
1048
+ release_version: `2.${12 - m}.0`,
1049
+ url: `${workspace}/releases/web-app/2.${12 - m}.0`,
1050
+ commit_sha: current ? null : faker.git.commitSha(),
1051
+ pipeline_id: pipelineId,
1052
+ stage_id: uuid(26, current ? 1 : 2),
1053
+ creator_id: userId(0),
1054
+ start_date: dateOnly(/* @__PURE__ */ new Date(released.getTime() - 30 * day)),
1055
+ target_date: dateOnly(released),
1056
+ started_at: /* @__PURE__ */ new Date(released.getTime() - 30 * day),
1057
+ completed_at: current ? null : released,
1058
+ canceled_at: null,
1059
+ trashed: false
1060
+ };
1061
+ });
1062
+ const releaseNotes = releases.filter((release) => release.completed_at !== null).map((release, k) => ({
1063
+ id: uuid(27, k),
1064
+ ...stamp(release.completed_at ?? now, release.completed_at ?? now),
1065
+ title: `What's new in ${release.release_version}`,
1066
+ content: "Faster search, clearer billing pages, and many small fixes.",
1067
+ url: `${release.url}/notes`,
1068
+ pipeline_id: pipelineId,
1069
+ release_ids: [release.id]
1070
+ }));
1071
+ return {
1072
+ ...teamSetup,
1073
+ ...projectSetup,
1074
+ ...initiativeSetup,
1075
+ customer_statuses: customerStatuses,
1076
+ customer_tiers: customerTiers,
1077
+ customers,
1078
+ release_pipelines: pipeline,
1079
+ release_stages: stages,
1080
+ releases,
1081
+ release_notes: releaseNotes
1082
+ };
1083
+ };
1084
+ //#endregion
1085
+ //#region src/demo/index.ts
1086
+ const demo = Demo.define({
1087
+ name: "producer-linear",
1088
+ setup: {
1089
+ tables: [
1090
+ Demo.table({
1091
+ name: "teams",
1092
+ rowSchema: TeamSchema,
1093
+ version: "version"
1094
+ }),
1095
+ Demo.table({
1096
+ name: "workflow_states",
1097
+ rowSchema: WorkflowStateSchema,
1098
+ version: "version"
1099
+ }),
1100
+ Demo.table({
1101
+ name: "users",
1102
+ rowSchema: UserSchema,
1103
+ version: "version"
1104
+ }),
1105
+ Demo.table({
1106
+ name: "team_memberships",
1107
+ rowSchema: TeamMembershipSchema,
1108
+ version: "version"
1109
+ }),
1110
+ Demo.table({
1111
+ name: "external_users",
1112
+ rowSchema: ExternalUserSchema,
1113
+ version: "version"
1114
+ }),
1115
+ Demo.table({
1116
+ name: "issue_labels",
1117
+ rowSchema: IssueLabelSchema,
1118
+ version: "version"
1119
+ }),
1120
+ Demo.table({
1121
+ name: "cycles",
1122
+ rowSchema: CycleSchema,
1123
+ version: "version"
1124
+ }),
1125
+ Demo.table({
1126
+ name: "project_statuses",
1127
+ rowSchema: ProjectStatusSchema,
1128
+ version: "version"
1129
+ }),
1130
+ Demo.table({
1131
+ name: "project_labels",
1132
+ rowSchema: ProjectLabelSchema,
1133
+ version: "version"
1134
+ }),
1135
+ Demo.table({
1136
+ name: "projects",
1137
+ rowSchema: ProjectSchema,
1138
+ version: "version"
1139
+ }),
1140
+ Demo.table({
1141
+ name: "project_milestones",
1142
+ rowSchema: ProjectMilestoneSchema,
1143
+ version: "version"
1144
+ }),
1145
+ Demo.table({
1146
+ name: "project_updates",
1147
+ rowSchema: ProjectUpdateSchema,
1148
+ version: "version"
1149
+ }),
1150
+ Demo.table({
1151
+ name: "project_relations",
1152
+ rowSchema: ProjectRelationSchema,
1153
+ version: "version"
1154
+ }),
1155
+ Demo.table({
1156
+ name: "documents",
1157
+ rowSchema: DocumentSchema,
1158
+ version: "version"
1159
+ }),
1160
+ Demo.table({
1161
+ name: "initiatives",
1162
+ rowSchema: InitiativeSchema,
1163
+ version: "version"
1164
+ }),
1165
+ Demo.table({
1166
+ name: "initiative_labels",
1167
+ rowSchema: InitiativeLabelSchema,
1168
+ version: "version"
1169
+ }),
1170
+ Demo.table({
1171
+ name: "initiative_updates",
1172
+ rowSchema: InitiativeUpdateSchema,
1173
+ version: "version"
1174
+ }),
1175
+ Demo.table({
1176
+ name: "initiative_relations",
1177
+ rowSchema: InitiativeRelationSchema,
1178
+ version: "version"
1179
+ }),
1180
+ Demo.table({
1181
+ name: "initiative_to_projects",
1182
+ rowSchema: InitiativeToProjectSchema,
1183
+ version: "version"
1184
+ }),
1185
+ Demo.table({
1186
+ name: "customer_statuses",
1187
+ rowSchema: CustomerStatusSchema,
1188
+ version: "version"
1189
+ }),
1190
+ Demo.table({
1191
+ name: "customer_tiers",
1192
+ rowSchema: CustomerTierSchema,
1193
+ version: "version"
1194
+ }),
1195
+ Demo.table({
1196
+ name: "customers",
1197
+ rowSchema: CustomerSchema,
1198
+ version: "version"
1199
+ }),
1200
+ Demo.table({
1201
+ name: "release_pipelines",
1202
+ rowSchema: ReleasePipelineSchema,
1203
+ version: "version"
1204
+ }),
1205
+ Demo.table({
1206
+ name: "release_stages",
1207
+ rowSchema: ReleaseStageSchema,
1208
+ version: "version"
1209
+ }),
1210
+ Demo.table({
1211
+ name: "releases",
1212
+ rowSchema: ReleaseSchema,
1213
+ version: "version"
1214
+ }),
1215
+ Demo.table({
1216
+ name: "release_notes",
1217
+ rowSchema: ReleaseNoteSchema,
1218
+ version: "version"
1219
+ })
1220
+ ],
1221
+ rows: setupRows
1222
+ },
1223
+ group: {
1224
+ tables: [
1225
+ Demo.table({
1226
+ name: "issues",
1227
+ rowSchema: IssueSchema,
1228
+ version: "version"
1229
+ }),
1230
+ Demo.table({
1231
+ name: "issue_history",
1232
+ rowSchema: IssueHistorySchema,
1233
+ version: "version"
1234
+ }),
1235
+ Demo.table({
1236
+ name: "comments",
1237
+ rowSchema: CommentSchema,
1238
+ version: "version"
1239
+ }),
1240
+ Demo.table({
1241
+ name: "issue_relations",
1242
+ rowSchema: IssueRelationSchema,
1243
+ version: "version"
1244
+ }),
1245
+ Demo.table({
1246
+ name: "attachments",
1247
+ rowSchema: AttachmentSchema,
1248
+ version: "version"
1249
+ }),
1250
+ Demo.table({
1251
+ name: "customer_needs",
1252
+ rowSchema: CustomerNeedSchema,
1253
+ version: "version"
1254
+ }),
1255
+ Demo.table({
1256
+ name: "issue_to_releases",
1257
+ rowSchema: IssueToReleaseSchema,
1258
+ version: "version"
1259
+ })
1260
+ ],
1261
+ rows: issueRows
1262
+ }
1263
+ });
1264
+ const demoCommand = ConnectorApp.makeDemoCommand(demo).pipe(Command.provide(RuntimeConfig.layerHosted()));
1265
+ //#endregion
1266
+ //#region src/sandbox.ts
1267
+ const ConnectorLayer$1 = layerConfig(LinearConfigDef.config);
1268
+ const TelemetryLayer$1 = Layer.mergeAll(Telemetry.layerOtlp(), Telemetry.layerMetricsConsoleDump());
1269
+ const sandboxCommand = Command.make("sandbox", {}, () => Effect.gen(function* () {
1270
+ const port = yield* RuntimeConfig.httpPort;
1271
+ const entrypoint = yield* LinearConnector;
1272
+ return yield* ConnectorApp.start(entrypoint, { port });
1273
+ }).pipe(Effect.annotateLogs({ component: "linear" }), Effect.provide(Layer.mergeAll(StateStore.layerMemory, Ingestor.layerConsole, ConnectorLayer$1, Logger.layer([Logger.consolePretty()]), TelemetryLayer$1)))).pipe(Command.withDescription("Run the connector locally and log ingested data"));
1274
+ //#endregion
1275
+ //#region src/start.ts
1276
+ const ConnectorLayer = layerConfig(LinearConfigDef.config);
1277
+ const TelemetryLayer = Telemetry.layerOtlp();
1278
+ const PostgresLayer = PgClient.layerConfig({
1279
+ url: Config.schema(Schema.Redacted(Schema.NonEmptyString), RuntimeConfig.PlatformRuntimeKey.postgresConnectionString),
1280
+ maxConnections: Config.succeed(2),
1281
+ connectTimeout: Config.succeed("5 seconds"),
1282
+ applicationName: Config.succeed("airfoil-producer-linear")
1283
+ });
1284
+ const StateStoreLayer = StateStore.layerSql().pipe(Layer.provide(PostgresLayer));
1285
+ const startCommand = Command.make("start", {}, () => Effect.gen(function* () {
1286
+ const port = yield* RuntimeConfig.httpPort;
1287
+ const entrypoint = yield* LinearConnector;
1288
+ return yield* ConnectorApp.start(entrypoint, { port }).pipe(Effect.provide(Ingestor.layerArrowFlightConfig(entrypoint)));
1289
+ }).pipe(Effect.annotateLogs({ component: "linear" }), Effect.provide(Layer.mergeAll(StateStoreLayer, ConnectorLayer, Logger.layer([Logger.consolePretty()]), TelemetryLayer)), Effect.provide(RuntimeConfig.layerHosted()))).pipe(Command.withDescription("Run the connector"));
1290
+ //#endregion
1291
+ //#region src/main.ts
1292
+ const BootstrapLayer = Layer.mergeAll(FetchHttpClient.layer, NodeServices.layer);
1293
+ const program = Command.make("producer-linear", {}, () => Effect.void).pipe(Command.withSubcommands([
1294
+ setupCommand,
1295
+ startCommand,
1296
+ sandboxCommand,
1297
+ createTableCommand,
1298
+ demoCommand
1299
+ ]));
1300
+ const cli = Command.run(program, { version });
1301
+ NodeRuntime.runMain(cli.pipe(Effect.provide(BootstrapLayer), Effect.scoped));
1302
+ //#endregion
1303
+ export {};
1304
+
1305
+ //# sourceMappingURL=main.mjs.map