@mastra/factory 0.2.2-alpha.0 → 0.2.2-alpha.2

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 (174) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/auth.d.ts +2 -2
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +401 -314
  5. package/dist/auth.js.map +1 -1
  6. package/dist/capabilities/connection.js +1 -1
  7. package/dist/capabilities/intake.js +1 -1
  8. package/dist/capabilities/version-control.js +1 -1
  9. package/dist/factory.d.ts.map +1 -1
  10. package/dist/factory.js +441 -39455
  11. package/dist/factory.js.map +1 -1
  12. package/dist/index.js +2 -39466
  13. package/dist/integrations/base.js +1 -1
  14. package/dist/integrations/github/config.js +36 -22
  15. package/dist/integrations/github/config.js.map +1 -1
  16. package/dist/integrations/github/factory-session.js +33 -37
  17. package/dist/integrations/github/factory-session.js.map +1 -1
  18. package/dist/integrations/github/integration.js +1037 -3624
  19. package/dist/integrations/github/integration.js.map +1 -1
  20. package/dist/integrations/github/issue-triage.js +71 -71
  21. package/dist/integrations/github/issue-triage.js.map +1 -1
  22. package/dist/integrations/github/pat.js +47 -36
  23. package/dist/integrations/github/pat.js.map +1 -1
  24. package/dist/integrations/github/provenance.js +72 -101
  25. package/dist/integrations/github/provenance.js.map +1 -1
  26. package/dist/integrations/github/routes.d.ts.map +1 -1
  27. package/dist/integrations/github/routes.js +1272 -1833
  28. package/dist/integrations/github/routes.js.map +1 -1
  29. package/dist/integrations/github/rules.js +203 -471
  30. package/dist/integrations/github/rules.js.map +1 -1
  31. package/dist/integrations/github/sandbox.d.ts +2 -0
  32. package/dist/integrations/github/sandbox.d.ts.map +1 -1
  33. package/dist/integrations/github/sandbox.js +401 -326
  34. package/dist/integrations/github/sandbox.js.map +1 -1
  35. package/dist/integrations/github/session-subscriptions.js +165 -223
  36. package/dist/integrations/github/session-subscriptions.js.map +1 -1
  37. package/dist/integrations/github/subscriptions.js +43 -51
  38. package/dist/integrations/github/subscriptions.js.map +1 -1
  39. package/dist/integrations/github/token-refresh.js +15 -18
  40. package/dist/integrations/github/token-refresh.js.map +1 -1
  41. package/dist/integrations/github/webhook.js +359 -343
  42. package/dist/integrations/github/webhook.js.map +1 -1
  43. package/dist/integrations/linear/agent-tools.js +77 -100
  44. package/dist/integrations/linear/agent-tools.js.map +1 -1
  45. package/dist/integrations/linear/integration.js +611 -1309
  46. package/dist/integrations/linear/integration.js.map +1 -1
  47. package/dist/integrations/linear/routes.js +227 -230
  48. package/dist/integrations/linear/routes.js.map +1 -1
  49. package/dist/integrations/linear/rules.js +126 -346
  50. package/dist/integrations/linear/rules.js.map +1 -1
  51. package/dist/integrations/linear/storage.js +1 -1
  52. package/dist/integrations/platform/api-client.js +131 -135
  53. package/dist/integrations/platform/api-client.js.map +1 -1
  54. package/dist/integrations/platform/github/event-worker.js +275 -573
  55. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  56. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  57. package/dist/integrations/platform/github/integration.js +845 -3942
  58. package/dist/integrations/platform/github/integration.js.map +1 -1
  59. package/dist/integrations/platform/linear/integration.js +457 -1309
  60. package/dist/integrations/platform/linear/integration.js.map +1 -1
  61. package/dist/integrations/workos/integration.js +80 -85
  62. package/dist/integrations/workos/integration.js.map +1 -1
  63. package/dist/routes/config.d.ts.map +1 -1
  64. package/dist/routes/config.js +933 -915
  65. package/dist/routes/config.js.map +1 -1
  66. package/dist/routes/custom-provider-source.js +110 -93
  67. package/dist/routes/custom-provider-source.js.map +1 -1
  68. package/dist/routes/fs.js +401 -349
  69. package/dist/routes/fs.js.map +1 -1
  70. package/dist/routes/intake.js +165 -165
  71. package/dist/routes/intake.js.map +1 -1
  72. package/dist/routes/oauth.js +447 -25166
  73. package/dist/routes/oauth.js.map +1 -1
  74. package/dist/routes/projects.js +437 -376
  75. package/dist/routes/projects.js.map +1 -1
  76. package/dist/routes/provider-credentials.js +76 -58
  77. package/dist/routes/provider-credentials.js.map +1 -1
  78. package/dist/routes/route.js +12 -8
  79. package/dist/routes/route.js.map +1 -1
  80. package/dist/routes/skills.js +160 -173
  81. package/dist/routes/skills.js.map +1 -1
  82. package/dist/routes/surface.js +250 -28618
  83. package/dist/routes/surface.js.map +1 -1
  84. package/dist/routes/tenant-credentials.js +141 -166
  85. package/dist/routes/tenant-credentials.js.map +1 -1
  86. package/dist/routes/work-items.js +654 -862
  87. package/dist/routes/work-items.js.map +1 -1
  88. package/dist/rules/binding-context.js +23 -35
  89. package/dist/rules/binding-context.js.map +1 -1
  90. package/dist/rules/defaults.js +200 -309
  91. package/dist/rules/defaults.js.map +1 -1
  92. package/dist/rules/dispatcher.d.ts.map +1 -1
  93. package/dist/rules/dispatcher.js +438 -677
  94. package/dist/rules/dispatcher.js.map +1 -1
  95. package/dist/rules/index.js +5 -599
  96. package/dist/rules/processor.js +344 -596
  97. package/dist/rules/processor.js.map +1 -1
  98. package/dist/rules/resolve.js +21 -18
  99. package/dist/rules/resolve.js.map +1 -1
  100. package/dist/rules/start-coordinator.js +168 -157
  101. package/dist/rules/start-coordinator.js.map +1 -1
  102. package/dist/rules/tools.js +50 -85
  103. package/dist/rules/tools.js.map +1 -1
  104. package/dist/rules/transition-service.js +183 -454
  105. package/dist/rules/transition-service.js.map +1 -1
  106. package/dist/rules/types.js +33 -29
  107. package/dist/rules/types.js.map +1 -1
  108. package/dist/rules/validation.js +266 -281
  109. package/dist/rules/validation.js.map +1 -1
  110. package/dist/sandbox/fleet.js +272 -250
  111. package/dist/sandbox/fleet.js.map +1 -1
  112. package/dist/sandbox/reattach.js +13 -6
  113. package/dist/sandbox/reattach.js.map +1 -1
  114. package/dist/server-error.js +12 -16
  115. package/dist/server-error.js.map +1 -1
  116. package/dist/skills/service.js +30 -35
  117. package/dist/skills/service.js.map +1 -1
  118. package/dist/spa-static.d.ts.map +1 -1
  119. package/dist/spa-static.js +91 -64
  120. package/dist/spa-static.js.map +1 -1
  121. package/dist/state-signing.js +73 -44
  122. package/dist/state-signing.js.map +1 -1
  123. package/dist/storage/domains/audit/agent-audit.js +60 -59
  124. package/dist/storage/domains/audit/agent-audit.js.map +1 -1
  125. package/dist/storage/domains/audit/base.js +169 -112
  126. package/dist/storage/domains/audit/base.js.map +1 -1
  127. package/dist/storage/domains/audit/domain.js +155 -153
  128. package/dist/storage/domains/audit/domain.js.map +1 -1
  129. package/dist/storage/domains/credentials/base.js +259 -243
  130. package/dist/storage/domains/credentials/base.js.map +1 -1
  131. package/dist/storage/domains/custom-providers/base.js +138 -143
  132. package/dist/storage/domains/custom-providers/base.js.map +1 -1
  133. package/dist/storage/domains/intake/base.js +75 -57
  134. package/dist/storage/domains/intake/base.js.map +1 -1
  135. package/dist/storage/domains/integrations/base.js +310 -245
  136. package/dist/storage/domains/integrations/base.js.map +1 -1
  137. package/dist/storage/domains/memory-settings/base.js +117 -102
  138. package/dist/storage/domains/memory-settings/base.js.map +1 -1
  139. package/dist/storage/domains/model-packs/base.js +89 -88
  140. package/dist/storage/domains/model-packs/base.js.map +1 -1
  141. package/dist/storage/domains/projects/base.js +97 -92
  142. package/dist/storage/domains/projects/base.js.map +1 -1
  143. package/dist/storage/domains/queue-health/base.js +111 -76
  144. package/dist/storage/domains/queue-health/base.js.map +1 -1
  145. package/dist/storage/domains/source-control/base.d.ts +9 -0
  146. package/dist/storage/domains/source-control/base.d.ts.map +1 -1
  147. package/dist/storage/domains/source-control/base.js +777 -702
  148. package/dist/storage/domains/source-control/base.js.map +1 -1
  149. package/dist/storage/domains/source-control/inmemory.d.ts +4 -0
  150. package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
  151. package/dist/storage/domains/source-control/inmemory.js +322 -344
  152. package/dist/storage/domains/source-control/inmemory.js.map +1 -1
  153. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  154. package/dist/storage/domains/work-items/base.js +1266 -1132
  155. package/dist/storage/domains/work-items/base.js.map +1 -1
  156. package/dist/storage/domains/work-items/metrics.js +202 -184
  157. package/dist/storage/domains/work-items/metrics.js.map +1 -1
  158. package/dist/timing.d.ts +15 -0
  159. package/dist/timing.d.ts.map +1 -0
  160. package/dist/timing.js +34 -0
  161. package/dist/timing.js.map +1 -0
  162. package/dist/workspace.d.ts +2 -3
  163. package/dist/workspace.d.ts.map +1 -1
  164. package/dist/workspace.js +236 -438
  165. package/dist/workspace.js.map +1 -1
  166. package/factory-skills/factory-review/SKILL.md +9 -2
  167. package/package.json +9 -9
  168. package/dist/capabilities/connection.js.map +0 -1
  169. package/dist/capabilities/intake.js.map +0 -1
  170. package/dist/capabilities/version-control.js.map +0 -1
  171. package/dist/index.js.map +0 -1
  172. package/dist/integrations/base.js.map +0 -1
  173. package/dist/integrations/linear/storage.js.map +0 -1
  174. package/dist/rules/index.js.map +0 -1
