@forumone/throughline-integrations 0.7.0 → 0.8.1

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.
@@ -1,4 +1,9 @@
1
1
  import { DEFAULT_INTEGRATIONS_SLUG } from './options.js';
2
+ /**
3
+ * Where Payload resolves the admin controls from. A package specifier, not a
4
+ * path, so the host's import map picks it up without any host-side file.
5
+ */
6
+ const CLIENT_ENTRY = '@forumone/throughline-integrations/client';
2
7
  const adminOrEditor = ({ req }) => {
3
8
  const roles = req.user?.['roles'] ?? [];
4
9
  return roles.includes('admin') || roles.includes('editor');
@@ -7,13 +12,27 @@ const adminOnly = ({ req }) => {
7
12
  const roles = req.user?.['roles'] ?? [];
8
13
  return roles.includes('admin');
9
14
  };
15
+ /**
16
+ * The same rule, at the field. `FieldAccess` is a different signature from
17
+ * `Access` — it may only answer a boolean, never a `where` query — so it cannot
18
+ * be the same function.
19
+ */
20
+ const adminOnlyField = ({ req }) => {
21
+ const roles = req.user?.['roles'] ?? [];
22
+ return roles.includes('admin');
23
+ };
10
24
  /**
11
25
  * Collection that persists per-instance integration configuration. Configuration
12
26
  * is admin-only by design: prompt injection that gave Claude write access here
13
27
  * would let an attacker re-target webhook URLs or rotate signing secrets.
14
28
  *
15
29
  * Editors can read instance status (used by the listing/status MCP tools);
16
- * write operations are reserved for admins editing in the Payload UI.
30
+ * write operations are reserved for admins editing in the Payload UI. *Status*
31
+ * is the operative word: `config` carries its own admin-only field access, so
32
+ * an editor's read returns the row without the credentials in it.
33
+ *
34
+ * The one control on the document that is not a field is the sidebar's Sync
35
+ * now button, which POSTs to the `:id/sync` endpoint passed in `endpoints`.
17
36
  */
18
37
  export function createIntegrationsCollection(options) {
19
38
  const slug = options.slug ?? DEFAULT_INTEGRATIONS_SLUG;
@@ -58,8 +77,60 @@ export function createIntegrationsCollection(options) {
58
77
  {
59
78
  name: 'config',
60
79
  type: 'json',
80
+ /*
81
+ Admin-only at the field, because this is where the credentials are.
82
+
83
+ Document read is admin *or* editor, and deliberately so — the reason an
84
+ editor opens this collection is to see whether last night's sync ran.
85
+ But a document read hands over the whole document, and `config` is one
86
+ JSON column holding whatever an integration needs to authenticate: a
87
+ HubSpot private app token, a signing secret, a webhook URL. The
88
+ docblock above has always said editors read instance *status*; without
89
+ this, that was a description of the intent rather than of the code.
90
+
91
+ Nothing that needs the value loses it. Every reader of `config` goes
92
+ through the Local API — `loadInstances` here, and the host's sync and
93
+ form endpoints — which overrides access. The MCP tools project a fixed
94
+ field list that never included `config`. What changes is `GET /api/<slug>`
95
+ and the admin screen for a non-admin, which now show status and no
96
+ secrets.
97
+
98
+ `create` and `update` as well, so the credential cannot be replaced by
99
+ somebody who could not read it. Redundant today, since the collection's
100
+ own create and update are already admin-only, and cheap insurance
101
+ against the day document write is widened for status edits.
102
+ */
103
+ access: {
104
+ read: adminOnlyField,
105
+ create: adminOnlyField,
106
+ update: adminOnlyField,
107
+ },
108
+ admin: {
109
+ description: 'Integration-specific configuration. The integration\'s configFields drive the admin UI; this JSON store carries the validated payload. Admin-only: it holds the credentials.',
110
+ },
111
+ },
112
+ {
113
+ /*
114
+ The only admin component this plugin ships. In the sidebar rather than
115
+ `beforeDocumentControls` because it belongs with the three fields it
116
+ moves — an operator watching for a sync to land is already reading
117
+ `lastSyncAt` — and because `beforeDocumentControls` also renders on the
118
+ create view, where there is no instance to sync.
119
+
120
+ A `ui` field: no column, no value, nothing to save.
121
+ */
122
+ name: 'triggerSync',
123
+ type: 'ui',
124
+ label: 'Manual sync',
61
125
  admin: {
62
- description: 'Integration-specific configuration. The integration\'s configFields drive the admin UI; this JSON store carries the validated payload.',
126
+ position: 'sidebar',
127
+ components: {
128
+ Field: {
129
+ path: CLIENT_ENTRY,
130
+ exportName: 'SyncButton',
131
+ clientProps: { collectionSlug: slug },
132
+ },
133
+ },
63
134
  },
64
135
  },
65
136
  {
@@ -85,6 +156,7 @@ export function createIntegrationsCollection(options) {
85
156
  admin: { readOnly: true },
86
157
  },
87
158
  ],
159
+ endpoints: options.endpoints ?? [],
88
160
  indexes: [
89
161
  { fields: ['integrationType', 'enabled'] },
90
162
  { fields: ['lastSyncStatus'] },
@@ -1 +1 @@
1
- {"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collection.js","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAExD;;;GAGG;AACH,MAAM,YAAY,GAAG,2CAA2C,CAAA;AAShE,MAAM,aAAa,GAAW,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IACxC,MAAM,KAAK,GAAI,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAA0B,IAAI,EAAE,CAAA;IACjE,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC5D,CAAC,CAAA;AAED,MAAM,SAAS,GAAW,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IACpC,MAAM,KAAK,GAAI,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAA0B,IAAI,EAAE,CAAA;IACjE,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,cAAc,GAAgB,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;IAC9C,MAAM,KAAK,GAAI,GAAG,CAAC,IAAI,EAAE,CAAC,OAAO,CAA0B,IAAI,EAAE,CAAA;IACjE,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AAChC,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,4BAA4B,CAC1C,OAA4C;IAE5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,yBAAyB,CAAA;IACtD,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAA;IAE5B,OAAO;QACL,IAAI;QACJ,KAAK,EAAE;YACL,UAAU,EAAE,MAAM;YAClB,cAAc,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,CAAC;YACtF,WAAW,EACT,4GAA4G;SAC/G;QACD,MAAM,EAAE;YACN,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,SAAS;SAClB;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,EAAE,WAAW,EAAE,iEAAiE,EAAE;aAC1F;YACD;gBACE,IAAI,EAAE,iBAAiB;gBACvB,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,QAAQ;qBACd,IAAI,EAAE;qBACN,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC7E,KAAK,EAAE,EAAE,WAAW,EAAE,4CAA4C,EAAE;aACrE;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,UAAU;gBAChB,YAAY,EAAE,KAAK;gBACnB,KAAK,EAAE;oBACL,WAAW,EACT,qHAAqH;iBACxH;aACF;YACD;gBACE,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,MAAM;gBACZ;;;;;;;;;;;;;;;;;;;;;;kBAsBE;gBACF,MAAM,EAAE;oBACN,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,cAAc;oBACtB,MAAM,EAAE,cAAc;iBACvB;gBACD,KAAK,EAAE;oBACL,WAAW,EACT,8KAA8K;iBACjL;aACF;YACD;gBACE;;;;;;;;kBAQE;gBACF,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,IAAI;gBACV,KAAK,EAAE,aAAa;gBACpB,KAAK,EAAE;oBACL,QAAQ,EAAE,SAAS;oBACnB,UAAU,EAAE;wBACV,KAAK,EAAE;4BACL,IAAI,EAAE,YAAY;4BAClB,UAAU,EAAE,YAAY;4BACxB,WAAW,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE;yBACtC;qBACF;iBACF;aACF;YACD;gBACE,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE;aAC/C;YACD;gBACE,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE;gBAC9C,OAAO,EAAE;oBACP,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;oBAC1C,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;oBACtC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;oBACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;iBACrC;gBACD,YAAY,EAAE,WAAW;aAC1B;YACD;gBACE,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;aAC1B;SACF;QACD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;QAClC,OAAO,EAAE;YACP,EAAE,MAAM,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,EAAE;YAC1C,EAAE,MAAM,EAAE,CAAC,gBAAgB,CAAC,EAAE;SAC/B;QACD,KAAK,EAAE;YACL,YAAY,EAAE;gBACZ,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;oBAC5B,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,QAAQ;wBAAE,OAAO,IAAI,CAAA;oBACjE,MAAM,QAAQ,GAAG,IAA+B,CAAA;oBAChD,MAAM,eAAe,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAA;oBACnD,IAAI,OAAO,eAAe,KAAK,QAAQ;wBAAE,OAAO,IAAI,CAAA;oBAEpD,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;oBACjD,IAAI,CAAC,WAAW,EAAE,CAAC;wBACjB,MAAM,IAAI,KAAK,CACb,6BAA6B,eAAe,mBAAmB,QAAQ;6BACpE,IAAI,EAAE;6BACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;6BAChB,IAAI,CAAC,IAAI,CAAC,IAAI,mBAAmB,GAAG,CACxC,CAAA;oBACH,CAAC;oBAED,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAA4B,CAAA;oBACpE,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;oBAC3D,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC;wBACnB,MAAM,IAAI,KAAK,CACb,sBAAsB,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC,MAAM,IAAI,iBAAiB,EAAE,CACpF,CAAA;oBACH,CAAC;oBACD,OAAO,IAAI,CAAA;gBACb,CAAC;aACF;SACF;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { Endpoint } from 'payload';
2
+ import type { Inngest } from 'inngest';
3
+ export interface CreateSyncEndpointDeps {
4
+ collectionSlug: string;
5
+ inngest: Inngest;
6
+ }
7
+ /** Default recorded on the event when the caller supplies no reason of its own. */
8
+ export declare const ADMIN_TRIGGER_REASON = "Triggered from the admin.";
9
+ /**
10
+ * `POST /api/<integrations>/:id/sync` — the admin's path to the same event
11
+ * `trigger_sync` fires.
12
+ *
13
+ * Authenticates off the Payload session cookie, so the person clicking the
14
+ * button needs no API key and the event records them rather than a service
15
+ * principal. The rules are `requestManualSync`'s, not this file's; all that
16
+ * lives here is the admin check and the mapping from a refusal to a status
17
+ * code.
18
+ *
19
+ * Admin-only, matching the MCP tool and the collection's own write access:
20
+ * triggering an integration makes it POST to an external system.
21
+ */
22
+ export declare function createSyncEndpoint(deps: CreateSyncEndpointDeps): Endpoint;
23
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/endpoints/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,SAAS,CAAA;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAGtC,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,8BAA8B,CAAA;AAY/D;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,QAAQ,CAiEzE"}
@@ -0,0 +1,85 @@
1
+ import { requestManualSync } from '../sync/manual-sync.js';
2
+ /** Default recorded on the event when the caller supplies no reason of its own. */
3
+ export const ADMIN_TRIGGER_REASON = 'Triggered from the admin.';
4
+ /** What each refusal means over HTTP. */
5
+ const STATUS = {
6
+ 'not-found': 404,
7
+ disabled: 409,
8
+ // The instance is fine; the queue is not. 502 rather than 500 says the
9
+ // failure is downstream, which is the difference between "retry" and
10
+ // "something here is broken".
11
+ 'send-failed': 502,
12
+ };
13
+ /**
14
+ * `POST /api/<integrations>/:id/sync` — the admin's path to the same event
15
+ * `trigger_sync` fires.
16
+ *
17
+ * Authenticates off the Payload session cookie, so the person clicking the
18
+ * button needs no API key and the event records them rather than a service
19
+ * principal. The rules are `requestManualSync`'s, not this file's; all that
20
+ * lives here is the admin check and the mapping from a refusal to a status
21
+ * code.
22
+ *
23
+ * Admin-only, matching the MCP tool and the collection's own write access:
24
+ * triggering an integration makes it POST to an external system.
25
+ */
26
+ export function createSyncEndpoint(deps) {
27
+ return {
28
+ path: '/:id/sync',
29
+ method: 'post',
30
+ handler: async (req) => {
31
+ if (!req.user) {
32
+ return json({ error: 'You must be logged in to trigger a sync.' }, 401);
33
+ }
34
+ const roles = req.user['roles'] ?? [];
35
+ if (!roles.includes('admin')) {
36
+ return json({ error: 'Only admins can manually trigger integrations.' }, 403);
37
+ }
38
+ const id = req.routeParams?.['id'];
39
+ if (typeof id !== 'string' && typeof id !== 'number') {
40
+ return json({ error: 'Expected an integration instance id in the path.' }, 400);
41
+ }
42
+ // The button sends no body at all, so an absent or unparseable one is
43
+ // not an error — only a body that is present and wrong.
44
+ let reason = null;
45
+ try {
46
+ const raw = (await req.json?.());
47
+ if (raw && typeof raw === 'object' && typeof raw.reason === 'string') {
48
+ reason = raw.reason.trim() || null;
49
+ }
50
+ }
51
+ catch {
52
+ reason = null;
53
+ }
54
+ const result = await requestManualSync({ payload: req.payload, collectionSlug: deps.collectionSlug, inngest: deps.inngest }, {
55
+ instanceId: String(id),
56
+ triggeredBy: req.user.id ?? null,
57
+ reason: reason ?? `${ADMIN_TRIGGER_REASON} (${req.user['email'] ?? req.user.id})`,
58
+ });
59
+ if (!result.ok) {
60
+ if (result.code === 'send-failed') {
61
+ req.payload.logger.error(`[integrations] could not queue a manual sync for ${String(id)}: ${result.message}`);
62
+ }
63
+ return json({ error: result.message, code: result.code }, STATUS[result.code]);
64
+ }
65
+ return json({
66
+ ok: true,
67
+ triggered: {
68
+ instanceId: result.instanceId,
69
+ instanceName: result.instanceName,
70
+ type: result.integrationType,
71
+ },
72
+ // What the caller polls against. The sync has not run yet.
73
+ lastSyncAt: result.lastSyncAt,
74
+ message: `Queued a sync for "${result.instanceName}". The status fields update when the run finishes.`,
75
+ }, 202);
76
+ },
77
+ };
78
+ }
79
+ function json(body, status) {
80
+ return new Response(JSON.stringify(body), {
81
+ status,
82
+ headers: { 'content-type': 'application/json' },
83
+ });
84
+ }
85
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/endpoints/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Client entry point for the admin controls, referenced from Payload's import
3
+ * map as `@forumone/throughline-integrations/client#SyncButton`.
4
+ *
5
+ * Kept separate from the package root so server-only consumers never pull React
6
+ * or `@payloadcms/ui` into their bundle.
7
+ */
8
+ export { SyncButton } from '../admin/SyncButton.js';
9
+ export type { ThroughlineSyncButtonProps } from '../admin/SyncButton.js';
10
+ export { describeSyncOutcome, fetchSyncStatus, formatSyncTime, syncHasFinished, triggerSync, } from '../admin/sync-client.js';
11
+ export type { FetchSyncStatusArgs, SyncOutcome, SyncStatus, SyncStatusValue, TriggerSyncArgs, TriggerSyncBody, TriggerSyncResult, } from '../admin/sync-client.js';
12
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,YAAY,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAA;AAExE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,eAAe,EACf,WAAW,GACZ,MAAM,yBAAyB,CAAA;AAChC,YAAY,EACV,mBAAmB,EACnB,WAAW,EACX,UAAU,EACV,eAAe,EACf,eAAe,EACf,eAAe,EACf,iBAAiB,GAClB,MAAM,yBAAyB,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Client entry point for the admin controls, referenced from Payload's import
3
+ * map as `@forumone/throughline-integrations/client#SyncButton`.
4
+ *
5
+ * Kept separate from the package root so server-only consumers never pull React
6
+ * or `@payloadcms/ui` into their bundle.
7
+ */
8
+ export { SyncButton } from '../admin/SyncButton.js';
9
+ export { describeSyncOutcome, fetchSyncStatus, formatSyncTime, syncHasFinished, triggerSync, } from '../admin/sync-client.js';
10
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGnD,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,eAAe,EACf,WAAW,GACZ,MAAM,yBAAyB,CAAA"}
package/dist/index.d.ts CHANGED
@@ -5,5 +5,9 @@ export type { IntegrationsPluginOptions } from './options.js';
5
5
  export { webhookIntegration, WEBHOOK_INTEGRATION_ID } from './integrations/index.js';
6
6
  export type { WebhookConfig } from './integrations/index.js';
7
7
  export type { Integration, IntegrationCategory, IntegrationContext, IntegrationAuditEvent, IntegrationConfigValidation, IntegrationHealth, IntegrationInstance, IntegrationInstanceLoaded, IntegrationSyncStatus, } from './types.js';
8
+ export { requestManualSync, MANUAL_SYNC_EVENT } from './sync/manual-sync.js';
9
+ export type { ManualSyncRefusal, RequestManualSyncArgs, RequestManualSyncDeps, RequestManualSyncResult, } from './sync/manual-sync.js';
10
+ export { createSyncEndpoint, ADMIN_TRIGGER_REASON } from './endpoints/sync.js';
11
+ export type { CreateSyncEndpointDeps } from './endpoints/sync.js';
8
12
  export { createListIntegrationsTool, createGetIntegrationStatusTool, createTriggerSyncTool, createTestIntegrationTool, createListIntegrationTypesTool, } from './tools/index.js';
9
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,YAAY,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAE7D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACpF,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAE5D,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,EACrB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,YAAY,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAE7D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACpF,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAE5D,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,2BAA2B,EAC3B,iBAAiB,EACjB,mBAAmB,EACnB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC9E,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAEjE,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,EACrB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAA"}
package/dist/index.js CHANGED
@@ -2,5 +2,7 @@ export { integrationsPlugin, getIntegrationRegistry, getIntegrationContext, } fr
2
2
  export { IntegrationRegistry } from './registry.js';
3
3
  export { DEFAULT_INTEGRATIONS_SLUG } from './options.js';
4
4
  export { webhookIntegration, WEBHOOK_INTEGRATION_ID } from './integrations/index.js';
5
+ export { requestManualSync, MANUAL_SYNC_EVENT } from './sync/manual-sync.js';
6
+ export { createSyncEndpoint, ADMIN_TRIGGER_REASON } from './endpoints/sync.js';
5
7
  export { createListIntegrationsTool, createGetIntegrationStatusTool, createTriggerSyncTool, createTestIntegrationTool, createListIntegrationTypesTool, } from './tools/index.js';
6
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAGxD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAepF,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,EACrB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AAGxD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAepF,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAQ5E,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAG9E,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,qBAAqB,EACrB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAA"}
package/dist/plugin.d.ts CHANGED
@@ -3,15 +3,19 @@ import { type IntegrationsPluginOptions } from './options.js';
3
3
  import { IntegrationRegistry } from './registry.js';
4
4
  import type { IntegrationContext } from './types.js';
5
5
  /**
6
- * Integrations server. Registers the Integrations collection, the
7
- * five-tool MCP server, and a process-local registry of integration
8
- * modules. The webhook integration is registered automatically; clients
6
+ * Integrations server. Registers the Integrations collection — with its
7
+ * manual-sync endpoint and the Sync now button in its sidebar — the five-tool
8
+ * MCP server, and a process-local registry of integration modules. The webhook integration is registered automatically; clients
9
9
  * extend the registry by passing additional integrations via options.
10
10
  *
11
11
  * Integration Inngest functions are not served here — they are exposed
12
12
  * via `getIntegrationRegistry(payload)` so the client app's Inngest
13
13
  * endpoint can merge them with its own functions. See
14
14
  * `docs/integrations-wiring.md` in the repository root.
15
+ *
16
+ * The collection carries one admin component, the sidebar's Sync now button,
17
+ * so hosts must run `payload generate:importmap` after adding this plugin (the
18
+ * dev server does it automatically). A stale import map 500s the admin screen.
15
19
  */
16
20
  export declare const integrationsPlugin: CorePlugin<IntegrationsPluginOptions>;
17
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,uCAAuC,CAAA;AAG1F,OAAO,EAAE,KAAK,yBAAyB,EAA8C,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAGnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAgBpD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAAU,CAAC,yBAAyB,CA+HlE,CAAA;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,GAAG,OAAO,EACjD,OAAO,EAAE,OAAO,GACf,mBAAmB,CAAC,EAAE,CAAC,GAAG,SAAS,CAIrC;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CAEtF"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,uCAAuC,CAAA;AAG1F,OAAO,EAAE,KAAK,yBAAyB,EAA8C,MAAM,cAAc,CAAA;AACzG,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAInD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAgBpD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,EAAE,UAAU,CAAC,yBAAyB,CAsIlE,CAAA;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,GAAG,OAAO,EACjD,OAAO,EAAE,OAAO,GACf,mBAAmB,CAAC,EAAE,CAAC,GAAG,SAAS,CAIrC;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,kBAAkB,GAAG,SAAS,CAEtF"}
package/dist/plugin.js CHANGED
@@ -3,6 +3,7 @@ import { createNamedLogger, defaultLogger, getAuditWriter } from '@forumone/thro
3
3
  import { validateOptions, DEFAULT_INTEGRATIONS_SLUG } from './options.js';
4
4
  import { IntegrationRegistry } from './registry.js';
5
5
  import { createIntegrationsCollection } from './collection.js';
6
+ import { createSyncEndpoint } from './endpoints/sync.js';
6
7
  import { webhookIntegration } from './integrations/index.js';
7
8
  import { INTEGRATIONS_TOOL_DESCRIPTORS, createGetIntegrationStatusTool, createListIntegrationsTool, createListIntegrationTypesTool, createTestIntegrationTool, createTriggerSyncTool, } from './tools/index.js';
8
9
  const PLUGIN_ID = '@forumone/throughline-integrations';
@@ -10,15 +11,19 @@ const PLUGIN_VERSION = '0.1.0';
10
11
  const REGISTRY_SYMBOL = Symbol.for('@forumone/throughline/integrations-registry');
11
12
  const CONTEXT_SYMBOL = Symbol.for('@forumone/throughline/integrations-context');
12
13
  /**
13
- * Integrations server. Registers the Integrations collection, the
14
- * five-tool MCP server, and a process-local registry of integration
15
- * modules. The webhook integration is registered automatically; clients
14
+ * Integrations server. Registers the Integrations collection — with its
15
+ * manual-sync endpoint and the Sync now button in its sidebar — the five-tool
16
+ * MCP server, and a process-local registry of integration modules. The webhook integration is registered automatically; clients
16
17
  * extend the registry by passing additional integrations via options.
17
18
  *
18
19
  * Integration Inngest functions are not served here — they are exposed
19
20
  * via `getIntegrationRegistry(payload)` so the client app's Inngest
20
21
  * endpoint can merge them with its own functions. See
21
22
  * `docs/integrations-wiring.md` in the repository root.
23
+ *
24
+ * The collection carries one admin component, the sidebar's Sync now button,
25
+ * so hosts must run `payload generate:importmap` after adding this plugin (the
26
+ * dev server does it automatically). A stale import map 500s the admin screen.
22
27
  */
23
28
  export const integrationsPlugin = (rawOptions) => (incomingConfig) => {
24
29
  if (rawOptions.enabled === false)
@@ -31,7 +36,14 @@ export const integrationsPlugin = (rawOptions) => (incomingConfig) => {
31
36
  for (const integration of options.integrations ?? []) {
32
37
  registry.register(integration);
33
38
  }
34
- const collection = createIntegrationsCollection({ slug: collectionSlug, registry });
39
+ const collection = createIntegrationsCollection({
40
+ slug: collectionSlug,
41
+ registry,
42
+ // The admin's path to `integration/manual-sync`, sharing
43
+ // `requestManualSync` with the `trigger_sync` MCP tool so the two cannot
44
+ // disagree about what a trigger checks or what event it sends.
45
+ endpoints: [createSyncEndpoint({ collectionSlug, inngest: options.inngest })],
46
+ });
35
47
  /*
36
48
  Declared here, bound at `onInit` — `mcpPlugin` generates its per-key
37
49
  checkboxes from these names and descriptions while the config is built, and
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { Inngest } from 'inngest';
2
+ import type { Payload } from 'payload';
3
+ /**
4
+ * The event every integration's manual-sync function subscribes to. Fired for
5
+ * *all* integrations, which is why each handler filters the payload down to
6
+ * its own instance rather than trusting the event.
7
+ */
8
+ export declare const MANUAL_SYNC_EVENT = "integration/manual-sync";
9
+ export interface RequestManualSyncDeps {
10
+ payload: Payload;
11
+ collectionSlug: string;
12
+ inngest: Inngest;
13
+ }
14
+ export interface RequestManualSyncArgs {
15
+ /** Payload id of the instance to sync. */
16
+ instanceId: string;
17
+ /** Who asked. Recorded on the event so the run can be traced back to them. */
18
+ triggeredBy?: number | string | null;
19
+ /** Why. Carried on the event for the audit trail; not otherwise used. */
20
+ reason?: string | null;
21
+ }
22
+ /**
23
+ * Why a trigger was refused. Callers map these onto whatever their transport
24
+ * uses to say no — an error envelope for MCP, a status code for HTTP.
25
+ */
26
+ export type ManualSyncRefusal =
27
+ /** No instance with that id. */
28
+ 'not-found'
29
+ /** The instance exists but `enabled` is false. */
30
+ | 'disabled'
31
+ /** Inngest would not take the event. */
32
+ | 'send-failed';
33
+ export type RequestManualSyncResult = {
34
+ ok: true;
35
+ instanceId: string;
36
+ instanceName: string;
37
+ integrationType: string;
38
+ /**
39
+ * The instance's `lastSyncAt` at the moment the event was sent, or null
40
+ * if it has never run. A caller watching for the run to finish compares
41
+ * against this rather than against whatever it last rendered.
42
+ */
43
+ lastSyncAt: string | null;
44
+ } | {
45
+ ok: false;
46
+ code: ManualSyncRefusal;
47
+ message: string;
48
+ };
49
+ /**
50
+ * Sends `integration/manual-sync` for one instance, having checked that the
51
+ * instance exists and is enabled.
52
+ *
53
+ * This is the single definition of what triggering a sync *means*, shared by
54
+ * the `trigger_sync` MCP tool and the admin endpoint behind the Sync now
55
+ * button. It deliberately does not check permissions: MCP and HTTP authenticate
56
+ * differently and each caller applies `admin`-only itself, before calling.
57
+ *
58
+ * It fires an event and returns. The sync runs in Inngest and finishes later —
59
+ * an `ok` result means the run was *requested*, never that it succeeded. The
60
+ * outcome lands on the instance's `lastSyncAt` / `lastSyncStatus` / `lastError`
61
+ * when the run completes.
62
+ */
63
+ export declare function requestManualSync(deps: RequestManualSyncDeps, args: RequestManualSyncArgs): Promise<RequestManualSyncResult>;
64
+ //# sourceMappingURL=manual-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manual-sync.d.ts","sourceRoot":"","sources":["../../src/sync/manual-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEtC;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,4BAA4B,CAAA;AAE1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,OAAO,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAA;IAClB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACpC,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB;AAC3B,gCAAgC;AAC9B,WAAW;AACb,kDAAkD;GAChD,UAAU;AACZ,wCAAwC;GACtC,aAAa,CAAA;AAEjB,MAAM,MAAM,uBAAuB,GAC/B;IACE,EAAE,EAAE,IAAI,CAAA;IACR,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3D;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,EAC3B,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,uBAAuB,CAAC,CA0ElC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The event every integration's manual-sync function subscribes to. Fired for
3
+ * *all* integrations, which is why each handler filters the payload down to
4
+ * its own instance rather than trusting the event.
5
+ */
6
+ export const MANUAL_SYNC_EVENT = 'integration/manual-sync';
7
+ /**
8
+ * Sends `integration/manual-sync` for one instance, having checked that the
9
+ * instance exists and is enabled.
10
+ *
11
+ * This is the single definition of what triggering a sync *means*, shared by
12
+ * the `trigger_sync` MCP tool and the admin endpoint behind the Sync now
13
+ * button. It deliberately does not check permissions: MCP and HTTP authenticate
14
+ * differently and each caller applies `admin`-only itself, before calling.
15
+ *
16
+ * It fires an event and returns. The sync runs in Inngest and finishes later —
17
+ * an `ok` result means the run was *requested*, never that it succeeded. The
18
+ * outcome lands on the instance's `lastSyncAt` / `lastSyncStatus` / `lastError`
19
+ * when the run completes.
20
+ */
21
+ export async function requestManualSync(deps, args) {
22
+ let doc = null;
23
+ try {
24
+ doc = (await deps.payload.findByID({
25
+ collection: deps.collectionSlug,
26
+ id: args.instanceId,
27
+ }));
28
+ }
29
+ catch {
30
+ doc = null;
31
+ }
32
+ if (!doc) {
33
+ return {
34
+ ok: false,
35
+ code: 'not-found',
36
+ message: `No integration instance with id "${args.instanceId}".`,
37
+ };
38
+ }
39
+ const instanceName = String(doc['name']);
40
+ if (doc['enabled'] !== true) {
41
+ return {
42
+ ok: false,
43
+ code: 'disabled',
44
+ message: `Integration "${instanceName}" is disabled. Enable it in the admin before triggering.`,
45
+ };
46
+ }
47
+ const integrationType = String(doc['integrationType']);
48
+ try {
49
+ await deps.inngest.send({
50
+ name: MANUAL_SYNC_EVENT,
51
+ data: {
52
+ integrationId: integrationType,
53
+ instanceId: args.instanceId,
54
+ triggeredBy: args.triggeredBy ?? null,
55
+ reason: args.reason ?? null,
56
+ },
57
+ });
58
+ }
59
+ catch (error) {
60
+ /*
61
+ A failed send used to escape as an unhandled rejection, which the MCP
62
+ transport turned into a generic tool error and a button would have turned
63
+ into nothing at all — the worst outcome, because a sync that was never
64
+ requested looks exactly like one that has not finished yet.
65
+ */
66
+ return {
67
+ ok: false,
68
+ code: 'send-failed',
69
+ message: `Could not reach Inngest to queue the sync: ${error instanceof Error ? error.message : String(error)}`,
70
+ };
71
+ }
72
+ // A `date` field comes back as an ISO string over REST and as a Date from
73
+ // the local API, and this function is called from both.
74
+ const rawLastSyncAt = doc['lastSyncAt'];
75
+ const lastSyncAt = rawLastSyncAt instanceof Date
76
+ ? rawLastSyncAt.toISOString()
77
+ : typeof rawLastSyncAt === 'string'
78
+ ? rawLastSyncAt
79
+ : null;
80
+ return {
81
+ ok: true,
82
+ instanceId: args.instanceId,
83
+ instanceName,
84
+ integrationType,
85
+ lastSyncAt,
86
+ };
87
+ }
88
+ //# sourceMappingURL=manual-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manual-sync.js","sourceRoot":"","sources":["../../src/sync/manual-sync.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,yBAAyB,CAAA;AA4C1D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAA2B,EAC3B,IAA2B;IAE3B,IAAI,GAAG,GAAmC,IAAI,CAAA;IAC9C,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YACjC,UAAU,EAAE,IAAI,CAAC,cAAc;YAC/B,EAAE,EAAE,IAAI,CAAC,UAAU;SACpB,CAAC,CAAmC,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,IAAI,CAAA;IACZ,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,oCAAoC,IAAI,CAAC,UAAU,IAAI;SACjE,CAAA;IACH,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IAExC,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,gBAAgB,YAAY,0DAA0D;SAChG,CAAA;IACH,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAA;IAEtD,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,iBAAiB;YACvB,IAAI,EAAE;gBACJ,aAAa,EAAE,eAAe;gBAC9B,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,IAAI;gBACrC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,IAAI;aAC5B;SACF,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf;;;;;UAKE;QACF,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,8CACP,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE;SACH,CAAA;IACH,CAAC;IAED,0EAA0E;IAC1E,wDAAwD;IACxD,MAAM,aAAa,GAAG,GAAG,CAAC,YAAY,CAAC,CAAA;IACvC,MAAM,UAAU,GACd,aAAa,YAAY,IAAI;QAC3B,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE;QAC7B,CAAC,CAAC,OAAO,aAAa,KAAK,QAAQ;YACjC,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,IAAI,CAAA;IAEZ,OAAO;QACL,EAAE,EAAE,IAAI;QACR,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,YAAY;QACZ,eAAe;QACf,UAAU;KACX,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"trigger-sync.d.ts","sourceRoot":"","sources":["../../src/tools/trigger-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAI9E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,QAAA,MAAM,WAAW;;;;;;;;;EAQf,CAAA;AAEF,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB,iBAAiB,CAAC,OAAO,WAAW,CAAC,CAkDvC"}
1
+ {"version":3,"file":"trigger-sync.d.ts","sourceRoot":"","sources":["../../src/tools/trigger-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAK9E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,QAAA,MAAM,WAAW;;;;;;;;;EAQf,CAAA;AAEF,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB,iBAAiB,CAAC,OAAO,WAAW,CAAC,CA+BvC"}