@cat-factory/node-server 0.6.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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config.d.ts +3 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +297 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/container.d.ts +88 -0
  7. package/dist/container.d.ts.map +1 -0
  8. package/dist/container.js +937 -0
  9. package/dist/container.js.map +1 -0
  10. package/dist/db/client.d.ts +13 -0
  11. package/dist/db/client.d.ts.map +1 -0
  12. package/dist/db/client.js +21 -0
  13. package/dist/db/client.js.map +1 -0
  14. package/dist/db/migrate.d.ts +12 -0
  15. package/dist/db/migrate.d.ts.map +1 -0
  16. package/dist/db/migrate.js +40 -0
  17. package/dist/db/migrate.js.map +1 -0
  18. package/dist/db/schema.d.ts +7858 -0
  19. package/dist/db/schema.d.ts.map +1 -0
  20. package/dist/db/schema.js +928 -0
  21. package/dist/db/schema.js.map +1 -0
  22. package/dist/environments.d.ts +11 -0
  23. package/dist/environments.d.ts.map +1 -0
  24. package/dist/environments.js +31 -0
  25. package/dist/environments.js.map +1 -0
  26. package/dist/execution/bootstrapRunner.d.ts +27 -0
  27. package/dist/execution/bootstrapRunner.d.ts.map +1 -0
  28. package/dist/execution/bootstrapRunner.js +79 -0
  29. package/dist/execution/bootstrapRunner.js.map +1 -0
  30. package/dist/execution/config.d.ts +37 -0
  31. package/dist/execution/config.d.ts.map +1 -0
  32. package/dist/execution/config.js +86 -0
  33. package/dist/execution/config.js.map +1 -0
  34. package/dist/execution/drive.d.ts +6 -0
  35. package/dist/execution/drive.d.ts.map +1 -0
  36. package/dist/execution/drive.js +13 -0
  37. package/dist/execution/drive.js.map +1 -0
  38. package/dist/execution/pgBossRunner.d.ts +82 -0
  39. package/dist/execution/pgBossRunner.d.ts.map +1 -0
  40. package/dist/execution/pgBossRunner.js +163 -0
  41. package/dist/execution/pgBossRunner.js.map +1 -0
  42. package/dist/gateways.d.ts +4 -0
  43. package/dist/gateways.d.ts.map +1 -0
  44. package/dist/gateways.js +91 -0
  45. package/dist/gateways.js.map +1 -0
  46. package/dist/index.d.ts +13 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +22 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/main.d.ts +2 -0
  51. package/dist/main.d.ts.map +1 -0
  52. package/dist/main.js +9 -0
  53. package/dist/main.js.map +1 -0
  54. package/dist/modelProvider.d.ts +6 -0
  55. package/dist/modelProvider.d.ts.map +1 -0
  56. package/dist/modelProvider.js +72 -0
  57. package/dist/modelProvider.js.map +1 -0
  58. package/dist/realtime.d.ts +62 -0
  59. package/dist/realtime.d.ts.map +1 -0
  60. package/dist/realtime.js +171 -0
  61. package/dist/realtime.js.map +1 -0
  62. package/dist/recurring.d.ts +11 -0
  63. package/dist/recurring.d.ts.map +1 -0
  64. package/dist/recurring.js +33 -0
  65. package/dist/recurring.js.map +1 -0
  66. package/dist/repositories/bootstrap.d.ts +25 -0
  67. package/dist/repositories/bootstrap.d.ts.map +1 -0
  68. package/dist/repositories/bootstrap.js +280 -0
  69. package/dist/repositories/bootstrap.js.map +1 -0
  70. package/dist/repositories/containerExecution.d.ts +33 -0
  71. package/dist/repositories/containerExecution.d.ts.map +1 -0
  72. package/dist/repositories/containerExecution.js +199 -0
  73. package/dist/repositories/containerExecution.js.map +1 -0
  74. package/dist/repositories/documents.d.ts +31 -0
  75. package/dist/repositories/documents.d.ts.map +1 -0
  76. package/dist/repositories/documents.js +176 -0
  77. package/dist/repositories/documents.js.map +1 -0
  78. package/dist/repositories/drizzle.d.ts +105 -0
  79. package/dist/repositories/drizzle.d.ts.map +1 -0
  80. package/dist/repositories/drizzle.js +1872 -0
  81. package/dist/repositories/drizzle.js.map +1 -0
  82. package/dist/repositories/environments.d.ts +23 -0
  83. package/dist/repositories/environments.d.ts.map +1 -0
  84. package/dist/repositories/environments.js +162 -0
  85. package/dist/repositories/environments.js.map +1 -0
  86. package/dist/repositories/fragments.d.ts +23 -0
  87. package/dist/repositories/fragments.d.ts.map +1 -0
  88. package/dist/repositories/fragments.js +190 -0
  89. package/dist/repositories/fragments.js.map +1 -0
  90. package/dist/repositories/github.d.ts +53 -0
  91. package/dist/repositories/github.d.ts.map +1 -0
  92. package/dist/repositories/github.js +441 -0
  93. package/dist/repositories/github.js.map +1 -0
  94. package/dist/repositories/localModelEndpoint.d.ts +12 -0
  95. package/dist/repositories/localModelEndpoint.d.ts.map +1 -0
  96. package/dist/repositories/localModelEndpoint.js +75 -0
  97. package/dist/repositories/localModelEndpoint.js.map +1 -0
  98. package/dist/repositories/notifications.d.ts +11 -0
  99. package/dist/repositories/notifications.d.ts.map +1 -0
  100. package/dist/repositories/notifications.js +88 -0
  101. package/dist/repositories/notifications.js.map +1 -0
  102. package/dist/repositories/personalSubscription.d.ts +22 -0
  103. package/dist/repositories/personalSubscription.d.ts.map +1 -0
  104. package/dist/repositories/personalSubscription.js +159 -0
  105. package/dist/repositories/personalSubscription.js.map +1 -0
  106. package/dist/repositories/providerApiKey.d.ts +18 -0
  107. package/dist/repositories/providerApiKey.d.ts.map +1 -0
  108. package/dist/repositories/providerApiKey.js +111 -0
  109. package/dist/repositories/providerApiKey.js.map +1 -0
  110. package/dist/repositories/providerSubscription.d.ts +16 -0
  111. package/dist/repositories/providerSubscription.d.ts.map +1 -0
  112. package/dist/repositories/providerSubscription.js +88 -0
  113. package/dist/repositories/providerSubscription.js.map +1 -0
  114. package/dist/repositories/slack.d.ts +23 -0
  115. package/dist/repositories/slack.d.ts.map +1 -0
  116. package/dist/repositories/slack.js +150 -0
  117. package/dist/repositories/slack.js.map +1 -0
  118. package/dist/repositories/tasks.d.ts +24 -0
  119. package/dist/repositories/tasks.d.ts.map +1 -0
  120. package/dist/repositories/tasks.js +194 -0
  121. package/dist/repositories/tasks.js.map +1 -0
  122. package/dist/retention.d.ts +38 -0
  123. package/dist/retention.d.ts.map +1 -0
  124. package/dist/retention.js +53 -0
  125. package/dist/retention.js.map +1 -0
  126. package/dist/runtime.d.ts +10 -0
  127. package/dist/runtime.d.ts.map +1 -0
  128. package/dist/runtime.js +13 -0
  129. package/dist/runtime.js.map +1 -0
  130. package/dist/server.d.ts +41 -0
  131. package/dist/server.d.ts.map +1 -0
  132. package/dist/server.js +138 -0
  133. package/dist/server.js.map +1 -0
  134. package/dist/tasks/JiraProvider.d.ts +27 -0
  135. package/dist/tasks/JiraProvider.d.ts.map +1 -0
  136. package/dist/tasks/JiraProvider.js +79 -0
  137. package/dist/tasks/JiraProvider.js.map +1 -0
  138. package/drizzle/20260622175812_flashy_maginty/migration.sql +689 -0
  139. package/drizzle/20260622175812_flashy_maginty/snapshot.json +8318 -0
  140. package/drizzle/20260623172634_loud_wallop/migration.sql +11 -0
  141. package/drizzle/20260623172634_loud_wallop/snapshot.json +8439 -0
  142. package/drizzle/20260623174706_acoustic_zemo/migration.sql +16 -0
  143. package/drizzle/20260623174706_acoustic_zemo/snapshot.json +8506 -0
  144. package/drizzle/20260623184400_silent_cardiac/migration.sql +24 -0
  145. package/drizzle/20260623184400_silent_cardiac/snapshot.json +8639 -0
  146. package/drizzle/20260623205323_quick_arclight/migration.sql +1 -0
  147. package/drizzle/20260623205323_quick_arclight/snapshot.json +8963 -0
  148. package/drizzle/20260623221910_black_zombie/migration.sql +22 -0
  149. package/drizzle/20260623221910_black_zombie/snapshot.json +9189 -0
  150. package/drizzle/20260624131343_far_lily_hollister/migration.sql +3 -0
  151. package/drizzle/20260624131343_far_lily_hollister/snapshot.json +9228 -0
  152. package/drizzle/20260624135452_tiny_norman_osborn/migration.sql +11 -0
  153. package/drizzle/20260624135452_tiny_norman_osborn/snapshot.json +9126 -0
  154. package/drizzle/20260624140138_wandering_avengers/migration.sql +1 -0
  155. package/drizzle/20260624140138_wandering_avengers/snapshot.json +9045 -0
  156. package/package.json +62 -0
