create-feedbax 0.2.0 → 0.2.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 (143) hide show
  1. package/README.md +17 -5
  2. package/dist/cli.js +2610 -291
  3. package/dist/index.js +2375 -200
  4. package/package.json +7 -7
  5. package/template/.feedbax-template.sha256 +1 -1
  6. package/template/.gitignore.template +1 -0
  7. package/template/.npmignore.template +1 -0
  8. package/template/.nvmrc +1 -0
  9. package/template/AGENTS.md +13 -0
  10. package/template/CONNECTED.md +418 -0
  11. package/template/README.md +97 -0
  12. package/template/components.json +1 -1
  13. package/template/eslint.config.mjs +23 -0
  14. package/template/feedbax-vite.ts +79 -0
  15. package/template/migrations/0001_connected.sql +6 -0
  16. package/template/migrations/0002_participation.sql +8 -0
  17. package/template/migrations/0003_images.sql +3 -0
  18. package/template/migrations/0004_followed_status.sql +9 -0
  19. package/template/migrations/0005_github.sql +4 -0
  20. package/template/migrations/0006_integration.sql +3 -0
  21. package/template/migrations/0007_ownership.sql +2 -0
  22. package/template/migrations/0008_integration_recovery.sql +5 -0
  23. package/template/migrations/0009_observed_history.sql +3 -0
  24. package/template/package.json +39 -34
  25. package/template/src/authorized-draft-post.tsx +1 -0
  26. package/template/src/changelog-page.tsx +63 -54
  27. package/template/src/changelog-runtime.ts +2 -1
  28. package/template/src/cloudflare-workers.d.ts +9 -0
  29. package/template/src/comment-creation.test.tsx +95 -7
  30. package/template/src/comment-thread-page.ts +11 -1
  31. package/template/src/components/command-palette.tsx +59 -30
  32. package/template/src/components/connected-identity-provider.tsx +135 -0
  33. package/template/src/components/device-profile-provider.tsx +41 -26
  34. package/template/src/components/follow-post-button.tsx +78 -0
  35. package/template/src/components/header.tsx +2 -0
  36. package/template/src/components/image-attachments.tsx +187 -0
  37. package/template/src/components/loader.tsx +48 -5
  38. package/template/src/components/notification-inbox.tsx +232 -0
  39. package/template/src/components/portal-footer.tsx +14 -0
  40. package/template/src/components/post-history.tsx +101 -0
  41. package/template/src/components/profile-menu.tsx +37 -0
  42. package/template/src/components/ui/components/command.tsx +30 -29
  43. package/template/src/components/ui/components/message-scroller.tsx +2 -2
  44. package/template/src/components/ui/components/scroll-area.tsx +0 -1
  45. package/template/src/components/ui/components/switch.tsx +29 -0
  46. package/template/src/components/ui/styles/globals.css +1 -1
  47. package/template/src/configured-feedback.test.ts +82 -0
  48. package/template/src/configured-feedback.ts +61 -0
  49. package/template/src/connected-identity.test.ts +148 -0
  50. package/template/src/connected-identity.ts +127 -0
  51. package/template/src/connected-participation.test.tsx +67 -0
  52. package/template/src/connected-runtime.test.ts +244 -0
  53. package/template/src/connected-runtime.ts +176 -0
  54. package/template/src/connected-social.test.tsx +158 -0
  55. package/template/src/feedback-cache-invalidation.ts +3 -0
  56. package/template/src/feedback-runtime.ts +123 -13
  57. package/template/src/feedbax/changelog/index.test.ts +35 -0
  58. package/template/src/feedbax/changelog/index.ts +5 -1
  59. package/template/src/feedbax/changelog/notion-changelog.test.ts +1 -1
  60. package/template/src/feedbax/changelog/notion-changelog.ts +1 -1
  61. package/template/src/feedbax/config/index.test.ts +73 -1
  62. package/template/src/feedbax/config/index.ts +205 -9
  63. package/template/src/feedbax/feedback/comment-storage.ts +38 -0
  64. package/template/src/feedbax/feedback/connected-feedback.ts +235 -0
  65. package/template/src/feedbax/feedback/connected.test.ts +272 -0
  66. package/template/src/feedbax/feedback/connected.ts +225 -0
  67. package/template/src/feedbax/feedback/email-delivery.test.ts +65 -0
  68. package/template/src/feedbax/feedback/email-delivery.ts +66 -0
  69. package/template/src/feedbax/feedback/feedback-storage.ts +1 -0
  70. package/template/src/feedbax/feedback/github-comments.ts +390 -0
  71. package/template/src/feedbax/feedback/github-feedback.test.ts +1138 -0
  72. package/template/src/feedbax/feedback/github-feedback.ts +581 -0
  73. package/template/src/feedbax/feedback/github-request.ts +120 -0
  74. package/template/src/feedbax/feedback/github-service-client.ts +56 -0
  75. package/template/src/feedbax/feedback/identity-handoff.test.ts +81 -0
  76. package/template/src/feedbax/feedback/identity-handoff.ts +119 -0
  77. package/template/src/feedbax/feedback/image-feedback.ts +114 -0
  78. package/template/src/feedbax/feedback/images.test.ts +223 -0
  79. package/template/src/feedbax/feedback/images.ts +350 -0
  80. package/template/src/feedbax/feedback/index.ts +226 -16
  81. package/template/src/feedbax/feedback/integration-auth.ts +138 -0
  82. package/template/src/feedbax/feedback/notion-comments.ts +2 -35
  83. package/template/src/feedbax/feedback/notion-image-review.ts +55 -0
  84. package/template/src/feedbax/feedback/observed-history.test.ts +150 -0
  85. package/template/src/feedbax/feedback/observed-history.ts +219 -0
  86. package/template/src/feedbax/feedback/ownership.ts +170 -0
  87. package/template/src/feedbax/feedback/participation.test.ts +653 -0
  88. package/template/src/feedbax/feedback/participation.ts +502 -0
  89. package/template/src/history-runtime.test.ts +80 -0
  90. package/template/src/history-runtime.ts +37 -0
  91. package/template/src/images-runtime.test.ts +133 -0
  92. package/template/src/images-runtime.ts +125 -0
  93. package/template/src/index.css +103 -440
  94. package/template/src/integration-runtime.test.ts +365 -0
  95. package/template/src/integration-runtime.ts +289 -0
  96. package/template/src/lazy-post-detail-overlay.tsx +13 -2
  97. package/template/src/my-feedback-page.test.tsx +152 -0
  98. package/template/src/my-feedback-page.tsx +398 -0
  99. package/template/src/my-feedback-runtime.test.ts +93 -0
  100. package/template/src/my-feedback-runtime.ts +154 -0
  101. package/template/src/overlay-post-detail.test.tsx +59 -8
  102. package/template/src/overlay-post-detail.tsx +20 -69
  103. package/template/src/participation-client.ts +63 -0
  104. package/template/src/participation-runtime.test.ts +35 -0
  105. package/template/src/participation-runtime.ts +255 -0
  106. package/template/src/portal-comments.ts +35 -5
  107. package/template/src/portal-feedback-form.tsx +29 -6
  108. package/template/src/portal-feedback-runtime.ts +3 -0
  109. package/template/src/portal-feedback-server-function.ts +6 -3
  110. package/template/src/portal-feedback-submission.ts +19 -0
  111. package/template/src/portal-server-entry.ts +13 -0
  112. package/template/src/post-creation-flow.tsx +2 -2
  113. package/template/src/post-detail-content.test.tsx +233 -0
  114. package/template/src/post-detail-content.tsx +162 -0
  115. package/template/src/post-detail-query.ts +34 -0
  116. package/template/src/post-results.tsx +1 -1
  117. package/template/src/public-cache-policy.test.ts +11 -4
  118. package/template/src/public-cache-policy.ts +1 -1
  119. package/template/src/public-feedback-index.tsx +9 -39
  120. package/template/src/public-feedback-page.test.tsx +65 -0
  121. package/template/src/public-feedback-page.ts +12 -1
  122. package/template/src/public-portal-error.tsx +1 -1
  123. package/template/src/public-post-detail-skeleton.tsx +54 -0
  124. package/template/src/public-post-detail.tsx +437 -271
  125. package/template/src/public-post-route.test.tsx +39 -3
  126. package/template/src/public-post-route.tsx +15 -28
  127. package/template/src/public-release-links.test.ts +120 -0
  128. package/template/src/public-release-links.ts +130 -0
  129. package/template/src/public-roadmap-route.test.tsx +38 -2
  130. package/template/src/public-roadmap-view.tsx +56 -23
  131. package/template/src/public-shell.test.tsx +26 -0
  132. package/template/src/routeTree.gen.ts +70 -3
  133. package/template/src/router.tsx +2 -0
  134. package/template/src/routes/__root.tsx +3 -5
  135. package/template/src/routes/email-preferences.tsx +77 -0
  136. package/template/src/routes/my-feedback.tsx +16 -0
  137. package/template/src/routes/submit.tsx +1 -1
  138. package/template/src/safe-public-failure.ts +3 -1
  139. package/template/src/server.ts +87 -2
  140. package/template/src/submission-intent.ts +26 -0
  141. package/template/src/trusted-feedback-handler.test.ts +1 -1
  142. package/template/src/vote-toggle.tsx +42 -9
  143. package/template/vite.config.ts +2 -0
package/dist/index.js CHANGED
@@ -1,9 +1,13 @@
1
1
  // src/index.ts
2
- import { createHash as createHash2, randomBytes } from "node:crypto";
3
- import { readFile as readFile2, readdir as readdir2, writeFile as writeFile2 } from "node:fs/promises";
2
+ import { createHash as createHash3, randomBytes as randomBytes2 } from "node:crypto";
3
+ import { readFile as readFile3, readdir as readdir2, writeFile as writeFile3 } from "node:fs/promises";
4
4
 
5
5
  // ../config/src/index.ts