@@ -1,150 +1,145 @@
1
- // src/storage/domains/custom-providers/base.ts
2
1
  import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
3
- var CUSTOM_PROVIDERS_SCHEMA = {
4
- name: "custom_providers",
5
- columns: {
6
- id: { type: "uuid-pk" },
7
- org_id: { type: "text" },
8
- created_by: { type: "text" },
9
- provider_id: { type: "text" },
10
- name: { type: "text" },
11
- url: { type: "text" },
12
- api_key: { type: "text", nullable: true },
13
- models: { type: "json" },
14
- created_at: { type: "timestamp" },
15
- updated_at: { type: "timestamp" }
16
- },
17
- uniqueIndexes: [{ name: "custom_providers_org_provider_key", columns: ["org_id", "provider_id"] }]
2
+ //#region src/storage/domains/custom-providers/base.ts
3
+ const CUSTOM_PROVIDERS_SCHEMA = {
4
+ name: "custom_providers",
5
+ columns: {
6
+ id: { type: "uuid-pk" },
7
+ org_id: { type: "text" },
8
+ created_by: { type: "text" },
9
+ provider_id: { type: "text" },
10
+ name: { type: "text" },
11
+ url: { type: "text" },
12
+ api_key: {
13
+ type: "text",
14
+ nullable: true
15
+ },
16
+ models: { type: "json" },
17
+ created_at: { type: "timestamp" },
18
+ updated_at: { type: "timestamp" }
19
+ },
20
+ uniqueIndexes: [{
21
+ name: "custom_providers_org_provider_key",
22
+ columns: ["org_id", "provider_id"]
23
+ }]
18
24
  };
19
25
  function toRecord(row) {
20
- return {
21
- id: row.id,
22
- orgId: row.org_id,
23
- createdBy: row.created_by,
24
- providerId: row.provider_id,
25
- name: row.name,
26
- url: row.url,
27
- apiKey: row.api_key,
28
- models: Array.isArray(row.models) ? row.models : [],
29
- createdAt: row.created_at,
30
- updatedAt: row.updated_at
31
- };
26
+ return {
27
+ id: row.id,
28
+ orgId: row.org_id,
29
+ createdBy: row.created_by,
30
+ providerId: row.provider_id,
31
+ name: row.name,
32
+ url: row.url,
33
+ apiKey: row.api_key,
34
+ models: Array.isArray(row.models) ? row.models : [],
35
+ createdAt: row.created_at,
36
+ updatedAt: row.updated_at
37
+ };
32
38
  }
33
39
  var CustomProvidersStorage = class extends FactoryStorageDomain {
34
- constructor() {
35
- super("custom-providers");
36
- }
37
- async init() {
38
- await this.ensureCollections([CUSTOM_PROVIDERS_SCHEMA]);
39
- }
40
- async dangerouslyClearAll() {
41
- await this.ops.deleteMany("custom_providers", {});
42
- }
43
- get #db() {
44
- return this.ops;
45
- }
46
- /**
47
- * Create or wholesale-replace a provider by `(orgId, providerId)` — mirrors
48
- * the settings.json upsert semantics (no key retention: an absent `apiKey`
49
- * clears the stored key). `previousProviderId` renames the provider: the
50
- * common path is a single atomic in-place update of the old row; renaming
51
- * onto an id that already exists overwrites the target first and removes the
52
- * old row last, so no interleaving or failure can lose the provider.
53
- */
54
- async upsert({
55
- orgId,
56
- userId,
57
- input,
58
- previousProviderId
59
- }) {
60
- const now = /* @__PURE__ */ new Date();
61
- const renameFrom = previousProviderId && previousProviderId !== input.providerId ? previousProviderId : void 0;
62
- if (renameFrom) {
63
- const target = await this.#db.findOne("custom_providers", {
64
- org_id: orgId,
65
- provider_id: input.providerId
66
- });
67
- if (!target) {
68
- const renamed = await this.#db.updateAtomic(
69
- "custom_providers",
70
- { org_id: orgId, provider_id: renameFrom },
71
- () => ({
72
- provider_id: input.providerId,
73
- name: input.name,
74
- url: input.url,
75
- api_key: input.apiKey ?? null,
76
- models: input.models,
77
- updated_at: now
78
- })
79
- );
80
- if (renamed) return toRecord(renamed);
81
- }
82
- }
83
- const record = await this.#write({ orgId, userId, input, now });
84
- if (renameFrom) {
85
- await this.#db.deleteMany("custom_providers", { org_id: orgId, provider_id: renameFrom });
86
- }
87
- return record;
88
- }
89
- /**
90
- * Update-first, then insert-and-catch-unique-violation (see `queue_health`):
91
- * concurrent creates of the same provider both succeed (last write wins on
92
- * the single row) instead of one failing on the unique index, and a row
93
- * deleted mid-flight is recreated rather than reported as a stale success.
94
- */
95
- async #write({
96
- orgId,
97
- userId,
98
- input,
99
- now
100
- }) {
101
- const updateExisting = () => this.#db.updateAtomic(
102
- "custom_providers",
103
- { org_id: orgId, provider_id: input.providerId },
104
- () => ({
105
- name: input.name,
106
- url: input.url,
107
- api_key: input.apiKey ?? null,
108
- models: input.models,
109
- updated_at: now
110
- })
111
- );
112
- const updated = await updateExisting();
113
- if (updated) return toRecord(updated);
114
- try {
115
- const row = await this.#db.insertOne("custom_providers", {
116
- org_id: orgId,
117
- created_by: userId,
118
- provider_id: input.providerId,
119
- name: input.name,
120
- url: input.url,
121
- api_key: input.apiKey ?? null,
122
- models: input.models,
123
- created_at: now,
124
- updated_at: now
125
- });
126
- return toRecord(row);
127
- } catch (error) {
128
- if (!(error instanceof UniqueViolationError)) throw error;
129
- const row = await updateExisting();
130
- if (!row) throw error;
131
- return toRecord(row);
132
- }
133
- }
134
- async list({ orgId }) {
135
- const rows = await this.#db.findMany(
136
- "custom_providers",
137
- { org_id: orgId },
138
- { orderBy: [["name", "asc"]] }
139
- );
140
- return rows.map(toRecord);
141
- }
142
- async delete({ orgId, providerId }) {
143
- return await this.#db.deleteMany("custom_providers", { org_id: orgId, provider_id: providerId }) > 0;
144
- }
145
- };
146
- export {
147
- CUSTOM_PROVIDERS_SCHEMA,
148
- CustomProvidersStorage
40
+ constructor() {
41
+ super("custom-providers");
42
+ }
43
+ async init() {
44
+ await this.ensureCollections([CUSTOM_PROVIDERS_SCHEMA]);
45
+ }
46
+ async dangerouslyClearAll() {
47
+ await this.ops.deleteMany("custom_providers", {});
48
+ }
49
+ get #db() {
50
+ return this.ops;
51
+ }
52
+ /**
53
+ * Create or wholesale-replace a provider by `(orgId, providerId)` — mirrors
54
+ * the settings.json upsert semantics (no key retention: an absent `apiKey`
55
+ * clears the stored key). `previousProviderId` renames the provider: the
56
+ * common path is a single atomic in-place update of the old row; renaming
57
+ * onto an id that already exists overwrites the target first and removes the
58
+ * old row last, so no interleaving or failure can lose the provider.
59
+ */
60
+ async upsert({ orgId, userId, input, previousProviderId }) {
61
+ const now = /* @__PURE__ */ new Date();
62
+ const renameFrom = previousProviderId && previousProviderId !== input.providerId ? previousProviderId : void 0;
63
+ if (renameFrom) {
64
+ if (!await this.#db.findOne("custom_providers", {
65
+ org_id: orgId,
66
+ provider_id: input.providerId
67
+ })) {
68
+ const renamed = await this.#db.updateAtomic("custom_providers", {
69
+ org_id: orgId,
70
+ provider_id: renameFrom
71
+ }, () => ({
72
+ provider_id: input.providerId,
73
+ name: input.name,
74
+ url: input.url,
75
+ api_key: input.apiKey ?? null,
76
+ models: input.models,
77
+ updated_at: now
78
+ }));
79
+ if (renamed) return toRecord(renamed);
80
+ }
81
+ }
82
+ const record = await this.#write({
83
+ orgId,
84
+ userId,
85
+ input,
86
+ now
87
+ });
88
+ if (renameFrom) await this.#db.deleteMany("custom_providers", {
89
+ org_id: orgId,
90
+ provider_id: renameFrom
91
+ });
92
+ return record;
93
+ }
94
+ /**
95
+ * Update-first, then insert-and-catch-unique-violation (see `queue_health`):
96
+ * concurrent creates of the same provider both succeed (last write wins on
97
+ * the single row) instead of one failing on the unique index, and a row
98
+ * deleted mid-flight is recreated rather than reported as a stale success.
99
+ */
100
+ async #write({ orgId, userId, input, now }) {
101
+ const updateExisting = () => this.#db.updateAtomic("custom_providers", {
102
+ org_id: orgId,
103
+ provider_id: input.providerId
104
+ }, () => ({
105
+ name: input.name,
106
+ url: input.url,
107
+ api_key: input.apiKey ?? null,
108
+ models: input.models,
109
+ updated_at: now
110
+ }));
111
+ const updated = await updateExisting();
112
+ if (updated) return toRecord(updated);
113
+ try {
114
+ return toRecord(await this.#db.insertOne("custom_providers", {
115
+ org_id: orgId,
116
+ created_by: userId,
117
+ provider_id: input.providerId,
118
+ name: input.name,
119
+ url: input.url,
120
+ api_key: input.apiKey ?? null,
121
+ models: input.models,
122
+ created_at: now,
123
+ updated_at: now
124
+ }));
125
+ } catch (error) {
126
+ if (!(error instanceof UniqueViolationError)) throw error;
127
+ const row = await updateExisting();
128
+ if (!row) throw error;
129
+ return toRecord(row);
130
+ }
131
+ }
132
+ async list({ orgId }) {
133
+ return (await this.#db.findMany("custom_providers", { org_id: orgId }, { orderBy: [["name", "asc"]] })).map(toRecord);
134
+ }
135
+ async delete({ orgId, providerId }) {
136
+ return await this.#db.deleteMany("custom_providers", {
137
+ org_id: orgId,
138
+ provider_id: providerId
139
+ }) > 0;
140
+ }
149
141
  };
