create-feedbax 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2042 -16
- package/dist/index.js +1997 -5
- package/package.json +1 -1
- package/template/.feedbax-template.sha256 +1 -1
- package/template/AGENTS.md +13 -0
- package/template/CONNECTED.md +404 -0
- package/template/README.md +58 -0
- package/template/components.json +1 -1
- package/template/eslint.config.mjs +23 -0
- package/template/migrations/0001_connected.sql +6 -0
- package/template/migrations/0002_participation.sql +8 -0
- package/template/migrations/0003_images.sql +3 -0
- package/template/migrations/0004_followed_status.sql +9 -0
- package/template/package.json +9 -5
- package/template/src/authorized-draft-post.tsx +1 -0
- package/template/src/changelog-page.tsx +63 -54
- package/template/src/cloudflare-workers.d.ts +6 -0
- package/template/src/comment-creation.test.tsx +42 -1
- package/template/src/comment-thread-page.ts +11 -1
- package/template/src/components/command-palette.tsx +59 -30
- package/template/src/components/connected-identity-provider.tsx +108 -0
- package/template/src/components/device-profile-provider.tsx +41 -26
- package/template/src/components/follow-post-button.tsx +89 -0
- package/template/src/components/header.tsx +2 -0
- package/template/src/components/image-attachments.tsx +187 -0
- package/template/src/components/loader.tsx +48 -5
- package/template/src/components/notification-inbox.tsx +232 -0
- package/template/src/components/portal-footer.tsx +14 -0
- package/template/src/components/profile-menu.tsx +30 -0
- package/template/src/components/ui/components/command.tsx +30 -29
- package/template/src/components/ui/components/message-scroller.tsx +2 -2
- package/template/src/components/ui/components/scroll-area.tsx +0 -1
- package/template/src/components/ui/components/switch.tsx +29 -0
- package/template/src/components/ui/styles/globals.css +1 -1
- package/template/src/connected-identity.test.ts +144 -0
- package/template/src/connected-identity.ts +122 -0
- package/template/src/connected-participation.test.tsx +67 -0
- package/template/src/connected-runtime.test.ts +241 -0
- package/template/src/connected-runtime.ts +176 -0
- package/template/src/connected-social.test.tsx +158 -0
- package/template/src/feedback-cache-invalidation.ts +1 -0
- package/template/src/feedback-runtime.ts +79 -12
- package/template/src/feedbax/config/index.test.ts +28 -0
- package/template/src/feedbax/config/index.ts +93 -0
- package/template/src/feedbax/feedback/connected-feedback.ts +206 -0
- package/template/src/feedbax/feedback/connected.test.ts +272 -0
- package/template/src/feedbax/feedback/connected.ts +215 -0
- package/template/src/feedbax/feedback/email-delivery.test.ts +65 -0
- package/template/src/feedbax/feedback/email-delivery.ts +66 -0
- package/template/src/feedbax/feedback/identity-handoff.test.ts +81 -0
- package/template/src/feedbax/feedback/identity-handoff.ts +119 -0
- package/template/src/feedbax/feedback/image-feedback.ts +101 -0
- package/template/src/feedbax/feedback/images.test.ts +223 -0
- package/template/src/feedbax/feedback/images.ts +324 -0
- package/template/src/feedbax/feedback/index.ts +55 -1
- package/template/src/feedbax/feedback/notion-image-review.ts +55 -0
- package/template/src/feedbax/feedback/participation.test.ts +653 -0
- package/template/src/feedbax/feedback/participation.ts +502 -0
- package/template/src/images-runtime.test.ts +133 -0
- package/template/src/images-runtime.ts +125 -0
- package/template/src/index.css +97 -440
- package/template/src/lazy-post-detail-overlay.tsx +13 -2
- package/template/src/overlay-post-detail.test.tsx +59 -8
- package/template/src/overlay-post-detail.tsx +20 -69
- package/template/src/participation-client.ts +63 -0
- package/template/src/participation-runtime.test.ts +35 -0
- package/template/src/participation-runtime.ts +255 -0
- package/template/src/portal-comments.ts +24 -5
- package/template/src/portal-feedback-form.tsx +18 -3
- package/template/src/portal-feedback-runtime.ts +3 -0
- package/template/src/portal-feedback-server-function.ts +6 -3
- package/template/src/portal-feedback-submission.ts +10 -0
- package/template/src/portal-server-entry.ts +4 -0
- package/template/src/post-creation-flow.tsx +2 -2
- package/template/src/post-detail-content.test.tsx +233 -0
- package/template/src/post-detail-content.tsx +162 -0
- package/template/src/post-detail-query.ts +34 -0
- package/template/src/post-results.tsx +1 -1
- package/template/src/public-cache-policy.test.ts +11 -4
- package/template/src/public-cache-policy.ts +1 -1
- package/template/src/public-feedback-index.tsx +9 -39
- package/template/src/public-feedback-page.test.tsx +65 -0
- package/template/src/public-feedback-page.ts +12 -1
- package/template/src/public-post-detail-skeleton.tsx +54 -0
- package/template/src/public-post-detail.tsx +298 -208
- package/template/src/public-post-route.test.tsx +39 -3
- package/template/src/public-post-route.tsx +15 -28
- package/template/src/public-roadmap-route.test.tsx +38 -2
- package/template/src/public-roadmap-view.tsx +56 -23
- package/template/src/public-shell.test.tsx +26 -0
- package/template/src/routeTree.gen.ts +49 -3
- package/template/src/router.tsx +2 -0
- package/template/src/routes/__root.tsx +3 -5
- package/template/src/routes/email-preferences.tsx +77 -0
- package/template/src/routes/submit.tsx +1 -1
- package/template/src/safe-public-failure.ts +3 -1
- package/template/src/server.ts +41 -1
- package/template/src/trusted-feedback-handler.test.ts +1 -1
- package/template/src/vote-toggle.tsx +42 -9
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,7 @@ import { readFile as readFile2, readdir as readdir2, writeFile as writeFile2 } f
|
|
|
12
12
|
|
|
13
13
|
// ../config/src/index.ts
|
|
14
14
|
var rootKeys = [
|
|
15
|
+
"connected",
|
|
15
16
|
"product",
|
|
16
17
|
"theme",
|
|
17
18
|
"notion",
|
|
@@ -68,6 +69,66 @@ function defineFeedbax(config) {
|
|
|
68
69
|
...optionalPublicUrl(product, "supportUrl"),
|
|
69
70
|
...optionalPublicUrl(product, "privacyUrl")
|
|
70
71
|
};
|
|
72
|
+
let connected;
|
|
73
|
+
if (value.connected !== void 0) {
|
|
74
|
+
const input = object(value.connected, "connected");
|
|
75
|
+
rejectUnknown(
|
|
76
|
+
input,
|
|
77
|
+
["issuer", "loginUrl", "email", "images", "processing"],
|
|
78
|
+
"connected"
|
|
79
|
+
);
|
|
80
|
+
const issuer = publicUrl(input.issuer, "connected.issuer", false);
|
|
81
|
+
const loginUrl = publicUrl(input.loginUrl, "connected.loginUrl", false);
|
|
82
|
+
if (!validatedProduct.siteUrl)
|
|
83
|
+
throw new Error("Connected Profile requires product.siteUrl.");
|
|
84
|
+
if (new URL(loginUrl).username || new URL(loginUrl).password || new URL(loginUrl).hash)
|
|
85
|
+
throw new Error(
|
|
86
|
+
"connected.loginUrl must not contain credentials or a fragment."
|
|
87
|
+
);
|
|
88
|
+
let email;
|
|
89
|
+
if (input.email !== void 0) {
|
|
90
|
+
const sender = object(input.email, "connected.email");
|
|
91
|
+
rejectUnknown(
|
|
92
|
+
sender,
|
|
93
|
+
["provider", "from", "endpoint"],
|
|
94
|
+
"connected.email"
|
|
95
|
+
);
|
|
96
|
+
if (!["cloudflare", "resend", "custom"].includes(String(sender.provider)))
|
|
97
|
+
throw new Error(
|
|
98
|
+
"connected.email.provider must be cloudflare, resend, or custom."
|
|
99
|
+
);
|
|
100
|
+
const from = text(sender.from, "connected.email.from");
|
|
101
|
+
if (from.length > 254 || !/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(from))
|
|
102
|
+
throw new Error(
|
|
103
|
+
"connected.email.from must be a plain sender email address."
|
|
104
|
+
);
|
|
105
|
+
const endpoint = sender.endpoint === void 0 ? void 0 : publicUrl(sender.endpoint, "connected.email.endpoint", false);
|
|
106
|
+
if (sender.provider === "custom" && !endpoint)
|
|
107
|
+
throw new Error("Custom email requires connected.email.endpoint.");
|
|
108
|
+
if (sender.provider !== "custom" && endpoint)
|
|
109
|
+
throw new Error("Only custom email uses connected.email.endpoint.");
|
|
110
|
+
if (endpoint && (new URL(endpoint).username || new URL(endpoint).password || new URL(endpoint).hash))
|
|
111
|
+
throw new Error(
|
|
112
|
+
"Custom email endpoint must not contain credentials or a fragment."
|
|
113
|
+
);
|
|
114
|
+
email = {
|
|
115
|
+
provider: sender.provider,
|
|
116
|
+
from,
|
|
117
|
+
...endpoint ? { endpoint } : {}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (input.images !== void 0 && typeof input.images !== "boolean")
|
|
121
|
+
throw new Error("connected.images must be true or false.");
|
|
122
|
+
if (input.processing !== void 0 && input.processing !== "small" && input.processing !== "standard")
|
|
123
|
+
throw new Error("connected.processing must be small or standard.");
|
|
124
|
+
connected = {
|
|
125
|
+
issuer,
|
|
126
|
+
loginUrl,
|
|
127
|
+
...input.processing !== void 0 ? { processing: input.processing } : {},
|
|
128
|
+
...email ? { email } : {},
|
|
129
|
+
...input.images !== void 0 ? { images: input.images } : {}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
71
132
|
const theme = object(value.theme, "theme");
|
|
72
133
|
rejectUnknown(theme, ["preset"], "theme");
|
|
73
134
|
const notion = storage(
|
|
@@ -110,6 +171,7 @@ function defineFeedbax(config) {
|
|
|
110
171
|
throw new Error("Turnstile is enabled but turnstile.siteKey is missing.");
|
|
111
172
|
return {
|
|
112
173
|
product: validatedProduct,
|
|
174
|
+
...connected ? { connected } : {},
|
|
113
175
|
theme: { preset: text(theme.preset, "theme.preset") },
|
|
114
176
|
notion,
|
|
115
177
|
...changelog ? { changelog } : {},
|
|
@@ -628,6 +690,1795 @@ function isPropertyMap(value) {
|
|
|
628
690
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
629
691
|
}
|
|
630
692
|
|
|
693
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/entity.js
|
|
694
|
+
var entityKind = /* @__PURE__ */ Symbol.for("drizzle:entityKind");
|
|
695
|
+
function is(value, type) {
|
|
696
|
+
if (!value || typeof value !== "object") {
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
if (value instanceof type) {
|
|
700
|
+
return true;
|
|
701
|
+
}
|
|
702
|
+
if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
|
|
703
|
+
throw new Error(
|
|
704
|
+
`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.`
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
let cls = Object.getPrototypeOf(value).constructor;
|
|
708
|
+
if (cls) {
|
|
709
|
+
while (cls) {
|
|
710
|
+
if (entityKind in cls && cls[entityKind] === type[entityKind]) {
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
cls = Object.getPrototypeOf(cls);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/column.js
|
|
720
|
+
var Column = class {
|
|
721
|
+
constructor(table, config) {
|
|
722
|
+
this.table = table;
|
|
723
|
+
this.config = config;
|
|
724
|
+
this.name = config.name;
|
|
725
|
+
this.keyAsName = config.keyAsName;
|
|
726
|
+
this.notNull = config.notNull;
|
|
727
|
+
this.default = config.default;
|
|
728
|
+
this.defaultFn = config.defaultFn;
|
|
729
|
+
this.onUpdateFn = config.onUpdateFn;
|
|
730
|
+
this.hasDefault = config.hasDefault;
|
|
731
|
+
this.primary = config.primaryKey;
|
|
732
|
+
this.isUnique = config.isUnique;
|
|
733
|
+
this.uniqueName = config.uniqueName;
|
|
734
|
+
this.uniqueType = config.uniqueType;
|
|
735
|
+
this.dataType = config.dataType;
|
|
736
|
+
this.columnType = config.columnType;
|
|
737
|
+
this.generated = config.generated;
|
|
738
|
+
this.generatedIdentity = config.generatedIdentity;
|
|
739
|
+
}
|
|
740
|
+
static [entityKind] = "Column";
|
|
741
|
+
name;
|
|
742
|
+
keyAsName;
|
|
743
|
+
primary;
|
|
744
|
+
notNull;
|
|
745
|
+
default;
|
|
746
|
+
defaultFn;
|
|
747
|
+
onUpdateFn;
|
|
748
|
+
hasDefault;
|
|
749
|
+
isUnique;
|
|
750
|
+
uniqueName;
|
|
751
|
+
uniqueType;
|
|
752
|
+
dataType;
|
|
753
|
+
columnType;
|
|
754
|
+
enumValues = void 0;
|
|
755
|
+
generated = void 0;
|
|
756
|
+
generatedIdentity = void 0;
|
|
757
|
+
config;
|
|
758
|
+
mapFromDriverValue(value) {
|
|
759
|
+
return value;
|
|
760
|
+
}
|
|
761
|
+
mapToDriverValue(value) {
|
|
762
|
+
return value;
|
|
763
|
+
}
|
|
764
|
+
// ** @internal */
|
|
765
|
+
shouldDisableInsert() {
|
|
766
|
+
return this.config.generated !== void 0 && this.config.generated.type !== "byDefault";
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/column-builder.js
|
|
771
|
+
var ColumnBuilder = class {
|
|
772
|
+
static [entityKind] = "ColumnBuilder";
|
|
773
|
+
config;
|
|
774
|
+
constructor(name, dataType, columnType) {
|
|
775
|
+
this.config = {
|
|
776
|
+
name,
|
|
777
|
+
keyAsName: name === "",
|
|
778
|
+
notNull: false,
|
|
779
|
+
default: void 0,
|
|
780
|
+
hasDefault: false,
|
|
781
|
+
primaryKey: false,
|
|
782
|
+
isUnique: false,
|
|
783
|
+
uniqueName: void 0,
|
|
784
|
+
uniqueType: void 0,
|
|
785
|
+
dataType,
|
|
786
|
+
columnType,
|
|
787
|
+
generated: void 0
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Changes the data type of the column. Commonly used with `json` columns. Also, useful for branded types.
|
|
792
|
+
*
|
|
793
|
+
* @example
|
|
794
|
+
* ```ts
|
|
795
|
+
* const users = pgTable('users', {
|
|
796
|
+
* id: integer('id').$type<UserId>().primaryKey(),
|
|
797
|
+
* details: json('details').$type<UserDetails>().notNull(),
|
|
798
|
+
* });
|
|
799
|
+
* ```
|
|
800
|
+
*/
|
|
801
|
+
$type() {
|
|
802
|
+
return this;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Adds a `not null` clause to the column definition.
|
|
806
|
+
*
|
|
807
|
+
* Affects the `select` model of the table - columns *without* `not null` will be nullable on select.
|
|
808
|
+
*/
|
|
809
|
+
notNull() {
|
|
810
|
+
this.config.notNull = true;
|
|
811
|
+
return this;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Adds a `default <value>` clause to the column definition.
|
|
815
|
+
*
|
|
816
|
+
* Affects the `insert` model of the table - columns *with* `default` are optional on insert.
|
|
817
|
+
*
|
|
818
|
+
* If you need to set a dynamic default value, use {@link $defaultFn} instead.
|
|
819
|
+
*/
|
|
820
|
+
default(value) {
|
|
821
|
+
this.config.default = value;
|
|
822
|
+
this.config.hasDefault = true;
|
|
823
|
+
return this;
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Adds a dynamic default value to the column.
|
|
827
|
+
* The function will be called when the row is inserted, and the returned value will be used as the column value.
|
|
828
|
+
*
|
|
829
|
+
* **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
|
|
830
|
+
*/
|
|
831
|
+
$defaultFn(fn) {
|
|
832
|
+
this.config.defaultFn = fn;
|
|
833
|
+
this.config.hasDefault = true;
|
|
834
|
+
return this;
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Alias for {@link $defaultFn}.
|
|
838
|
+
*/
|
|
839
|
+
$default = this.$defaultFn;
|
|
840
|
+
/**
|
|
841
|
+
* Adds a dynamic update value to the column.
|
|
842
|
+
* 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.
|
|
843
|
+
* 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.
|
|
844
|
+
*
|
|
845
|
+
* **Note:** This value does not affect the `drizzle-kit` behavior, it is only used at runtime in `drizzle-orm`.
|
|
846
|
+
*/
|
|
847
|
+
$onUpdateFn(fn) {
|
|
848
|
+
this.config.onUpdateFn = fn;
|
|
849
|
+
this.config.hasDefault = true;
|
|
850
|
+
return this;
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Alias for {@link $onUpdateFn}.
|
|
854
|
+
*/
|
|
855
|
+
$onUpdate = this.$onUpdateFn;
|
|
856
|
+
/**
|
|
857
|
+
* Adds a `primary key` clause to the column definition. This implicitly makes the column `not null`.
|
|
858
|
+
*
|
|
859
|
+
* In SQLite, `integer primary key` implicitly makes the column auto-incrementing.
|
|
860
|
+
*/
|
|
861
|
+
primaryKey() {
|
|
862
|
+
this.config.primaryKey = true;
|
|
863
|
+
this.config.notNull = true;
|
|
864
|
+
return this;
|
|
865
|
+
}
|
|
866
|
+
/** @internal Sets the name of the column to the key within the table definition if a name was not given. */
|
|
867
|
+
setName(name) {
|
|
868
|
+
if (this.config.name !== "") return;
|
|
869
|
+
this.config.name = name;
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/table.utils.js
|
|
874
|
+
var TableName = /* @__PURE__ */ Symbol.for("drizzle:Name");
|
|
875
|
+
|
|
876
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/foreign-keys.js
|
|
877
|
+
var ForeignKeyBuilder = class {
|
|
878
|
+
static [entityKind] = "PgForeignKeyBuilder";
|
|
879
|
+
/** @internal */
|
|
880
|
+
reference;
|
|
881
|
+
/** @internal */
|
|
882
|
+
_onUpdate = "no action";
|
|
883
|
+
/** @internal */
|
|
884
|
+
_onDelete = "no action";
|
|
885
|
+
constructor(config, actions) {
|
|
886
|
+
this.reference = () => {
|
|
887
|
+
const { name, columns, foreignColumns } = config();
|
|
888
|
+
return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
|
|
889
|
+
};
|
|
890
|
+
if (actions) {
|
|
891
|
+
this._onUpdate = actions.onUpdate;
|
|
892
|
+
this._onDelete = actions.onDelete;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
onUpdate(action) {
|
|
896
|
+
this._onUpdate = action === void 0 ? "no action" : action;
|
|
897
|
+
return this;
|
|
898
|
+
}
|
|
899
|
+
onDelete(action) {
|
|
900
|
+
this._onDelete = action === void 0 ? "no action" : action;
|
|
901
|
+
return this;
|
|
902
|
+
}
|
|
903
|
+
/** @internal */
|
|
904
|
+
build(table) {
|
|
905
|
+
return new ForeignKey(table, this);
|
|
906
|
+
}
|
|
907
|
+
};
|
|
908
|
+
var ForeignKey = class {
|
|
909
|
+
constructor(table, builder) {
|
|
910
|
+
this.table = table;
|
|
911
|
+
this.reference = builder.reference;
|
|
912
|
+
this.onUpdate = builder._onUpdate;
|
|
913
|
+
this.onDelete = builder._onDelete;
|
|
914
|
+
}
|
|
915
|
+
static [entityKind] = "PgForeignKey";
|
|
916
|
+
reference;
|
|
917
|
+
onUpdate;
|
|
918
|
+
onDelete;
|
|
919
|
+
getName() {
|
|
920
|
+
const { name, columns, foreignColumns } = this.reference();
|
|
921
|
+
const columnNames = columns.map((column) => column.name);
|
|
922
|
+
const foreignColumnNames = foreignColumns.map((column) => column.name);
|
|
923
|
+
const chunks = [
|
|
924
|
+
this.table[TableName],
|
|
925
|
+
...columnNames,
|
|
926
|
+
foreignColumns[0].table[TableName],
|
|
927
|
+
...foreignColumnNames
|
|
928
|
+
];
|
|
929
|
+
return name ?? `${chunks.join("_")}_fk`;
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/tracing-utils.js
|
|
934
|
+
function iife(fn, ...args) {
|
|
935
|
+
return fn(...args);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/unique-constraint.js
|
|
939
|
+
function uniqueKeyName(table, columns) {
|
|
940
|
+
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
941
|
+
}
|
|
942
|
+
var UniqueConstraintBuilder = class {
|
|
943
|
+
constructor(columns, name) {
|
|
944
|
+
this.name = name;
|
|
945
|
+
this.columns = columns;
|
|
946
|
+
}
|
|
947
|
+
static [entityKind] = "PgUniqueConstraintBuilder";
|
|
948
|
+
/** @internal */
|
|
949
|
+
columns;
|
|
950
|
+
/** @internal */
|
|
951
|
+
nullsNotDistinctConfig = false;
|
|
952
|
+
nullsNotDistinct() {
|
|
953
|
+
this.nullsNotDistinctConfig = true;
|
|
954
|
+
return this;
|
|
955
|
+
}
|
|
956
|
+
/** @internal */
|
|
957
|
+
build(table) {
|
|
958
|
+
return new UniqueConstraint(table, this.columns, this.nullsNotDistinctConfig, this.name);
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
var UniqueOnConstraintBuilder = class {
|
|
962
|
+
static [entityKind] = "PgUniqueOnConstraintBuilder";
|
|
963
|
+
/** @internal */
|
|
964
|
+
name;
|
|
965
|
+
constructor(name) {
|
|
966
|
+
this.name = name;
|
|
967
|
+
}
|
|
968
|
+
on(...columns) {
|
|
969
|
+
return new UniqueConstraintBuilder(columns, this.name);
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
var UniqueConstraint = class {
|
|
973
|
+
constructor(table, columns, nullsNotDistinct, name) {
|
|
974
|
+
this.table = table;
|
|
975
|
+
this.columns = columns;
|
|
976
|
+
this.name = name ?? uniqueKeyName(this.table, this.columns.map((column) => column.name));
|
|
977
|
+
this.nullsNotDistinct = nullsNotDistinct;
|
|
978
|
+
}
|
|
979
|
+
static [entityKind] = "PgUniqueConstraint";
|
|
980
|
+
columns;
|
|
981
|
+
name;
|
|
982
|
+
nullsNotDistinct = false;
|
|
983
|
+
getName() {
|
|
984
|
+
return this.name;
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/utils/array.js
|
|
989
|
+
function parsePgArrayValue(arrayString, startFrom, inQuotes) {
|
|
990
|
+
for (let i = startFrom; i < arrayString.length; i++) {
|
|
991
|
+
const char = arrayString[i];
|
|
992
|
+
if (char === "\\") {
|
|
993
|
+
i++;
|
|
994
|
+
continue;
|
|
995
|
+
}
|
|
996
|
+
if (char === '"') {
|
|
997
|
+
return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i + 1];
|
|
998
|
+
}
|
|
999
|
+
if (inQuotes) {
|
|
1000
|
+
continue;
|
|
1001
|
+
}
|
|
1002
|
+
if (char === "," || char === "}") {
|
|
1003
|
+
return [arrayString.slice(startFrom, i).replace(/\\/g, ""), i];
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
return [arrayString.slice(startFrom).replace(/\\/g, ""), arrayString.length];
|
|
1007
|
+
}
|
|
1008
|
+
function parsePgNestedArray(arrayString, startFrom = 0) {
|
|
1009
|
+
const result = [];
|
|
1010
|
+
let i = startFrom;
|
|
1011
|
+
let lastCharIsComma = false;
|
|
1012
|
+
while (i < arrayString.length) {
|
|
1013
|
+
const char = arrayString[i];
|
|
1014
|
+
if (char === ",") {
|
|
1015
|
+
if (lastCharIsComma || i === startFrom) {
|
|
1016
|
+
result.push("");
|
|
1017
|
+
}
|
|
1018
|
+
lastCharIsComma = true;
|
|
1019
|
+
i++;
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
lastCharIsComma = false;
|
|
1023
|
+
if (char === "\\") {
|
|
1024
|
+
i += 2;
|
|
1025
|
+
continue;
|
|
1026
|
+
}
|
|
1027
|
+
if (char === '"') {
|
|
1028
|
+
const [value2, startFrom2] = parsePgArrayValue(arrayString, i + 1, true);
|
|
1029
|
+
result.push(value2);
|
|
1030
|
+
i = startFrom2;
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
if (char === "}") {
|
|
1034
|
+
return [result, i + 1];
|
|
1035
|
+
}
|
|
1036
|
+
if (char === "{") {
|
|
1037
|
+
const [value2, startFrom2] = parsePgNestedArray(arrayString, i + 1);
|
|
1038
|
+
result.push(value2);
|
|
1039
|
+
i = startFrom2;
|
|
1040
|
+
continue;
|
|
1041
|
+
}
|
|
1042
|
+
const [value, newStartFrom] = parsePgArrayValue(arrayString, i, false);
|
|
1043
|
+
result.push(value);
|
|
1044
|
+
i = newStartFrom;
|
|
1045
|
+
}
|
|
1046
|
+
return [result, i];
|
|
1047
|
+
}
|
|
1048
|
+
function parsePgArray(arrayString) {
|
|
1049
|
+
const [result] = parsePgNestedArray(arrayString, 1);
|
|
1050
|
+
return result;
|
|
1051
|
+
}
|
|
1052
|
+
function makePgArray(array) {
|
|
1053
|
+
return `{${array.map((item) => {
|
|
1054
|
+
if (Array.isArray(item)) {
|
|
1055
|
+
return makePgArray(item);
|
|
1056
|
+
}
|
|
1057
|
+
if (typeof item === "string") {
|
|
1058
|
+
return `"${item.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
1059
|
+
}
|
|
1060
|
+
return `${item}`;
|
|
1061
|
+
}).join(",")}}`;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/columns/common.js
|
|
1065
|
+
var PgColumnBuilder = class extends ColumnBuilder {
|
|
1066
|
+
foreignKeyConfigs = [];
|
|
1067
|
+
static [entityKind] = "PgColumnBuilder";
|
|
1068
|
+
array(size) {
|
|
1069
|
+
return new PgArrayBuilder(this.config.name, this, size);
|
|
1070
|
+
}
|
|
1071
|
+
references(ref, actions = {}) {
|
|
1072
|
+
this.foreignKeyConfigs.push({ ref, actions });
|
|
1073
|
+
return this;
|
|
1074
|
+
}
|
|
1075
|
+
unique(name, config) {
|
|
1076
|
+
this.config.isUnique = true;
|
|
1077
|
+
this.config.uniqueName = name;
|
|
1078
|
+
this.config.uniqueType = config?.nulls;
|
|
1079
|
+
return this;
|
|
1080
|
+
}
|
|
1081
|
+
generatedAlwaysAs(as) {
|
|
1082
|
+
this.config.generated = {
|
|
1083
|
+
as,
|
|
1084
|
+
type: "always",
|
|
1085
|
+
mode: "stored"
|
|
1086
|
+
};
|
|
1087
|
+
return this;
|
|
1088
|
+
}
|
|
1089
|
+
/** @internal */
|
|
1090
|
+
buildForeignKeys(column, table) {
|
|
1091
|
+
return this.foreignKeyConfigs.map(({ ref, actions }) => {
|
|
1092
|
+
return iife(
|
|
1093
|
+
(ref2, actions2) => {
|
|
1094
|
+
const builder = new ForeignKeyBuilder(() => {
|
|
1095
|
+
const foreignColumn = ref2();
|
|
1096
|
+
return { columns: [column], foreignColumns: [foreignColumn] };
|
|
1097
|
+
});
|
|
1098
|
+
if (actions2.onUpdate) {
|
|
1099
|
+
builder.onUpdate(actions2.onUpdate);
|
|
1100
|
+
}
|
|
1101
|
+
if (actions2.onDelete) {
|
|
1102
|
+
builder.onDelete(actions2.onDelete);
|
|
1103
|
+
}
|
|
1104
|
+
return builder.build(table);
|
|
1105
|
+
},
|
|
1106
|
+
ref,
|
|
1107
|
+
actions
|
|
1108
|
+
);
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
/** @internal */
|
|
1112
|
+
buildExtraConfigColumn(table) {
|
|
1113
|
+
return new ExtraConfigColumn(table, this.config);
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
var PgColumn = class extends Column {
|
|
1117
|
+
constructor(table, config) {
|
|
1118
|
+
if (!config.uniqueName) {
|
|
1119
|
+
config.uniqueName = uniqueKeyName(table, [config.name]);
|
|
1120
|
+
}
|
|
1121
|
+
super(table, config);
|
|
1122
|
+
this.table = table;
|
|
1123
|
+
}
|
|
1124
|
+
static [entityKind] = "PgColumn";
|
|
1125
|
+
};
|
|
1126
|
+
var ExtraConfigColumn = class extends PgColumn {
|
|
1127
|
+
static [entityKind] = "ExtraConfigColumn";
|
|
1128
|
+
getSQLType() {
|
|
1129
|
+
return this.getSQLType();
|
|
1130
|
+
}
|
|
1131
|
+
indexConfig = {
|
|
1132
|
+
order: this.config.order ?? "asc",
|
|
1133
|
+
nulls: this.config.nulls ?? "last",
|
|
1134
|
+
opClass: this.config.opClass
|
|
1135
|
+
};
|
|
1136
|
+
defaultConfig = {
|
|
1137
|
+
order: "asc",
|
|
1138
|
+
nulls: "last",
|
|
1139
|
+
opClass: void 0
|
|
1140
|
+
};
|
|
1141
|
+
asc() {
|
|
1142
|
+
this.indexConfig.order = "asc";
|
|
1143
|
+
return this;
|
|
1144
|
+
}
|
|
1145
|
+
desc() {
|
|
1146
|
+
this.indexConfig.order = "desc";
|
|
1147
|
+
return this;
|
|
1148
|
+
}
|
|
1149
|
+
nullsFirst() {
|
|
1150
|
+
this.indexConfig.nulls = "first";
|
|
1151
|
+
return this;
|
|
1152
|
+
}
|
|
1153
|
+
nullsLast() {
|
|
1154
|
+
this.indexConfig.nulls = "last";
|
|
1155
|
+
return this;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* ### PostgreSQL documentation quote
|
|
1159
|
+
*
|
|
1160
|
+
* > An operator class with optional parameters can be specified for each column of an index.
|
|
1161
|
+
* The operator class identifies the operators to be used by the index for that column.
|
|
1162
|
+
* For example, a B-tree index on four-byte integers would use the int4_ops class;
|
|
1163
|
+
* this operator class includes comparison functions for four-byte integers.
|
|
1164
|
+
* In practice the default operator class for the column's data type is usually sufficient.
|
|
1165
|
+
* The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.
|
|
1166
|
+
* For example, we might want to sort a complex-number data type either by absolute value or by real part.
|
|
1167
|
+
* We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.
|
|
1168
|
+
* More information about operator classes check:
|
|
1169
|
+
*
|
|
1170
|
+
* ### Useful links
|
|
1171
|
+
* https://www.postgresql.org/docs/current/sql-createindex.html
|
|
1172
|
+
*
|
|
1173
|
+
* https://www.postgresql.org/docs/current/indexes-opclass.html
|
|
1174
|
+
*
|
|
1175
|
+
* https://www.postgresql.org/docs/current/xindex.html
|
|
1176
|
+
*
|
|
1177
|
+
* ### Additional types
|
|
1178
|
+
* If you have the `pg_vector` extension installed in your database, you can use the
|
|
1179
|
+
* `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.
|
|
1180
|
+
*
|
|
1181
|
+
* **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**
|
|
1182
|
+
*
|
|
1183
|
+
* @param opClass
|
|
1184
|
+
* @returns
|
|
1185
|
+
*/
|
|
1186
|
+
op(opClass) {
|
|
1187
|
+
this.indexConfig.opClass = opClass;
|
|
1188
|
+
return this;
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
var IndexedColumn = class {
|
|
1192
|
+
static [entityKind] = "IndexedColumn";
|
|
1193
|
+
constructor(name, keyAsName, type, indexConfig) {
|
|
1194
|
+
this.name = name;
|
|
1195
|
+
this.keyAsName = keyAsName;
|
|
1196
|
+
this.type = type;
|
|
1197
|
+
this.indexConfig = indexConfig;
|
|
1198
|
+
}
|
|
1199
|
+
name;
|
|
1200
|
+
keyAsName;
|
|
1201
|
+
type;
|
|
1202
|
+
indexConfig;
|
|
1203
|
+
};
|
|
1204
|
+
var PgArrayBuilder = class extends PgColumnBuilder {
|
|
1205
|
+
static [entityKind] = "PgArrayBuilder";
|
|
1206
|
+
constructor(name, baseBuilder, size) {
|
|
1207
|
+
super(name, "array", "PgArray");
|
|
1208
|
+
this.config.baseBuilder = baseBuilder;
|
|
1209
|
+
this.config.size = size;
|
|
1210
|
+
}
|
|
1211
|
+
/** @internal */
|
|
1212
|
+
build(table) {
|
|
1213
|
+
const baseColumn = this.config.baseBuilder.build(table);
|
|
1214
|
+
return new PgArray(
|
|
1215
|
+
table,
|
|
1216
|
+
this.config,
|
|
1217
|
+
baseColumn
|
|
1218
|
+
);
|
|
1219
|
+
}
|
|
1220
|
+
};
|
|
1221
|
+
var PgArray = class _PgArray extends PgColumn {
|
|
1222
|
+
constructor(table, config, baseColumn, range) {
|
|
1223
|
+
super(table, config);
|
|
1224
|
+
this.baseColumn = baseColumn;
|
|
1225
|
+
this.range = range;
|
|
1226
|
+
this.size = config.size;
|
|
1227
|
+
}
|
|
1228
|
+
size;
|
|
1229
|
+
static [entityKind] = "PgArray";
|
|
1230
|
+
getSQLType() {
|
|
1231
|
+
return `${this.baseColumn.getSQLType()}[${typeof this.size === "number" ? this.size : ""}]`;
|
|
1232
|
+
}
|
|
1233
|
+
mapFromDriverValue(value) {
|
|
1234
|
+
if (typeof value === "string") {
|
|
1235
|
+
value = parsePgArray(value);
|
|
1236
|
+
}
|
|
1237
|
+
return value.map((v) => this.baseColumn.mapFromDriverValue(v));
|
|
1238
|
+
}
|
|
1239
|
+
mapToDriverValue(value, isNestedArray = false) {
|
|
1240
|
+
const a = value.map(
|
|
1241
|
+
(v) => v === null ? null : is(this.baseColumn, _PgArray) ? this.baseColumn.mapToDriverValue(v, true) : this.baseColumn.mapToDriverValue(v)
|
|
1242
|
+
);
|
|
1243
|
+
if (isNestedArray) return a;
|
|
1244
|
+
return makePgArray(a);
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
|
|
1248
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/pg-core/columns/enum.js
|
|
1249
|
+
var PgEnumObjectColumnBuilder = class extends PgColumnBuilder {
|
|
1250
|
+
static [entityKind] = "PgEnumObjectColumnBuilder";
|
|
1251
|
+
constructor(name, enumInstance) {
|
|
1252
|
+
super(name, "string", "PgEnumObjectColumn");
|
|
1253
|
+
this.config.enum = enumInstance;
|
|
1254
|
+
}
|
|
1255
|
+
/** @internal */
|
|
1256
|
+
build(table) {
|
|
1257
|
+
return new PgEnumObjectColumn(
|
|
1258
|
+
table,
|
|
1259
|
+
this.config
|
|
1260
|
+
);
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
var PgEnumObjectColumn = class extends PgColumn {
|
|
1264
|
+
static [entityKind] = "PgEnumObjectColumn";
|
|
1265
|
+
enum;
|
|
1266
|
+
enumValues = this.config.enum.enumValues;
|
|
1267
|
+
constructor(table, config) {
|
|
1268
|
+
super(table, config);
|
|
1269
|
+
this.enum = config.enum;
|
|
1270
|
+
}
|
|
1271
|
+
getSQLType() {
|
|
1272
|
+
return this.enum.enumName;
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
var isPgEnumSym = /* @__PURE__ */ Symbol.for("drizzle:isPgEnum");
|
|
1276
|
+
function isPgEnum(obj) {
|
|
1277
|
+
return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
|
|
1278
|
+
}
|
|
1279
|
+
var PgEnumColumnBuilder = class extends PgColumnBuilder {
|
|
1280
|
+
static [entityKind] = "PgEnumColumnBuilder";
|
|
1281
|
+
constructor(name, enumInstance) {
|
|
1282
|
+
super(name, "string", "PgEnumColumn");
|
|
1283
|
+
this.config.enum = enumInstance;
|
|
1284
|
+
}
|
|
1285
|
+
/** @internal */
|
|
1286
|
+
build(table) {
|
|
1287
|
+
return new PgEnumColumn(
|
|
1288
|
+
table,
|
|
1289
|
+
this.config
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
var PgEnumColumn = class extends PgColumn {
|
|
1294
|
+
static [entityKind] = "PgEnumColumn";
|
|
1295
|
+
enum = this.config.enum;
|
|
1296
|
+
enumValues = this.config.enum.enumValues;
|
|
1297
|
+
constructor(table, config) {
|
|
1298
|
+
super(table, config);
|
|
1299
|
+
this.enum = config.enum;
|
|
1300
|
+
}
|
|
1301
|
+
getSQLType() {
|
|
1302
|
+
return this.enum.enumName;
|
|
1303
|
+
}
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/subquery.js
|
|
1307
|
+
var Subquery = class {
|
|
1308
|
+
static [entityKind] = "Subquery";
|
|
1309
|
+
constructor(sql2, fields, alias, isWith = false, usedTables = []) {
|
|
1310
|
+
this._ = {
|
|
1311
|
+
brand: "Subquery",
|
|
1312
|
+
sql: sql2,
|
|
1313
|
+
selectedFields: fields,
|
|
1314
|
+
alias,
|
|
1315
|
+
isWith,
|
|
1316
|
+
usedTables
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
// getSQL(): SQL<unknown> {
|
|
1320
|
+
// return new SQL([this]);
|
|
1321
|
+
// }
|
|
1322
|
+
};
|
|
1323
|
+
var WithSubquery = class extends Subquery {
|
|
1324
|
+
static [entityKind] = "WithSubquery";
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/version.js
|
|
1328
|
+
var version = "0.45.2";
|
|
1329
|
+
|
|
1330
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/tracing.js
|
|
1331
|
+
var otel;
|
|
1332
|
+
var rawTracer;
|
|
1333
|
+
var tracer = {
|
|
1334
|
+
startActiveSpan(name, fn) {
|
|
1335
|
+
if (!otel) {
|
|
1336
|
+
return fn();
|
|
1337
|
+
}
|
|
1338
|
+
if (!rawTracer) {
|
|
1339
|
+
rawTracer = otel.trace.getTracer("drizzle-orm", version);
|
|
1340
|
+
}
|
|
1341
|
+
return iife(
|
|
1342
|
+
(otel2, rawTracer2) => rawTracer2.startActiveSpan(
|
|
1343
|
+
name,
|
|
1344
|
+
(span) => {
|
|
1345
|
+
try {
|
|
1346
|
+
return fn(span);
|
|
1347
|
+
} catch (e) {
|
|
1348
|
+
span.setStatus({
|
|
1349
|
+
code: otel2.SpanStatusCode.ERROR,
|
|
1350
|
+
message: e instanceof Error ? e.message : "Unknown error"
|
|
1351
|
+
// eslint-disable-line no-instanceof/no-instanceof
|
|
1352
|
+
});
|
|
1353
|
+
throw e;
|
|
1354
|
+
} finally {
|
|
1355
|
+
span.end();
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
),
|
|
1359
|
+
otel,
|
|
1360
|
+
rawTracer
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1365
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/view-common.js
|
|
1366
|
+
var ViewBaseConfig = /* @__PURE__ */ Symbol.for("drizzle:ViewBaseConfig");
|
|
1367
|
+
|
|
1368
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/table.js
|
|
1369
|
+
var Schema = /* @__PURE__ */ Symbol.for("drizzle:Schema");
|
|
1370
|
+
var Columns = /* @__PURE__ */ Symbol.for("drizzle:Columns");
|
|
1371
|
+
var ExtraConfigColumns = /* @__PURE__ */ Symbol.for("drizzle:ExtraConfigColumns");
|
|
1372
|
+
var OriginalName = /* @__PURE__ */ Symbol.for("drizzle:OriginalName");
|
|
1373
|
+
var BaseName = /* @__PURE__ */ Symbol.for("drizzle:BaseName");
|
|
1374
|
+
var IsAlias = /* @__PURE__ */ Symbol.for("drizzle:IsAlias");
|
|
1375
|
+
var ExtraConfigBuilder = /* @__PURE__ */ Symbol.for("drizzle:ExtraConfigBuilder");
|
|
1376
|
+
var IsDrizzleTable = /* @__PURE__ */ Symbol.for("drizzle:IsDrizzleTable");
|
|
1377
|
+
var Table = class {
|
|
1378
|
+
static [entityKind] = "Table";
|
|
1379
|
+
/** @internal */
|
|
1380
|
+
static Symbol = {
|
|
1381
|
+
Name: TableName,
|
|
1382
|
+
Schema,
|
|
1383
|
+
OriginalName,
|
|
1384
|
+
Columns,
|
|
1385
|
+
ExtraConfigColumns,
|
|
1386
|
+
BaseName,
|
|
1387
|
+
IsAlias,
|
|
1388
|
+
ExtraConfigBuilder
|
|
1389
|
+
};
|
|
1390
|
+
/**
|
|
1391
|
+
* @internal
|
|
1392
|
+
* Can be changed if the table is aliased.
|
|
1393
|
+
*/
|
|
1394
|
+
[TableName];
|
|
1395
|
+
/**
|
|
1396
|
+
* @internal
|
|
1397
|
+
* Used to store the original name of the table, before any aliasing.
|
|
1398
|
+
*/
|
|
1399
|
+
[OriginalName];
|
|
1400
|
+
/** @internal */
|
|
1401
|
+
[Schema];
|
|
1402
|
+
/** @internal */
|
|
1403
|
+
[Columns];
|
|
1404
|
+
/** @internal */
|
|
1405
|
+
[ExtraConfigColumns];
|
|
1406
|
+
/**
|
|
1407
|
+
* @internal
|
|
1408
|
+
* Used to store the table name before the transformation via the `tableCreator` functions.
|
|
1409
|
+
*/
|
|
1410
|
+
[BaseName];
|
|
1411
|
+
/** @internal */
|
|
1412
|
+
[IsAlias] = false;
|
|
1413
|
+
/** @internal */
|
|
1414
|
+
[IsDrizzleTable] = true;
|
|
1415
|
+
/** @internal */
|
|
1416
|
+
[ExtraConfigBuilder] = void 0;
|
|
1417
|
+
constructor(name, schema, baseName) {
|
|
1418
|
+
this[TableName] = this[OriginalName] = name;
|
|
1419
|
+
this[Schema] = schema;
|
|
1420
|
+
this[BaseName] = baseName;
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
1423
|
+
|
|
1424
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sql/sql.js
|
|
1425
|
+
var FakePrimitiveParam = class {
|
|
1426
|
+
static [entityKind] = "FakePrimitiveParam";
|
|
1427
|
+
};
|
|
1428
|
+
function isSQLWrapper(value) {
|
|
1429
|
+
return value !== null && value !== void 0 && typeof value.getSQL === "function";
|
|
1430
|
+
}
|
|
1431
|
+
function mergeQueries(queries) {
|
|
1432
|
+
const result = { sql: "", params: [] };
|
|
1433
|
+
for (const query of queries) {
|
|
1434
|
+
result.sql += query.sql;
|
|
1435
|
+
result.params.push(...query.params);
|
|
1436
|
+
if (query.typings?.length) {
|
|
1437
|
+
if (!result.typings) {
|
|
1438
|
+
result.typings = [];
|
|
1439
|
+
}
|
|
1440
|
+
result.typings.push(...query.typings);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
return result;
|
|
1444
|
+
}
|
|
1445
|
+
var StringChunk = class {
|
|
1446
|
+
static [entityKind] = "StringChunk";
|
|
1447
|
+
value;
|
|
1448
|
+
constructor(value) {
|
|
1449
|
+
this.value = Array.isArray(value) ? value : [value];
|
|
1450
|
+
}
|
|
1451
|
+
getSQL() {
|
|
1452
|
+
return new SQL([this]);
|
|
1453
|
+
}
|
|
1454
|
+
};
|
|
1455
|
+
var SQL = class _SQL {
|
|
1456
|
+
constructor(queryChunks) {
|
|
1457
|
+
this.queryChunks = queryChunks;
|
|
1458
|
+
for (const chunk of queryChunks) {
|
|
1459
|
+
if (is(chunk, Table)) {
|
|
1460
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
1461
|
+
this.usedTables.push(
|
|
1462
|
+
schemaName === void 0 ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]
|
|
1463
|
+
);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
static [entityKind] = "SQL";
|
|
1468
|
+
/** @internal */
|
|
1469
|
+
decoder = noopDecoder;
|
|
1470
|
+
shouldInlineParams = false;
|
|
1471
|
+
/** @internal */
|
|
1472
|
+
usedTables = [];
|
|
1473
|
+
append(query) {
|
|
1474
|
+
this.queryChunks.push(...query.queryChunks);
|
|
1475
|
+
return this;
|
|
1476
|
+
}
|
|
1477
|
+
toQuery(config) {
|
|
1478
|
+
return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
|
|
1479
|
+
const query = this.buildQueryFromSourceParams(this.queryChunks, config);
|
|
1480
|
+
span?.setAttributes({
|
|
1481
|
+
"drizzle.query.text": query.sql,
|
|
1482
|
+
"drizzle.query.params": JSON.stringify(query.params)
|
|
1483
|
+
});
|
|
1484
|
+
return query;
|
|
1485
|
+
});
|
|
1486
|
+
}
|
|
1487
|
+
buildQueryFromSourceParams(chunks, _config) {
|
|
1488
|
+
const config = Object.assign({}, _config, {
|
|
1489
|
+
inlineParams: _config.inlineParams || this.shouldInlineParams,
|
|
1490
|
+
paramStartIndex: _config.paramStartIndex || { value: 0 }
|
|
1491
|
+
});
|
|
1492
|
+
const {
|
|
1493
|
+
casing,
|
|
1494
|
+
escapeName,
|
|
1495
|
+
escapeParam,
|
|
1496
|
+
prepareTyping,
|
|
1497
|
+
inlineParams,
|
|
1498
|
+
paramStartIndex
|
|
1499
|
+
} = config;
|
|
1500
|
+
return mergeQueries(chunks.map((chunk) => {
|
|
1501
|
+
if (is(chunk, StringChunk)) {
|
|
1502
|
+
return { sql: chunk.value.join(""), params: [] };
|
|
1503
|
+
}
|
|
1504
|
+
if (is(chunk, Name)) {
|
|
1505
|
+
return { sql: escapeName(chunk.value), params: [] };
|
|
1506
|
+
}
|
|
1507
|
+
if (chunk === void 0) {
|
|
1508
|
+
return { sql: "", params: [] };
|
|
1509
|
+
}
|
|
1510
|
+
if (Array.isArray(chunk)) {
|
|
1511
|
+
const result = [new StringChunk("(")];
|
|
1512
|
+
for (const [i, p] of chunk.entries()) {
|
|
1513
|
+
result.push(p);
|
|
1514
|
+
if (i < chunk.length - 1) {
|
|
1515
|
+
result.push(new StringChunk(", "));
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
result.push(new StringChunk(")"));
|
|
1519
|
+
return this.buildQueryFromSourceParams(result, config);
|
|
1520
|
+
}
|
|
1521
|
+
if (is(chunk, _SQL)) {
|
|
1522
|
+
return this.buildQueryFromSourceParams(chunk.queryChunks, {
|
|
1523
|
+
...config,
|
|
1524
|
+
inlineParams: inlineParams || chunk.shouldInlineParams
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
if (is(chunk, Table)) {
|
|
1528
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
1529
|
+
const tableName = chunk[Table.Symbol.Name];
|
|
1530
|
+
return {
|
|
1531
|
+
sql: schemaName === void 0 || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
|
|
1532
|
+
params: []
|
|
1533
|
+
};
|
|
1534
|
+
}
|
|
1535
|
+
if (is(chunk, Column)) {
|
|
1536
|
+
const columnName = casing.getColumnCasing(chunk);
|
|
1537
|
+
if (_config.invokeSource === "indexes") {
|
|
1538
|
+
return { sql: escapeName(columnName), params: [] };
|
|
1539
|
+
}
|
|
1540
|
+
const schemaName = chunk.table[Table.Symbol.Schema];
|
|
1541
|
+
return {
|
|
1542
|
+
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),
|
|
1543
|
+
params: []
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
if (is(chunk, View)) {
|
|
1547
|
+
const schemaName = chunk[ViewBaseConfig].schema;
|
|
1548
|
+
const viewName = chunk[ViewBaseConfig].name;
|
|
1549
|
+
return {
|
|
1550
|
+
sql: schemaName === void 0 || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
|
|
1551
|
+
params: []
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
if (is(chunk, Param)) {
|
|
1555
|
+
if (is(chunk.value, Placeholder)) {
|
|
1556
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
1557
|
+
}
|
|
1558
|
+
const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
|
|
1559
|
+
if (is(mappedValue, _SQL)) {
|
|
1560
|
+
return this.buildQueryFromSourceParams([mappedValue], config);
|
|
1561
|
+
}
|
|
1562
|
+
if (inlineParams) {
|
|
1563
|
+
return { sql: this.mapInlineParam(mappedValue, config), params: [] };
|
|
1564
|
+
}
|
|
1565
|
+
let typings = ["none"];
|
|
1566
|
+
if (prepareTyping) {
|
|
1567
|
+
typings = [prepareTyping(chunk.encoder)];
|
|
1568
|
+
}
|
|
1569
|
+
return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
|
|
1570
|
+
}
|
|
1571
|
+
if (is(chunk, Placeholder)) {
|
|
1572
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
1573
|
+
}
|
|
1574
|
+
if (is(chunk, _SQL.Aliased) && chunk.fieldAlias !== void 0) {
|
|
1575
|
+
return { sql: escapeName(chunk.fieldAlias), params: [] };
|
|
1576
|
+
}
|
|
1577
|
+
if (is(chunk, Subquery)) {
|
|
1578
|
+
if (chunk._.isWith) {
|
|
1579
|
+
return { sql: escapeName(chunk._.alias), params: [] };
|
|
1580
|
+
}
|
|
1581
|
+
return this.buildQueryFromSourceParams([
|
|
1582
|
+
new StringChunk("("),
|
|
1583
|
+
chunk._.sql,
|
|
1584
|
+
new StringChunk(") "),
|
|
1585
|
+
new Name(chunk._.alias)
|
|
1586
|
+
], config);
|
|
1587
|
+
}
|
|
1588
|
+
if (isPgEnum(chunk)) {
|
|
1589
|
+
if (chunk.schema) {
|
|
1590
|
+
return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
|
|
1591
|
+
}
|
|
1592
|
+
return { sql: escapeName(chunk.enumName), params: [] };
|
|
1593
|
+
}
|
|
1594
|
+
if (isSQLWrapper(chunk)) {
|
|
1595
|
+
if (chunk.shouldOmitSQLParens?.()) {
|
|
1596
|
+
return this.buildQueryFromSourceParams([chunk.getSQL()], config);
|
|
1597
|
+
}
|
|
1598
|
+
return this.buildQueryFromSourceParams([
|
|
1599
|
+
new StringChunk("("),
|
|
1600
|
+
chunk.getSQL(),
|
|
1601
|
+
new StringChunk(")")
|
|
1602
|
+
], config);
|
|
1603
|
+
}
|
|
1604
|
+
if (inlineParams) {
|
|
1605
|
+
return { sql: this.mapInlineParam(chunk, config), params: [] };
|
|
1606
|
+
}
|
|
1607
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
1608
|
+
}));
|
|
1609
|
+
}
|
|
1610
|
+
mapInlineParam(chunk, { escapeString }) {
|
|
1611
|
+
if (chunk === null) {
|
|
1612
|
+
return "null";
|
|
1613
|
+
}
|
|
1614
|
+
if (typeof chunk === "number" || typeof chunk === "boolean") {
|
|
1615
|
+
return chunk.toString();
|
|
1616
|
+
}
|
|
1617
|
+
if (typeof chunk === "string") {
|
|
1618
|
+
return escapeString(chunk);
|
|
1619
|
+
}
|
|
1620
|
+
if (typeof chunk === "object") {
|
|
1621
|
+
const mappedValueAsString = chunk.toString();
|
|
1622
|
+
if (mappedValueAsString === "[object Object]") {
|
|
1623
|
+
return escapeString(JSON.stringify(chunk));
|
|
1624
|
+
}
|
|
1625
|
+
return escapeString(mappedValueAsString);
|
|
1626
|
+
}
|
|
1627
|
+
throw new Error("Unexpected param value: " + chunk);
|
|
1628
|
+
}
|
|
1629
|
+
getSQL() {
|
|
1630
|
+
return this;
|
|
1631
|
+
}
|
|
1632
|
+
as(alias) {
|
|
1633
|
+
if (alias === void 0) {
|
|
1634
|
+
return this;
|
|
1635
|
+
}
|
|
1636
|
+
return new _SQL.Aliased(this, alias);
|
|
1637
|
+
}
|
|
1638
|
+
mapWith(decoder) {
|
|
1639
|
+
this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
|
|
1640
|
+
return this;
|
|
1641
|
+
}
|
|
1642
|
+
inlineParams() {
|
|
1643
|
+
this.shouldInlineParams = true;
|
|
1644
|
+
return this;
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* This method is used to conditionally include a part of the query.
|
|
1648
|
+
*
|
|
1649
|
+
* @param condition - Condition to check
|
|
1650
|
+
* @returns itself if the condition is `true`, otherwise `undefined`
|
|
1651
|
+
*/
|
|
1652
|
+
if(condition) {
|
|
1653
|
+
return condition ? this : void 0;
|
|
1654
|
+
}
|
|
1655
|
+
};
|
|
1656
|
+
var Name = class {
|
|
1657
|
+
constructor(value) {
|
|
1658
|
+
this.value = value;
|
|
1659
|
+
}
|
|
1660
|
+
static [entityKind] = "Name";
|
|
1661
|
+
brand;
|
|
1662
|
+
getSQL() {
|
|
1663
|
+
return new SQL([this]);
|
|
1664
|
+
}
|
|
1665
|
+
};
|
|
1666
|
+
var noopDecoder = {
|
|
1667
|
+
mapFromDriverValue: (value) => value
|
|
1668
|
+
};
|
|
1669
|
+
var noopEncoder = {
|
|
1670
|
+
mapToDriverValue: (value) => value
|
|
1671
|
+
};
|
|
1672
|
+
var noopMapper = {
|
|
1673
|
+
...noopDecoder,
|
|
1674
|
+
...noopEncoder
|
|
1675
|
+
};
|
|
1676
|
+
var Param = class {
|
|
1677
|
+
/**
|
|
1678
|
+
* @param value - Parameter value
|
|
1679
|
+
* @param encoder - Encoder to convert the value to a driver parameter
|
|
1680
|
+
*/
|
|
1681
|
+
constructor(value, encoder = noopEncoder) {
|
|
1682
|
+
this.value = value;
|
|
1683
|
+
this.encoder = encoder;
|
|
1684
|
+
}
|
|
1685
|
+
static [entityKind] = "Param";
|
|
1686
|
+
brand;
|
|
1687
|
+
getSQL() {
|
|
1688
|
+
return new SQL([this]);
|
|
1689
|
+
}
|
|
1690
|
+
};
|
|
1691
|
+
function sql(strings, ...params) {
|
|
1692
|
+
const queryChunks = [];
|
|
1693
|
+
if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
|
|
1694
|
+
queryChunks.push(new StringChunk(strings[0]));
|
|
1695
|
+
}
|
|
1696
|
+
for (const [paramIndex, param2] of params.entries()) {
|
|
1697
|
+
queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
|
|
1698
|
+
}
|
|
1699
|
+
return new SQL(queryChunks);
|
|
1700
|
+
}
|
|
1701
|
+
((sql2) => {
|
|
1702
|
+
function empty() {
|
|
1703
|
+
return new SQL([]);
|
|
1704
|
+
}
|
|
1705
|
+
sql2.empty = empty;
|
|
1706
|
+
function fromList(list) {
|
|
1707
|
+
return new SQL(list);
|
|
1708
|
+
}
|
|
1709
|
+
sql2.fromList = fromList;
|
|
1710
|
+
function raw(str) {
|
|
1711
|
+
return new SQL([new StringChunk(str)]);
|
|
1712
|
+
}
|
|
1713
|
+
sql2.raw = raw;
|
|
1714
|
+
function join3(chunks, separator) {
|
|
1715
|
+
const result = [];
|
|
1716
|
+
for (const [i, chunk] of chunks.entries()) {
|
|
1717
|
+
if (i > 0 && separator !== void 0) {
|
|
1718
|
+
result.push(separator);
|
|
1719
|
+
}
|
|
1720
|
+
result.push(chunk);
|
|
1721
|
+
}
|
|
1722
|
+
return new SQL(result);
|
|
1723
|
+
}
|
|
1724
|
+
sql2.join = join3;
|
|
1725
|
+
function identifier(value) {
|
|
1726
|
+
return new Name(value);
|
|
1727
|
+
}
|
|
1728
|
+
sql2.identifier = identifier;
|
|
1729
|
+
function placeholder2(name2) {
|
|
1730
|
+
return new Placeholder(name2);
|
|
1731
|
+
}
|
|
1732
|
+
sql2.placeholder = placeholder2;
|
|
1733
|
+
function param2(value, encoder) {
|
|
1734
|
+
return new Param(value, encoder);
|
|
1735
|
+
}
|
|
1736
|
+
sql2.param = param2;
|
|
1737
|
+
})(sql || (sql = {}));
|
|
1738
|
+
((SQL2) => {
|
|
1739
|
+
class Aliased {
|
|
1740
|
+
constructor(sql2, fieldAlias) {
|
|
1741
|
+
this.sql = sql2;
|
|
1742
|
+
this.fieldAlias = fieldAlias;
|
|
1743
|
+
}
|
|
1744
|
+
static [entityKind] = "SQL.Aliased";
|
|
1745
|
+
/** @internal */
|
|
1746
|
+
isSelectionField = false;
|
|
1747
|
+
getSQL() {
|
|
1748
|
+
return this.sql;
|
|
1749
|
+
}
|
|
1750
|
+
/** @internal */
|
|
1751
|
+
clone() {
|
|
1752
|
+
return new Aliased(this.sql, this.fieldAlias);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
SQL2.Aliased = Aliased;
|
|
1756
|
+
})(SQL || (SQL = {}));
|
|
1757
|
+
var Placeholder = class {
|
|
1758
|
+
constructor(name2) {
|
|
1759
|
+
this.name = name2;
|
|
1760
|
+
}
|
|
1761
|
+
static [entityKind] = "Placeholder";
|
|
1762
|
+
getSQL() {
|
|
1763
|
+
return new SQL([this]);
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
var IsDrizzleView = /* @__PURE__ */ Symbol.for("drizzle:IsDrizzleView");
|
|
1767
|
+
var View = class {
|
|
1768
|
+
static [entityKind] = "View";
|
|
1769
|
+
/** @internal */
|
|
1770
|
+
[ViewBaseConfig];
|
|
1771
|
+
/** @internal */
|
|
1772
|
+
[IsDrizzleView] = true;
|
|
1773
|
+
constructor({ name: name2, schema, selectedFields, query }) {
|
|
1774
|
+
this[ViewBaseConfig] = {
|
|
1775
|
+
name: name2,
|
|
1776
|
+
originalName: name2,
|
|
1777
|
+
schema,
|
|
1778
|
+
selectedFields,
|
|
1779
|
+
query,
|
|
1780
|
+
isExisting: !query,
|
|
1781
|
+
isAlias: false
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
getSQL() {
|
|
1785
|
+
return new SQL([this]);
|
|
1786
|
+
}
|
|
1787
|
+
};
|
|
1788
|
+
Column.prototype.getSQL = function() {
|
|
1789
|
+
return new SQL([this]);
|
|
1790
|
+
};
|
|
1791
|
+
Table.prototype.getSQL = function() {
|
|
1792
|
+
return new SQL([this]);
|
|
1793
|
+
};
|
|
1794
|
+
Subquery.prototype.getSQL = function() {
|
|
1795
|
+
return new SQL([this]);
|
|
1796
|
+
};
|
|
1797
|
+
|
|
1798
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/utils.js
|
|
1799
|
+
function getColumnNameAndConfig(a, b) {
|
|
1800
|
+
return {
|
|
1801
|
+
name: typeof a === "string" && a.length > 0 ? a : "",
|
|
1802
|
+
config: typeof a === "object" ? a : b
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
var textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder();
|
|
1806
|
+
|
|
1807
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
|
|
1808
|
+
var ForeignKeyBuilder2 = class {
|
|
1809
|
+
static [entityKind] = "SQLiteForeignKeyBuilder";
|
|
1810
|
+
/** @internal */
|
|
1811
|
+
reference;
|
|
1812
|
+
/** @internal */
|
|
1813
|
+
_onUpdate;
|
|
1814
|
+
/** @internal */
|
|
1815
|
+
_onDelete;
|
|
1816
|
+
constructor(config, actions) {
|
|
1817
|
+
this.reference = () => {
|
|
1818
|
+
const { name, columns, foreignColumns } = config();
|
|
1819
|
+
return { name, columns, foreignTable: foreignColumns[0].table, foreignColumns };
|
|
1820
|
+
};
|
|
1821
|
+
if (actions) {
|
|
1822
|
+
this._onUpdate = actions.onUpdate;
|
|
1823
|
+
this._onDelete = actions.onDelete;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
onUpdate(action) {
|
|
1827
|
+
this._onUpdate = action;
|
|
1828
|
+
return this;
|
|
1829
|
+
}
|
|
1830
|
+
onDelete(action) {
|
|
1831
|
+
this._onDelete = action;
|
|
1832
|
+
return this;
|
|
1833
|
+
}
|
|
1834
|
+
/** @internal */
|
|
1835
|
+
build(table) {
|
|
1836
|
+
return new ForeignKey2(table, this);
|
|
1837
|
+
}
|
|
1838
|
+
};
|
|
1839
|
+
var ForeignKey2 = class {
|
|
1840
|
+
constructor(table, builder) {
|
|
1841
|
+
this.table = table;
|
|
1842
|
+
this.reference = builder.reference;
|
|
1843
|
+
this.onUpdate = builder._onUpdate;
|
|
1844
|
+
this.onDelete = builder._onDelete;
|
|
1845
|
+
}
|
|
1846
|
+
static [entityKind] = "SQLiteForeignKey";
|
|
1847
|
+
reference;
|
|
1848
|
+
onUpdate;
|
|
1849
|
+
onDelete;
|
|
1850
|
+
getName() {
|
|
1851
|
+
const { name, columns, foreignColumns } = this.reference();
|
|
1852
|
+
const columnNames = columns.map((column) => column.name);
|
|
1853
|
+
const foreignColumnNames = foreignColumns.map((column) => column.name);
|
|
1854
|
+
const chunks = [
|
|
1855
|
+
this.table[TableName],
|
|
1856
|
+
...columnNames,
|
|
1857
|
+
foreignColumns[0].table[TableName],
|
|
1858
|
+
...foreignColumnNames
|
|
1859
|
+
];
|
|
1860
|
+
return name ?? `${chunks.join("_")}_fk`;
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
|
|
1864
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
|
|
1865
|
+
function uniqueKeyName2(table, columns) {
|
|
1866
|
+
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
1867
|
+
}
|
|
1868
|
+
var UniqueConstraintBuilder2 = class {
|
|
1869
|
+
constructor(columns, name) {
|
|
1870
|
+
this.name = name;
|
|
1871
|
+
this.columns = columns;
|
|
1872
|
+
}
|
|
1873
|
+
static [entityKind] = "SQLiteUniqueConstraintBuilder";
|
|
1874
|
+
/** @internal */
|
|
1875
|
+
columns;
|
|
1876
|
+
/** @internal */
|
|
1877
|
+
build(table) {
|
|
1878
|
+
return new UniqueConstraint2(table, this.columns, this.name);
|
|
1879
|
+
}
|
|
1880
|
+
};
|
|
1881
|
+
var UniqueOnConstraintBuilder2 = class {
|
|
1882
|
+
static [entityKind] = "SQLiteUniqueOnConstraintBuilder";
|
|
1883
|
+
/** @internal */
|
|
1884
|
+
name;
|
|
1885
|
+
constructor(name) {
|
|
1886
|
+
this.name = name;
|
|
1887
|
+
}
|
|
1888
|
+
on(...columns) {
|
|
1889
|
+
return new UniqueConstraintBuilder2(columns, this.name);
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
var UniqueConstraint2 = class {
|
|
1893
|
+
constructor(table, columns, name) {
|
|
1894
|
+
this.table = table;
|
|
1895
|
+
this.columns = columns;
|
|
1896
|
+
this.name = name ?? uniqueKeyName2(this.table, this.columns.map((column) => column.name));
|
|
1897
|
+
}
|
|
1898
|
+
static [entityKind] = "SQLiteUniqueConstraint";
|
|
1899
|
+
columns;
|
|
1900
|
+
name;
|
|
1901
|
+
getName() {
|
|
1902
|
+
return this.name;
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
|
|
1906
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/common.js
|
|
1907
|
+
var SQLiteColumnBuilder = class extends ColumnBuilder {
|
|
1908
|
+
static [entityKind] = "SQLiteColumnBuilder";
|
|
1909
|
+
foreignKeyConfigs = [];
|
|
1910
|
+
references(ref, actions = {}) {
|
|
1911
|
+
this.foreignKeyConfigs.push({ ref, actions });
|
|
1912
|
+
return this;
|
|
1913
|
+
}
|
|
1914
|
+
unique(name) {
|
|
1915
|
+
this.config.isUnique = true;
|
|
1916
|
+
this.config.uniqueName = name;
|
|
1917
|
+
return this;
|
|
1918
|
+
}
|
|
1919
|
+
generatedAlwaysAs(as, config) {
|
|
1920
|
+
this.config.generated = {
|
|
1921
|
+
as,
|
|
1922
|
+
type: "always",
|
|
1923
|
+
mode: config?.mode ?? "virtual"
|
|
1924
|
+
};
|
|
1925
|
+
return this;
|
|
1926
|
+
}
|
|
1927
|
+
/** @internal */
|
|
1928
|
+
buildForeignKeys(column, table) {
|
|
1929
|
+
return this.foreignKeyConfigs.map(({ ref, actions }) => {
|
|
1930
|
+
return ((ref2, actions2) => {
|
|
1931
|
+
const builder = new ForeignKeyBuilder2(() => {
|
|
1932
|
+
const foreignColumn = ref2();
|
|
1933
|
+
return { columns: [column], foreignColumns: [foreignColumn] };
|
|
1934
|
+
});
|
|
1935
|
+
if (actions2.onUpdate) {
|
|
1936
|
+
builder.onUpdate(actions2.onUpdate);
|
|
1937
|
+
}
|
|
1938
|
+
if (actions2.onDelete) {
|
|
1939
|
+
builder.onDelete(actions2.onDelete);
|
|
1940
|
+
}
|
|
1941
|
+
return builder.build(table);
|
|
1942
|
+
})(ref, actions);
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
var SQLiteColumn = class extends Column {
|
|
1947
|
+
constructor(table, config) {
|
|
1948
|
+
if (!config.uniqueName) {
|
|
1949
|
+
config.uniqueName = uniqueKeyName2(table, [config.name]);
|
|
1950
|
+
}
|
|
1951
|
+
super(table, config);
|
|
1952
|
+
this.table = table;
|
|
1953
|
+
}
|
|
1954
|
+
static [entityKind] = "SQLiteColumn";
|
|
1955
|
+
};
|
|
1956
|
+
|
|
1957
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/blob.js
|
|
1958
|
+
var SQLiteBigIntBuilder = class extends SQLiteColumnBuilder {
|
|
1959
|
+
static [entityKind] = "SQLiteBigIntBuilder";
|
|
1960
|
+
constructor(name) {
|
|
1961
|
+
super(name, "bigint", "SQLiteBigInt");
|
|
1962
|
+
}
|
|
1963
|
+
/** @internal */
|
|
1964
|
+
build(table) {
|
|
1965
|
+
return new SQLiteBigInt(table, this.config);
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1968
|
+
var SQLiteBigInt = class extends SQLiteColumn {
|
|
1969
|
+
static [entityKind] = "SQLiteBigInt";
|
|
1970
|
+
getSQLType() {
|
|
1971
|
+
return "blob";
|
|
1972
|
+
}
|
|
1973
|
+
mapFromDriverValue(value) {
|
|
1974
|
+
if (typeof Buffer !== "undefined" && Buffer.from) {
|
|
1975
|
+
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);
|
|
1976
|
+
return BigInt(buf.toString("utf8"));
|
|
1977
|
+
}
|
|
1978
|
+
return BigInt(textDecoder.decode(value));
|
|
1979
|
+
}
|
|
1980
|
+
mapToDriverValue(value) {
|
|
1981
|
+
return Buffer.from(value.toString());
|
|
1982
|
+
}
|
|
1983
|
+
};
|
|
1984
|
+
var SQLiteBlobJsonBuilder = class extends SQLiteColumnBuilder {
|
|
1985
|
+
static [entityKind] = "SQLiteBlobJsonBuilder";
|
|
1986
|
+
constructor(name) {
|
|
1987
|
+
super(name, "json", "SQLiteBlobJson");
|
|
1988
|
+
}
|
|
1989
|
+
/** @internal */
|
|
1990
|
+
build(table) {
|
|
1991
|
+
return new SQLiteBlobJson(
|
|
1992
|
+
table,
|
|
1993
|
+
this.config
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
};
|
|
1997
|
+
var SQLiteBlobJson = class extends SQLiteColumn {
|
|
1998
|
+
static [entityKind] = "SQLiteBlobJson";
|
|
1999
|
+
getSQLType() {
|
|
2000
|
+
return "blob";
|
|
2001
|
+
}
|
|
2002
|
+
mapFromDriverValue(value) {
|
|
2003
|
+
if (typeof Buffer !== "undefined" && Buffer.from) {
|
|
2004
|
+
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);
|
|
2005
|
+
return JSON.parse(buf.toString("utf8"));
|
|
2006
|
+
}
|
|
2007
|
+
return JSON.parse(textDecoder.decode(value));
|
|
2008
|
+
}
|
|
2009
|
+
mapToDriverValue(value) {
|
|
2010
|
+
return Buffer.from(JSON.stringify(value));
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
2013
|
+
var SQLiteBlobBufferBuilder = class extends SQLiteColumnBuilder {
|
|
2014
|
+
static [entityKind] = "SQLiteBlobBufferBuilder";
|
|
2015
|
+
constructor(name) {
|
|
2016
|
+
super(name, "buffer", "SQLiteBlobBuffer");
|
|
2017
|
+
}
|
|
2018
|
+
/** @internal */
|
|
2019
|
+
build(table) {
|
|
2020
|
+
return new SQLiteBlobBuffer(table, this.config);
|
|
2021
|
+
}
|
|
2022
|
+
};
|
|
2023
|
+
var SQLiteBlobBuffer = class extends SQLiteColumn {
|
|
2024
|
+
static [entityKind] = "SQLiteBlobBuffer";
|
|
2025
|
+
mapFromDriverValue(value) {
|
|
2026
|
+
if (Buffer.isBuffer(value)) {
|
|
2027
|
+
return value;
|
|
2028
|
+
}
|
|
2029
|
+
return Buffer.from(value);
|
|
2030
|
+
}
|
|
2031
|
+
getSQLType() {
|
|
2032
|
+
return "blob";
|
|
2033
|
+
}
|
|
2034
|
+
};
|
|
2035
|
+
function blob(a, b) {
|
|
2036
|
+
const { name, config } = getColumnNameAndConfig(a, b);
|
|
2037
|
+
if (config?.mode === "json") {
|
|
2038
|
+
return new SQLiteBlobJsonBuilder(name);
|
|
2039
|
+
}
|
|
2040
|
+
if (config?.mode === "bigint") {
|
|
2041
|
+
return new SQLiteBigIntBuilder(name);
|
|
2042
|
+
}
|
|
2043
|
+
return new SQLiteBlobBufferBuilder(name);
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/custom.js
|
|
2047
|
+
var SQLiteCustomColumnBuilder = class extends SQLiteColumnBuilder {
|
|
2048
|
+
static [entityKind] = "SQLiteCustomColumnBuilder";
|
|
2049
|
+
constructor(name, fieldConfig, customTypeParams) {
|
|
2050
|
+
super(name, "custom", "SQLiteCustomColumn");
|
|
2051
|
+
this.config.fieldConfig = fieldConfig;
|
|
2052
|
+
this.config.customTypeParams = customTypeParams;
|
|
2053
|
+
}
|
|
2054
|
+
/** @internal */
|
|
2055
|
+
build(table) {
|
|
2056
|
+
return new SQLiteCustomColumn(
|
|
2057
|
+
table,
|
|
2058
|
+
this.config
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
};
|
|
2062
|
+
var SQLiteCustomColumn = class extends SQLiteColumn {
|
|
2063
|
+
static [entityKind] = "SQLiteCustomColumn";
|
|
2064
|
+
sqlName;
|
|
2065
|
+
mapTo;
|
|
2066
|
+
mapFrom;
|
|
2067
|
+
constructor(table, config) {
|
|
2068
|
+
super(table, config);
|
|
2069
|
+
this.sqlName = config.customTypeParams.dataType(config.fieldConfig);
|
|
2070
|
+
this.mapTo = config.customTypeParams.toDriver;
|
|
2071
|
+
this.mapFrom = config.customTypeParams.fromDriver;
|
|
2072
|
+
}
|
|
2073
|
+
getSQLType() {
|
|
2074
|
+
return this.sqlName;
|
|
2075
|
+
}
|
|
2076
|
+
mapFromDriverValue(value) {
|
|
2077
|
+
return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
|
|
2078
|
+
}
|
|
2079
|
+
mapToDriverValue(value) {
|
|
2080
|
+
return typeof this.mapTo === "function" ? this.mapTo(value) : value;
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2083
|
+
function customType(customTypeParams) {
|
|
2084
|
+
return (a, b) => {
|
|
2085
|
+
const { name, config } = getColumnNameAndConfig(a, b);
|
|
2086
|
+
return new SQLiteCustomColumnBuilder(
|
|
2087
|
+
name,
|
|
2088
|
+
config,
|
|
2089
|
+
customTypeParams
|
|
2090
|
+
);
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/integer.js
|
|
2095
|
+
var SQLiteBaseIntegerBuilder = class extends SQLiteColumnBuilder {
|
|
2096
|
+
static [entityKind] = "SQLiteBaseIntegerBuilder";
|
|
2097
|
+
constructor(name, dataType, columnType) {
|
|
2098
|
+
super(name, dataType, columnType);
|
|
2099
|
+
this.config.autoIncrement = false;
|
|
2100
|
+
}
|
|
2101
|
+
primaryKey(config) {
|
|
2102
|
+
if (config?.autoIncrement) {
|
|
2103
|
+
this.config.autoIncrement = true;
|
|
2104
|
+
}
|
|
2105
|
+
this.config.hasDefault = true;
|
|
2106
|
+
return super.primaryKey();
|
|
2107
|
+
}
|
|
2108
|
+
};
|
|
2109
|
+
var SQLiteBaseInteger = class extends SQLiteColumn {
|
|
2110
|
+
static [entityKind] = "SQLiteBaseInteger";
|
|
2111
|
+
autoIncrement = this.config.autoIncrement;
|
|
2112
|
+
getSQLType() {
|
|
2113
|
+
return "integer";
|
|
2114
|
+
}
|
|
2115
|
+
};
|
|
2116
|
+
var SQLiteIntegerBuilder = class extends SQLiteBaseIntegerBuilder {
|
|
2117
|
+
static [entityKind] = "SQLiteIntegerBuilder";
|
|
2118
|
+
constructor(name) {
|
|
2119
|
+
super(name, "number", "SQLiteInteger");
|
|
2120
|
+
}
|
|
2121
|
+
build(table) {
|
|
2122
|
+
return new SQLiteInteger(
|
|
2123
|
+
table,
|
|
2124
|
+
this.config
|
|
2125
|
+
);
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
var SQLiteInteger = class extends SQLiteBaseInteger {
|
|
2129
|
+
static [entityKind] = "SQLiteInteger";
|
|
2130
|
+
};
|
|
2131
|
+
var SQLiteTimestampBuilder = class extends SQLiteBaseIntegerBuilder {
|
|
2132
|
+
static [entityKind] = "SQLiteTimestampBuilder";
|
|
2133
|
+
constructor(name, mode) {
|
|
2134
|
+
super(name, "date", "SQLiteTimestamp");
|
|
2135
|
+
this.config.mode = mode;
|
|
2136
|
+
}
|
|
2137
|
+
/**
|
|
2138
|
+
* @deprecated Use `default()` with your own expression instead.
|
|
2139
|
+
*
|
|
2140
|
+
* Adds `DEFAULT (cast((julianday('now') - 2440587.5)*86400000 as integer))` to the column, which is the current epoch timestamp in milliseconds.
|
|
2141
|
+
*/
|
|
2142
|
+
defaultNow() {
|
|
2143
|
+
return this.default(sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`);
|
|
2144
|
+
}
|
|
2145
|
+
build(table) {
|
|
2146
|
+
return new SQLiteTimestamp(
|
|
2147
|
+
table,
|
|
2148
|
+
this.config
|
|
2149
|
+
);
|
|
2150
|
+
}
|
|
2151
|
+
};
|
|
2152
|
+
var SQLiteTimestamp = class extends SQLiteBaseInteger {
|
|
2153
|
+
static [entityKind] = "SQLiteTimestamp";
|
|
2154
|
+
mode = this.config.mode;
|
|
2155
|
+
mapFromDriverValue(value) {
|
|
2156
|
+
if (this.config.mode === "timestamp") {
|
|
2157
|
+
return new Date(value * 1e3);
|
|
2158
|
+
}
|
|
2159
|
+
return new Date(value);
|
|
2160
|
+
}
|
|
2161
|
+
mapToDriverValue(value) {
|
|
2162
|
+
const unix = value.getTime();
|
|
2163
|
+
if (this.config.mode === "timestamp") {
|
|
2164
|
+
return Math.floor(unix / 1e3);
|
|
2165
|
+
}
|
|
2166
|
+
return unix;
|
|
2167
|
+
}
|
|
2168
|
+
};
|
|
2169
|
+
var SQLiteBooleanBuilder = class extends SQLiteBaseIntegerBuilder {
|
|
2170
|
+
static [entityKind] = "SQLiteBooleanBuilder";
|
|
2171
|
+
constructor(name, mode) {
|
|
2172
|
+
super(name, "boolean", "SQLiteBoolean");
|
|
2173
|
+
this.config.mode = mode;
|
|
2174
|
+
}
|
|
2175
|
+
build(table) {
|
|
2176
|
+
return new SQLiteBoolean(
|
|
2177
|
+
table,
|
|
2178
|
+
this.config
|
|
2179
|
+
);
|
|
2180
|
+
}
|
|
2181
|
+
};
|
|
2182
|
+
var SQLiteBoolean = class extends SQLiteBaseInteger {
|
|
2183
|
+
static [entityKind] = "SQLiteBoolean";
|
|
2184
|
+
mode = this.config.mode;
|
|
2185
|
+
mapFromDriverValue(value) {
|
|
2186
|
+
return Number(value) === 1;
|
|
2187
|
+
}
|
|
2188
|
+
mapToDriverValue(value) {
|
|
2189
|
+
return value ? 1 : 0;
|
|
2190
|
+
}
|
|
2191
|
+
};
|
|
2192
|
+
function integer(a, b) {
|
|
2193
|
+
const { name, config } = getColumnNameAndConfig(a, b);
|
|
2194
|
+
if (config?.mode === "timestamp" || config?.mode === "timestamp_ms") {
|
|
2195
|
+
return new SQLiteTimestampBuilder(name, config.mode);
|
|
2196
|
+
}
|
|
2197
|
+
if (config?.mode === "boolean") {
|
|
2198
|
+
return new SQLiteBooleanBuilder(name, config.mode);
|
|
2199
|
+
}
|
|
2200
|
+
return new SQLiteIntegerBuilder(name);
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
|
|
2204
|
+
var SQLiteNumericBuilder = class extends SQLiteColumnBuilder {
|
|
2205
|
+
static [entityKind] = "SQLiteNumericBuilder";
|
|
2206
|
+
constructor(name) {
|
|
2207
|
+
super(name, "string", "SQLiteNumeric");
|
|
2208
|
+
}
|
|
2209
|
+
/** @internal */
|
|
2210
|
+
build(table) {
|
|
2211
|
+
return new SQLiteNumeric(
|
|
2212
|
+
table,
|
|
2213
|
+
this.config
|
|
2214
|
+
);
|
|
2215
|
+
}
|
|
2216
|
+
};
|
|
2217
|
+
var SQLiteNumeric = class extends SQLiteColumn {
|
|
2218
|
+
static [entityKind] = "SQLiteNumeric";
|
|
2219
|
+
mapFromDriverValue(value) {
|
|
2220
|
+
if (typeof value === "string") return value;
|
|
2221
|
+
return String(value);
|
|
2222
|
+
}
|
|
2223
|
+
getSQLType() {
|
|
2224
|
+
return "numeric";
|
|
2225
|
+
}
|
|
2226
|
+
};
|
|
2227
|
+
var SQLiteNumericNumberBuilder = class extends SQLiteColumnBuilder {
|
|
2228
|
+
static [entityKind] = "SQLiteNumericNumberBuilder";
|
|
2229
|
+
constructor(name) {
|
|
2230
|
+
super(name, "number", "SQLiteNumericNumber");
|
|
2231
|
+
}
|
|
2232
|
+
/** @internal */
|
|
2233
|
+
build(table) {
|
|
2234
|
+
return new SQLiteNumericNumber(
|
|
2235
|
+
table,
|
|
2236
|
+
this.config
|
|
2237
|
+
);
|
|
2238
|
+
}
|
|
2239
|
+
};
|
|
2240
|
+
var SQLiteNumericNumber = class extends SQLiteColumn {
|
|
2241
|
+
static [entityKind] = "SQLiteNumericNumber";
|
|
2242
|
+
mapFromDriverValue(value) {
|
|
2243
|
+
if (typeof value === "number") return value;
|
|
2244
|
+
return Number(value);
|
|
2245
|
+
}
|
|
2246
|
+
mapToDriverValue = String;
|
|
2247
|
+
getSQLType() {
|
|
2248
|
+
return "numeric";
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
var SQLiteNumericBigIntBuilder = class extends SQLiteColumnBuilder {
|
|
2252
|
+
static [entityKind] = "SQLiteNumericBigIntBuilder";
|
|
2253
|
+
constructor(name) {
|
|
2254
|
+
super(name, "bigint", "SQLiteNumericBigInt");
|
|
2255
|
+
}
|
|
2256
|
+
/** @internal */
|
|
2257
|
+
build(table) {
|
|
2258
|
+
return new SQLiteNumericBigInt(
|
|
2259
|
+
table,
|
|
2260
|
+
this.config
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2263
|
+
};
|
|
2264
|
+
var SQLiteNumericBigInt = class extends SQLiteColumn {
|
|
2265
|
+
static [entityKind] = "SQLiteNumericBigInt";
|
|
2266
|
+
mapFromDriverValue = BigInt;
|
|
2267
|
+
mapToDriverValue = String;
|
|
2268
|
+
getSQLType() {
|
|
2269
|
+
return "numeric";
|
|
2270
|
+
}
|
|
2271
|
+
};
|
|
2272
|
+
function numeric(a, b) {
|
|
2273
|
+
const { name, config } = getColumnNameAndConfig(a, b);
|
|
2274
|
+
const mode = config?.mode;
|
|
2275
|
+
return mode === "number" ? new SQLiteNumericNumberBuilder(name) : mode === "bigint" ? new SQLiteNumericBigIntBuilder(name) : new SQLiteNumericBuilder(name);
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/real.js
|
|
2279
|
+
var SQLiteRealBuilder = class extends SQLiteColumnBuilder {
|
|
2280
|
+
static [entityKind] = "SQLiteRealBuilder";
|
|
2281
|
+
constructor(name) {
|
|
2282
|
+
super(name, "number", "SQLiteReal");
|
|
2283
|
+
}
|
|
2284
|
+
/** @internal */
|
|
2285
|
+
build(table) {
|
|
2286
|
+
return new SQLiteReal(table, this.config);
|
|
2287
|
+
}
|
|
2288
|
+
};
|
|
2289
|
+
var SQLiteReal = class extends SQLiteColumn {
|
|
2290
|
+
static [entityKind] = "SQLiteReal";
|
|
2291
|
+
getSQLType() {
|
|
2292
|
+
return "real";
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
function real(name) {
|
|
2296
|
+
return new SQLiteRealBuilder(name ?? "");
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/text.js
|
|
2300
|
+
var SQLiteTextBuilder = class extends SQLiteColumnBuilder {
|
|
2301
|
+
static [entityKind] = "SQLiteTextBuilder";
|
|
2302
|
+
constructor(name, config) {
|
|
2303
|
+
super(name, "string", "SQLiteText");
|
|
2304
|
+
this.config.enumValues = config.enum;
|
|
2305
|
+
this.config.length = config.length;
|
|
2306
|
+
}
|
|
2307
|
+
/** @internal */
|
|
2308
|
+
build(table) {
|
|
2309
|
+
return new SQLiteText(
|
|
2310
|
+
table,
|
|
2311
|
+
this.config
|
|
2312
|
+
);
|
|
2313
|
+
}
|
|
2314
|
+
};
|
|
2315
|
+
var SQLiteText = class extends SQLiteColumn {
|
|
2316
|
+
static [entityKind] = "SQLiteText";
|
|
2317
|
+
enumValues = this.config.enumValues;
|
|
2318
|
+
length = this.config.length;
|
|
2319
|
+
constructor(table, config) {
|
|
2320
|
+
super(table, config);
|
|
2321
|
+
}
|
|
2322
|
+
getSQLType() {
|
|
2323
|
+
return `text${this.config.length ? `(${this.config.length})` : ""}`;
|
|
2324
|
+
}
|
|
2325
|
+
};
|
|
2326
|
+
var SQLiteTextJsonBuilder = class extends SQLiteColumnBuilder {
|
|
2327
|
+
static [entityKind] = "SQLiteTextJsonBuilder";
|
|
2328
|
+
constructor(name) {
|
|
2329
|
+
super(name, "json", "SQLiteTextJson");
|
|
2330
|
+
}
|
|
2331
|
+
/** @internal */
|
|
2332
|
+
build(table) {
|
|
2333
|
+
return new SQLiteTextJson(
|
|
2334
|
+
table,
|
|
2335
|
+
this.config
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
};
|
|
2339
|
+
var SQLiteTextJson = class extends SQLiteColumn {
|
|
2340
|
+
static [entityKind] = "SQLiteTextJson";
|
|
2341
|
+
getSQLType() {
|
|
2342
|
+
return "text";
|
|
2343
|
+
}
|
|
2344
|
+
mapFromDriverValue(value) {
|
|
2345
|
+
return JSON.parse(value);
|
|
2346
|
+
}
|
|
2347
|
+
mapToDriverValue(value) {
|
|
2348
|
+
return JSON.stringify(value);
|
|
2349
|
+
}
|
|
2350
|
+
};
|
|
2351
|
+
function text2(a, b = {}) {
|
|
2352
|
+
const { name, config } = getColumnNameAndConfig(a, b);
|
|
2353
|
+
if (config.mode === "json") {
|
|
2354
|
+
return new SQLiteTextJsonBuilder(name);
|
|
2355
|
+
}
|
|
2356
|
+
return new SQLiteTextBuilder(name, config);
|
|
2357
|
+
}
|
|
2358
|
+
|
|
2359
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/columns/all.js
|
|
2360
|
+
function getSQLiteColumnBuilders() {
|
|
2361
|
+
return {
|
|
2362
|
+
blob,
|
|
2363
|
+
customType,
|
|
2364
|
+
integer,
|
|
2365
|
+
numeric,
|
|
2366
|
+
real,
|
|
2367
|
+
text: text2
|
|
2368
|
+
};
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/table.js
|
|
2372
|
+
var InlineForeignKeys = /* @__PURE__ */ Symbol.for("drizzle:SQLiteInlineForeignKeys");
|
|
2373
|
+
var SQLiteTable = class extends Table {
|
|
2374
|
+
static [entityKind] = "SQLiteTable";
|
|
2375
|
+
/** @internal */
|
|
2376
|
+
static Symbol = Object.assign({}, Table.Symbol, {
|
|
2377
|
+
InlineForeignKeys
|
|
2378
|
+
});
|
|
2379
|
+
/** @internal */
|
|
2380
|
+
[Table.Symbol.Columns];
|
|
2381
|
+
/** @internal */
|
|
2382
|
+
[InlineForeignKeys] = [];
|
|
2383
|
+
/** @internal */
|
|
2384
|
+
[Table.Symbol.ExtraConfigBuilder] = void 0;
|
|
2385
|
+
};
|
|
2386
|
+
function sqliteTableBase(name, columns, extraConfig, schema, baseName = name) {
|
|
2387
|
+
const rawTable = new SQLiteTable(name, schema, baseName);
|
|
2388
|
+
const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
|
|
2389
|
+
const builtColumns = Object.fromEntries(
|
|
2390
|
+
Object.entries(parsedColumns).map(([name2, colBuilderBase]) => {
|
|
2391
|
+
const colBuilder = colBuilderBase;
|
|
2392
|
+
colBuilder.setName(name2);
|
|
2393
|
+
const column = colBuilder.build(rawTable);
|
|
2394
|
+
rawTable[InlineForeignKeys].push(...colBuilder.buildForeignKeys(column, rawTable));
|
|
2395
|
+
return [name2, column];
|
|
2396
|
+
})
|
|
2397
|
+
);
|
|
2398
|
+
const table = Object.assign(rawTable, builtColumns);
|
|
2399
|
+
table[Table.Symbol.Columns] = builtColumns;
|
|
2400
|
+
table[Table.Symbol.ExtraConfigColumns] = builtColumns;
|
|
2401
|
+
if (extraConfig) {
|
|
2402
|
+
table[SQLiteTable.Symbol.ExtraConfigBuilder] = extraConfig;
|
|
2403
|
+
}
|
|
2404
|
+
return table;
|
|
2405
|
+
}
|
|
2406
|
+
var sqliteTable = (name, columns, extraConfig) => {
|
|
2407
|
+
return sqliteTableBase(name, columns, extraConfig);
|
|
2408
|
+
};
|
|
2409
|
+
|
|
2410
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@5.20261014.1_kysely@0.29.6/node_modules/drizzle-orm/sqlite-core/primary-keys.js
|
|
2411
|
+
function primaryKey(...config) {
|
|
2412
|
+
if (config[0].columns) {
|
|
2413
|
+
return new PrimaryKeyBuilder(config[0].columns, config[0].name);
|
|
2414
|
+
}
|
|
2415
|
+
return new PrimaryKeyBuilder(config);
|
|
2416
|
+
}
|
|
2417
|
+
var PrimaryKeyBuilder = class {
|
|
2418
|
+
static [entityKind] = "SQLitePrimaryKeyBuilder";
|
|
2419
|
+
/** @internal */
|
|
2420
|
+
columns;
|
|
2421
|
+
/** @internal */
|
|
2422
|
+
name;
|
|
2423
|
+
constructor(columns, name) {
|
|
2424
|
+
this.columns = columns;
|
|
2425
|
+
this.name = name;
|
|
2426
|
+
}
|
|
2427
|
+
/** @internal */
|
|
2428
|
+
build(table) {
|
|
2429
|
+
return new PrimaryKey(table, this.columns, this.name);
|
|
2430
|
+
}
|
|
2431
|
+
};
|
|
2432
|
+
var PrimaryKey = class {
|
|
2433
|
+
constructor(table, columns, name) {
|
|
2434
|
+
this.table = table;
|
|
2435
|
+
this.columns = columns;
|
|
2436
|
+
this.name = name;
|
|
2437
|
+
}
|
|
2438
|
+
static [entityKind] = "SQLitePrimaryKey";
|
|
2439
|
+
columns;
|
|
2440
|
+
name;
|
|
2441
|
+
getName() {
|
|
2442
|
+
return this.name ?? `${this.table[SQLiteTable.Symbol.Name]}_${this.columns.map((column) => column.name).join("_")}_pk`;
|
|
2443
|
+
}
|
|
2444
|
+
};
|
|
2445
|
+
|
|
2446
|
+
// ../feedback/src/connected.ts
|
|
2447
|
+
var participants = sqliteTable("participants", {
|
|
2448
|
+
subject: text2("subject").primaryKey(),
|
|
2449
|
+
displayName: text2("display_name").notNull()
|
|
2450
|
+
});
|
|
2451
|
+
var contacts = sqliteTable("participant_contacts", {
|
|
2452
|
+
subject: text2("subject").primaryKey(),
|
|
2453
|
+
email: text2("email"),
|
|
2454
|
+
emailEnabled: integer("email_enabled").notNull().default(0)
|
|
2455
|
+
});
|
|
2456
|
+
var nonces = sqliteTable("identity_nonces", {
|
|
2457
|
+
nonce: text2("nonce").primaryKey(),
|
|
2458
|
+
expiresAt: integer("expires_at").notNull()
|
|
2459
|
+
});
|
|
2460
|
+
var sessions = sqliteTable("participant_sessions", {
|
|
2461
|
+
tokenHash: text2("token_hash").primaryKey(),
|
|
2462
|
+
subject: text2("subject").notNull().references(() => participants.subject),
|
|
2463
|
+
expiresAt: integer("expires_at").notNull()
|
|
2464
|
+
});
|
|
2465
|
+
var votes = sqliteTable(
|
|
2466
|
+
"participant_votes",
|
|
2467
|
+
{
|
|
2468
|
+
postSlug: text2("post_slug").notNull(),
|
|
2469
|
+
subject: text2("subject").notNull().references(() => participants.subject)
|
|
2470
|
+
},
|
|
2471
|
+
(t) => [primaryKey({ columns: [t.postSlug, t.subject] })]
|
|
2472
|
+
);
|
|
2473
|
+
var attribution = sqliteTable("comment_attribution", {
|
|
2474
|
+
commentId: text2("comment_id").primaryKey(),
|
|
2475
|
+
subject: text2("subject").notNull().references(() => participants.subject),
|
|
2476
|
+
displayName: text2("display_name").notNull()
|
|
2477
|
+
});
|
|
2478
|
+
|
|
2479
|
+
// ../feedback/src/images.ts
|
|
2480
|
+
var limit = 5 * 1024 * 1024;
|
|
2481
|
+
|
|
631
2482
|
// ../feedback/src/index.ts
|
|
632
2483
|
var postCreationQueue = Promise.resolve();
|
|
633
2484
|
|
|
@@ -781,12 +2632,16 @@ function isRecord(value) {
|
|
|
781
2632
|
}
|
|
782
2633
|
|
|
783
2634
|
// src/index.ts
|
|
2635
|
+
function defaultProcessingQueueName(workerName) {
|
|
2636
|
+
return workerName.length <= 55 ? `${workerName}-updates` : `${workerName.slice(0, 46)}-${createHash("sha256").update(workerName).digest("hex").slice(0, 8)}-updates`;
|
|
2637
|
+
}
|
|
784
2638
|
async function provisionGuidedInstallation({
|
|
785
2639
|
destination,
|
|
786
2640
|
product,
|
|
787
2641
|
themePreset,
|
|
788
2642
|
workerName,
|
|
789
2643
|
commentProbePageId,
|
|
2644
|
+
connected,
|
|
790
2645
|
features,
|
|
791
2646
|
feedbackSelection,
|
|
792
2647
|
changelogSelection,
|
|
@@ -805,11 +2660,46 @@ async function provisionGuidedInstallation({
|
|
|
805
2660
|
}
|
|
806
2661
|
if (product.siteUrl && new URL(product.siteUrl).protocol !== "https:")
|
|
807
2662
|
throw new Error("product.siteUrl must be an HTTPS URL.");
|
|
2663
|
+
if (connected) {
|
|
2664
|
+
if (!product.siteUrl || connected.handoffSecret.length < 32 || !/^[0-9a-f-]{36}$/i.test(connected.databaseId) || !connected.databaseName.trim())
|
|
2665
|
+
throw new Error(
|
|
2666
|
+
"Connected setup requires a public site URL, dedicated D1 identifiers, and a handoff secret of at least 32 characters."
|
|
2667
|
+
);
|
|
2668
|
+
for (const url of [connected.issuer, connected.loginUrl])
|
|
2669
|
+
if (new URL(url).protocol !== "https:" || new URL(url).username || new URL(url).password)
|
|
2670
|
+
throw new Error(
|
|
2671
|
+
"Connected identity URLs must use HTTPS without credentials."
|
|
2672
|
+
);
|
|
2673
|
+
}
|
|
2674
|
+
if (connected?.email) {
|
|
2675
|
+
const sender = connected.email;
|
|
2676
|
+
if (!["cloudflare", "resend", "custom"].includes(sender.provider) || !/^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(sender.from))
|
|
2677
|
+
throw new Error(
|
|
2678
|
+
"Choose cloudflare, resend, or custom and a plain sender email address."
|
|
2679
|
+
);
|
|
2680
|
+
if (sender.provider !== "cloudflare" && !sender.secret?.trim())
|
|
2681
|
+
throw new Error(
|
|
2682
|
+
"Resend and custom delivery require a server-only email secret."
|
|
2683
|
+
);
|
|
2684
|
+
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))
|
|
2685
|
+
throw new Error(
|
|
2686
|
+
"Custom delivery requires an HTTPS endpoint without credentials or fragments."
|
|
2687
|
+
);
|
|
2688
|
+
}
|
|
2689
|
+
if (connected?.imageBucket && !/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/.test(connected.imageBucket))
|
|
2690
|
+
throw new Error(
|
|
2691
|
+
"Use a dedicated private R2 bucket name of 3\u201363 lowercase letters, digits, or hyphens."
|
|
2692
|
+
);
|
|
808
2693
|
const targetName = workerName ?? basename(destination).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
809
2694
|
if (!/^[a-z0-9][a-z0-9-]{0,62}$/.test(targetName))
|
|
810
2695
|
throw new Error(
|
|
811
2696
|
"Worker name must contain 1\u201363 lowercase letters, numbers, or hyphens."
|
|
812
2697
|
);
|
|
2698
|
+
const processingQueue = connected && connected.processing !== "standard" ? connected.queueName ?? defaultProcessingQueueName(targetName) : void 0;
|
|
2699
|
+
if (processingQueue && !/^[a-z0-9][a-z0-9-]{0,62}$/.test(processingQueue))
|
|
2700
|
+
throw new Error(
|
|
2701
|
+
"Processing queue name must contain 1\u201363 lowercase letters, numbers, or hyphens."
|
|
2702
|
+
);
|
|
813
2703
|
const approved = await preview(
|
|
814
2704
|
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.`
|
|
815
2705
|
);
|
|
@@ -855,7 +2745,58 @@ async function provisionGuidedInstallation({
|
|
|
855
2745
|
const wrangler = JSON.parse(await readFile2(wranglerPath, "utf8"));
|
|
856
2746
|
await writeFile2(
|
|
857
2747
|
wranglerPath,
|
|
858
|
-
JSON.stringify(
|
|
2748
|
+
JSON.stringify(
|
|
2749
|
+
{
|
|
2750
|
+
...wrangler,
|
|
2751
|
+
name: targetName,
|
|
2752
|
+
...connected ? {
|
|
2753
|
+
triggers: { crons: ["*/5 * * * *"] },
|
|
2754
|
+
...processingQueue ? {
|
|
2755
|
+
queues: {
|
|
2756
|
+
producers: [
|
|
2757
|
+
{ binding: "FEEDBAX_UPDATES", queue: processingQueue }
|
|
2758
|
+
],
|
|
2759
|
+
consumers: [
|
|
2760
|
+
{
|
|
2761
|
+
queue: processingQueue,
|
|
2762
|
+
max_batch_size: 1,
|
|
2763
|
+
max_batch_timeout: 1,
|
|
2764
|
+
max_retries: 3,
|
|
2765
|
+
max_concurrency: 1,
|
|
2766
|
+
retry_delay: 60
|
|
2767
|
+
}
|
|
2768
|
+
]
|
|
2769
|
+
}
|
|
2770
|
+
} : {},
|
|
2771
|
+
...connected.email?.provider === "cloudflare" ? {
|
|
2772
|
+
send_email: [
|
|
2773
|
+
{
|
|
2774
|
+
name: "FEEDBAX_EMAIL",
|
|
2775
|
+
allowed_sender_addresses: [connected.email.from]
|
|
2776
|
+
}
|
|
2777
|
+
]
|
|
2778
|
+
} : {},
|
|
2779
|
+
...connected.imageBucket ? {
|
|
2780
|
+
r2_buckets: [
|
|
2781
|
+
{
|
|
2782
|
+
binding: "FEEDBAX_IMAGES",
|
|
2783
|
+
bucket_name: connected.imageBucket
|
|
2784
|
+
}
|
|
2785
|
+
]
|
|
2786
|
+
} : {},
|
|
2787
|
+
d1_databases: [
|
|
2788
|
+
{
|
|
2789
|
+
binding: "FEEDBAX_DB",
|
|
2790
|
+
database_id: connected.databaseId,
|
|
2791
|
+
database_name: connected.databaseName,
|
|
2792
|
+
migrations_dir: "migrations"
|
|
2793
|
+
}
|
|
2794
|
+
]
|
|
2795
|
+
} : {}
|
|
2796
|
+
},
|
|
2797
|
+
null,
|
|
2798
|
+
2
|
|
2799
|
+
) + "\n"
|
|
859
2800
|
);
|
|
860
2801
|
const apiKey = randomBytes(32).toString("base64url");
|
|
861
2802
|
const signingSecret = randomBytes(32).toString("base64url");
|
|
@@ -866,6 +2807,8 @@ async function provisionGuidedInstallation({
|
|
|
866
2807
|
...prefixProperties("NOTION_FEEDBACK", feedback.propertyIds),
|
|
867
2808
|
FEEDBAX_API_KEY_HASH: createHash("sha256").update(apiKey).digest("base64url"),
|
|
868
2809
|
PARTICIPATION_SIGNING_SECRET: signingSecret,
|
|
2810
|
+
...connected ? { IDENTITY_HANDOFF_SECRET: connected.handoffSecret } : {},
|
|
2811
|
+
...connected?.email?.secret ? { EMAIL_PROVIDER_SECRET: connected.email.secret } : {},
|
|
869
2812
|
FEEDBAX_VOTING_ENABLED: String(features.voting),
|
|
870
2813
|
FEEDBAX_COMMENTS_ENABLED: String(features.comments),
|
|
871
2814
|
FEEDBAX_CHANGELOG_ENABLED: String(features.changelog),
|
|
@@ -885,6 +2828,21 @@ async function provisionGuidedInstallation({
|
|
|
885
2828
|
const configuration = defineFeedbax({
|
|
886
2829
|
product: { ...product, logo: "/feedbax-mark.svg" },
|
|
887
2830
|
theme: { preset: themePreset },
|
|
2831
|
+
...connected ? {
|
|
2832
|
+
connected: {
|
|
2833
|
+
processing: connected.processing ?? "small",
|
|
2834
|
+
issuer: connected.issuer,
|
|
2835
|
+
loginUrl: connected.loginUrl,
|
|
2836
|
+
...connected.email ? {
|
|
2837
|
+
email: {
|
|
2838
|
+
provider: connected.email.provider,
|
|
2839
|
+
from: connected.email.from,
|
|
2840
|
+
...connected.email.endpoint ? { endpoint: connected.email.endpoint } : {}
|
|
2841
|
+
}
|
|
2842
|
+
} : {},
|
|
2843
|
+
...connected.imageBucket ? { images: true } : {}
|
|
2844
|
+
}
|
|
2845
|
+
} : {},
|
|
888
2846
|
notion: {
|
|
889
2847
|
databaseId: feedback.databaseId,
|
|
890
2848
|
dataSourceId: feedback.dataSourceId,
|
|
@@ -922,7 +2880,7 @@ export default defineFeedbax(${JSON.stringify(configuration, null, 2)});
|
|
|
922
2880
|
`,
|
|
923
2881
|
{ flag: "a", mode: 384 }
|
|
924
2882
|
);
|
|
925
|
-
return { apiKey, feedback, changelog };
|
|
2883
|
+
return { apiKey, feedback, changelog, processingQueue };
|
|
926
2884
|
}
|
|
927
2885
|
function prefixProperties(prefix, properties) {
|
|
928
2886
|
return Object.fromEntries(
|
|
@@ -1073,7 +3031,7 @@ try {
|
|
|
1073
3031
|
if (args.some((arg) => arg.startsWith("-") && arg !== "--template-only"))
|
|
1074
3032
|
throw new Error("Unknown option. Run create-feedbax --help.");
|
|
1075
3033
|
const destination = resolve2(
|
|
1076
|
-
args.find((arg) => !arg.startsWith("-")) ?? await
|
|
3034
|
+
args.find((arg) => !arg.startsWith("-")) ?? await text4("Project directory", "my-feedback")
|
|
1077
3035
|
);
|
|
1078
3036
|
if (args.includes("--template-only")) {
|
|
1079
3037
|
await copyPackagedTemplate(destination);
|
|
@@ -1081,21 +3039,66 @@ try {
|
|
|
1081
3039
|
} else {
|
|
1082
3040
|
prompt.intro("Create a Feedbax portal");
|
|
1083
3041
|
const product = {
|
|
1084
|
-
name: await
|
|
1085
|
-
description: await
|
|
3042
|
+
name: await text4("Product name", "My product"),
|
|
3043
|
+
description: await text4(
|
|
1086
3044
|
"Public description",
|
|
1087
3045
|
"Share feedback and follow product progress."
|
|
1088
3046
|
),
|
|
1089
|
-
siteUrl: await
|
|
3047
|
+
siteUrl: await text4(
|
|
1090
3048
|
"Public portal URL (your workers.dev URL or custom domain)",
|
|
1091
3049
|
"https://my-feedback.example.workers.dev"
|
|
1092
3050
|
)
|
|
1093
3051
|
};
|
|
1094
|
-
const workerName = await
|
|
3052
|
+
const workerName = await text4(
|
|
1095
3053
|
"Cloudflare Worker name (choose a distinct name for this product)",
|
|
1096
3054
|
basename2(destination).toLowerCase().replace(/[^a-z0-9-]/g, "-")
|
|
1097
3055
|
);
|
|
1098
|
-
const
|
|
3056
|
+
const connected = await confirm2(
|
|
3057
|
+
"Enable Connected Profile using your application's sign-in, dedicated D1, and a processing queue? Small processing supports Workers Free with Resend/custom email.",
|
|
3058
|
+
false
|
|
3059
|
+
) ? {
|
|
3060
|
+
issuer: await text4("Application identity issuer (HTTPS URL)"),
|
|
3061
|
+
loginUrl: await text4(
|
|
3062
|
+
"Application signed-handoff login URL (HTTPS)"
|
|
3063
|
+
),
|
|
3064
|
+
databaseId: await text4("Dedicated Cloudflare D1 database ID"),
|
|
3065
|
+
databaseName: await text4("Dedicated Cloudflare D1 database name"),
|
|
3066
|
+
queueName: await text4(
|
|
3067
|
+
"Dedicated Cloudflare Queue name (create it with wrangler queues create first)",
|
|
3068
|
+
defaultProcessingQueueName(workerName)
|
|
3069
|
+
),
|
|
3070
|
+
handoffSecret: await secret(
|
|
3071
|
+
"Shared server-only identity handoff secret (at least 32 characters)"
|
|
3072
|
+
)
|
|
3073
|
+
} : void 0;
|
|
3074
|
+
let email;
|
|
3075
|
+
let imageBucket;
|
|
3076
|
+
if (connected) {
|
|
3077
|
+
const provider = await text4(
|
|
3078
|
+
"Email sender: cloudflare, resend, custom, or none",
|
|
3079
|
+
"none"
|
|
3080
|
+
);
|
|
3081
|
+
if (provider !== "none") {
|
|
3082
|
+
if (provider !== "cloudflare" && provider !== "resend" && provider !== "custom")
|
|
3083
|
+
throw new Error(
|
|
3084
|
+
"Email sender must be cloudflare, resend, custom, or none."
|
|
3085
|
+
);
|
|
3086
|
+
email = {
|
|
3087
|
+
provider,
|
|
3088
|
+
from: await text4("Verified sender email address"),
|
|
3089
|
+
...provider === "custom" ? { endpoint: await text4("Custom HTTPS delivery endpoint") } : {},
|
|
3090
|
+
...provider !== "cloudflare" ? { secret: await secret("Server-only email provider secret") } : {}
|
|
3091
|
+
};
|
|
3092
|
+
}
|
|
3093
|
+
if (await confirm2(
|
|
3094
|
+
"Enable Participant image attachments using an existing private R2 bucket?",
|
|
3095
|
+
false
|
|
3096
|
+
))
|
|
3097
|
+
imageBucket = await text4(
|
|
3098
|
+
"Dedicated private R2 bucket name (create it in Cloudflare first)"
|
|
3099
|
+
);
|
|
3100
|
+
}
|
|
3101
|
+
const themePreset = await text4(
|
|
1099
3102
|
"shadcn preset code, or lyra-neutral for the included preset",
|
|
1100
3103
|
"lyra-neutral"
|
|
1101
3104
|
);
|
|
@@ -1106,20 +3109,20 @@ try {
|
|
|
1106
3109
|
);
|
|
1107
3110
|
const feedbackSelection = existing ? { kind: "existing", configuration: await existingFeedback() } : {
|
|
1108
3111
|
kind: "create",
|
|
1109
|
-
parentPageId: await
|
|
3112
|
+
parentPageId: await text4(
|
|
1110
3113
|
"Notion parent page ID (share it with the integration)"
|
|
1111
3114
|
)
|
|
1112
3115
|
};
|
|
1113
3116
|
const features = await collectFeatureSelection({
|
|
1114
3117
|
confirm: ({ message, initialValue }) => confirm2(message, initialValue)
|
|
1115
3118
|
});
|
|
1116
|
-
const commentProbePageId = existing && features.comments ? await
|
|
3119
|
+
const commentProbePageId = existing && features.comments ? await text4("Shared Notion page ID for checking Comment permissions") : void 0;
|
|
1117
3120
|
const changelogSelection = features.changelog && await confirm2(
|
|
1118
3121
|
"Use an existing compatible Changelog Data Source?",
|
|
1119
3122
|
false
|
|
1120
3123
|
) ? {
|
|
1121
3124
|
kind: "existing",
|
|
1122
|
-
dataSourceId: await
|
|
3125
|
+
dataSourceId: await text4("Changelog Data Source ID"),
|
|
1123
3126
|
propertyIds: await propertyIds([
|
|
1124
3127
|
"title",
|
|
1125
3128
|
"slug",
|
|
@@ -1137,7 +3140,7 @@ try {
|
|
|
1137
3140
|
"Enable Cloudflare Turnstile? Recommended for production.",
|
|
1138
3141
|
true
|
|
1139
3142
|
) ? {
|
|
1140
|
-
siteKey: await
|
|
3143
|
+
siteKey: await text4("Turnstile site key"),
|
|
1141
3144
|
secretKey: process.env.TURNSTILE_SECRET_KEY || await secret("Turnstile secret key")
|
|
1142
3145
|
} : {};
|
|
1143
3146
|
const result = await provisionGuidedInstallation({
|
|
@@ -1146,6 +3149,11 @@ try {
|
|
|
1146
3149
|
themePreset,
|
|
1147
3150
|
workerName,
|
|
1148
3151
|
commentProbePageId,
|
|
3152
|
+
connected: connected ? {
|
|
3153
|
+
...connected,
|
|
3154
|
+
...email ? { email } : {},
|
|
3155
|
+
...imageBucket ? { imageBucket } : {}
|
|
3156
|
+
} : void 0,
|
|
1149
3157
|
features,
|
|
1150
3158
|
feedbackSelection,
|
|
1151
3159
|
changelogSelection,
|
|
@@ -1175,6 +3183,24 @@ ${result.apiKey}`
|
|
|
1175
3183
|
"--write",
|
|
1176
3184
|
"src/feedbax.ts"
|
|
1177
3185
|
]);
|
|
3186
|
+
if (connected) {
|
|
3187
|
+
if (!await confirm2(
|
|
3188
|
+
`Apply the included Connected schema migration to D1 ${connected.databaseName} (${connected.databaseId}) in your authenticated Cloudflare account?`,
|
|
3189
|
+
false
|
|
3190
|
+
))
|
|
3191
|
+
throw new Error(
|
|
3192
|
+
"Connected source is preserved. Apply the D1 migration described in CONNECTED.md before running doctor or deploying."
|
|
3193
|
+
);
|
|
3194
|
+
await runIn(destination, "pnpm", [
|
|
3195
|
+
"exec",
|
|
3196
|
+
"wrangler",
|
|
3197
|
+
"d1",
|
|
3198
|
+
"migrations",
|
|
3199
|
+
"apply",
|
|
3200
|
+
"FEEDBAX_DB",
|
|
3201
|
+
"--remote"
|
|
3202
|
+
]);
|
|
3203
|
+
}
|
|
1178
3204
|
await runIn(destination, "pnpm", ["exec", "feedbax", "doctor"]);
|
|
1179
3205
|
if (await confirm2(
|
|
1180
3206
|
"Authenticate with Cloudflare and deploy this portal?",
|
|
@@ -1196,7 +3222,7 @@ function checked(value) {
|
|
|
1196
3222
|
if (prompt.isCancel(value)) throw new Error("Setup cancelled.");
|
|
1197
3223
|
return value;
|
|
1198
3224
|
}
|
|
1199
|
-
async function
|
|
3225
|
+
async function text4(message, defaultValue) {
|
|
1200
3226
|
return checked(
|
|
1201
3227
|
await prompt.text({
|
|
1202
3228
|
message,
|
|
@@ -1220,13 +3246,13 @@ async function confirm2(message, initialValue) {
|
|
|
1220
3246
|
async function propertyIds(keys) {
|
|
1221
3247
|
const entries = [];
|
|
1222
3248
|
for (const key of keys)
|
|
1223
|
-
entries.push([key, await
|
|
3249
|
+
entries.push([key, await text4(`Stable property ID: ${key}`)]);
|
|
1224
3250
|
return Object.fromEntries(entries);
|
|
1225
3251
|
}
|
|
1226
3252
|
async function existingFeedback() {
|
|
1227
3253
|
return {
|
|
1228
|
-
databaseId: await
|
|
1229
|
-
dataSourceId: await
|
|
3254
|
+
databaseId: await text4("Feedback Database ID"),
|
|
3255
|
+
dataSourceId: await text4("Feedback Data Source ID"),
|
|
1230
3256
|
propertyIds: await propertyIds([
|
|
1231
3257
|
"title",
|
|
1232
3258
|
"slug",
|