6
6
  var rootKeys = [
7
+ "history",
8
+ "provider",
9
+ "github",
10
+ "connected",
7
11
  "product",
8
12
  "theme",
9
13
  "notion",
@@ -46,6 +50,8 @@ var changelogPropertyKeys = [
46
50
  function defineFeedbax(config) {
47
51
  const value = object(config, "Feedbax configuration");
48
52
  rejectUnknown(value, rootKeys, "Feedbax configuration");
53
+ if (value.history !== void 0 && typeof value.history !== "boolean")
54
+ throw new Error("history must be true or false.");
49
55
  const product = object(value.product, "product");
50
56
  rejectUnknown(
51
57
  product,
@@ -60,13 +66,81 @@ function defineFeedbax(config) {
60
66
  ...optionalPublicUrl(product, "supportUrl"),
61
67
  ...optionalPublicUrl(product, "privacyUrl")
62
68
  };
69
+ let connected;
70
+ if (value.connected !== void 0) {
71
+ const input = object(value.connected, "connected");
72
+ rejectUnknown(
73
+ input,
74
+ ["issuer", "loginUrl", "email", "images", "processing"],
75
+ "connected"
76
+ );
77
+ const issuer = publicUrl(input.issuer, "connected.issuer", false);
78
+ const loginUrl = publicUrl(input.loginUrl, "connected.loginUrl", false);
79
+ if (!validatedProduct.siteUrl)
80
+ throw new Error("Connected Profile requires product.siteUrl.");
81
+ if (new URL(loginUrl).username || new URL(loginUrl).password || new URL(loginUrl).hash)
82
+ throw new Error(
83
+ "connected.loginUrl must not contain credentials or a fragment."
84
+ );
85
+ let email;
86
+ if (input.email !== void 0) {
87
+ const sender = object(input.email, "connected.email");
88
+ rejectUnknown(
89
+ sender,
90
+ ["provider", "from", "endpoint"],
91
+ "connected.email"
92
+ );
93
+ if (!["cloudflare", "resend", "custom"].includes(String(sender.provider)))
94
+ throw new Error(
95
+ "connected.email.provider must be cloudflare, resend, or custom."
96
+ );
97
+ const from = text(sender.from, "connected.email.from");
98
+ if (from.length > 254 || !/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(from))
99
+ throw new Error(
100
+ "connected.email.from must be a plain sender email address."
101
+ );
102
+ const endpoint = sender.endpoint === void 0 ? void 0 : publicUrl(sender.endpoint, "connected.email.endpoint", false);
103
+ if (sender.provider === "custom" && !endpoint)
104
+ throw new Error("Custom email requires connected.email.endpoint.");
105
+ if (sender.provider !== "custom" && endpoint)
106
+ throw new Error("Only custom email uses connected.email.endpoint.");
107
+ if (endpoint && (new URL(endpoint).username || new URL(endpoint).password || new URL(endpoint).hash))
108
+ throw new Error(
109
+ "Custom email endpoint must not contain credentials or a fragment."
110
+ );
111
+ email = {
112
+ provider: sender.provider,
113
+ from,
114
+ ...endpoint ? { endpoint } : {}
115
+ };
116
+ }
117
+ if (input.images !== void 0 && typeof input.images !== "boolean")
118
+ throw new Error("connected.images must be true or false.");
119
+ if (input.processing !== void 0 && input.processing !== "small" && input.processing !== "standard")
120
+ throw new Error("connected.processing must be small or standard.");
121
+ connected = {
122
+ issuer,
123
+ loginUrl,
124
+ ...input.processing !== void 0 ? { processing: input.processing } : {},
125
+ ...email ? { email } : {},
126
+ ...input.images !== void 0 ? { images: input.images } : {}
127
+ };
128
+ }
63
129
  const theme = object(value.theme, "theme");
64
130
  rejectUnknown(theme, ["preset"], "theme");
65
- const notion = storage(
66
- value.notion,
67
- feedbackPropertyKeys,
68
- "notion"
69
- );
131
+ if (value.provider !== void 0 && !["notion", "github"].includes(String(value.provider)))
132
+ throw new Error("provider must be notion or github.");
133
+ const githubMode = value.provider === "github";
134
+ if (githubMode && value.notion !== void 0 || !githubMode && value.github !== void 0)
135
+ throw new Error("Select exactly one Content Provider: notion or github.");
136
+ const content = githubMode ? { provider: "github", github: githubConfiguration(value.github) } : {
137
+ ...value.provider ? { provider: "notion" } : {},
138
+ notion: storage(
139
+ value.notion,
140
+ feedbackPropertyKeys,
141
+ "notion"
142
+ )
143
+ };
70
144
  const features = object(value.features, "features");
71
145
  rejectUnknown(features, featureKeys, "features");
72
146
  const validatedFeatures = Object.fromEntries(
@@ -76,6 +150,10 @@ function defineFeedbax(config) {
76
150
  return [key, features[key]];
77
151
  })
78
152
  );
153
+ if (githubMode && (validatedFeatures.changelog || value.changelog !== void 0))
154
+ throw new Error(
155
+ "GitHub Installations must disable Changelog (features.changelog: false) and remove Notion Changelog configuration."
156
+ );
79
157
  const changelog = value.changelog === void 0 ? void 0 : storage(
80
158
  value.changelog,
81
159
  changelogPropertyKeys,
@@ -102,8 +180,10 @@ function defineFeedbax(config) {
102
180
  throw new Error("Turnstile is enabled but turnstile.siteKey is missing.");
103
181
  return {
104
182
  product: validatedProduct,
183
+ ...value.history !== void 0 ? { history: value.history } : {},
184
+ ...connected ? { connected } : {},
105
185
  theme: { preset: text(theme.preset, "theme.preset") },
106
- notion,
186
+ ...content,
107
187
  ...changelog ? { changelog } : {},
108
188
  features: validatedFeatures,
109
189
  submissions: {
@@ -168,9 +248,44 @@ function publicUrl(value, label, allowRelative) {
168
248
  `${label} must be ${allowRelative ? "root-relative or " : ""}an HTTPS URL.`
169
249
  );
170
250
  }
251
+ function githubConfiguration(value) {
252
+ const input = object(value, "github");
253
+ rejectUnknown(
254
+ input,
255
+ ["installationId", "serviceUrl", "repository", "botUserId"],
256
+ "github"
257
+ );
258
+ const installationId = text(input.installationId, "github.installationId");
259
+ if (!/^[a-zA-Z0-9_-]{1,128}$/.test(installationId))
260
+ throw new Error(
261
+ "github.installationId must be a stable Installation identifier."
262
+ );
263
+ const serviceUrl = publicUrl(input.serviceUrl, "github.serviceUrl", false);
264
+ const url = new URL(serviceUrl);
265
+ if (url.origin !== serviceUrl || url.username || url.password)
266
+ throw new Error(
267
+ "github.serviceUrl must be an HTTPS origin without a path or credentials."
268
+ );
269
+ const repository = object(input.repository, "github.repository");
270
+ rejectUnknown(repository, ["id", "owner", "name"], "github.repository");
271
+ const owner = text(repository.owner, "github.repository.owner");
272
+ const name = text(repository.name, "github.repository.name");
273
+ if (!/^[A-Za-z0-9-]+$/.test(owner) || !/^[A-Za-z0-9_.-]+$/.test(name))
274
+ throw new Error("Use a valid GitHub repository owner and name.");
275
+ return {
276
+ installationId,
277
+ serviceUrl,
278
+ repository: {
279
+ id: positiveInteger(repository.id, "github.repository.id"),
280
+ owner,
281
+ name
282
+ },
283
+ botUserId: positiveInteger(input.botUserId, "github.botUserId")
284
+ };
285
+ }
171
286
 
172
287
  // src/index.ts
173
- import { basename, join as join2 } from "node:path";
288
+ import { basename, join as join3 } from "node:path";
174
289
 
175
290
  // src/template.ts
176
291
  import { createHash } from "node:crypto";
@@ -197,6 +312,22 @@ async function assembleFlatTemplate(coreRoot, destination) {
197
312
  await mkdir(join(target, "src/feedbax"), { recursive: true });
198
313
  await copy(join(coreRoot, "apps/portal/src"), join(target, "src"));
199
314
  await copy(join(coreRoot, "apps/portal/public"), join(target, "public"));
315
+ await copy(
316
+ join(coreRoot, "apps/portal/migrations"),
317
+ join(target, "migrations")
318
+ );
319
+ await copy(
320
+ join(coreRoot, "docs/connected-profile.md"),
321
+ join(target, "CONNECTED.md")
322
+ );
323
+ await copy(
324
+ join(coreRoot, "packages/create-feedbax/docs/installation-readme.md"),
325
+ join(target, "README.md")
326
+ );
327
+ await copy(
328
+ join(coreRoot, "packages/create-feedbax/docs/installation-agents.md"),
329
+ join(target, "AGENTS.md")
330
+ );
200
331
  await copy(
201
332
  join(coreRoot, "packages/feedback/src"),
202
333
  join(target, "src/feedbax/feedback")
@@ -213,12 +344,28 @@ async function assembleFlatTemplate(coreRoot, destination) {
213
344
  join(coreRoot, "packages/ui/src"),
214
345
  join(target, "src/components/ui")
215
346
  );
216
- for (const name of ["vite.config.ts"])
347
+ const stylesheet = join(target, "src/index.css");
348
+ await writeFile(
349
+ stylesheet,
350
+ (await readFile(stylesheet, "utf8")).replace(
351
+ '@import "@feedbax/ui/globals.css";',
352
+ '@import "./components/ui/styles/globals.css";'
353
+ )
354
+ );
355
+ const globals = join(target, "src/components/ui/styles/globals.css");
356
+ await writeFile(
357
+ globals,
358
+ (await readFile(globals, "utf8")).replace(
359
+ '@source "../../../../apps/**/*.{ts,tsx}";',
360
+ '@source "../../../**/*.{ts,tsx}";'
361
+ )
362
+ );
363
+ for (const name of ["vite.config.ts", "feedbax-vite.ts"])
217
364
  await copy(join(coreRoot, "apps/portal", name), join(target, name));
218
365
  const components = parse(
219
366
  await readFile(join(coreRoot, "apps/portal/components.json"), "utf8")
220
367
  );
221
- components.tailwind.css = "src/components/ui/styles/globals.css";
368
+ components.tailwind.css = "src/index.css";
222
369
  await writeFile(
223
370
  join(target, "components.json"),
224
371
  JSON.stringify(components, null, 2) + "\n"
@@ -235,6 +382,7 @@ async function assembleFlatTemplate(coreRoot, destination) {
235
382
  JSON.stringify(wrangler, null, 2) + "\n"
236
383
  );
237
384
  await copy(join(coreRoot, "LICENSE"), join(target, "LICENSE"));
385
+ await copy(join(coreRoot, ".nvmrc"), join(target, ".nvmrc"));
238
386
  await copy(
239
387
  join(coreRoot, "eslint.config.mjs"),
240
388
  join(target, "eslint.config.mjs")
@@ -332,11 +480,11 @@ export default defineFeedbax(${JSON.stringify(fixture, null, 2)});
332
480
  );
333
481
  await writeFile(
334
482
  join(target, ".gitignore.template"),
335
- ".dev.vars\n.env*\ndist/\n.wrangler/\n*.log\nnode_modules/\n"
483
+ ".dev.vars\n.env*\n.feedbax/\ndist/\n.wrangler/\n*.log\nnode_modules/\n"
336
484
  );
337
485
  await writeFile(
338
486
  join(target, ".npmignore.template"),
339
- ".dev.vars\n.env*\ndist/\n.wrangler/\n*.log\n"
487
+ ".dev.vars\n.env*\n.feedbax/\ndist/\n.wrangler/\n*.log\n"
340
488
  );
341
489
  await writeFile(
342
490
  join(target, ".prettierignore.template"),
@@ -408,9 +556,9 @@ async function flatManifest(coreRoot) {
408
556
  ])
409
557
  );
410
558
  const collect = (section) => Object.fromEntries(
411
- manifests.flatMap((manifest) => Object.entries(manifest[section] ?? {})).filter(([name]) => !name.startsWith("@feedbax/")).map(([name, version]) => [
559
+ manifests.flatMap((manifest) => Object.entries(manifest[section] ?? {})).filter(([name]) => !name.startsWith("@feedbax/")).map(([name, version2]) => [
412
560
  name,
413
- version === "catalog:" ? catalog[name] : version
561
+ version2 === "catalog:" ? catalog[name] : version2
414
562
  ])
415
563
  );
416
564
  return {
@@ -434,18 +582,19 @@ async function flatManifest(coreRoot) {
434
582
  devDependencies: {
435
583
  ...collect("devDependencies"),
436
584
  "@eslint/js": "10.0.1",
437
- "@types/node": "22.20.1",
585
+ "@shadcn/lint": "0.2.1",
586
+ "@types/node": "24.19.2",
438
587
  feedbax: JSON.parse(
439
588
  await readFile(join(coreRoot, "packages/feedbax/package.json"), "utf8")
440
589
  ).version,
441
- eslint: "10.8.1",
442
- globals: "17.11.0",
443
- prettier: "3.9.6",
444
- "typescript-eslint": "8.67.0",
445
- vitest: "4.1.11"
590
+ eslint: "10.12.0",
591
+ globals: "17.13.0",
592
+ prettier: "3.9.10",
593
+ "typescript-eslint": "8.71.2",
594
+ vitest: "5.0.4"
446
595
  },
447
596
  pnpm: { onlyBuiltDependencies: ["esbuild"] },
448
- engines: { node: ">=22.14.0" },
597
+ engines: { node: "^24.15.0 || >=26.0.0" },
449
598
  packageManager: "pnpm@10.29.3",
450
599
  license: "Apache-2.0"
451
600
  };
@@ -905,188 +1054,2144 @@ function isPropertyMap(value) {
905
1054
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
906
1055
  }
907
1056
 
908
- // ../feedback/src/index.ts
909
- var postCreationQueue = Promise.resolve();
1057
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/entity.js
1058
+ var entityKind = /* @__PURE__ */ Symbol.for("drizzle:entityKind");
1059
+ function is(value, type) {
1060
+ if (!value || typeof value !== "object") {
1061
+ return false;
1062
+ }
1063
+ if (value instanceof type) {
1064
+ return true;
1065
+ }
1066
+ if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
1067
+ throw new Error(
1068
+ `Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`
1069
+ );
1070
+ }
1071
+ let cls = Object.getPrototypeOf(value).constructor;
1072
+ if (cls) {
1073
+ while (cls) {
1074
+ if (entityKind in cls && cls[entityKind] === type[entityKind]) {
1075
+ return true;
1076
+ }
1077
+ cls = Object.getPrototypeOf(cls);
1078
+ }
1079
+ }
1080
+ return false;
1081
+ }
910
1082
 
911
- // ../changelog/src/notion-changelog.ts
912
- var NOTION_API_URL2 = "https://api.notion.com/v1";
913
- var NOTION_API_VERSION2 = "2026-03-11";
914
- var canonicalProperties2 = {
915
- title: { name: "Title", type: "title", schema: { title: {} } },
916
- slug: { name: "Slug", type: "rich_text", schema: { rich_text: {} } },
917
- date: { name: "Date", type: "date", schema: { date: {} } },
918
- summary: {
919
- name: "Summary",
920
- type: "rich_text",
921
- schema: { rich_text: {} }
922
- },
923
- body: { name: "Body", type: "rich_text", schema: { rich_text: {} } },
924
- labels: {
925
- name: "Labels",
926
- type: "multi_select",
927
- schema: { multi_select: { options: [] } }
928
- },
929
- image: { name: "Image", type: "files", schema: { files: {} } },
930
- published: {
931
- name: "Published",
932
- type: "checkbox",
933
- schema: { checkbox: {} }
934
- },
935
- createdAt: {
936
- name: "Created At",
937
- type: "created_time",
938
- schema: { created_time: {} }
939
- },
940
- updatedAt: {
941
- name: "Updated At",
942
- type: "last_edited_time",
943
- schema: { last_edited_time: {} }
1083
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/column.js
1084
+ var Column = class {
1085
+ constructor(table, config) {
1086
+ this.table = table;
1087
+ this.config = config;
1088
+ this.name = config.name;
1089
+ this.keyAsName = config.keyAsName;
1090
+ this.notNull = config.notNull;
1091
+ this.default = config.default;
1092
+ this.defaultFn = config.defaultFn;
1093
+ this.onUpdateFn = config.onUpdateFn;
1094
+ this.hasDefault = config.hasDefault;
1095
+ this.primary = config.primaryKey;
1096
+ this.isUnique = config.isUnique;
1097
+ this.uniqueName = config.uniqueName;
1098
+ this.uniqueType = config.uniqueType;
1099
+ this.dataType = config.dataType;
1100
+ this.columnType = config.columnType;
1101
+ this.generated = config.generated;
1102
+ this.generatedIdentity = config.generatedIdentity;
1103
+ }
1104
+ static [entityKind] = "Column";
1105
+ name;
1106
+ keyAsName;
1107
+ primary;
1108
+ notNull;
1109
+ default;
1110
+ defaultFn;
1111
+ onUpdateFn;
1112
+ hasDefault;
1113
+ isUnique;
1114
+ uniqueName;
1115
+ uniqueType;
1116
+ dataType;
1117
+ columnType;
1118
+ enumValues = void 0;
1119
+ generated = void 0;
1120
+ generatedIdentity = void 0;
1121
+ config;
1122
+ mapFromDriverValue(value) {
1123
+ return value;
1124
+ }
1125
+ mapToDriverValue(value) {
1126
+ return value;
1127
+ }
1128
+ // ** @internal */
1129
+ shouldDisableInsert() {
1130
+ return this.config.generated !== void 0 && this.config.generated.type !== "byDefault";
944
1131
  }
945
1132
  };
946
- async function createNotionChangelogDataSource({
947
- token,
948
- databaseId,
949
- request = fetch
950
- }) {
951
- const response = await request(`${NOTION_API_URL2}/data_sources`, {
952
- method: "POST",
953
- headers: notionHeaders2(token),
954
- body: JSON.stringify({
955
- parent: { database_id: databaseId },
956
- title: [{ type: "text", text: { content: "Changelog" } }],
957
- properties: Object.fromEntries(
958
- Object.values(canonicalProperties2).map(({ name, schema }) => [
959
- name,
960
- schema
961
- ])
962
- )
963
- })
964
- });
965
- return configurationFromResponse(
966
- await readObject(response, "Changelog Data Source"),
967
- databaseId
968
- );
969
- }
970
- async function validateNotionChangelogDataSource({
971
- token,
972
- dataSourceId,
973
- propertyIds,
974
- request = fetch
975
- }) {
976
- const response = await request(
977
- `${NOTION_API_URL2}/data_sources/${dataSourceId}`,
978
- { headers: notionHeaders2(token) }
979
- );
980
- const dataSource = await readObject(response, "Changelog Data Source");
981
- const properties = recordAt(dataSource, "properties");
982
- const propertiesById = new Map(
983
- Object.values(properties).flatMap((property) => {
984
- if (!isRecord(property) || typeof property.id !== "string") return [];
985
- return [[property.id, property]];
986
- })
987
- );
988
- const repairs = [];
989
- for (const [key, { name, type }] of Object.entries(canonicalProperties2)) {
990
- const configuredId = propertyIds[key];
991
- const property = propertiesById.get(configuredId);
992
- if (!property) {
993
- repairs.push(
994
- `Restore the "${name}" property with ID "${configuredId}" and type "${type}", then update the configured property ID if Notion assigns a new one.`
995
- );
996
- } else if (property.type !== type) {
997
- repairs.push(
998
- `Change the property configured as "${name}" (ID "${configuredId}") from "${String(property.type)}" to "${type}", or restore a ${type} property and configure its ID.`
999
- );
1133
+
1134
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/column-builder.js
1135
+ var ColumnBuilder = class {
1136
+ static [entityKind] = "ColumnBuilder";
1137
+ config;
1138
+ constructor(name, dataType, columnType) {
1139
+ this.config = {
1140
+ name,
1141
+ keyAsName: name === "",
1142
+ notNull: false,
1143
+ default: void 0,
1144
+ hasDefault: false,
1145
+ primaryKey: false,
1146
+ isUnique: false,
1147
+ uniqueName: void 0,
1148
+ uniqueType: void 0,
1149
+ dataType,
1150
+ columnType,
1151
+ generated: void 0
1152
+ };
1153
+ }
1154
+ /**
1155
+ * Changes the data type of the column. Commonly used with `json` columns. Also, useful for branded types.
1156
+ *
1157
+ * @example
1158
+ * ```ts
1159
+ * const users = pgTable('users', {
1160
+ * id: integer('id').$type<UserId>().primaryKey(),
1161
+ * details: json('details').$type<UserDetails>().notNull(),
1162
+ * });
1163
+ * ```
1164
+ */
1165
+ $type() {
1166
+ return this;
1167
+ }
1168
+ /**
1169
+ * Adds a `not null` clause to the column definition.
1170
+ *
1171
+ * Affects the `select` model of the table - columns *without* `not null` will be nullable on select.
1172
+ */
1173
+ notNull() {
1174
+ this.config.notNull = true;
1175
+ return this;
1176
+ }
1177
+ /**
1178
+ * Adds a `default <value>` clause to the column definition.
1179
+ *
1180
+ * Affects the `insert` model of the table - columns *with* `default` are optional on insert.
1181
+ *
1182
+ * If you need to set a dynamic default value, use {@link $defaultFn} instead.
1183
+ */
1184
+ default(value) {
1185
+ this.config.default = value;
1186
+ this.config.hasDefault = true;
1187
+ return this;
1188
+ }
1189
+ /**
1190
+ * Adds a dynamic default value to the column.
1191
+ * The function will be called when the row is inserted, and the returned value will be used as the column value.
1192
+ *
1193
+ * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
1194
+ */
1195
+ $defaultFn(fn) {
1196
+ this.config.defaultFn = fn;
1197
+ this.config.hasDefault = true;
1198
+ return this;
1199
+ }
1200
+ /**
1201
+ * Alias for {@link $defaultFn}.
1202
+ */
1203
+ $default = this.$defaultFn;
1204
+ /**
1205
+ * Adds a dynamic update value to the column.
1206
+ * The function will be called when the row is updated, and the returned value will be used as the column value if none is provided.
1207
+ * If no `default` (or `$defaultFn`) value is provided, the function will be called when the row is inserted as well, and the returned value will be used as the column value.
1208
+ *
1209
+ * **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
1210
+ */
1211
+ $onUpdateFn(fn) {
1212
+ this.config.onUpdateFn = fn;
1213
+ this.config.hasDefault = true;
1214
+ return this;
1215
+ }
1216
+ /**
1217
+ * Alias for {@link $onUpdateFn}.
1218
+ */
1219
+ $onUpdate = this.$onUpdateFn;
1220
+ /**
1221
+ * Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`.
1222
+ *
1223
+ * In SQLite, `integer primary key` implicitly makes the column auto-incrementing.
1224
+ */
1225
+ primaryKey() {
1226
+ this.config.primaryKey = true;
1227
+ this.config.notNull = true;
1228
+ return this;
1229
+ }
1230
+ /** @internal Sets the name of the column to the key within the table definition if a name was not given. */
1231
+ setName(name) {
1232
+ if (this.config.name !== "") return;
1233
+ this.config.name = name;
1234
+ }
1235
+ };
1236
+
1237
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/table.utils.js
1238
+ var TableName = /* @__PURE__ */ Symbol.for("drizzle:Name");
1239
+
1240
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/foreign-keys.js
1241
+ var ForeignKeyBuilder = class {
1242
+ static [entityKind] = "PgForeignKeyBuilder";
1243
+ /** @internal */
1244
+ reference;
1245
+ /** @internal */
1246
+ _onUpdate = "no action";
1247
+ /** @internal */
1248
+ _onDelete = "no action";
1249
+ constructor(config, actions) {
1250
+ this.reference = () => {
1251
+ const { name, columns, foreignColumns } = config();
1252
+ return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
1253
+ };
1254
+ if (actions) {
1255
+ this._onUpdate = actions.onUpdate;
1256
+ this._onDelete = actions.onDelete;
1000
1257
  }
1001
1258
  }
1002
- if (repairs.length) throw new Error(repairs.join("\n"));
1003
- return {
1004
- databaseId: databaseIdFromResponse(dataSource),
1005
- dataSourceId,
1006
- propertyIds: { ...propertyIds }
1007
- };
1008
- }
1009
- function configurationFromResponse(dataSource, databaseId) {
1010
- const properties = recordAt(dataSource, "properties");
1011
- return {
1012
- databaseId,
1013
- dataSourceId: requiredString(dataSource.id),
1014
- propertyIds: Object.fromEntries(
1015
- Object.entries(canonicalProperties2).map(([key, { name }]) => [
1016
- key,
1017
- requiredString(recordAt(properties, name).id)
1018
- ])
1019
- )
1020
- };
1021
- }
1022
- function databaseIdFromResponse(dataSource) {
1023
- return requiredString(recordAt(dataSource, "parent").database_id);
1259
+ onUpdate(action) {
1260
+ this._onUpdate = action === void 0 ? "no action" : action;
1261
+ return this;
1262
+ }
1263
+ onDelete(action) {
1264
+ this._onDelete = action === void 0 ? "no action" : action;
1265
+ return this;
1266
+ }
1267
+ /** @internal */
1268
+ build(table) {
1269
+ return new ForeignKey(table, this);
1270
+ }
1271
+ };
1272
+ var ForeignKey = class {
1273
+ constructor(table, builder) {
1274
+ this.table = table;
1275
+ this.reference = builder.reference;
1276
+ this.onUpdate = builder._onUpdate;
1277
+ this.onDelete = builder._onDelete;
1278
+ }
1279
+ static [entityKind] = "PgForeignKey";
1280
+ reference;
1281
+ onUpdate;
1282
+ onDelete;
1283
+ getName() {
1284
+ const { name, columns, foreignColumns } = this.reference();
1285
+ const columnNames = columns.map((column) => column.name);
1286
+ const foreignColumnNames = foreignColumns.map((column) => column.name);
1287
+ const chunks = [
1288
+ this.table[TableName],
1289
+ ...columnNames,
1290
+ foreignColumns[0].table[TableName],
1291
+ ...foreignColumnNames
1292
+ ];
1293
+ return name ?? `${chunks.join("_")}_fk`;
1294
+ }
1295
+ };
1296
+
1297
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/tracing-utils.js
1298
+ function iife(fn, ...args) {
1299
+ return fn(...args);
1024
1300
  }
1025
- function notionHeaders2(token) {
1026
- return {
1027
- Authorization: `Bearer ${token}`,
1028
- "Content-Type": "application/json",
1029
- "Notion-Version": NOTION_API_VERSION2
1030
- };
1301
+
1302
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/unique-constraint.js
1303
+ function uniqueKeyName(table, columns) {
1304
+ return `${table[TableName]}_${columns.join("_")}_unique`;
1031
1305
  }
1032
- async function readObject(response, subject) {
1033
- const body = await response.json();
1034
- if (!response.ok) {
1035
- throw new Error(
1036
- `Notion rejected the ${subject} request (${response.status}).`
1037
- );
1306
+ var UniqueConstraintBuilder = class {
1307
+ constructor(columns, name) {
1308
+ this.name = name;
1309
+ this.columns = columns;
1038
1310
  }
1039
- if (!isRecord(body))
1040
- throw new Error(`Notion returned an invalid ${subject} response.`);
1041
- return body;
1042
- }
1043
- function recordAt(value, key) {
1044
- return record(value[key]);
1311
+ static [entityKind] = "PgUniqueConstraintBuilder";
1312
+ /** @internal */
1313
+ columns;
1314
+ /** @internal */
1315
+ nullsNotDistinctConfig = false;
1316
+ nullsNotDistinct() {
1317
+ this.nullsNotDistinctConfig = true;
1318
+ return this;
1319
+ }
1320
+ /** @internal */
1321
+ build(table) {
1322
+ return new UniqueConstraint(table, this.columns, this.nullsNotDistinctConfig, this.name);
1323
+ }
1324
+ };
1325
+ var UniqueOnConstraintBuilder = class {
1326
+ static [entityKind] = "PgUniqueOnConstraintBuilder";
1327
+ /** @internal */
1328
+ name;
1329
+ constructor(name) {
1330
+ this.name = name;
1331
+ }
1332
+ on(...columns) {
1333
+ return new UniqueConstraintBuilder(columns, this.name);
1334
+ }
1335
+ };
1336
+ var UniqueConstraint = class {
1337
+ constructor(table, columns, nullsNotDistinct, name) {
1338
+ this.table = table;
1339
+ this.columns = columns;
1340
+ this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name));
1341
+ this.nullsNotDistinct = nullsNotDistinct;
1342
+ }
1343
+ static [entityKind] = "PgUniqueConstraint";
1344
+ columns;
1345
+ name;
1346
+ nullsNotDistinct = false;
1347
+ getName() {
1348
+ return this.name;
1349
+ }
1350
+ };
1351
+
1352
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/utils/array.js
1353
+ function parsePgArrayValue(arrayString, startFrom, inQuotes) {
1354
+ for (let i = startFrom; i < arrayString.length; i++) {
1355
+ const char = arrayString[i];
1356
+ if (char === "\\") {
1357
+ i++;
1358
+ continue;
1359
+ }
1360
+ if (char === '"') {
1361
+ return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i + 1];
1362
+ }
1363
+ if (inQuotes) {
1364
+ continue;
1365
+ }
1366
+ if (char === "," || char === "}") {
1367
+ return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i];
1368
+ }
1369
+ }
1370
+ return [arrayString.slice(startFrom).replace(/\\/g, ""), arrayString.length];
1045
1371
  }
1046
- function record(value) {
1047
- if (!isRecord(value))
1048
- throw new Error("Notion returned an invalid Changelog response.");
1049
- return value;
1372
+ function parsePgNestedArray(arrayString, startFrom = 0) {
1373
+ const result = [];
1374
+ let i = startFrom;
1375
+ let lastCharIsComma = false;
1376
+ while (i < arrayString.length) {
1377
+ const char = arrayString[i];
1378
+ if (char === ",") {
1379
+ if (lastCharIsComma || i === startFrom) {
1380
+ result.push("");
1381
+ }
1382
+ lastCharIsComma = true;
1383
+ i++;
1384
+ continue;
1385
+ }
1386
+ lastCharIsComma = false;
1387
+ if (char === "\\") {
1388
+ i += 2;
1389
+ continue;
1390
+ }
1391
+ if (char === '"') {
1392
+ const [value2, startFrom2] = parsePgArrayValue(arrayString, i + 1, true);
1393
+ result.push(value2);
1394
+ i = startFrom2;
1395
+ continue;
1396
+ }
1397
+ if (char === "}") {
1398
+ return [result, i + 1];
1399
+ }
1400
+ if (char === "{") {
1401
+ const [value2, startFrom2] = parsePgNestedArray(arrayString, i + 1);
1402
+ result.push(value2);
1403
+ i = startFrom2;
1404
+ continue;
1405
+ }
1406
+ const [value, newStartFrom] = parsePgArrayValue(arrayString, i, false);
1407
+ result.push(value);
1408
+ i = newStartFrom;
1409
+ }
1410
+ return [result, i];
1050
1411
  }
1051
- function requiredString(value) {
1052
- if (typeof value !== "string")
1053
- throw new Error("Notion returned an invalid Changelog response.");
1054
- return value;
1412
+ function parsePgArray(arrayString) {
1413
+ const [result] = parsePgNestedArray(arrayString, 1);
1414
+ return result;
1055
1415
  }
1056
- function isRecord(value) {
1057
- return typeof value === "object" && value !== null && !Array.isArray(value);
1416
+ function makePgArray(array) {
1417
+ return `{${array.map((item) => {
1418
+ if (Array.isArray(item)) {
1419
+ return makePgArray(item);
1420
+ }
1421
+ if (typeof item === "string") {
1422
+ return `"${item.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
1423
+ }
1424
+ return `${item}`;
1425
+ }).join(",")}}`;
1058
1426
  }
1059
1427
 
1060
- // src/index.ts
1061
- async function provisionGuidedInstallation({
1062
- destination,
1063
- product,
1064
- themePreset,
1065
- workerName,
1066
- commentProbePageId,
1067
- features,
1068
- feedbackSelection,
1069
- changelogSelection,
1070
- notionToken,
1071
- turnstile,
1072
- preview,
1073
- request = fetch
1074
- }) {
1075
- try {
1076
- if ((await readdir2(destination)).length)
1077
- throw new Error(
1078
- `Refusing to generate into non-empty destination: ${destination}`
1079
- );
1080
- } catch (error) {
1081
- if (error.code !== "ENOENT") throw error;
1428
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/columns/common.js
1429
+ var PgColumnBuilder = class extends ColumnBuilder {
1430
+ foreignKeyConfigs = [];
1431
+ static [entityKind] = "PgColumnBuilder";
1432
+ array(size) {
1433
+ return new PgArrayBuilder(this.config.name, this, size);
1082
1434
  }
1083
- if (product.siteUrl && new URL(product.siteUrl).protocol !== "https:")
1084
- throw new Error("product.siteUrl must be an HTTPS URL.");
1085
- const targetName = workerName ?? basename(destination).toLowerCase().replace(/[^a-z0-9-]/g, "-");
1435
+ references(ref, actions = {}) {
1436
+ this.foreignKeyConfigs.push({ ref, actions });
1437
+ return this;
1438
+ }
1439
+ unique(name, config) {
1440
+ this.config.isUnique = true;
1441
+ this.config.uniqueName = name;
1442
+ this.config.uniqueType = config?.nulls;
1443
+ return this;
1444
+ }
1445
+ generatedAlwaysAs(as) {
1446
+ this.config.generated = {
1447
+ as,
1448
+ type: "always",
1449
+ mode: "stored"
1450
+ };
1451
+ return this;
1452
+ }
1453
+ /** @internal */
1454
+ buildForeignKeys(column, table) {
1455
+ return this.foreignKeyConfigs.map(({ ref, actions }) => {
1456
+ return iife(
1457
+ (ref2, actions2) => {
1458
+ const builder = new ForeignKeyBuilder(() => {
1459
+ const foreignColumn = ref2();
1460
+ return { columns: [column], foreignColumns: [foreignColumn] };
1461
+ });
1462
+ if (actions2.onUpdate) {
1463
+ builder.onUpdate(actions2.onUpdate);
1464
+ }
1465
+ if (actions2.onDelete) {
1466
+ builder.onDelete(actions2.onDelete);
1467
+ }
1468
+ return builder.build(table);
1469
+ },
1470
+ ref,
1471
+ actions
1472
+ );
1473
+ });
1474
+ }
1475
+ /** @internal */
1476
+ buildExtraConfigColumn(table) {
1477
+ return new ExtraConfigColumn(table, this.config);
1478
+ }
1479
+ };
1480
+ var PgColumn = class extends Column {
1481
+ constructor(table, config) {
1482
+ if (!config.uniqueName) {
1483
+ config.uniqueName = uniqueKeyName(table, [config.name]);
1484
+ }
1485
+ super(table, config);
1486
+ this.table = table;
1487
+ }
1488
+ static [entityKind] = "PgColumn";
1489
+ };
1490
+ var ExtraConfigColumn = class extends PgColumn {
1491
+ static [entityKind] = "ExtraConfigColumn";
1492
+ getSQLType() {
1493
+ return this.getSQLType();
1494
+ }
1495
+ indexConfig = {
1496
+ order: this.config.order ?? "asc",
1497
+ nulls: this.config.nulls ?? "last",
1498
+ opClass: this.config.opClass
1499
+ };
1500
+ defaultConfig = {
1501
+ order: "asc",
1502
+ nulls: "last",
1503
+ opClass: void 0
1504
+ };
1505
+ asc() {
1506
+ this.indexConfig.order = "asc";
1507
+ return this;
1508
+ }
1509
+ desc() {
1510
+ this.indexConfig.order = "desc";
1511
+ return this;
1512
+ }
1513
+ nullsFirst() {
1514
+ this.indexConfig.nulls = "first";
1515
+ return this;
1516
+ }
1517
+ nullsLast() {
1518
+ this.indexConfig.nulls = "last";
1519
+ return this;
1520
+ }
1521
+ /**
1522
+ * ### PostgreSQL documentation quote
1523
+ *
1524
+ * > An operator class with optional parameters can be specified for each column of an index.
1525
+ * The operator class identifies the operators to be used by the index for that column.
1526
+ * For example, a B-tree index on four-byte integers would use the int4_ops class;
1527
+ * this operator class includes comparison functions for four-byte integers.
1528
+ * In practice the default operator class for the column's data type is usually sufficient.
1529
+ * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.
1530
+ * For example, we might want to sort a complex-number data type either by absolute value or by real part.
1531
+ * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.
1532
+ * More information about operator classes check:
1533
+ *
1534
+ * ### Useful links
1535
+ * https://www.postgresql.org/docs/current/sql-createindex.html
1536
+ *
1537
+ * https://www.postgresql.org/docs/current/indexes-opclass.html
1538
+ *
1539
+ * https://www.postgresql.org/docs/current/xindex.html
1540
+ *
1541
+ * ### Additional types
1542
+ * If you have the `pg_vector` extension installed in your database, you can use the
1543
+ * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.
1544
+ *
1545
+ * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**
1546
+ *
1547
+ * @param opClass
1548
+ * @returns
1549
+ */
1550
+ op(opClass) {
1551
+ this.indexConfig.opClass = opClass;
1552
+ return this;
1553
+ }
1554
+ };
1555
+ var IndexedColumn = class {
1556
+ static [entityKind] = "IndexedColumn";
1557
+ constructor(name, keyAsName, type, indexConfig) {
1558
+ this.name = name;
1559
+ this.keyAsName = keyAsName;
1560
+ this.type = type;
1561
+ this.indexConfig = indexConfig;
1562
+ }
1563
+ name;
1564
+ keyAsName;
1565
+ type;
1566
+ indexConfig;
1567
+ };
1568
+ var PgArrayBuilder = class extends PgColumnBuilder {
1569
+ static [entityKind] = "PgArrayBuilder";
1570
+ constructor(name, baseBuilder, size) {
1571
+ super(name, "array", "PgArray");
1572
+ this.config.baseBuilder = baseBuilder;
1573
+ this.config.size = size;
1574
+ }
1575
+ /** @internal */
1576
+ build(table) {
1577
+ const baseColumn = this.config.baseBuilder.build(table);
1578
+ return new PgArray(
1579
+ table,
1580
+ this.config,
1581
+ baseColumn
1582
+ );
1583
+ }
1584
+ };
1585
+ var PgArray = class _PgArray extends PgColumn {
1586
+ constructor(table, config, baseColumn, range) {
1587
+ super(table, config);
1588
+ this.baseColumn = baseColumn;
1589
+ this.range = range;
1590
+ this.size = config.size;
1591
+ }
1592
+ size;
1593
+ static [entityKind] = "PgArray";
1594
+ getSQLType() {
1595
+ return `${this.baseColumn.getSQLType()}[${typeof this.size === "number" ? this.size : ""}]`;
1596
+ }
1597
+ mapFromDriverValue(value) {
1598
+ if (typeof value === "string") {
1599
+ value = parsePgArray(value);
1600
+ }
1601
+ return value.map((v) => this.baseColumn.mapFromDriverValue(v));
1602
+ }
1603
+ mapToDriverValue(value, isNestedArray = false) {
1604
+ const a = value.map(
1605
+ (v) => v === null ? null : is(this.baseColumn, _PgArray) ? this.baseColumn.mapToDriverValue(v, true) : this.baseColumn.mapToDriverValue(v)
1606
+ );
1607
+ if (isNestedArray) return a;
1608
+ return makePgArray(a);
1609
+ }
1610
+ };
1611
+
1612
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/columns/enum.js
1613
+ var PgEnumObjectColumnBuilder = class extends PgColumnBuilder {
1614
+ static [entityKind] = "PgEnumObjectColumnBuilder";
1615
+ constructor(name, enumInstance) {
1616
+ super(name, "string", "PgEnumObjectColumn");
1617
+ this.config.enum = enumInstance;
1618
+ }
1619
+ /** @internal */
1620
+ build(table) {
1621
+ return new PgEnumObjectColumn(
1622
+ table,
1623
+ this.config
1624
+ );
1625
+ }
1626
+ };
1627
+ var PgEnumObjectColumn = class extends PgColumn {
1628
+ static [entityKind] = "PgEnumObjectColumn";
1629
+ enum;
1630
+ enumValues = this.config.enum.enumValues;
1631
+ constructor(table, config) {
1632
+ super(table, config);
1633
+ this.enum = config.enum;
1634
+ }
1635
+ getSQLType() {
1636
+ return this.enum.enumName;
1637
+ }
1638
+ };
1639
+ var isPgEnumSym = /* @__PURE__ */ Symbol.for("drizzle:isPgEnum");
1640
+ function isPgEnum(obj) {
1641
+ return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
1642
+ }
1643
+ var PgEnumColumnBuilder = class extends PgColumnBuilder {
1644
+ static [entityKind] = "PgEnumColumnBuilder";
1645
+ constructor(name, enumInstance) {
1646
+ super(name, "string", "PgEnumColumn");
1647
+ this.config.enum = enumInstance;
1648
+ }
1649
+ /** @internal */
1650
+ build(table) {
1651
+ return new PgEnumColumn(
1652
+ table,
1653
+ this.config
1654
+ );
1655
+ }
1656
+ };
1657
+ var PgEnumColumn = class extends PgColumn {
1658
+ static [entityKind] = "PgEnumColumn";
1659
+ enum = this.config.enum;
1660
+ enumValues = this.config.enum.enumValues;
1661
+ constructor(table, config) {
1662
+ super(table, config);
1663
+ this.enum = config.enum;
1664
+ }
1665
+ getSQLType() {
1666
+ return this.enum.enumName;
1667
+ }
1668
+ };
1669
+
1670
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/subquery.js
1671
+ var Subquery = class {
1672
+ static [entityKind] = "Subquery";
1673
+ constructor(sql2, fields, alias, isWith = false, usedTables = []) {
1674
+ this._ = {
1675
+ brand: "Subquery",
1676
+ sql: sql2,
1677
+ selectedFields: fields,
1678
+ alias,
1679
+ isWith,
1680
+ usedTables
1681
+ };
1682
+ }
1683
+ // getSQL(): SQL<unknown> {
1684
+ // return new SQL([this]);
1685
+ // }
1686
+ };
1687
+ var WithSubquery = class extends Subquery {
1688
+ static [entityKind] = "WithSubquery";
1689
+ };
1690
+
1691
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/version.js
1692
+ var version = "0.45.4";
1693
+
1694
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/tracing.js
1695
+ var otel;
1696
+ var rawTracer;
1697
+ var tracer = {
1698
+ startActiveSpan(name, fn) {
1699
+ if (!otel) {
1700
+ return fn();
1701
+ }
1702
+ if (!rawTracer) {
1703
+ rawTracer = otel.trace.getTracer("drizzle-orm", version);
1704
+ }
1705
+ return iife(
1706
+ (otel2, rawTracer2) => rawTracer2.startActiveSpan(
1707
+ name,
1708
+ (span) => {
1709
+ try {
1710
+ return fn(span);
1711
+ } catch (e) {
1712
+ span.setStatus({
1713
+ code: otel2.SpanStatusCode.ERROR,
1714
+ message: e instanceof Error ? e.message : "Unknown error"
1715
+ // eslint-disable-line no-instanceof/no-instanceof
1716
+ });
1717
+ throw e;
1718
+ } finally {
1719
+ span.end();
1720
+ }
1721
+ }
1722
+ ),
1723
+ otel,
1724
+ rawTracer
1725
+ );
1726
+ }
1727
+ };
1728
+
1729
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/view-common.js
1730
+ var ViewBaseConfig = /* @__PURE__ */ Symbol.for("drizzle:ViewBaseConfig");
1731
+
1732
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/table.js
1733
+ var Schema = /* @__PURE__ */ Symbol.for("drizzle:Schema");
1734
+ var Columns = /* @__PURE__ */ Symbol.for("drizzle:Columns");
1735
+ var ExtraConfigColumns = /* @__PURE__ */ Symbol.for("drizzle:ExtraConfigColumns");
1736
+ var OriginalName = /* @__PURE__ */ Symbol.for("drizzle:OriginalName");
1737
+ var BaseName = /* @__PURE__ */ Symbol.for("drizzle:BaseName");
1738
+ var IsAlias = /* @__PURE__ */ Symbol.for("drizzle:IsAlias");
1739
+ var ExtraConfigBuilder = /* @__PURE__ */ Symbol.for("drizzle:ExtraConfigBuilder");
1740
+ var IsDrizzleTable = /* @__PURE__ */ Symbol.for("drizzle:IsDrizzleTable");
1741
+ var Table = class {
1742
+ static [entityKind] = "Table";
1743
+ /** @internal */
1744
+ static Symbol = {
1745
+ Name: TableName,
1746
+ Schema,
1747
+ OriginalName,
1748
+ Columns,
1749
+ ExtraConfigColumns,
1750
+ BaseName,
1751
+ IsAlias,
1752
+ ExtraConfigBuilder
1753
+ };
1754
+ /**
1755
+ * @internal
1756
+ * Can be changed if the table is aliased.
1757
+ */
1758
+ [TableName];
1759
+ /**
1760
+ * @internal
1761
+ * Used to store the original name of the table, before any aliasing.
1762
+ */
1763
+ [OriginalName];
1764
+ /** @internal */
1765
+ [Schema];
1766
+ /** @internal */
1767
+ [Columns];
1768
+ /** @internal */
1769
+ [ExtraConfigColumns];
1770
+ /**
1771
+ * @internal
1772
+ * Used to store the table name before the transformation via the `tableCreator` functions.
1773
+ */
1774
+ [BaseName];
1775
+ /** @internal */
1776
+ [IsAlias] = false;
1777
+ /** @internal */
1778
+ [IsDrizzleTable] = true;
1779
+ /** @internal */
1780
+ [ExtraConfigBuilder] = void 0;
1781
+ constructor(name, schema, baseName) {
1782
+ this[TableName] = this[OriginalName] = name;
1783
+ this[Schema] = schema;
1784
+ this[BaseName] = baseName;
1785
+ }
1786
+ };
1787
+
1788
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sql/sql.js
1789
+ var FakePrimitiveParam = class {
1790
+ static [entityKind] = "FakePrimitiveParam";
1791
+ };
1792
+ function isSQLWrapper(value) {
1793
+ return value !== null && value !== void 0 && typeof value.getSQL === "function";
1794
+ }
1795
+ function mergeQueries(queries) {
1796
+ const result = { sql: "", params: [] };
1797
+ for (const query of queries) {
1798
+ result.sql += query.sql;
1799
+ result.params.push(...query.params);
1800
+ if (query.typings?.length) {
1801
+ if (!result.typings) {
1802
+ result.typings = [];
1803
+ }
1804
+ result.typings.push(...query.typings);
1805
+ }
1806
+ }
1807
+ return result;
1808
+ }
1809
+ var StringChunk = class {
1810
+ static [entityKind] = "StringChunk";
1811
+ value;
1812
+ constructor(value) {
1813
+ this.value = Array.isArray(value) ? value : [value];
1814
+ }
1815
+ getSQL() {
1816
+ return new SQL([this]);
1817
+ }
1818
+ };
1819
+ var SQL = class _SQL {
1820
+ constructor(queryChunks) {
1821
+ this.queryChunks = queryChunks;
1822
+ for (const chunk of queryChunks) {
1823
+ if (is(chunk, Table)) {
1824
+ const schemaName = chunk[Table.Symbol.Schema];
1825
+ this.usedTables.push(
1826
+ schemaName === void 0 ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]
1827
+ );
1828
+ }
1829
+ }
1830
+ }
1831
+ static [entityKind] = "SQL";
1832
+ /** @internal */
1833
+ decoder = noopDecoder;
1834
+ shouldInlineParams = false;
1835
+ /** @internal */
1836
+ usedTables = [];
1837
+ append(query) {
1838
+ this.queryChunks.push(...query.queryChunks);
1839
+ return this;
1840
+ }
1841
+ toQuery(config) {
1842
+ return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
1843
+ const query = this.buildQueryFromSourceParams(this.queryChunks, config);
1844
+ span?.setAttributes({
1845
+ "drizzle.query.text": query.sql,
1846
+ "drizzle.query.params": JSON.stringify(query.params)
1847
+ });
1848
+ return query;
1849
+ });
1850
+ }
1851
+ buildQueryFromSourceParams(chunks, _config) {
1852
+ const config = Object.assign({}, _config, {
1853
+ inlineParams: _config.inlineParams || this.shouldInlineParams,
1854
+ paramStartIndex: _config.paramStartIndex || { value: 0 }
1855
+ });
1856
+ const {
1857
+ casing,
1858
+ escapeName,
1859
+ escapeParam,
1860
+ prepareTyping,
1861
+ inlineParams,
1862
+ paramStartIndex
1863
+ } = config;
1864
+ return mergeQueries(chunks.map((chunk) => {
1865
+ if (is(chunk, StringChunk)) {
1866
+ return { sql: chunk.value.join(""), params: [] };
1867
+ }
1868
+ if (is(chunk, Name)) {
1869
+ return { sql: escapeName(chunk.value), params: [] };
1870
+ }
1871
+ if (chunk === void 0) {
1872
+ return { sql: "", params: [] };
1873
+ }
1874
+ if (Array.isArray(chunk)) {
1875
+ const result = [new StringChunk("(")];
1876
+ for (const [i, p] of chunk.entries()) {
1877
+ result.push(p);
1878
+ if (i < chunk.length - 1) {
1879
+ result.push(new StringChunk(", "));
1880
+ }
1881
+ }
1882
+ result.push(new StringChunk(")"));
1883
+ return this.buildQueryFromSourceParams(result, config);
1884
+ }
1885
+ if (is(chunk, _SQL)) {
1886
+ return this.buildQueryFromSourceParams(chunk.queryChunks, {
1887
+ ...config,
1888
+ inlineParams: inlineParams || chunk.shouldInlineParams
1889
+ });
1890
+ }
1891
+ if (is(chunk, Table)) {
1892
+ const schemaName = chunk[Table.Symbol.Schema];
1893
+ const tableName = chunk[Table.Symbol.Name];
1894
+ return {
1895
+ sql: schemaName === void 0 || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
1896
+ params: []
1897
+ };
1898
+ }
1899
+ if (is(chunk, Column)) {
1900
+ const columnName = casing.getColumnCasing(chunk);
1901
+ if (_config.invokeSource === "indexes") {
1902
+ return { sql: escapeName(columnName), params: [] };
1903
+ }
1904
+ const schemaName = chunk.table[Table.Symbol.Schema];
1905
+ return {
1906
+ sql: chunk.table[IsAlias] || schemaName === void 0 ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
1907
+ params: []
1908
+ };
1909
+ }
1910
+ if (is(chunk, View)) {
1911
+ const schemaName = chunk[ViewBaseConfig].schema;
1912
+ const viewName = chunk[ViewBaseConfig].name;
1913
+ return {
1914
+ sql: schemaName === void 0 || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
1915
+ params: []
1916
+ };
1917
+ }
1918
+ if (is(chunk, Param)) {
1919
+ if (is(chunk.value, Placeholder)) {
1920
+ return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
1921
+ }
1922
+ const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
1923
+ if (is(mappedValue, _SQL)) {
1924
+ return this.buildQueryFromSourceParams([mappedValue], config);
1925
+ }
1926
+ if (inlineParams) {
1927
+ return { sql: this.mapInlineParam(mappedValue, config), params: [] };
1928
+ }
1929
+ let typings = ["none"];
1930
+ if (prepareTyping) {
1931
+ typings = [prepareTyping(chunk.encoder)];
1932
+ }
1933
+ return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
1934
+ }
1935
+ if (is(chunk, Placeholder)) {
1936
+ return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
1937
+ }
1938
+ if (is(chunk, _SQL.Aliased) && chunk.fieldAlias !== void 0) {
1939
+ return { sql: escapeName(chunk.fieldAlias), params: [] };
1940
+ }
1941
+ if (is(chunk, Subquery)) {
1942
+ if (chunk._.isWith) {
1943
+ return { sql: escapeName(chunk._.alias), params: [] };
1944
+ }
1945
+ return this.buildQueryFromSourceParams([
1946
+ new StringChunk("("),
1947
+ chunk._.sql,
1948
+ new StringChunk(") "),
1949
+ new Name(chunk._.alias)
1950
+ ], config);
1951
+ }
1952
+ if (isPgEnum(chunk)) {
1953
+ if (chunk.schema) {
1954
+ return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
1955
+ }
1956
+ return { sql: escapeName(chunk.enumName), params: [] };
1957
+ }
1958
+ if (isSQLWrapper(chunk)) {
1959
+ if (chunk.shouldOmitSQLParens?.()) {
1960
+ return this.buildQueryFromSourceParams([chunk.getSQL()], config);
1961
+ }
1962
+ return this.buildQueryFromSourceParams([
1963
+ new StringChunk("("),
1964
+ chunk.getSQL(),
1965
+ new StringChunk(")")
1966
+ ], config);
1967
+ }
1968
+ if (inlineParams) {
1969
+ return { sql: this.mapInlineParam(chunk, config), params: [] };
1970
+ }
1971
+ return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
1972
+ }));
1973
+ }
1974
+ mapInlineParam(chunk, { escapeString }) {
1975
+ if (chunk === null) {
1976
+ return "null";
1977
+ }
1978
+ if (typeof chunk === "number" || typeof chunk === "boolean") {
1979
+ return chunk.toString();
1980
+ }
1981
+ if (typeof chunk === "string") {
1982
+ return escapeString(chunk);
1983
+ }
1984
+ if (typeof chunk === "object") {
1985
+ const mappedValueAsString = chunk.toString();
1986
+ if (mappedValueAsString === "[object Object]") {
1987
+ return escapeString(JSON.stringify(chunk));
1988
+ }
1989
+ return escapeString(mappedValueAsString);
1990
+ }
1991
+ throw new Error("Unexpected param value: " + chunk);
1992
+ }
1993
+ getSQL() {
1994
+ return this;
1995
+ }
1996
+ as(alias) {
1997
+ if (alias === void 0) {
1998
+ return this;
1999
+ }
2000
+ return new _SQL.Aliased(this, alias);
2001
+ }
2002
+ mapWith(decoder) {
2003
+ this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
2004
+ return this;
2005
+ }
2006
+ inlineParams() {
2007
+ this.shouldInlineParams = true;
2008
+ return this;
2009
+ }
2010
+ /**
2011
+ * This method is used to conditionally include a part of the query.
2012
+ *
2013
+ * @param condition - Condition to check
2014
+ * @returns itself if the condition is `true`, otherwise `undefined`
2015
+ */
2016
+ if(condition) {
2017
+ return condition ? this : void 0;
2018
+ }
2019
+ };
2020
+ var Name = class {
2021
+ constructor(value) {
2022
+ this.value = value;
2023
+ }
2024
+ static [entityKind] = "Name";
2025
+ brand;
2026
+ getSQL() {
2027
+ return new SQL([this]);
2028
+ }
2029
+ };
2030
+ var noopDecoder = {
2031
+ mapFromDriverValue: (value) => value
2032
+ };
2033
+ var noopEncoder = {
2034
+ mapToDriverValue: (value) => value
2035
+ };
2036
+ var noopMapper = {
2037
+ ...noopDecoder,
2038
+ ...noopEncoder
2039
+ };
2040
+ var Param = class {
2041
+ /**
2042
+ * @param value - Parameter value
2043
+ * @param encoder - Encoder to convert the value to a driver parameter
2044
+ */
2045
+ constructor(value, encoder = noopEncoder) {
2046
+ this.value = value;
2047
+ this.encoder = encoder;
2048
+ }
2049
+ static [entityKind] = "Param";
2050
+ brand;
2051
+ getSQL() {
2052
+ return new SQL([this]);
2053
+ }
2054
+ };
2055
+ function sql(strings, ...params) {
2056
+ const queryChunks = [];
2057
+ if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
2058
+ queryChunks.push(new StringChunk(strings[0]));
2059
+ }
2060
+ for (const [paramIndex, param2] of params.entries()) {
2061
+ queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
2062
+ }
2063
+ return new SQL(queryChunks);
2064
+ }
2065
+ ((sql2) => {
2066
+ function empty() {
2067
+ return new SQL([]);
2068
+ }
2069
+ sql2.empty = empty;
2070
+ function fromList(list) {
2071
+ return new SQL(list);
2072
+ }
2073
+ sql2.fromList = fromList;
2074
+ function raw(str) {
2075
+ return new SQL([new StringChunk(str)]);
2076
+ }
2077
+ sql2.raw = raw;
2078
+ function join4(chunks, separator) {
2079
+ const result = [];
2080
+ for (const [i, chunk] of chunks.entries()) {
2081
+ if (i > 0 && separator !== void 0) {
2082
+ result.push(separator);
2083
+ }
2084
+ result.push(chunk);
2085
+ }
2086
+ return new SQL(result);
2087
+ }
2088
+ sql2.join = join4;
2089
+ function identifier(value) {
2090
+ return new Name(value);
2091
+ }
2092
+ sql2.identifier = identifier;
2093
+ function placeholder2(name2) {
2094
+ return new Placeholder(name2);
2095
+ }
2096
+ sql2.placeholder = placeholder2;
2097
+ function param2(value, encoder) {
2098
+ return new Param(value, encoder);
2099
+ }
2100
+ sql2.param = param2;
2101
+ })(sql || (sql = {}));
2102
+ ((SQL2) => {
2103
+ class Aliased {
2104
+ constructor(sql2, fieldAlias) {
2105
+ this.sql = sql2;
2106
+ this.fieldAlias = fieldAlias;
2107
+ }
2108
+ static [entityKind] = "SQL.Aliased";
2109
+ /** @internal */
2110
+ isSelectionField = false;
2111
+ getSQL() {
2112
+ return this.sql;
2113
+ }
2114
+ /** @internal */
2115
+ clone() {
2116
+ return new Aliased(this.sql, this.fieldAlias);
2117
+ }
2118
+ }
2119
+ SQL2.Aliased = Aliased;
2120
+ })(SQL || (SQL = {}));
2121
+ var Placeholder = class {
2122
+ constructor(name2) {
2123
+ this.name = name2;
2124
+ }
2125
+ static [entityKind] = "Placeholder";
2126
+ getSQL() {
2127
+ return new SQL([this]);
2128
+ }
2129
+ };
2130
+ var IsDrizzleView = /* @__PURE__ */ Symbol.for("drizzle:IsDrizzleView");
2131
+ var View = class {
2132
+ static [entityKind] = "View";
2133
+ /** @internal */
2134
+ [ViewBaseConfig];
2135
+ /** @internal */
2136
+ [IsDrizzleView] = true;
2137
+ constructor({ name: name2, schema, selectedFields, query }) {
2138
+ this[ViewBaseConfig] = {
2139
+ name: name2,
2140
+ originalName: name2,
2141
+ schema,
2142
+ selectedFields,
2143
+ query,
2144
+ isExisting: !query,
2145
+ isAlias: false
2146
+ };
2147
+ }
2148
+ getSQL() {
2149
+ return new SQL([this]);
2150
+ }
2151
+ };
2152
+ Column.prototype.getSQL = function() {
2153
+ return new SQL([this]);
2154
+ };
2155
+ Table.prototype.getSQL = function() {
2156
+ return new SQL([this]);
2157
+ };
2158
+ Subquery.prototype.getSQL = function() {
2159
+ return new SQL([this]);
2160
+ };
2161
+
2162
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/utils.js
2163
+ function getColumnNameAndConfig(a, b) {
2164
+ return {
2165
+ name: typeof a === "string" && a.length > 0 ? a : "",
2166
+ config: typeof a === "object" ? a : b
2167
+ };
2168
+ }
2169
+ var textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder();
2170
+
2171
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
2172
+ var ForeignKeyBuilder2 = class {
2173
+ static [entityKind] = "SQLiteForeignKeyBuilder";
2174
+ /** @internal */
2175
+ reference;
2176
+ /** @internal */
2177
+ _onUpdate;
2178
+ /** @internal */
2179
+ _onDelete;
2180
+ constructor(config, actions) {
2181
+ this.reference = () => {
2182
+ const { name, columns, foreignColumns } = config();
2183
+ return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
2184
+ };
2185
+ if (actions) {
2186
+ this._onUpdate = actions.onUpdate;
2187
+ this._onDelete = actions.onDelete;
2188
+ }
2189
+ }
2190
+ onUpdate(action) {
2191
+ this._onUpdate = action;
2192
+ return this;
2193
+ }
2194
+ onDelete(action) {
2195
+ this._onDelete = action;
2196
+ return this;
2197
+ }
2198
+ /** @internal */
2199
+ build(table) {
2200
+ return new ForeignKey2(table, this);
2201
+ }
2202
+ };
2203
+ var ForeignKey2 = class {
2204
+ constructor(table, builder) {
2205
+ this.table = table;
2206
+ this.reference = builder.reference;
2207
+ this.onUpdate = builder._onUpdate;
2208
+ this.onDelete = builder._onDelete;
2209
+ }
2210
+ static [entityKind] = "SQLiteForeignKey";
2211
+ reference;
2212
+ onUpdate;
2213
+ onDelete;
2214
+ getName() {
2215
+ const { name, columns, foreignColumns } = this.reference();
2216
+ const columnNames = columns.map((column) => column.name);
2217
+ const foreignColumnNames = foreignColumns.map((column) => column.name);
2218
+ const chunks = [
2219
+ this.table[TableName],
2220
+ ...columnNames,
2221
+ foreignColumns[0].table[TableName],
2222
+ ...foreignColumnNames
2223
+ ];
2224
+ return name ?? `${chunks.join("_")}_fk`;
2225
+ }
2226
+ };
2227
+
2228
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
2229
+ function uniqueKeyName2(table, columns) {
2230
+ return `${table[TableName]}_${columns.join("_")}_unique`;
2231
+ }
2232
+ var UniqueConstraintBuilder2 = class {
2233
+ constructor(columns, name) {
2234
+ this.name = name;
2235
+ this.columns = columns;
2236
+ }
2237
+ static [entityKind] = "SQLiteUniqueConstraintBuilder";
2238
+ /** @internal */
2239
+ columns;
2240
+ /** @internal */
2241
+ build(table) {
2242
+ return new UniqueConstraint2(table, this.columns, this.name);
2243
+ }
2244
+ };
2245
+ var UniqueOnConstraintBuilder2 = class {
2246
+ static [entityKind] = "SQLiteUniqueOnConstraintBuilder";
2247
+ /** @internal */
2248
+ name;
2249
+ constructor(name) {
2250
+ this.name = name;
2251
+ }
2252
+ on(...columns) {
2253
+ return new UniqueConstraintBuilder2(columns, this.name);
2254
+ }
2255
+ };
2256
+ var UniqueConstraint2 = class {
2257
+ constructor(table, columns, name) {
2258
+ this.table = table;
2259
+ this.columns = columns;
2260
+ this.name = name ?? uniqueKeyName2(this.table, this.columns.map((column) => column.name));
2261
+ }
2262
+ static [entityKind] = "SQLiteUniqueConstraint";
2263
+ columns;
2264
+ name;
2265
+ getName() {
2266
+ return this.name;
2267
+ }
2268
+ };
2269
+
2270
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/common.js
2271
+ var SQLiteColumnBuilder = class extends ColumnBuilder {
2272
+ static [entityKind] = "SQLiteColumnBuilder";
2273
+ foreignKeyConfigs = [];
2274
+ references(ref, actions = {}) {
2275
+ this.foreignKeyConfigs.push({ ref, actions });
2276
+ return this;
2277
+ }
2278
+ unique(name) {
2279
+ this.config.isUnique = true;
2280
+ this.config.uniqueName = name;
2281
+ return this;
2282
+ }
2283
+ generatedAlwaysAs(as, config) {
2284
+ this.config.generated = {
2285
+ as,
2286
+ type: "always",
2287
+ mode: config?.mode ?? "virtual"
2288
+ };
2289
+ return this;
2290
+ }
2291
+ /** @internal */
2292
+ buildForeignKeys(column, table) {
2293
+ return this.foreignKeyConfigs.map(({ ref, actions }) => {
2294
+ return ((ref2, actions2) => {
2295
+ const builder = new ForeignKeyBuilder2(() => {
2296
+ const foreignColumn = ref2();
2297
+ return { columns: [column], foreignColumns: [foreignColumn] };
2298
+ });
2299
+ if (actions2.onUpdate) {
2300
+ builder.onUpdate(actions2.onUpdate);
2301
+ }
2302
+ if (actions2.onDelete) {
2303
+ builder.onDelete(actions2.onDelete);
2304
+ }
2305
+ return builder.build(table);
2306
+ })(ref, actions);
2307
+ });
2308
+ }
2309
+ };
2310
+ var SQLiteColumn = class extends Column {
2311
+ constructor(table, config) {
2312
+ if (!config.uniqueName) {
2313
+ config.uniqueName = uniqueKeyName2(table, [config.name]);
2314
+ }
2315
+ super(table, config);
2316
+ this.table = table;
2317
+ }
2318
+ static [entityKind] = "SQLiteColumn";
2319
+ };
2320
+
2321
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/blob.js
2322
+ var SQLiteBigIntBuilder = class extends SQLiteColumnBuilder {
2323
+ static [entityKind] = "SQLiteBigIntBuilder";
2324
+ constructor(name) {
2325
+ super(name, "bigint", "SQLiteBigInt");
2326
+ }
2327
+ /** @internal */
2328
+ build(table) {
2329
+ return new SQLiteBigInt(table, this.config);
2330
+ }
2331
+ };
2332
+ var SQLiteBigInt = class extends SQLiteColumn {
2333
+ static [entityKind] = "SQLiteBigInt";
2334
+ getSQLType() {
2335
+ return "blob";
2336
+ }
2337
+ mapFromDriverValue(value) {
2338
+ if (typeof Buffer !== "undefined" && Buffer.from) {
2339
+ const buf = Buffer.isBuffer(value) ? value : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value);
2340
+ return BigInt(buf.toString("utf8"));
2341
+ }
2342
+ return BigInt(textDecoder.decode(value));
2343
+ }
2344
+ mapToDriverValue(value) {
2345
+ return Buffer.from(value.toString());
2346
+ }
2347
+ };
2348
+ var SQLiteBlobJsonBuilder = class extends SQLiteColumnBuilder {
2349
+ static [entityKind] = "SQLiteBlobJsonBuilder";
2350
+ constructor(name) {
2351
+ super(name, "json", "SQLiteBlobJson");
2352
+ }
2353
+ /** @internal */
2354
+ build(table) {
2355
+ return new SQLiteBlobJson(
2356
+ table,
2357
+ this.config
2358
+ );
2359
+ }
2360
+ };
2361
+ var SQLiteBlobJson = class extends SQLiteColumn {
2362
+ static [entityKind] = "SQLiteBlobJson";
2363
+ getSQLType() {
2364
+ return "blob";
2365
+ }
2366
+ mapFromDriverValue(value) {
2367
+ if (typeof Buffer !== "undefined" && Buffer.from) {
2368
+ const buf = Buffer.isBuffer(value) ? value : value instanceof ArrayBuffer ? Buffer.from(value) : value.buffer ? Buffer.from(value.buffer, value.byteOffset, value.byteLength) : Buffer.from(value);
2369
+ return JSON.parse(buf.toString("utf8"));
2370
+ }
2371
+ return JSON.parse(textDecoder.decode(value));
2372
+ }
2373
+ mapToDriverValue(value) {
2374
+ return Buffer.from(JSON.stringify(value));
2375
+ }
2376
+ };
2377
+ var SQLiteBlobBufferBuilder = class extends SQLiteColumnBuilder {
2378
+ static [entityKind] = "SQLiteBlobBufferBuilder";
2379
+ constructor(name) {
2380
+ super(name, "buffer", "SQLiteBlobBuffer");
2381
+ }
2382
+ /** @internal */
2383
+ build(table) {
2384
+ return new SQLiteBlobBuffer(table, this.config);
2385
+ }
2386
+ };
2387
+ var SQLiteBlobBuffer = class extends SQLiteColumn {
2388
+ static [entityKind] = "SQLiteBlobBuffer";
2389
+ mapFromDriverValue(value) {
2390
+ if (Buffer.isBuffer(value)) {
2391
+ return value;
2392
+ }
2393
+ return Buffer.from(value);
2394
+ }
2395
+ getSQLType() {
2396
+ return "blob";
2397
+ }
2398
+ };
2399
+ function blob(a, b) {
2400
+ const { name, config } = getColumnNameAndConfig(a, b);
2401
+ if (config?.mode === "json") {
2402
+ return new SQLiteBlobJsonBuilder(name);
2403
+ }
2404
+ if (config?.mode === "bigint") {
2405
+ return new SQLiteBigIntBuilder(name);
2406
+ }
2407
+ return new SQLiteBlobBufferBuilder(name);
2408
+ }
2409
+
2410
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/custom.js
2411
+ var SQLiteCustomColumnBuilder = class extends SQLiteColumnBuilder {
2412
+ static [entityKind] = "SQLiteCustomColumnBuilder";
2413
+ constructor(name, fieldConfig, customTypeParams) {
2414
+ super(name, "custom", "SQLiteCustomColumn");
2415
+ this.config.fieldConfig = fieldConfig;
2416
+ this.config.customTypeParams = customTypeParams;
2417
+ }
2418
+ /** @internal */
2419
+ build(table) {
2420
+ return new SQLiteCustomColumn(
2421
+ table,
2422
+ this.config
2423
+ );
2424
+ }
2425
+ };
2426
+ var SQLiteCustomColumn = class extends SQLiteColumn {
2427
+ static [entityKind] = "SQLiteCustomColumn";
2428
+ sqlName;
2429
+ mapTo;
2430
+ mapFrom;
2431
+ constructor(table, config) {
2432
+ super(table, config);
2433
+ this.sqlName = config.customTypeParams.dataType(config.fieldConfig);
2434
+ this.mapTo = config.customTypeParams.toDriver;
2435
+ this.mapFrom = config.customTypeParams.fromDriver;
2436
+ }
2437
+ getSQLType() {
2438
+ return this.sqlName;
2439
+ }
2440
+ mapFromDriverValue(value) {
2441
+ return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
2442
+ }
2443
+ mapToDriverValue(value) {
2444
+ return typeof this.mapTo === "function" ? this.mapTo(value) : value;
2445
+ }
2446
+ };
2447
+ function customType(customTypeParams) {
2448
+ return (a, b) => {
2449
+ const { name, config } = getColumnNameAndConfig(a, b);
2450
+ return new SQLiteCustomColumnBuilder(
2451
+ name,
2452
+ config,
2453
+ customTypeParams
2454
+ );
2455
+ };
2456
+ }
2457
+
2458
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/integer.js
2459
+ var SQLiteBaseIntegerBuilder = class extends SQLiteColumnBuilder {
2460
+ static [entityKind] = "SQLiteBaseIntegerBuilder";
2461
+ constructor(name, dataType, columnType) {
2462
+ super(name, dataType, columnType);
2463
+ this.config.autoIncrement = false;
2464
+ }
2465
+ primaryKey(config) {
2466
+ if (config?.autoIncrement) {
2467
+ this.config.autoIncrement = true;
2468
+ }
2469
+ this.config.hasDefault = true;
2470
+ return super.primaryKey();
2471
+ }
2472
+ };
2473
+ var SQLiteBaseInteger = class extends SQLiteColumn {
2474
+ static [entityKind] = "SQLiteBaseInteger";
2475
+ autoIncrement = this.config.autoIncrement;
2476
+ getSQLType() {
2477
+ return "integer";
2478
+ }
2479
+ };
2480
+ var SQLiteIntegerBuilder = class extends SQLiteBaseIntegerBuilder {
2481
+ static [entityKind] = "SQLiteIntegerBuilder";
2482
+ constructor(name) {
2483
+ super(name, "number", "SQLiteInteger");
2484
+ }
2485
+ build(table) {
2486
+ return new SQLiteInteger(
2487
+ table,
2488
+ this.config
2489
+ );
2490
+ }
2491
+ };
2492
+ var SQLiteInteger = class extends SQLiteBaseInteger {
2493
+ static [entityKind] = "SQLiteInteger";
2494
+ };
2495
+ var SQLiteTimestampBuilder = class extends SQLiteBaseIntegerBuilder {
2496
+ static [entityKind] = "SQLiteTimestampBuilder";
2497
+ constructor(name, mode) {
2498
+ super(name, "date", "SQLiteTimestamp");
2499
+ this.config.mode = mode;
2500
+ }
2501
+ /**
2502
+ * @deprecated Use `default()` with your own expression instead.
2503
+ *
2504
+ * Adds `DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer))` to the column, which is the current epoch timestamp in milliseconds.
2505
+ */
2506
+ defaultNow() {
2507
+ return this.default(sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`);
2508
+ }
2509
+ build(table) {
2510
+ return new SQLiteTimestamp(
2511
+ table,
2512
+ this.config
2513
+ );
2514
+ }
2515
+ };
2516
+ var SQLiteTimestamp = class extends SQLiteBaseInteger {
2517
+ static [entityKind] = "SQLiteTimestamp";
2518
+ mode = this.config.mode;
2519
+ mapFromDriverValue(value) {
2520
+ if (this.config.mode === "timestamp") {
2521
+ return new Date(value * 1e3);
2522
+ }
2523
+ return new Date(value);
2524
+ }
2525
+ mapToDriverValue(value) {
2526
+ const unix = value.getTime();
2527
+ if (this.config.mode === "timestamp") {
2528
+ return Math.floor(unix / 1e3);
2529
+ }
2530
+ return unix;
2531
+ }
2532
+ };
2533
+ var SQLiteBooleanBuilder = class extends SQLiteBaseIntegerBuilder {
2534
+ static [entityKind] = "SQLiteBooleanBuilder";
2535
+ constructor(name, mode) {
2536
+ super(name, "boolean", "SQLiteBoolean");
2537
+ this.config.mode = mode;
2538
+ }
2539
+ build(table) {
2540
+ return new SQLiteBoolean(
2541
+ table,
2542
+ this.config
2543
+ );
2544
+ }
2545
+ };
2546
+ var SQLiteBoolean = class extends SQLiteBaseInteger {
2547
+ static [entityKind] = "SQLiteBoolean";
2548
+ mode = this.config.mode;
2549
+ mapFromDriverValue(value) {
2550
+ return Number(value) === 1;
2551
+ }
2552
+ mapToDriverValue(value) {
2553
+ return value ? 1 : 0;
2554
+ }
2555
+ };
2556
+ function integer(a, b) {
2557
+ const { name, config } = getColumnNameAndConfig(a, b);
2558
+ if (config?.mode === "timestamp" || config?.mode === "timestamp_ms") {
2559
+ return new SQLiteTimestampBuilder(name, config.mode);
2560
+ }
2561
+ if (config?.mode === "boolean") {
2562
+ return new SQLiteBooleanBuilder(name, config.mode);
2563
+ }
2564
+ return new SQLiteIntegerBuilder(name);
2565
+ }
2566
+
2567
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
2568
+ var SQLiteNumericBuilder = class extends SQLiteColumnBuilder {
2569
+ static [entityKind] = "SQLiteNumericBuilder";
2570
+ constructor(name) {
2571
+ super(name, "string", "SQLiteNumeric");
2572
+ }
2573
+ /** @internal */
2574
+ build(table) {
2575
+ return new SQLiteNumeric(
2576
+ table,
2577
+ this.config
2578
+ );
2579
+ }
2580
+ };
2581
+ var SQLiteNumeric = class extends SQLiteColumn {
2582
+ static [entityKind] = "SQLiteNumeric";
2583
+ mapFromDriverValue(value) {
2584
+ if (typeof value === "string") return value;
2585
+ return String(value);
2586
+ }
2587
+ getSQLType() {
2588
+ return "numeric";
2589
+ }
2590
+ };
2591
+ var SQLiteNumericNumberBuilder = class extends SQLiteColumnBuilder {
2592
+ static [entityKind] = "SQLiteNumericNumberBuilder";
2593
+ constructor(name) {
2594
+ super(name, "number", "SQLiteNumericNumber");
2595
+ }
2596
+ /** @internal */
2597
+ build(table) {
2598
+ return new SQLiteNumericNumber(
2599
+ table,
2600
+ this.config
2601
+ );
2602
+ }
2603
+ };
2604
+ var SQLiteNumericNumber = class extends SQLiteColumn {
2605
+ static [entityKind] = "SQLiteNumericNumber";
2606
+ mapFromDriverValue(value) {
2607
+ if (typeof value === "number") return value;
2608
+ return Number(value);
2609
+ }
2610
+ mapToDriverValue = String;
2611
+ getSQLType() {
2612
+ return "numeric";
2613
+ }
2614
+ };
2615
+ var SQLiteNumericBigIntBuilder = class extends SQLiteColumnBuilder {
2616
+ static [entityKind] = "SQLiteNumericBigIntBuilder";
2617
+ constructor(name) {
2618
+ super(name, "bigint", "SQLiteNumericBigInt");
2619
+ }
2620
+ /** @internal */
2621
+ build(table) {
2622
+ return new SQLiteNumericBigInt(
2623
+ table,
2624
+ this.config
2625
+ );
2626
+ }
2627
+ };
2628
+ var SQLiteNumericBigInt = class extends SQLiteColumn {
2629
+ static [entityKind] = "SQLiteNumericBigInt";
2630
+ mapFromDriverValue = BigInt;
2631
+ mapToDriverValue = String;
2632
+ getSQLType() {
2633
+ return "numeric";
2634
+ }
2635
+ };
2636
+ function numeric(a, b) {
2637
+ const { name, config } = getColumnNameAndConfig(a, b);
2638
+ const mode = config?.mode;
2639
+ return mode === "number" ? new SQLiteNumericNumberBuilder(name) : mode === "bigint" ? new SQLiteNumericBigIntBuilder(name) : new SQLiteNumericBuilder(name);
2640
+ }
2641
+
2642
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/real.js
2643
+ var SQLiteRealBuilder = class extends SQLiteColumnBuilder {
2644
+ static [entityKind] = "SQLiteRealBuilder";
2645
+ constructor(name) {
2646
+ super(name, "number", "SQLiteReal");
2647
+ }
2648
+ /** @internal */
2649
+ build(table) {
2650
+ return new SQLiteReal(table, this.config);
2651
+ }
2652
+ };
2653
+ var SQLiteReal = class extends SQLiteColumn {
2654
+ static [entityKind] = "SQLiteReal";
2655
+ getSQLType() {
2656
+ return "real";
2657
+ }
2658
+ };
2659
+ function real(name) {
2660
+ return new SQLiteRealBuilder(name ?? "");
2661
+ }
2662
+
2663
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/text.js
2664
+ var SQLiteTextBuilder = class extends SQLiteColumnBuilder {
2665
+ static [entityKind] = "SQLiteTextBuilder";
2666
+ constructor(name, config) {
2667
+ super(name, "string", "SQLiteText");
2668
+ this.config.enumValues = config.enum;
2669
+ this.config.length = config.length;
2670
+ }
2671
+ /** @internal */
2672
+ build(table) {
2673
+ return new SQLiteText(
2674
+ table,
2675
+ this.config
2676
+ );
2677
+ }
2678
+ };
2679
+ var SQLiteText = class extends SQLiteColumn {
2680
+ static [entityKind] = "SQLiteText";
2681
+ enumValues = this.config.enumValues;
2682
+ length = this.config.length;
2683
+ constructor(table, config) {
2684
+ super(table, config);
2685
+ }
2686
+ getSQLType() {
2687
+ return `text${this.config.length ? `(${this.config.length})` : ""}`;
2688
+ }
2689
+ };
2690
+ var SQLiteTextJsonBuilder = class extends SQLiteColumnBuilder {
2691
+ static [entityKind] = "SQLiteTextJsonBuilder";
2692
+ constructor(name) {
2693
+ super(name, "json", "SQLiteTextJson");
2694
+ }
2695
+ /** @internal */
2696
+ build(table) {
2697
+ return new SQLiteTextJson(
2698
+ table,
2699
+ this.config
2700
+ );
2701
+ }
2702
+ };
2703
+ var SQLiteTextJson = class extends SQLiteColumn {
2704
+ static [entityKind] = "SQLiteTextJson";
2705
+ getSQLType() {
2706
+ return "text";
2707
+ }
2708
+ mapFromDriverValue(value) {
2709
+ return JSON.parse(value);
2710
+ }
2711
+ mapToDriverValue(value) {
2712
+ return JSON.stringify(value);
2713
+ }
2714
+ };
2715
+ function text2(a, b = {}) {
2716
+ const { name, config } = getColumnNameAndConfig(a, b);
2717
+ if (config.mode === "json") {
2718
+ return new SQLiteTextJsonBuilder(name);
2719
+ }
2720
+ return new SQLiteTextBuilder(name, config);
2721
+ }
2722
+
2723
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/all.js
2724
+ function getSQLiteColumnBuilders() {
2725
+ return {
2726
+ blob,
2727
+ customType,
2728
+ integer,
2729
+ numeric,
2730
+ real,
2731
+ text: text2
2732
+ };
2733
+ }
2734
+
2735
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/table.js
2736
+ var InlineForeignKeys = /* @__PURE__ */ Symbol.for("drizzle:SQLiteInlineForeignKeys");
2737
+ var SQLiteTable = class extends Table {
2738
+ static [entityKind] = "SQLiteTable";
2739
+ /** @internal */
2740
+ static Symbol = Object.assign({}, Table.Symbol, {
2741
+ InlineForeignKeys
2742
+ });
2743
+ /** @internal */
2744
+ [Table.Symbol.Columns];
2745
+ /** @internal */
2746
+ [InlineForeignKeys] = [];
2747
+ /** @internal */
2748
+ [Table.Symbol.ExtraConfigBuilder] = void 0;
2749
+ };
2750
+ function sqliteTableBase(name, columns, extraConfig, schema, baseName = name) {
2751
+ const rawTable = new SQLiteTable(name, schema, baseName);
2752
+ const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
2753
+ const builtColumns = Object.fromEntries(
2754
+ Object.entries(parsedColumns).map(([name2, colBuilderBase]) => {
2755
+ const colBuilder = colBuilderBase;
2756
+ colBuilder.setName(name2);
2757
+ const column = colBuilder.build(rawTable);
2758
+ rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
2759
+ return [name2, column];
2760
+ })
2761
+ );
2762
+ const table = Object.assign(rawTable, builtColumns);
2763
+ table[Table.Symbol.Columns] = builtColumns;
2764
+ table[Table.Symbol.ExtraConfigColumns] = builtColumns;
2765
+ if (extraConfig) {
2766
+ table[SQLiteTable.Symbol.ExtraConfigBuilder] = extraConfig;
2767
+ }
2768
+ return table;
2769
+ }
2770
+ var sqliteTable = (name, columns, extraConfig) => {
2771
+ return sqliteTableBase(name, columns, extraConfig);
2772
+ };
2773
+
2774
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.4_@cloudflare+workers-types@5.20261015.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/primary-keys.js
2775
+ function primaryKey(...config) {
2776
+ if (config[0].columns) {
2777
+ return new PrimaryKeyBuilder(config[0].columns, config[0].name);
2778
+ }
2779
+ return new PrimaryKeyBuilder(config);
2780
+ }
2781
+ var PrimaryKeyBuilder = class {
2782
+ static [entityKind] = "SQLitePrimaryKeyBuilder";
2783
+ /** @internal */
2784
+ columns;
2785
+ /** @internal */
2786
+ name;
2787
+ constructor(columns, name) {
2788
+ this.columns = columns;
2789
+ this.name = name;
2790
+ }
2791
+ /** @internal */
2792
+ build(table) {
2793
+ return new PrimaryKey(table, this.columns, this.name);
2794
+ }
2795
+ };
2796
+ var PrimaryKey = class {
2797
+ constructor(table, columns, name) {
2798
+ this.table = table;
2799
+ this.columns = columns;
2800
+ this.name = name;
2801
+ }
2802
+ static [entityKind] = "SQLitePrimaryKey";
2803
+ columns;
2804
+ name;
2805
+ getName() {
2806
+ return this.name ?? `${this.table[SQLiteTable.Symbol.Name]}_${this.columns.map((column) => column.name).join("_")}_pk`;
2807
+ }
2808
+ };
2809
+
2810
+ // ../feedback/src/connected.ts
2811
+ var participants = sqliteTable("participants", {
2812
+ subject: text2("subject").primaryKey(),
2813
+ displayName: text2("display_name").notNull()
2814
+ });
2815
+ var contacts = sqliteTable("participant_contacts", {
2816
+ subject: text2("subject").primaryKey(),
2817
+ email: text2("email"),
2818
+ emailEnabled: integer("email_enabled").notNull().default(0)
2819
+ });
2820
+ var nonces = sqliteTable("identity_nonces", {
2821
+ nonce: text2("nonce").primaryKey(),
2822
+ expiresAt: integer("expires_at").notNull()
2823
+ });
2824
+ var sessions = sqliteTable("participant_sessions", {
2825
+ tokenHash: text2("token_hash").primaryKey(),
2826
+ subject: text2("subject").notNull().references(() => participants.subject),
2827
+ expiresAt: integer("expires_at").notNull()
2828
+ });
2829
+ var votes = sqliteTable(
2830
+ "participant_votes",
2831
+ {
2832
+ postSlug: text2("post_slug").notNull(),
2833
+ subject: text2("subject").notNull().references(() => participants.subject)
2834
+ },
2835
+ (t) => [primaryKey({ columns: [t.postSlug, t.subject] })]
2836
+ );
2837
+ var attribution = sqliteTable("comment_attribution", {
2838
+ commentId: text2("comment_id").primaryKey(),
2839
+ subject: text2("subject").notNull().references(() => participants.subject),
2840
+ displayName: text2("display_name").notNull()
2841
+ });
2842
+
2843
+ // ../feedback/src/images.ts
2844
+ var limit = 5 * 1024 * 1024;
2845
+
2846
+ // ../feedback/src/index.ts
2847
+ var postCreationQueue = Promise.resolve();
2848
+
2849
+ // ../changelog/src/notion-changelog.ts
2850
+ var NOTION_API_URL2 = "https://api.notion.com/v1";
2851
+ var NOTION_API_VERSION2 = "2026-03-11";
2852
+ var canonicalProperties2 = {
2853
+ title: { name: "Title", type: "title", schema: { title: {} } },
2854
+ slug: { name: "Slug", type: "rich_text", schema: { rich_text: {} } },
2855
+ date: { name: "Date", type: "date", schema: { date: {} } },
2856
+ summary: {
2857
+ name: "Summary",
2858
+ type: "rich_text",
2859
+ schema: { rich_text: {} }
2860
+ },
2861
+ body: { name: "Body", type: "rich_text", schema: { rich_text: {} } },
2862
+ labels: {
2863
+ name: "Labels",
2864
+ type: "multi_select",
2865
+ schema: { multi_select: { options: [] } }
2866
+ },
2867
+ image: { name: "Image", type: "files", schema: { files: {} } },
2868
+ published: {
2869
+ name: "Published",
2870
+ type: "checkbox",
2871
+ schema: { checkbox: {} }
2872
+ },
2873
+ createdAt: {
2874
+ name: "Created At",
2875
+ type: "created_time",
2876
+ schema: { created_time: {} }
2877
+ },
2878
+ updatedAt: {
2879
+ name: "Updated At",
2880
+ type: "last_edited_time",
2881
+ schema: { last_edited_time: {} }
2882
+ }
2883
+ };
2884
+ async function createNotionChangelogDataSource({
2885
+ token,
2886
+ databaseId,
2887
+ request = fetch
2888
+ }) {
2889
+ const response = await request(`${NOTION_API_URL2}/data_sources`, {
2890
+ method: "POST",
2891
+ headers: notionHeaders2(token),
2892
+ body: JSON.stringify({
2893
+ parent: { database_id: databaseId },
2894
+ title: [{ type: "text", text: { content: "Changelog" } }],
2895
+ properties: Object.fromEntries(
2896
+ Object.values(canonicalProperties2).map(({ name, schema }) => [
2897
+ name,
2898
+ schema
2899
+ ])
2900
+ )
2901
+ })
2902
+ });
2903
+ return configurationFromResponse(
2904
+ await readObject(response, "Changelog Data Source"),
2905
+ databaseId
2906
+ );
2907
+ }
2908
+ async function validateNotionChangelogDataSource({
2909
+ token,
2910
+ dataSourceId,
2911
+ propertyIds,
2912
+ request = fetch
2913
+ }) {
2914
+ const response = await request(
2915
+ `${NOTION_API_URL2}/data_sources/${dataSourceId}`,
2916
+ { headers: notionHeaders2(token) }
2917
+ );
2918
+ const dataSource = await readObject(response, "Changelog Data Source");
2919
+ const properties = recordAt(dataSource, "properties");
2920
+ const propertiesById = new Map(
2921
+ Object.values(properties).flatMap((property) => {
2922
+ if (!isRecord2(property) || typeof property.id !== "string") return [];
2923
+ return [[property.id, property]];
2924
+ })
2925
+ );
2926
+ const repairs = [];
2927
+ for (const [key, { name, type }] of Object.entries(canonicalProperties2)) {
2928
+ const configuredId = propertyIds[key];
2929
+ const property = propertiesById.get(configuredId);
2930
+ if (!property) {
2931
+ repairs.push(
2932
+ `Restore the "${name}" property with ID "${configuredId}" and type "${type}", then update the configured property ID if Notion assigns a new one.`
2933
+ );
2934
+ } else if (property.type !== type) {
2935
+ repairs.push(
2936
+ `Change the property configured as "${name}" (ID "${configuredId}") from "${String(property.type)}" to "${type}", or restore a ${type} property and configure its ID.`
2937
+ );
2938
+ }
2939
+ }
2940
+ if (repairs.length) throw new Error(repairs.join("\n"));
2941
+ return {
2942
+ databaseId: databaseIdFromResponse(dataSource),
2943
+ dataSourceId,
2944
+ propertyIds: { ...propertyIds }
2945
+ };
2946
+ }
2947
+ function configurationFromResponse(dataSource, databaseId) {
2948
+ const properties = recordAt(dataSource, "properties");
2949
+ return {
2950
+ databaseId,
2951
+ dataSourceId: requiredString(dataSource.id),
2952
+ propertyIds: Object.fromEntries(
2953
+ Object.entries(canonicalProperties2).map(([key, { name }]) => [
2954
+ key,
2955
+ requiredString(recordAt(properties, name).id)
2956
+ ])
2957
+ )
2958
+ };
2959
+ }
2960
+ function databaseIdFromResponse(dataSource) {
2961
+ return requiredString(recordAt(dataSource, "parent").database_id);
2962
+ }
2963
+ function notionHeaders2(token) {
2964
+ return {
2965
+ Authorization: `Bearer ${token}`,
2966
+ "Content-Type": "application/json",
2967
+ "Notion-Version": NOTION_API_VERSION2
2968
+ };
2969
+ }
2970
+ async function readObject(response, subject) {
2971
+ const body = await response.json();
2972
+ if (!response.ok) {
2973
+ throw new Error(
2974
+ `Notion rejected the ${subject} request (${response.status}).`
2975
+ );
2976
+ }
2977
+ if (!isRecord2(body))
2978
+ throw new Error(`Notion returned an invalid ${subject} response.`);
2979
+ return body;
2980
+ }
2981
+ function recordAt(value, key) {
2982
+ return record(value[key]);
2983
+ }
2984
+ function record(value) {
2985
+ if (!isRecord2(value))
2986
+ throw new Error("Notion returned an invalid Changelog response.");
2987
+ return value;
2988
+ }
2989
+ function requiredString(value) {
2990
+ if (typeof value !== "string")
2991
+ throw new Error("Notion returned an invalid Changelog response.");
2992
+ return value;
2993
+ }
2994
+ function isRecord2(value) {
2995
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2996
+ }
2997
+
2998
+ // src/github.ts
2999
+ import { createHash as createHash2, randomBytes } from "node:crypto";
3000
+ import { readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
3001
+ import { join as join2 } from "node:path";
3002
+ async function provisionGitHubInstallation(options) {
3003
+ const { connected, github } = options;
3004
+ if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(options.workerName) || !/^[0-9a-f-]{36}$/i.test(options.database.id) || !options.database.name.trim())
3005
+ throw new Error(
3006
+ "GitHub setup requires a distinct Worker and an explicitly provisioned FEEDBAX_DB D1 database."
3007
+ );
3008
+ if (connected && (connected.databaseId !== options.database.id || connected.handoffSecret.length < 32 || connected.processing !== "standard" && !connected.queueName))
3009
+ throw new Error(
3010
+ "Connected setup requires the same D1 database, a handoff secret, and an existing processing queue for small processing."
3011
+ );
3012
+ if (connected?.imageBucket && !/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(connected.imageBucket))
3013
+ throw new Error("Use a dedicated private R2 bucket for images.");
3014
+ const config = defineFeedbax({
3015
+ provider: "github",
3016
+ github,
3017
+ product: { ...options.product, logo: "/feedbax-mark.svg" },
3018
+ theme: { preset: "lyra-neutral" },
3019
+ features: options.features,
3020
+ ...connected ? {
3021
+ connected: {
3022
+ processing: connected.processing ?? "small",
3023
+ issuer: connected.issuer,
3024
+ loginUrl: connected.loginUrl,
3025
+ ...connected.imageBucket ? { images: true } : {},
3026
+ ...connected.email ? {
3027
+ email: {
3028
+ provider: connected.email.provider,
3029
+ from: connected.email.from,
3030
+ ...connected.email.endpoint ? { endpoint: connected.email.endpoint } : {}
3031
+ }
3032
+ } : {}
3033
+ }
3034
+ } : {},
3035
+ submissions: {
3036
+ moderation: "required",
3037
+ maxTitleLength: 160,
3038
+ maxDescriptionLength: 5e3
3039
+ },
3040
+ turnstile: {
3041
+ enabled: Boolean(options.turnstile?.siteKey),
3042
+ ...options.turnstile?.siteKey ? { siteKey: options.turnstile.siteKey } : {}
3043
+ }
3044
+ });
3045
+ if (!await options.preview(
3046
+ "Create GitHub-backed portal source and private pairing secrets. GitHub requires D1 independently of sign-in. If the repository is public, issue titles/bodies are public immediately even while portal Posts await moderation. This does not create issues, pair the App, or deploy."
3047
+ ))
3048
+ throw new Error("GitHub setup was not approved.");
3049
+ await copyPackagedTemplate(options.destination);
3050
+ const path = join2(options.destination, "wrangler.jsonc");
3051
+ const base = JSON.parse(await readFile2(path, "utf8"));
3052
+ const wrangler = {
3053
+ ...base,
3054
+ name: options.workerName,
3055
+ compatibility_flags: [
3056
+ .../* @__PURE__ */ new Set([
3057
+ ...base.compatibility_flags ?? [],
3058
+ "global_fetch_strictly_public"
3059
+ ])
3060
+ ],
3061
+ d1_databases: [
3062
+ {
3063
+ binding: "FEEDBAX_DB",
3064
+ database_id: options.database.id,
3065
+ database_name: options.database.name,
3066
+ migrations_dir: "migrations"
3067
+ }
3068
+ ],
3069
+ triggers: { crons: ["*/5 * * * *"] },
3070
+ ...connected?.queueName ? {
3071
+ queues: {
3072
+ producers: [
3073
+ { binding: "FEEDBAX_UPDATES", queue: connected.queueName }
3074
+ ],
3075
+ consumers: [
3076
+ {
3077
+ queue: connected.queueName,
3078
+ max_batch_size: 1,
3079
+ max_concurrency: 1,
3080
+ max_retries: 3,
3081
+ retry_delay: 60
3082
+ }
3083
+ ]
3084
+ }
3085
+ } : {},
3086
+ ...connected?.imageBucket ? {
3087
+ r2_buckets: [
3088
+ { binding: "FEEDBAX_IMAGES", bucket_name: connected.imageBucket }
3089
+ ]
3090
+ } : {},
3091
+ ...connected?.email?.provider === "cloudflare" ? {
3092
+ send_email: [
3093
+ {
3094
+ name: "FEEDBAX_EMAIL",
3095
+ allowed_sender_addresses: [connected.email.from]
3096
+ }
3097
+ ]
3098
+ } : {}
3099
+ };
3100
+ const apiKey = randomBytes(32).toString("base64url");
3101
+ const pairingSecret = randomBytes(32).toString("base64url");
3102
+ const secrets = {
3103
+ FEEDBAX_API_KEY_HASH: createHash2("sha256").update(apiKey).digest("base64url"),
3104
+ PARTICIPATION_SIGNING_SECRET: randomBytes(32).toString("base64url"),
3105
+ GITHUB_PAIRING_SECRET: pairingSecret,
3106
+ ...connected ? { IDENTITY_HANDOFF_SECRET: connected.handoffSecret } : {},
3107
+ ...connected?.email?.secret ? { EMAIL_PROVIDER_SECRET: connected.email.secret } : {},
3108
+ ...options.turnstile?.secretKey ? { TURNSTILE_SECRET_KEY: options.turnstile.secretKey } : {}
3109
+ };
3110
+ await writeFile2(path, JSON.stringify(wrangler, null, 2) + "\n");
3111
+ await writeFile2(
3112
+ join2(options.destination, "src/feedbax.ts"),
3113
+ `import { defineFeedbax } from "@feedbax/config";
3114
+
3115
+ export default defineFeedbax(${JSON.stringify(config, null, 2)});
3116
+ `
3117
+ );
3118
+ await writeFile2(
3119
+ join2(options.destination, ".dev.vars"),
3120
+ Object.entries(secrets).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n") + "\n",
3121
+ { mode: 384 }
3122
+ );
3123
+ return { apiKey, pairingSecret, configuration: config };
3124
+ }
3125
+
3126
+ // src/index.ts
3127
+ function defaultProcessingQueueName(workerName) {
3128
+ return workerName.length <= 55 ? `${workerName}-updates` : `${workerName.slice(0, 46)}-${createHash3("sha256").update(workerName).digest("hex").slice(0, 8)}-updates`;
3129
+ }
3130
+ async function provisionGuidedInstallation({
3131
+ destination,
3132
+ product,
3133
+ themePreset,
3134
+ workerName,
3135
+ commentProbePageId,
3136
+ connected,
3137
+ features,
3138
+ feedbackSelection,
3139
+ changelogSelection,
3140
+ notionToken,
3141
+ turnstile,
3142
+ preview,
3143
+ request = fetch
3144
+ }) {
3145
+ try {
3146
+ if ((await readdir2(destination)).length)
3147
+ throw new Error(
3148
+ `Refusing to generate into non-empty destination: ${destination}`
3149
+ );
3150
+ } catch (error) {
3151
+ if (error.code !== "ENOENT") throw error;
3152
+ }
3153
+ if (product.siteUrl && new URL(product.siteUrl).protocol !== "https:")
3154
+ throw new Error("product.siteUrl must be an HTTPS URL.");
3155
+ if (connected) {
3156
+ if (!product.siteUrl || connected.handoffSecret.length < 32 || !/^[0-9a-f-]{36}$/i.test(connected.databaseId) || !connected.databaseName.trim())
3157
+ throw new Error(
3158
+ "Connected setup requires a public site URL, dedicated D1 identifiers, and a handoff secret of at least 32 characters."
3159
+ );
3160
+ for (const url of [connected.issuer, connected.loginUrl])
3161
+ if (new URL(url).protocol !== "https:" || new URL(url).username || new URL(url).password)
3162
+ throw new Error(
3163
+ "Connected identity URLs must use HTTPS without credentials."
3164
+ );
3165
+ }
3166
+ if (connected?.email) {
3167
+ const sender = connected.email;
3168
+ if (!["cloudflare", "resend", "custom"].includes(sender.provider) || !/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(sender.from))
3169
+ throw new Error(
3170
+ "Choose cloudflare, resend, or custom and a plain sender email address."
3171
+ );
3172
+ if (sender.provider !== "cloudflare" && !sender.secret?.trim())
3173
+ throw new Error(
3174
+ "Resend and custom delivery require a server-only email secret."
3175
+ );
3176
+ if (sender.provider === "custom" && (!sender.endpoint || new URL(sender.endpoint).protocol !== "https:" || new URL(sender.endpoint).username || new URL(sender.endpoint).password || new URL(sender.endpoint).hash))
3177
+ throw new Error(
3178
+ "Custom delivery requires an HTTPS endpoint without credentials or fragments."
3179
+ );
3180
+ }
3181
+ if (connected?.imageBucket && !/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(connected.imageBucket))
3182
+ throw new Error(
3183
+ "Use a dedicated private R2 bucket name of 3\u201363 lowercase letters, digits, or hyphens."
3184
+ );
3185
+ const targetName = workerName ?? basename(destination).toLowerCase().replace(/[^a-z0-9-]/g, "-");
1086
3186
  if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(targetName))
1087
3187
  throw new Error(
1088
3188
  "Worker name must contain 1\u201363 lowercase letters, numbers, or hyphens."
1089
3189
  );
3190
+ const processingQueue = connected && connected.processing !== "standard" ? connected.queueName ?? defaultProcessingQueueName(targetName) : void 0;
3191
+ if (processingQueue && !/^[a-z0-9][a-z0-9-]{0,62}$/.test(processingQueue))
3192
+ throw new Error(
3193
+ "Processing queue name must contain 1\u201363 lowercase letters, numbers, or hyphens."
3194
+ );
1090
3195
  const approved = await preview(
1091
3196
  feedbackSelection.kind === "create" ? `Create the canonical Feedback Data Source inside Notion page ${feedbackSelection.parentPageId}.` : `Validate existing Feedback Data Source ${feedbackSelection.configuration.dataSourceId} without changing it.`
1092
3197
  );
@@ -1128,21 +3233,74 @@ async function provisionGuidedInstallation({
1128
3233
  preview
1129
3234
  });
1130
3235
  await copyPackagedTemplate(destination);
1131
- const wranglerPath = join2(destination, "wrangler.jsonc");
1132
- const wrangler = JSON.parse(await readFile2(wranglerPath, "utf8"));
1133
- await writeFile2(
3236
+ const wranglerPath = join3(destination, "wrangler.jsonc");
3237
+ const wrangler = JSON.parse(await readFile3(wranglerPath, "utf8"));
3238
+ await writeFile3(
1134
3239
  wranglerPath,
1135
- JSON.stringify({ ...wrangler, name: targetName }, null, 2) + "\n"
3240
+ JSON.stringify(
3241
+ {
3242
+ ...wrangler,
3243
+ name: targetName,
3244
+ ...connected ? {
3245
+ triggers: { crons: ["*/5 * * * *"] },
3246
+ ...processingQueue ? {
3247
+ queues: {
3248
+ producers: [
3249
+ { binding: "FEEDBAX_UPDATES", queue: processingQueue }
3250
+ ],
3251
+ consumers: [
3252
+ {
3253
+ queue: processingQueue,
3254
+ max_batch_size: 1,
3255
+ max_batch_timeout: 1,
3256
+ max_retries: 3,
3257
+ max_concurrency: 1,
3258
+ retry_delay: 60
3259
+ }
3260
+ ]
3261
+ }
3262
+ } : {},
3263
+ ...connected.email?.provider === "cloudflare" ? {
3264
+ send_email: [
3265
+ {
3266
+ name: "FEEDBAX_EMAIL",
3267
+ allowed_sender_addresses: [connected.email.from]
3268
+ }
3269
+ ]
3270
+ } : {},
3271
+ ...connected.imageBucket ? {
3272
+ r2_buckets: [
3273
+ {
3274
+ binding: "FEEDBAX_IMAGES",
3275
+ bucket_name: connected.imageBucket
3276
+ }
3277
+ ]
3278
+ } : {},
3279
+ d1_databases: [
3280
+ {
3281
+ binding: "FEEDBAX_DB",
3282
+ database_id: connected.databaseId,
3283
+ database_name: connected.databaseName,
3284
+ migrations_dir: "migrations"
3285
+ }
3286
+ ]
3287
+ } : {}
3288
+ },
3289
+ null,
3290
+ 2
3291
+ ) + "\n"
1136
3292
  );
1137
- const apiKey = randomBytes(32).toString("base64url");
1138
- const signingSecret = randomBytes(32).toString("base64url");
3293
+ const apiKey = randomBytes2(32).toString("base64url");
3294
+ const signingSecret = randomBytes2(32).toString("base64url");
1139
3295
  const values = {
1140
3296
  NOTION_TOKEN: notionToken,
1141
3297
  NOTION_FEEDBACK_DATABASE_ID: feedback.databaseId,
1142
3298
  NOTION_FEEDBACK_DATA_SOURCE_ID: feedback.dataSourceId,
1143
3299
  ...prefixProperties("NOTION_FEEDBACK", feedback.propertyIds),
1144
- FEEDBAX_API_KEY_HASH: createHash2("sha256").update(apiKey).digest("base64url"),
3300
+ FEEDBAX_API_KEY_HASH: createHash3("sha256").update(apiKey).digest("base64url"),
1145
3301
  PARTICIPATION_SIGNING_SECRET: signingSecret,
3302
+ ...connected ? { IDENTITY_HANDOFF_SECRET: connected.handoffSecret } : {},
3303
+ ...connected?.email?.secret ? { EMAIL_PROVIDER_SECRET: connected.email.secret } : {},
1146
3304
  FEEDBAX_VOTING_ENABLED: String(features.voting),
1147
3305
  FEEDBAX_COMMENTS_ENABLED: String(features.comments),
1148
3306
  FEEDBAX_CHANGELOG_ENABLED: String(features.changelog),
@@ -1154,14 +3312,29 @@ async function provisionGuidedInstallation({
1154
3312
  ...prefixProperties("NOTION_CHANGELOG", changelog.propertyIds)
1155
3313
  } : {}
1156
3314
  };
1157
- await writeFile2(
1158
- join2(destination, ".dev.vars"),
3315
+ await writeFile3(
3316
+ join3(destination, ".dev.vars"),
1159
3317
  Object.entries(values).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join("\n") + "\n",
1160
3318
  { mode: 384 }
1161
3319
  );
1162
3320
  const configuration = defineFeedbax({
1163
3321
  product: { ...product, logo: "/feedbax-mark.svg" },
1164
3322
  theme: { preset: themePreset },
3323
+ ...connected ? {
3324
+ connected: {
3325
+ processing: connected.processing ?? "small",
3326
+ issuer: connected.issuer,
3327
+ loginUrl: connected.loginUrl,
3328
+ ...connected.email ? {
3329
+ email: {
3330
+ provider: connected.email.provider,
3331
+ from: connected.email.from,
3332
+ ...connected.email.endpoint ? { endpoint: connected.email.endpoint } : {}
3333
+ }
3334
+ } : {},
3335
+ ...connected.imageBucket ? { images: true } : {}
3336
+ }
3337
+ } : {},
1165
3338
  notion: {
1166
3339
  databaseId: feedback.databaseId,
1167
3340
  dataSourceId: feedback.dataSourceId,
@@ -1185,21 +3358,21 @@ async function provisionGuidedInstallation({
1185
3358
  ...turnstile.siteKey ? { siteKey: turnstile.siteKey } : {}
1186
3359
  }
1187
3360
  });
1188
- await writeFile2(
1189
- join2(destination, "src/feedbax.ts"),
3361
+ await writeFile3(
3362
+ join3(destination, "src/feedbax.ts"),
1190
3363
  `import { defineFeedbax } from "@feedbax/config";
1191
3364
 
1192
3365
  export default defineFeedbax(${JSON.stringify(configuration, null, 2)});
1193
3366
  `
1194
3367
  );
1195
3368
  const probePage = commentProbePageId ?? (feedbackSelection.kind === "create" ? feedbackSelection.parentPageId : feedback.databaseId);
1196
- await writeFile2(
1197
- join2(destination, ".dev.vars"),
3369
+ await writeFile3(
3370
+ join3(destination, ".dev.vars"),
1198
3371
  `NOTION_COMMENT_CAPABILITY_PROBE_PAGE_ID=${JSON.stringify(probePage)}
1199
3372
  `,
1200
3373
  { flag: "a", mode: 384 }
1201
3374
  );
1202
- return { apiKey, feedback, changelog };
3375
+ return { apiKey, feedback, changelog, processingQueue };
1203
3376
  }
1204
3377
  function prefixProperties(prefix, properties) {
1205
3378
  return Object.fromEntries(
@@ -1403,9 +3576,11 @@ export {
1403
3576
  collectFeatureSelection,
1404
3577
  configureChangelogStorage,
1405
3578
  copyPackagedTemplate,
3579
+ defaultProcessingQueueName,
1406
3580
  doctorChangelogStorage,
1407
3581
  doctorInstallation,
1408
3582
  featureChoices,
3583
+ provisionGitHubInstallation,
1409
3584
  provisionGuidedInstallation,
1410
3585
  renderChangelogConfiguration,
1411
3586
  renderFeatureConfiguration,