142
+ //#endregion
143
+ export { CUSTOM_PROVIDERS_SCHEMA, CustomProvidersStorage };
144
+
150
145
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/storage/domains/custom-providers/base.ts"],"sourcesContent":["import { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\n/**\n * A user-defined OpenAI-compatible provider. The DB-backed counterpart of the\n * local `settings.json` `customProviders` entries: org-scoped rows keyed by the\n * derived provider id (name slug), API key stored alongside so a deployed\n * server never reads the shared settings file.\n */\nexport interface CustomProviderRecord {\n id: string;\n orgId: string;\n createdBy: string;\n /** Stable slug derived from the name (`getCustomProviderId`). */\n providerId: string;\n name: string;\n url: string;\n apiKey: string | null;\n models: string[];\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpsertCustomProviderInput {\n providerId: string;\n name: string;\n url: string;\n apiKey?: string;\n models: string[];\n}\n\nexport const CUSTOM_PROVIDERS_SCHEMA: CollectionSchema = {\n name: 'custom_providers',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n created_by: { type: 'text' },\n provider_id: { type: 'text' },\n name: { type: 'text' },\n url: { type: 'text' },\n api_key: { type: 'text', nullable: true },\n models: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'custom_providers_org_provider_key', columns: ['org_id', 'provider_id'] }],\n};\n\ninterface CustomProviderDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n created_by: string;\n provider_id: string;\n name: string;\n url: string;\n api_key: string | null;\n models: string[];\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toRecord(row: CustomProviderDbRow): CustomProviderRecord {\n return {\n id: row.id,\n orgId: row.org_id,\n createdBy: row.created_by,\n providerId: row.provider_id,\n name: row.name,\n url: row.url,\n apiKey: row.api_key,\n models: Array.isArray(row.models) ? row.models : [],\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class CustomProvidersStorage extends FactoryStorageDomain {\n constructor() {\n super('custom-providers');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([CUSTOM_PROVIDERS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('custom_providers', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n /**\n * Create or wholesale-replace a provider by `(orgId, providerId)` — mirrors\n * the settings.json upsert semantics (no key retention: an absent `apiKey`\n * clears the stored key). `previousProviderId` renames the provider: the\n * common path is a single atomic in-place update of the old row; renaming\n * onto an id that already exists overwrites the target first and removes the\n * old row last, so no interleaving or failure can lose the provider.\n */\n async upsert({\n orgId,\n userId,\n input,\n previousProviderId,\n }: {\n orgId: string;\n userId: string;\n input: UpsertCustomProviderInput;\n previousProviderId?: string;\n }): Promise<CustomProviderRecord> {\n const now = new Date();\n const renameFrom = previousProviderId && previousProviderId !== input.providerId ? previousProviderId : undefined;\n\n if (renameFrom) {\n const target = await this.#db.findOne<CustomProviderDbRow>('custom_providers', {\n org_id: orgId,\n provider_id: input.providerId,\n });\n if (!target) {\n // In-place rename: one atomic write with no delete/insert gap, so a\n // failure can never drop the provider (and `created_at`/`created_by`\n // are preserved). If a concurrent create grabs the new id between the\n // lookup and this update, the unique index rejects the update and the\n // old row stays intact — the request fails cleanly and a retry\n // converges on the rename-onto-existing path below.\n const renamed = await this.#db.updateAtomic<CustomProviderDbRow>(\n 'custom_providers',\n { org_id: orgId, provider_id: renameFrom },\n () => ({\n provider_id: input.providerId,\n name: input.name,\n url: input.url,\n api_key: input.apiKey ?? null,\n models: input.models,\n updated_at: now,\n }),\n );\n if (renamed) return toRecord(renamed);\n // Old row already gone — fall through to a plain create of the new id.\n }\n // Rename onto an existing id: overwrite the target below, then delete\n // the old row last — a failure in the gap leaves a redundant duplicate\n // (recoverable by re-submitting or deleting) instead of losing data.\n }\n\n const record = await this.#write({ orgId, userId, input, now });\n if (renameFrom) {\n await this.#db.deleteMany('custom_providers', { org_id: orgId, provider_id: renameFrom });\n }\n return record;\n }\n\n /**\n * Update-first, then insert-and-catch-unique-violation (see `queue_health`):\n * concurrent creates of the same provider both succeed (last write wins on\n * the single row) instead of one failing on the unique index, and a row\n * deleted mid-flight is recreated rather than reported as a stale success.\n */\n async #write({\n orgId,\n userId,\n input,\n now,\n }: {\n orgId: string;\n userId: string;\n input: UpsertCustomProviderInput;\n now: Date;\n }): Promise<CustomProviderRecord> {\n const updateExisting = () =>\n this.#db.updateAtomic<CustomProviderDbRow>(\n 'custom_providers',\n { org_id: orgId, provider_id: input.providerId },\n () => ({\n name: input.name,\n url: input.url,\n api_key: input.apiKey ?? null,\n models: input.models,\n updated_at: now,\n }),\n );\n\n const updated = await updateExisting();\n if (updated) return toRecord(updated);\n\n try {\n const row = await this.#db.insertOne<CustomProviderDbRow>('custom_providers', {\n org_id: orgId,\n created_by: userId,\n provider_id: input.providerId,\n name: input.name,\n url: input.url,\n api_key: input.apiKey ?? null,\n models: input.models,\n created_at: now,\n updated_at: now,\n });\n return toRecord(row);\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n // Lost the insert race — apply this write to the winning row.\n const row = await updateExisting();\n if (!row) throw error;\n return toRecord(row);\n }\n }\n\n async list({ orgId }: { orgId: string }): Promise<CustomProviderRecord[]> {\n const rows = await this.#db.findMany<CustomProviderDbRow>(\n 'custom_providers',\n { org_id: orgId },\n { orderBy: [['name', 'asc']] },\n );\n return rows.map(toRecord);\n }\n\n async delete({ orgId, providerId }: { orgId: string; providerId: string }): Promise<boolean> {\n return (await this.#db.deleteMany('custom_providers', { org_id: orgId, provider_id: providerId })) > 0;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"base.js","names":["#db","#write"],"sources":["../../../../src/storage/domains/custom-providers/base.ts"],"sourcesContent":["import { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\n/**\n * A user-defined OpenAI-compatible provider. The DB-backed counterpart of the\n * local `settings.json` `customProviders` entries: org-scoped rows keyed by the\n * derived provider id (name slug), API key stored alongside so a deployed\n * server never reads the shared settings file.\n */\nexport interface CustomProviderRecord {\n id: string;\n orgId: string;\n createdBy: string;\n /** Stable slug derived from the name (`getCustomProviderId`). */\n providerId: string;\n name: string;\n url: string;\n apiKey: string | null;\n models: string[];\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpsertCustomProviderInput {\n providerId: string;\n name: string;\n url: string;\n apiKey?: string;\n models: string[];\n}\n\nexport const CUSTOM_PROVIDERS_SCHEMA: CollectionSchema = {\n name: 'custom_providers',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n created_by: { type: 'text' },\n provider_id: { type: 'text' },\n name: { type: 'text' },\n url: { type: 'text' },\n api_key: { type: 'text', nullable: true },\n models: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'custom_providers_org_provider_key', columns: ['org_id', 'provider_id'] }],\n};\n\ninterface CustomProviderDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n created_by: string;\n provider_id: string;\n name: string;\n url: string;\n api_key: string | null;\n models: string[];\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toRecord(row: CustomProviderDbRow): CustomProviderRecord {\n return {\n id: row.id,\n orgId: row.org_id,\n createdBy: row.created_by,\n providerId: row.provider_id,\n name: row.name,\n url: row.url,\n apiKey: row.api_key,\n models: Array.isArray(row.models) ? row.models : [],\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class CustomProvidersStorage extends FactoryStorageDomain {\n constructor() {\n super('custom-providers');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([CUSTOM_PROVIDERS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('custom_providers', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n /**\n * Create or wholesale-replace a provider by `(orgId, providerId)` — mirrors\n * the settings.json upsert semantics (no key retention: an absent `apiKey`\n * clears the stored key). `previousProviderId` renames the provider: the\n * common path is a single atomic in-place update of the old row; renaming\n * onto an id that already exists overwrites the target first and removes the\n * old row last, so no interleaving or failure can lose the provider.\n */\n async upsert({\n orgId,\n userId,\n input,\n previousProviderId,\n }: {\n orgId: string;\n userId: string;\n input: UpsertCustomProviderInput;\n previousProviderId?: string;\n }): Promise<CustomProviderRecord> {\n const now = new Date();\n const renameFrom = previousProviderId && previousProviderId !== input.providerId ? previousProviderId : undefined;\n\n if (renameFrom) {\n const target = await this.#db.findOne<CustomProviderDbRow>('custom_providers', {\n org_id: orgId,\n provider_id: input.providerId,\n });\n if (!target) {\n // In-place rename: one atomic write with no delete/insert gap, so a\n // failure can never drop the provider (and `created_at`/`created_by`\n // are preserved). If a concurrent create grabs the new id between the\n // lookup and this update, the unique index rejects the update and the\n // old row stays intact — the request fails cleanly and a retry\n // converges on the rename-onto-existing path below.\n const renamed = await this.#db.updateAtomic<CustomProviderDbRow>(\n 'custom_providers',\n { org_id: orgId, provider_id: renameFrom },\n () => ({\n provider_id: input.providerId,\n name: input.name,\n url: input.url,\n api_key: input.apiKey ?? null,\n models: input.models,\n updated_at: now,\n }),\n );\n if (renamed) return toRecord(renamed);\n // Old row already gone — fall through to a plain create of the new id.\n }\n // Rename onto an existing id: overwrite the target below, then delete\n // the old row last — a failure in the gap leaves a redundant duplicate\n // (recoverable by re-submitting or deleting) instead of losing data.\n }\n\n const record = await this.#write({ orgId, userId, input, now });\n if (renameFrom) {\n await this.#db.deleteMany('custom_providers', { org_id: orgId, provider_id: renameFrom });\n }\n return record;\n }\n\n /**\n * Update-first, then insert-and-catch-unique-violation (see `queue_health`):\n * concurrent creates of the same provider both succeed (last write wins on\n * the single row) instead of one failing on the unique index, and a row\n * deleted mid-flight is recreated rather than reported as a stale success.\n */\n async #write({\n orgId,\n userId,\n input,\n now,\n }: {\n orgId: string;\n userId: string;\n input: UpsertCustomProviderInput;\n now: Date;\n }): Promise<CustomProviderRecord> {\n const updateExisting = () =>\n this.#db.updateAtomic<CustomProviderDbRow>(\n 'custom_providers',\n { org_id: orgId, provider_id: input.providerId },\n () => ({\n name: input.name,\n url: input.url,\n api_key: input.apiKey ?? null,\n models: input.models,\n updated_at: now,\n }),\n );\n\n const updated = await updateExisting();\n if (updated) return toRecord(updated);\n\n try {\n const row = await this.#db.insertOne<CustomProviderDbRow>('custom_providers', {\n org_id: orgId,\n created_by: userId,\n provider_id: input.providerId,\n name: input.name,\n url: input.url,\n api_key: input.apiKey ?? null,\n models: input.models,\n created_at: now,\n updated_at: now,\n });\n return toRecord(row);\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n // Lost the insert race — apply this write to the winning row.\n const row = await updateExisting();\n if (!row) throw error;\n return toRecord(row);\n }\n }\n\n async list({ orgId }: { orgId: string }): Promise<CustomProviderRecord[]> {\n const rows = await this.#db.findMany<CustomProviderDbRow>(\n 'custom_providers',\n { org_id: orgId },\n { orderBy: [['name', 'asc']] },\n );\n return rows.map(toRecord);\n }\n\n async delete({ orgId, providerId }: { orgId: string; providerId: string }): Promise<boolean> {\n return (await this.#db.deleteMany('custom_providers', { org_id: orgId, provider_id: providerId })) > 0;\n }\n}\n"],"mappings":"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"}
@@ -1,62 +1,80 @@
1
- // src/storage/domains/intake/base.ts
2
1
  import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
3
- var DEFAULT_INTAKE_CONFIG = {};
4
- var INTAKE_SETTINGS_SCHEMA = {
5
- name: "intake_settings",
6
- columns: {
7
- id: { type: "uuid-pk" },
8
- org_id: { type: "text" },
9
- user_id: { type: "text" },
10
- config: { type: "json" },
11
- created_at: { type: "timestamp" },
12
- updated_at: { type: "timestamp" }
13
- },
14
- uniqueIndexes: [{ name: "intake_settings_org_user_unique", columns: ["org_id", "user_id"] }]
2
+ //#region src/storage/domains/intake/base.ts
3
+ /**
4
+ * Per-user intake selections for every configured intake integration.
5
+ *
6
+ * Integration ids are dynamic. Each integration contributes provider-neutral
7
+ * sources through `FactoryIntegration.intake`; this domain only persists which
8
+ * source ids the user selected.
9
+ */
10
+ const DEFAULT_INTAKE_CONFIG = {};
11
+ const INTAKE_SETTINGS_SCHEMA = {
12
+ name: "intake_settings",
13
+ columns: {
14
+ id: { type: "uuid-pk" },
15
+ org_id: { type: "text" },
16
+ user_id: { type: "text" },
17
+ config: { type: "json" },
18
+ created_at: { type: "timestamp" },
19
+ updated_at: { type: "timestamp" }
20
+ },
21
+ uniqueIndexes: [{
22
+ name: "intake_settings_org_user_unique",
23
+ columns: ["org_id", "user_id"]
24
+ }]
15
25
  };
16
26
  var IntakeStorage = class extends FactoryStorageDomain {
17
- constructor() {
18
- super("intake");
19
- }
20
- async init() {
21
- await this.ensureCollections([INTAKE_SETTINGS_SCHEMA]);
22
- }
23
- async dangerouslyClearAll() {
24
- await this.ops.deleteMany("intake_settings", {});
25
- }
26
- get #db() {
27
- return this.ops;
28
- }
29
- async getConfig({
30
- orgId,
31
- userId,
32
- integrationIds
33
- }) {
34
- const row = await this.#db.findOne("intake_settings", {
35
- org_id: orgId,
36
- user_id: userId
37
- });
38
- const saved = structuredClone(row?.config ?? DEFAULT_INTAKE_CONFIG);
39
- if (!integrationIds) return saved;
40
- return Object.fromEntries(
41
- integrationIds.map((integrationId) => [integrationId, saved[integrationId] ?? { enabled: true, sourceIds: null }])
42
- );
43
- }
44
- async saveConfig({ orgId, userId, config }) {
45
- const now = /* @__PURE__ */ new Date();
46
- const where = { org_id: orgId, user_id: userId };
47
- const updated = await this.#db.updateMany("intake_settings", where, { config, updated_at: now });
48
- if (updated > 0) return;
49
- try {
50
- await this.#db.insertOne("intake_settings", { ...where, config, created_at: now, updated_at: now });
51
- } catch (error) {
52
- if (!(error instanceof UniqueViolationError)) throw error;
53
- await this.#db.updateMany("intake_settings", where, { config, updated_at: now });
54
- }
55
- }
56
- };
57
- export {
58
- DEFAULT_INTAKE_CONFIG,
59
- INTAKE_SETTINGS_SCHEMA,
60
- IntakeStorage
27
+ constructor() {
28
+ super("intake");
29
+ }
30
+ async init() {
31
+ await this.ensureCollections([INTAKE_SETTINGS_SCHEMA]);
32
+ }
33
+ async dangerouslyClearAll() {
34
+ await this.ops.deleteMany("intake_settings", {});
35
+ }
36
+ get #db() {
37
+ return this.ops;
38
+ }
39
+ async getConfig({ orgId, userId, integrationIds }) {
40
+ const row = await this.#db.findOne("intake_settings", {
41
+ org_id: orgId,
42
+ user_id: userId
43
+ });
44
+ const saved = structuredClone(row?.config ?? DEFAULT_INTAKE_CONFIG);
45
+ if (!integrationIds) return saved;
46
+ return Object.fromEntries(integrationIds.map((integrationId) => [integrationId, saved[integrationId] ?? {
47
+ enabled: true,
48
+ sourceIds: null
49
+ }]));
50
+ }
51
+ async saveConfig({ orgId, userId, config }) {
52
+ const now = /* @__PURE__ */ new Date();
53
+ const where = {
54
+ org_id: orgId,
55
+ user_id: userId
56
+ };
57
+ if (await this.#db.updateMany("intake_settings", where, {
58
+ config,
59
+ updated_at: now
60
+ }) > 0) return;
61
+ try {
62
+ await this.#db.insertOne("intake_settings", {
63
+ ...where,
64
+ config,
65
+ created_at: now,
66
+ updated_at: now
67
+ });
68
+ } catch (error) {
69
+ if (!(error instanceof UniqueViolationError)) throw error;
70
+ await this.#db.updateMany("intake_settings", where, {
71
+ config,
72
+ updated_at: now
73
+ });
74
+ }
75
+ }
61
76
  };