package/dist/server.js ADDED
@@ -0,0 +1,138 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { handleError, logger, mountAuthGate, registerCoreControllers, resolveCorsOrigin, } from '@cat-factory/server';
3
+ import { Hono } from 'hono';
4
+ import { cors } from 'hono/cors';
5
+ import { PgBoss } from 'pg-boss';
6
+ import { buildNodeContainer } from './container.js';
7
+ import { createDbClient } from './db/client.js';
8
+ import { migrate } from './db/migrate.js';
9
+ import { executionRuntime } from './execution/config.js';
10
+ import { startDecisionTimeoutWorker, startExecutionWorker, startStaleRunSweeper, } from './execution/pgBossRunner.js';
11
+ import { startBootstrapWorker } from './execution/bootstrapRunner.js';
12
+ import { startEnvironmentSweeper } from './environments.js';
13
+ import { startScheduleSweeper } from './recurring.js';
14
+ import { NodeRealtimeHub, attachRealtime } from './realtime.js';
15
+ import { createDrizzleRepositories } from './repositories/drizzle.js';
16
+ import { DrizzleSubscriptionActivationRepository } from './repositories/personalSubscription.js';
17
+ import { startRetentionSweeper } from './retention.js';
18
+ import { SystemClock } from './runtime.js';
19
+ /** Build the Hono app around a ready container (shared by `createServer` + `start`). */
20
+ export function createApp(container, env = process.env) {
21
+ const app = new Hono();
22
+ app.use('*', cors({ origin: (origin) => resolveCorsOrigin(origin, env.CORS_ALLOWED_ORIGINS) }));
23
+ app.use('*', async (c, next) => {
24
+ c.set('container', container);
25
+ await next();
26
+ });
27
+ app.get('/health', (c) => c.json({ status: 'ok' }));
28
+ // Default-deny session gate + per-workspace authz, shared verbatim with the Worker
29
+ // (one implementation in @cat-factory/server so the runtimes can't drift).
30
+ mountAuthGate(app);
31
+ registerCoreControllers(app);
32
+ app.onError(handleError);
33
+ return app;
34
+ }
35
+ /**
36
+ * Build the app from container options (convenience, e.g. embedding / tests).
37
+ *
38
+ * WARNING: unless a started `boss` is passed in `options`, the container wires the
39
+ * engine's NoopWorkRunner — a started execution then returns `running` but is never
40
+ * driven to completion. Use {@link start} for a fully-wired service (durable pg-boss
41
+ * worker + stale-run sweeper); pass `boss` here only if you drive runs yourself.
42
+ */
43
+ export function createServer(options) {
44
+ return createApp(buildNodeContainer(options), options.env);
45
+ }
46
+ /**
47
+ * Boot the Node HTTP server: connect to Postgres (`DATABASE_URL`), ensure the schema,
48
+ * start pg-boss + the durable execution worker + the stale-run sweeper, build the app,
49
+ * and listen. Registers SIGTERM/SIGINT handlers for a clean, ordered shutdown.
50
+ */
51
+ export async function start(options = {}) {
52
+ const env = options.env ?? process.env;
53
+ const databaseUrl = env.DATABASE_URL;
54
+ if (!databaseUrl) {
55
+ throw new Error('DATABASE_URL is required to start the Node server');
56
+ }
57
+ const { db, pool } = createDbClient(databaseUrl);
58
+ await migrate(db, pool);
59
+ const boss = new PgBoss(databaseUrl);
60
+ await boss.start();
61
+ // Build the repositories once and share them with both the container and the
62
+ // retention sweeper (so the sweeper prunes the very stores the app writes to).
63
+ const clock = new SystemClock();
64
+ const repos = createDrizzleRepositories(db, clock);
65
+ const buildContainer = options.buildContainer ?? buildNodeContainer;
66
+ // The per-workspace real-time subscriber registry. Created here (not in the container
67
+ // builder) because it must be shared between the engine's event publisher — wired
68
+ // inside the container — and the HTTP server's WebSocket upgrade listener attached
69
+ // below. The local facade's builder forwards this option to buildNodeContainer
70
+ // unchanged, so local mode gets live updates too.
71
+ const realtimeHub = new NodeRealtimeHub();
72
+ const container = buildContainer({ db, boss, env, repos, realtimeHub });
73
+ const runtime = executionRuntime(container.config, env);
74
+ // The decision-timeout worker creates its queue first so the advance worker's send to
75
+ // it (when a run parks on a decision) always has a target.
76
+ await startDecisionTimeoutWorker(boss, container, logger);
77
+ await startExecutionWorker(boss, container, runtime.drive, logger, {
78
+ concurrency: runtime.concurrency,
79
+ decisionTimeoutSeconds: runtime.decisionTimeoutSeconds,
80
+ });
81
+ // Durably drive bootstrap runs too (the Worker uses a per-run BootstrapWorkflow);
82
+ // a no-op queue when the bootstrap module isn't wired.
83
+ await startBootstrapWorker(boss, container, runtime.drive, logger, {
84
+ concurrency: runtime.concurrency,
85
+ });
86
+ const stopSweeper = startStaleRunSweeper(boss, container, runtime.sweeper, runtime.queue, logger);
87
+ // Bound the unbounded tables (`token_usage`, the heavy `llm_call_metrics`): the Worker
88
+ // prunes these from cron, Node has none, so a timer mirrors it. Without this the
89
+ // observability sink — full per-call prompt/response — grows forever on Postgres.
90
+ const stopRetention = startRetentionSweeper({
91
+ tokenUsageRepository: repos.tokenUsageRepository,
92
+ llmCallMetricRepository: repos.llmCallMetricRepository,
93
+ pipelineScheduleRepository: repos.pipelineScheduleRepository,
94
+ subscriptionActivationRepository: new DrizzleSubscriptionActivationRepository(db),
95
+ }, container.config.retention, clock, logger);
96
+ // Fire due recurring pipelines on a one-minute timer (the Worker uses cron).
97
+ const stopScheduleSweeper = startScheduleSweeper(container, clock, logger);
98
+ // Tear down expired ephemeral environments (the Worker uses cron); no-op unless the
99
+ // environments integration is wired.
100
+ const stopEnvironmentSweeper = startEnvironmentSweeper(container, clock, logger);
101
+ const app = createApp(container, env);
102
+ const port = Number(env.PORT ?? 8787);
103
+ const host = options.host ?? env.HOST?.trim() ?? undefined;
104
+ const server = serve({ fetch: app.fetch, port, ...(host ? { hostname: host } : {}) });
105
+ // Accept the SPA's WebSocket event-stream upgrades on the same listener and push the
106
+ // engine's events to subscribers (the Worker uses a per-workspace Durable Object;
107
+ // `@hono/node-server` doesn't upgrade on its own, so we attach a `ws` server here).
108
+ const stopRealtime = attachRealtime(server, realtimeHub, container.config.auth, logger);
109
+ logger.info({ port, host: host ?? '0.0.0.0' }, 'cat-factory node server listening');
110
+ // Ordered graceful shutdown: stop accepting connections, halt the sweeper + pg-boss
111
+ // worker, release the pool, then exit. Without closing the HTTP server the process
112
+ // would keep the event loop alive and hang until the orchestrator SIGKILLs it.
113
+ let shuttingDown = false;
114
+ const shutdown = async (signal) => {
115
+ if (shuttingDown)
116
+ return;
117
+ shuttingDown = true;
118
+ logger.info({ signal }, 'shutting down cat-factory node server');
119
+ stopSweeper();
120
+ stopRetention();
121
+ stopScheduleSweeper();
122
+ stopEnvironmentSweeper();
123
+ stopRealtime();
124
+ await new Promise((resolve) => server.close(() => resolve()));
125
+ try {
126
+ await boss.stop();
127
+ await pool.end();
128
+ }
129
+ catch (err) {
130
+ logger.error({ err: err instanceof Error ? err.message : String(err) }, 'shutdown error');
131
+ }
132
+ process.exit(0);
133
+ };
134
+ process.once('SIGTERM', () => void shutdown('SIGTERM'));
135
+ process.once('SIGINT', () => void shutdown('SIGINT'));
136
+ return server;
137
+ }
138
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type TaskContent, type TaskCredentials, type TaskSourceProvider, type NormalizedTaskConnection } from '@cat-factory/kernel';
2
+ export declare class JiraApiError extends Error {
3
+ readonly status: number;
4
+ constructor(status: number, message: string);
5
+ }
6
+ export declare class JiraProvider implements TaskSourceProvider {
7
+ readonly kind: 'jira';
8
+ readonly descriptor: {
9
+ source: "github" | "jira";
10
+ label: string;
11
+ icon: string;
12
+ credentialFields: {
13
+ key: string;
14
+ label: string;
15
+ help?: string | undefined;
16
+ placeholder?: string | undefined;
17
+ secret?: boolean | undefined;
18
+ }[];
19
+ refLabel: string;
20
+ refPlaceholder: string;
21
+ searchable?: boolean | undefined;
22
+ };
23
+ normalizeConnection(input: TaskCredentials): NormalizedTaskConnection;
24
+ parseRef(input: string): string | null;
25
+ fetchTask(credentials: TaskCredentials, externalId: string): Promise<TaskContent>;
26
+ }
27
+ //# sourceMappingURL=JiraProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraProvider.d.ts","sourceRoot":"","sources":["../../src/tasks/JiraProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC9B,MAAM,qBAAqB,CAAA;AAY5B,qBAAa,YAAa,SAAQ,KAAK;IAEnC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAIhB;CACF;AAsBD,qBAAa,YAAa,YAAW,kBAAkB;IACrD,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAS;IAC/B,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;MAAkB;IAErC,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,wBAAwB,CAapE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,SAAS,CAAC,WAAW,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA4CtF;CACF"}
@@ -0,0 +1,79 @@
1
+ import { ValidationError, atlassianLogic, } from '@cat-factory/kernel';
2
+ import { JIRA_DESCRIPTOR, jiraLogic } from '@cat-factory/integrations';
3
+ // JiraProvider for the Node facade — a faithful copy of the Cloudflare facade's
4
+ // provider (`runtimes/cloudflare/src/infrastructure/tasks/JiraProvider.ts`). Both
5
+ // are thin `fetch` shells around the shared Jira *pure* logic in
6
+ // `@cat-factory/integrations` (ref parsing, ADF→Markdown); only the HTTP shell is
7
+ // runtime-bound. Node exposes the same global `fetch` + `btoa`, so the two stay
8
+ // behaviourally identical (see CLAUDE.md "Keep the runtimes symmetric").
9
+ const USER_AGENT = 'cat-factory';
10
+ export class JiraApiError extends Error {
11
+ status;
12
+ constructor(status, message) {
13
+ super(message);
14
+ this.status = status;
15
+ this.name = 'JiraApiError';
16
+ }
17
+ }
18
+ export class JiraProvider {
19
+ kind = 'jira';
20
+ descriptor = JIRA_DESCRIPTOR;
21
+ normalizeConnection(input) {
22
+ const baseUrlRaw = input.baseUrl?.trim();
23
+ const accountEmail = input.accountEmail?.trim();
24
+ const apiToken = input.apiToken?.trim();
25
+ if (!baseUrlRaw || !accountEmail || !apiToken) {
26
+ throw new ValidationError('Jira requires a site URL, account email and API token');
27
+ }
28
+ const baseUrl = atlassianLogic.normalizeAtlassianBaseUrl(baseUrlRaw);
29
+ atlassianLogic.assertSafeAtlassianBaseUrl(baseUrl);
30
+ return {
31
+ credentials: { baseUrl, accountEmail, apiToken },
32
+ label: baseUrl,
33
+ };
34
+ }
35
+ parseRef(input) {
36
+ return jiraLogic.parseJiraRef(input);
37
+ }
38
+ async fetchTask(credentials, externalId) {
39
+ const base = credentials.baseUrl.replace(/\/+$/, '');
40
+ const fields = 'summary,description,status,issuetype,assignee,priority,labels,comment';
41
+ const url = `${base}/rest/api/3/issue/${encodeURIComponent(externalId)}?fields=${fields}`;
42
+ const auth = btoa(`${credentials.accountEmail}:${credentials.apiToken}`);
43
+ const res = await fetch(url, {
44
+ method: 'GET',
45
+ headers: {
46
+ authorization: `Basic ${auth}`,
47
+ accept: 'application/json',
48
+ 'user-agent': USER_AGENT,
49
+ },
50
+ });
51
+ if (!res.ok) {
52
+ const text = await res.text().catch(() => '');
53
+ throw new JiraApiError(res.status, `Jira GET ${url} → ${res.status}: ${text.slice(0, 300)}`);
54
+ }
55
+ const json = (await res.json().catch(() => null));
56
+ if (!json || !json.key || !json.fields) {
57
+ throw new JiraApiError(502, `Jira returned an unexpected body for issue ${externalId}`);
58
+ }
59
+ const f = json.fields;
60
+ const comments = (f.comment?.comments ?? []).map((c) => ({
61
+ author: c.author?.displayName ?? '',
62
+ createdAt: c.created ?? '',
63
+ body: jiraLogic.adfToMarkdown(c.body),
64
+ }));
65
+ return {
66
+ externalId: json.key,
67
+ url: `${base}/browse/${json.key}`,
68
+ title: f.summary ?? '(untitled)',
69
+ status: f.status?.name ?? '',
70
+ type: f.issuetype?.name ?? '',
71
+ assignee: f.assignee?.displayName ?? null,
72
+ priority: f.priority?.name ?? null,
73
+ labels: Array.isArray(f.labels) ? f.labels : [],
74
+ description: jiraLogic.adfToMarkdown(f.description),
75
+ comments,
76
+ };
77
+ }
78
+ }
79
+ //# sourceMappingURL=JiraProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JiraProvider.js","sourceRoot":"","sources":["../../src/tasks/JiraProvider.ts"],"names":[],"mappings":"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"}