77
+ //#endregion
78
+ export { DEFAULT_INTAKE_CONFIG, INTAKE_SETTINGS_SCHEMA, IntakeStorage };
79
+
62
80
  //# sourceMappingURL=base.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/storage/domains/intake/base.ts"],"sourcesContent":["/**\n * Per-user intake selections for every configured intake integration.\n *\n * Integration ids are dynamic. Each integration contributes provider-neutral\n * sources through `FactoryIntegration.intake`; this domain only persists which\n * source ids the user selected.\n */\n\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport interface IntakeSelection {\n enabled: boolean;\n /** Provider-owned source ids; `null` means nothing is selected. */\n sourceIds: string[] | null;\n}\n\nexport type IntakeConfig = Record<string, IntakeSelection>;\n\nexport const DEFAULT_INTAKE_CONFIG: IntakeConfig = {};\n\nexport const INTAKE_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'intake_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'intake_settings_org_user_unique', columns: ['org_id', 'user_id'] }],\n};\n\nexport class IntakeStorage extends FactoryStorageDomain {\n constructor() {\n super('intake');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([INTAKE_SETTINGS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('intake_settings', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async getConfig({\n orgId,\n userId,\n integrationIds,\n }: {\n orgId: string;\n userId: string;\n /**\n * When provided, the result contains exactly these integration ids, with\n * unset integrations defaulting to `{ enabled: true, sourceIds: null }`.\n */\n integrationIds?: string[];\n }): Promise<IntakeConfig> {\n const row = await this.#db.findOne<{ config: IntakeConfig }>('intake_settings', {\n org_id: orgId,\n user_id: userId,\n });\n const saved = structuredClone(row?.config ?? DEFAULT_INTAKE_CONFIG);\n if (!integrationIds) return saved;\n return Object.fromEntries(\n integrationIds.map(integrationId => [integrationId, saved[integrationId] ?? { enabled: true, sourceIds: null }]),\n );\n }\n\n async saveConfig({ orgId, userId, config }: { orgId: string; userId: string; config: IntakeConfig }): Promise<void> {\n const now = new Date();\n const where = { org_id: orgId, user_id: userId };\n const updated = await this.#db.updateMany('intake_settings', where, { config, updated_at: now });\n if (updated > 0) return;\n try {\n await this.#db.insertOne('intake_settings', { ...where, config, created_at: now, updated_at: now });\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n await this.#db.updateMany('intake_settings', where, { config, updated_at: now });\n }\n }\n}\n"],"mappings":";AAQA,SAAS,sBAAsB,4BAA4B;AAWpD,IAAM,wBAAsC,CAAC;AAE7C,IAAM,yBAA2C;AAAA,EACtD,MAAM;AAAA,EACN,SAAS;AAAA,IACP,IAAI,EAAE,MAAM,UAAU;AAAA,IACtB,QAAQ,EAAE,MAAM,OAAO;AAAA,IACvB,SAAS,EAAE,MAAM,OAAO;AAAA,IACxB,QAAQ,EAAE,MAAM,OAAO;AAAA,IACvB,YAAY,EAAE,MAAM,YAAY;AAAA,IAChC,YAAY,EAAE,MAAM,YAAY;AAAA,EAClC;AAAA,EACA,eAAe,CAAC,EAAE,MAAM,mCAAmC,SAAS,CAAC,UAAU,SAAS,EAAE,CAAC;AAC7F;AAEO,IAAM,gBAAN,cAA4B,qBAAqB;AAAA,EACtD,cAAc;AACZ,UAAM,QAAQ;AAAA,EAChB;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,KAAK,kBAAkB,CAAC,sBAAsB,CAAC;AAAA,EACvD;AAAA,EAEA,MAAM,sBAAqC;AACzC,UAAM,KAAK,IAAI,WAAW,mBAAmB,CAAC,CAAC;AAAA,EACjD;AAAA,EAEA,IAAI,MAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAU;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAQ0B;AACxB,UAAM,MAAM,MAAM,KAAK,IAAI,QAAkC,mBAAmB;AAAA,MAC9E,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AACD,UAAM,QAAQ,gBAAgB,KAAK,UAAU,qBAAqB;AAClE,QAAI,CAAC,eAAgB,QAAO;AAC5B,WAAO,OAAO;AAAA,MACZ,eAAe,IAAI,mBAAiB,CAAC,eAAe,MAAM,aAAa,KAAK,EAAE,SAAS,MAAM,WAAW,KAAK,CAAC,CAAC;AAAA,IACjH;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,EAAE,OAAO,QAAQ,OAAO,GAA2E;AAClH,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,QAAQ,EAAE,QAAQ,OAAO,SAAS,OAAO;AAC/C,UAAM,UAAU,MAAM,KAAK,IAAI,WAAW,mBAAmB,OAAO,EAAE,QAAQ,YAAY,IAAI,CAAC;AAC/F,QAAI,UAAU,EAAG;AACjB,QAAI;AACF,YAAM,KAAK,IAAI,UAAU,mBAAmB,EAAE,GAAG,OAAO,QAAQ,YAAY,KAAK,YAAY,IAAI,CAAC;AAAA,IACpG,SAAS,OAAO;AACd,UAAI,EAAE,iBAAiB,sBAAuB,OAAM;AACpD,YAAM,KAAK,IAAI,WAAW,mBAAmB,OAAO,EAAE,QAAQ,YAAY,IAAI,CAAC;AAAA,IACjF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"file":"base.js","names":["#db"],"sources":["../../../../src/storage/domains/intake/base.ts"],"sourcesContent":["/**\n * Per-user intake selections for every configured intake integration.\n *\n * Integration ids are dynamic. Each integration contributes provider-neutral\n * sources through `FactoryIntegration.intake`; this domain only persists which\n * source ids the user selected.\n */\n\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport interface IntakeSelection {\n enabled: boolean;\n /** Provider-owned source ids; `null` means nothing is selected. */\n sourceIds: string[] | null;\n}\n\nexport type IntakeConfig = Record<string, IntakeSelection>;\n\nexport const DEFAULT_INTAKE_CONFIG: IntakeConfig = {};\n\nexport const INTAKE_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'intake_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'intake_settings_org_user_unique', columns: ['org_id', 'user_id'] }],\n};\n\nexport class IntakeStorage extends FactoryStorageDomain {\n constructor() {\n super('intake');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([INTAKE_SETTINGS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('intake_settings', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async getConfig({\n orgId,\n userId,\n integrationIds,\n }: {\n orgId: string;\n userId: string;\n /**\n * When provided, the result contains exactly these integration ids, with\n * unset integrations defaulting to `{ enabled: true, sourceIds: null }`.\n */\n integrationIds?: string[];\n }): Promise<IntakeConfig> {\n const row = await this.#db.findOne<{ config: IntakeConfig }>('intake_settings', {\n org_id: orgId,\n user_id: userId,\n });\n const saved = structuredClone(row?.config ?? DEFAULT_INTAKE_CONFIG);\n if (!integrationIds) return saved;\n return Object.fromEntries(\n integrationIds.map(integrationId => [integrationId, saved[integrationId] ?? { enabled: true, sourceIds: null }]),\n );\n }\n\n async saveConfig({ orgId, userId, config }: { orgId: string; userId: string; config: IntakeConfig }): Promise<void> {\n const now = new Date();\n const where = { org_id: orgId, user_id: userId };\n const updated = await this.#db.updateMany('intake_settings', where, { config, updated_at: now });\n if (updated > 0) return;\n try {\n await this.#db.insertOne('intake_settings', { ...where, config, created_at: now, updated_at: now });\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n await this.#db.updateMany('intake_settings', where, { config, updated_at: now });\n }\n }\n}\n"],"mappings":";;;;;;;;;AAmBA,MAAa,wBAAsC,CAAC;AAEpD,MAAa,yBAA2C;CACtD,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,SAAS,EAAE,MAAM,OAAO;EACxB,QAAQ,EAAE,MAAM,OAAO;EACvB,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,eAAe,CAAC;EAAE,MAAM;EAAmC,SAAS,CAAC,UAAU,SAAS;CAAE,CAAC;AAC7F;AAEA,IAAa,gBAAb,cAAmC,qBAAqB;CACtD,cAAc;EACZ,MAAM,QAAQ;CAChB;CAEA,MAAM,OAAsB;EAC1B,MAAM,KAAK,kBAAkB,CAAC,sBAAsB,CAAC;CACvD;CAEA,MAAM,sBAAqC;EACzC,MAAM,KAAK,IAAI,WAAW,mBAAmB,CAAC,CAAC;CACjD;CAEA,IAAIA,MAAyB;EAC3B,OAAO,KAAK;CACd;CAEA,MAAM,UAAU,EACd,OACA,QACA,kBASwB;EACxB,MAAM,MAAM,MAAM,KAAKA,IAAI,QAAkC,mBAAmB;GAC9E,QAAQ;GACR,SAAS;EACX,CAAC;EACD,MAAM,QAAQ,gBAAgB,KAAK,UAAU,qBAAqB;EAClE,IAAI,CAAC,gBAAgB,OAAO;EAC5B,OAAO,OAAO,YACZ,eAAe,KAAI,kBAAiB,CAAC,eAAe,MAAM,kBAAkB;GAAE,SAAS;GAAM,WAAW;EAAK,CAAC,CAAC,CACjH;CACF;CAEA,MAAM,WAAW,EAAE,OAAO,QAAQ,UAAkF;EAClH,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,QAAQ;GAAE,QAAQ;GAAO,SAAS;EAAO;EAE/C,IAAI,MADkB,KAAKA,IAAI,WAAW,mBAAmB,OAAO;GAAE;GAAQ,YAAY;EAAI,CAAC,IACjF,GAAG;EACjB,IAAI;GACF,MAAM,KAAKA,IAAI,UAAU,mBAAmB;IAAE,GAAG;IAAO;IAAQ,YAAY;IAAK,YAAY;GAAI,CAAC;EACpG,SAAS,OAAO;GACd,IAAI,EAAE,iBAAiB,uBAAuB,MAAM;GACpD,MAAM,KAAKA,IAAI,WAAW,mBAAmB,OAAO;IAAE;IAAQ,YAAY;GAAI,CAAC;EACjF;CACF;AACF"}