added migrations to git
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -83,9 +83,6 @@ next-env.d.ts
|
||||
*.rdb
|
||||
|
||||
|
||||
shared/drizzle
|
||||
|
||||
|
||||
run.sh
|
||||
commands.sh
|
||||
env.sh
|
||||
|
||||
2
ai
2
ai
Submodule ai updated: a6d3ad0403...b1efb8d303
116
bun.lock
116
bun.lock
@@ -315,10 +315,12 @@
|
||||
"inquirer": "^12.6.3",
|
||||
"ioredis": "^5.10.0",
|
||||
"p-limit": "^7.2.0",
|
||||
"pg": "8.20.0",
|
||||
"react": "^18.3.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.3.11",
|
||||
"@types/pg": "8.11.10",
|
||||
"@types/react": "^18.3.1",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "^5.7.3",
|
||||
@@ -2438,7 +2440,7 @@
|
||||
|
||||
"@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
|
||||
|
||||
"@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
|
||||
"@types/pg": ["@types/pg@8.11.10", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^4.0.1" } }, "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg=="],
|
||||
|
||||
"@types/pg-pool": ["@types/pg-pool@2.0.7", "", { "dependencies": { "@types/pg": "*" } }, "sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng=="],
|
||||
|
||||
@@ -4678,6 +4680,8 @@
|
||||
|
||||
"object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
|
||||
|
||||
"obuf": ["obuf@1.1.2", "", {}, "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg=="],
|
||||
|
||||
"ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="],
|
||||
|
||||
"on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
|
||||
@@ -4816,11 +4820,13 @@
|
||||
|
||||
"pg-node-migrations": ["pg-node-migrations@0.0.8", "", { "dependencies": { "pg": "^8.6.0", "sql-template-strings": "^2.2.2" }, "bin": { "pg-validate-migrations": "dist/bin/validate.js" } }, "sha512-44cMl9umOmCv0hzZyEcvjEq8Bm8u7mrzggZ06qXTJVSsMMB4j2OsjG+rSp+uzeKWyP2Vu0K9Ye2wKtjFUJwrdw=="],
|
||||
|
||||
"pg-numeric": ["pg-numeric@1.0.2", "", {}, "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw=="],
|
||||
|
||||
"pg-pool": ["pg-pool@3.13.0", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA=="],
|
||||
|
||||
"pg-protocol": ["pg-protocol@1.13.0", "", {}, "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w=="],
|
||||
|
||||
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
"pg-types": ["pg-types@4.1.0", "", { "dependencies": { "pg-int8": "1.0.1", "pg-numeric": "1.0.2", "postgres-array": "~3.0.1", "postgres-bytea": "~3.0.0", "postgres-date": "~2.1.0", "postgres-interval": "^3.0.0", "postgres-range": "^1.1.1" } }, "sha512-o2XFanIMy/3+mThw69O8d4n1E5zsLhdO+OPqswezu7Z5ekP4hYDqlDjlmOpYMbzY2Br0ufCwJLdDIXeNVwcWFg=="],
|
||||
|
||||
"pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
||||
|
||||
@@ -4888,13 +4894,15 @@
|
||||
|
||||
"postgres": ["postgres@3.4.7", "", {}, "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw=="],
|
||||
|
||||
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
"postgres-array": ["postgres-array@3.0.4", "", {}, "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ=="],
|
||||
|
||||
"postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
"postgres-bytea": ["postgres-bytea@3.0.0", "", { "dependencies": { "obuf": "~1.1.2" } }, "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw=="],
|
||||
|
||||
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
"postgres-date": ["postgres-date@2.1.0", "", {}, "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA=="],
|
||||
|
||||
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
"postgres-interval": ["postgres-interval@3.0.0", "", {}, "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw=="],
|
||||
|
||||
"postgres-range": ["postgres-range@1.1.4", "", {}, "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w=="],
|
||||
|
||||
"posthog-js": ["posthog-js@1.372.10", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/api-logs": "^0.208.0", "@opentelemetry/exporter-logs-otlp-http": "^0.208.0", "@opentelemetry/resources": "^2.2.0", "@opentelemetry/sdk-logs": "^0.208.0", "@posthog/core": "1.28.4", "@posthog/types": "1.372.10", "core-js": "^3.38.1", "dompurify": "^3.3.2", "fflate": "^0.4.8", "preact": "^10.28.2", "query-selector-shadow-dom": "^1.0.1", "web-vitals": "^5.1.0" } }, "sha512-ZQslIenDM8UpwKhmeeEnJ+t2nXr8mOIjCG+Ej3DCJnTBk9NX9Sr5RMuwHeGG8UJitwvtGOADyiY7DignOXaZwg=="],
|
||||
|
||||
@@ -5930,6 +5938,8 @@
|
||||
|
||||
"@autumn/server/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"@autumn/server/@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
|
||||
|
||||
"@autumn/server/@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260511.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260511.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260511.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260511.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260511.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260511.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260511.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260511.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-cUyY4Sr6065280lB6hCwTMCBMTxlEIGjSLzHym28yikA5sFiEsAzlwiU0i+XkTUIqr5K5M/SzSJiioDN+vpjtA=="],
|
||||
|
||||
"@autumn/server/autumn-js": ["autumn-js@0.1.85", "", { "dependencies": { "query-string": "^9.2.2", "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": "^1.3.17", "better-call": "^1.0.12", "convex": "^1.25.4", "react": "*" }, "optionalPeers": ["better-auth", "better-call", "convex", "react"] }, "sha512-PDud/t8z5bDJcD7ptyHzTaoJ0A8zkxvQ4TYcJ48RtgKDdOkVY36D1T6udVLwLDnWw4J5KXwJgEuGxHdd+cuABw=="],
|
||||
@@ -5938,6 +5948,8 @@
|
||||
|
||||
"@autumn/shared/@date-fns/utc": ["@date-fns/utc@2.1.0", "", {}, "sha512-176grgAgU2U303rD2/vcOmNg0kGPbhzckuH1TEP2al7n0AQipZIy9P15usd2TKQCG1g+E1jX/ZVQSzs4sUDwgA=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
|
||||
|
||||
"@autumn/vite/@types/node": ["@types/node@22.19.19", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew=="],
|
||||
|
||||
"@autumn/vite/date-fns": ["date-fns@3.6.0", "", {}, "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww=="],
|
||||
@@ -6134,6 +6146,8 @@
|
||||
|
||||
"@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"@better-auth/cli/@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
|
||||
|
||||
"@better-auth/cli/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
||||
|
||||
"@better-auth/cli/dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="],
|
||||
@@ -6834,6 +6848,8 @@
|
||||
|
||||
"@types/pg/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"@types/pg-pool/@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
|
||||
|
||||
"@types/react-syntax-highlighter/@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||
|
||||
"@types/responselike/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
@@ -7346,6 +7362,8 @@
|
||||
|
||||
"path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"pino/pino-abstract-transport": ["pino-abstract-transport@2.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw=="],
|
||||
|
||||
"pino-pretty/pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="],
|
||||
@@ -7462,6 +7480,8 @@
|
||||
|
||||
"sdk-test/@types/node": ["@types/node@20.19.41", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ=="],
|
||||
|
||||
"sdk-test/@types/pg": ["@types/pg@8.20.0", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow=="],
|
||||
|
||||
"sdk-test/@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||
|
||||
"sdk-test/@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||
@@ -7710,6 +7730,8 @@
|
||||
|
||||
"@autumn/server/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@autumn/server/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"@autumn/server/@typescript/native-preview/@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260511.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-SYrqVOlapDxDG7FzHBIJbfgaix+mXPkYzYGqwpz/TAhoPA7sgbfAoGLaqi3ut9N88C/OYNhEX4tjz/0PC9i1nw=="],
|
||||
|
||||
"@autumn/server/@typescript/native-preview/@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260511.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zIe31OYgBvkgTIQEwJtKim6SYyuVTkr+9fK/87hVwKN15X3Ikjeh0C0g2W/Vl4rXeMvy95wBGDN1jpW11DIvgg=="],
|
||||
@@ -7748,6 +7770,10 @@
|
||||
|
||||
"@autumn/server/ink/widest-line": ["widest-line@6.0.0", "", { "dependencies": { "string-width": "^8.1.0" } }, "sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"@autumn/vite/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
"@autumn/website/eslint/@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="],
|
||||
@@ -7866,6 +7892,10 @@
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"@datadog/datadog-api-client/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
|
||||
@@ -8314,6 +8344,8 @@
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"@opentelemetry/instrumentation-redis/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.211.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-swFdZq8MCdmdR22jTVGQDhwqDzcI4M10nhjXkLr1EsIzXgZBqm4ZlmmcWsg3TSNf+3mzgOiqveXmBLZuDi2Lgg=="],
|
||||
|
||||
"@opentelemetry/instrumentation-redis/@opentelemetry/instrumentation/import-in-the-middle": ["import-in-the-middle@2.0.6", "", { "dependencies": { "acorn": "^8.15.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^2.2.0", "module-details-from-path": "^1.0.4" } }, "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw=="],
|
||||
@@ -8478,6 +8510,10 @@
|
||||
|
||||
"@types/node-fetch/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"@types/pg/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@types/responselike/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
@@ -8938,6 +8974,14 @@
|
||||
|
||||
"p-locate/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||
|
||||
"pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"pkg-conf/find-up/locate-path": ["locate-path@7.2.0", "", { "dependencies": { "p-locate": "^6.0.0" } }, "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA=="],
|
||||
|
||||
"pkg-conf/find-up/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="],
|
||||
@@ -9072,6 +9116,10 @@
|
||||
|
||||
"sdk-test/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
"sdk-test/@types/pg/@types/node": ["@types/node@25.6.2", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw=="],
|
||||
|
||||
"sdk-test/@types/pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||
|
||||
"sdk-test/next/@next/env": ["@next/env@16.1.6", "", {}, "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ=="],
|
||||
|
||||
"sdk-test/next/@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw=="],
|
||||
@@ -9230,10 +9278,28 @@
|
||||
|
||||
"@artilleryio/int-core/socket.io-client/engine.io-client/xmlhttprequest-ssl": ["xmlhttprequest-ssl@2.1.2", "", {}, "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ=="],
|
||||
|
||||
"@autumn/server/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"@autumn/server/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"@autumn/server/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"@autumn/server/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"@autumn/server/ink/@alcalzone/ansi-tokenize/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
||||
|
||||
"@autumn/server/ink/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"@autumn/stripe-sync/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"@autumn/website/eslint/@eslint/config-array/@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="],
|
||||
|
||||
"@aws-sdk/client-sso-oidc/@aws-sdk/core/@smithy/signature-v4/@smithy/is-array-buffer": ["@smithy/is-array-buffer@3.0.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ=="],
|
||||
@@ -9298,6 +9364,16 @@
|
||||
|
||||
"@aws-sdk/signature-v4/@smithy/signature-v4/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@1.1.0", "", { "dependencies": { "@smithy/is-array-buffer": "^1.1.0", "tslib": "^2.5.0" } }, "sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"@better-auth/cli/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"@dotenvx/dotenvx/execa/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
|
||||
"@eslint/config-array/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
@@ -9580,6 +9656,14 @@
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"@opentelemetry/instrumentation-pg/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"@opentelemetry/instrumentation-redis/@opentelemetry/instrumentation/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="],
|
||||
|
||||
"@opentelemetry/instrumentation-tedious/@opentelemetry/instrumentation/import-in-the-middle/cjs-module-lexer": ["cjs-module-lexer@2.2.0", "", {}, "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ=="],
|
||||
@@ -9642,6 +9726,16 @@
|
||||
|
||||
"@types/bun/bun-types/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"@types/pg-pool/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"artillery-plugin-ensure/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"artillery-plugin-ensure/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
@@ -9878,6 +9972,16 @@
|
||||
|
||||
"run-jxa/execa/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
|
||||
"sdk-test/@types/pg/@types/node/undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
|
||||
|
||||
"sdk-test/@types/pg/pg-types/postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
||||
|
||||
"sdk-test/@types/pg/pg-types/postgres-bytea": ["postgres-bytea@1.0.1", "", {}, "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ=="],
|
||||
|
||||
"sdk-test/@types/pg/pg-types/postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
||||
|
||||
"sdk-test/@types/pg/pg-types/postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
||||
|
||||
"sdk-test/next/postcss/nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
|
||||
|
||||
"shadcn/cosmiconfig/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
@@ -112,9 +112,7 @@
|
||||
"setupci": "node scripts/setup/setupci.js",
|
||||
"replicate": "bun scripts/db/replicate.ts",
|
||||
"db:pull": "bun scripts/db/pull.ts",
|
||||
"db:push": " bun -F @autumn/shared db:push",
|
||||
"db:generate": "bun -F @autumn/shared db:generate",
|
||||
"db:migrate": " bun -F @autumn/shared db:migrate",
|
||||
"db": "bun scripts/db/index.ts",
|
||||
"test:integration": "cd server && bun test:integration",
|
||||
"exp": "sh -c 'infisical run --recursive --env=staging -- bun run server/experiments/$0'",
|
||||
"q": "lsof -ti:8080 -ti:3000 | xargs kill -9",
|
||||
|
||||
168
scripts/db/README.md
Normal file
168
scripts/db/README.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# `bun db` — Drizzle Migration CLI
|
||||
|
||||
Unified entrypoint for everything migration-related. Subcommands route through `scripts/db/index.ts`, which auto-wraps DB-touching subcommands in `infisical run` so `DATABASE_URL` is injected from the right secret environment.
|
||||
|
||||
## Surface
|
||||
|
||||
```
|
||||
bun db help # print usage
|
||||
bun db generate # write a new migration .sql from schema changes
|
||||
bun db migrate [--env=dev|staging|prod] # apply pending migrations to the target DB
|
||||
bun db migrate:dry [--env=dev|staging|prod] # preview pending SQL + safety checks, don't apply
|
||||
bun db mark-applied [--env=dev|staging|prod] # seed drizzle.__drizzle_migrations on an existing DB
|
||||
bun db rebase # auto-resolve a local migration that collided with origin/dev
|
||||
```
|
||||
|
||||
`migrate` and `migrate:dry` also run a safety check that **refuses to apply any pending migration containing `CREATE INDEX`, `DROP INDEX`, or `REINDEX` without `CONCURRENTLY`**. Those DDL statements take an ACCESS EXCLUSIVE lock and can block reads/writes on busy tables. To get through the check: either rewrite the SQL with `CONCURRENTLY` and apply manually + `mark-applied`, or add `.concurrently()` to the index in your schema and regenerate.
|
||||
|
||||
`--env` defaults to `dev`. `generate` and `rebase` never touch a DB and don't take `--env`.
|
||||
|
||||
---
|
||||
|
||||
## Day-to-day workflow
|
||||
|
||||
```bash
|
||||
# 1. Make a schema change in shared/db/**.ts or shared/models/**.ts
|
||||
# 2. Generate the migration
|
||||
bun db generate
|
||||
|
||||
# 3. Review the new shared/drizzle/{N}_*.sql and updated meta/.
|
||||
# Commit both with the code change in your PR.
|
||||
|
||||
# 4. Apply locally
|
||||
bun db migrate
|
||||
```
|
||||
|
||||
If your branch's migration collides with one that landed on `origin/dev` first (CI will tell you via duplicate-idx errors), pull and run:
|
||||
|
||||
```bash
|
||||
git pull origin dev
|
||||
bun db rebase # auto-renumbers your migration, regenerates against the new baseline
|
||||
```
|
||||
|
||||
`bun db rebase` is idempotent and bails out cleanly if drizzle-kit would need interactive input (e.g. column rename detection) — see the "Edge cases" section below.
|
||||
|
||||
---
|
||||
|
||||
## Bootstrapping a new DB
|
||||
|
||||
`bun db migrate` won't run against a DB that has the tables but no `drizzle.__drizzle_migrations` tracking row — it'd try to `CREATE TABLE` on tables that already exist and fail. Seed the tracking table first:
|
||||
|
||||
```bash
|
||||
bun db mark-applied # local dev DB
|
||||
bun db mark-applied --env=staging # if/when staging is wired up — see below
|
||||
bun db mark-applied --env=prod # if/when prod is wired up — see below
|
||||
```
|
||||
|
||||
Idempotent. Re-running is safe.
|
||||
|
||||
---
|
||||
|
||||
## Status: staging & prod are NOT wired into the CLI yet
|
||||
|
||||
**Right now, staging and prod migrations are still applied manually (paste the `.sql` into TablePlus per env).** The `--env=staging|prod` plumbing exists in the code and works, but we haven't:
|
||||
|
||||
1. Run `bun db mark-applied --env=staging` / `--env=prod` to seed the tracking table on those DBs.
|
||||
2. Switched the deploy pipeline to call `bun db migrate --env=…` automatically.
|
||||
|
||||
Until both happen, **do not run `bun db migrate --env=staging` or `--env=prod`** — without the mark-applied step, it will try to re-create existing tables and fail. (Failing safely, but failing.)
|
||||
|
||||
---
|
||||
|
||||
## Upgrade path: moving staging / prod into the CLI
|
||||
|
||||
When you're ready to flip from "TablePlus paste" to automated migrations on a shared env, the sequence is:
|
||||
|
||||
### One-time per env
|
||||
|
||||
1. **Confirm the env's secret name in infisical.** The CLI assumes:
|
||||
- `dev` → infisical env `dev`, `ENV_FILE=.env`
|
||||
- `staging` → infisical env `staging`, `ENV_FILE=.env.staging`
|
||||
- `prod` → infisical env `prod`, `ENV_FILE=.env.prod`
|
||||
|
||||
This mapping lives in `scripts/db/helpers/env.ts`. If your infisical env names diverge, update there.
|
||||
|
||||
2. **Confirm `DATABASE_URL` in that infisical env points at the right DB.** A wrong URL here means migrations apply to the wrong DB. Run:
|
||||
|
||||
```bash
|
||||
bun db mark-applied --env=<env>
|
||||
```
|
||||
|
||||
The first log line prints the host parsed from `DATABASE_URL` (e.g. `host=staging-pg.foo.com:5432`) — verify it before letting the script run further. Hit Ctrl-C if it's wrong; mark-applied does its writes after the log line.
|
||||
|
||||
3. **Run mark-applied.** Same command as step 2. It seeds `drizzle.__drizzle_migrations` with rows for every migration currently in `shared/drizzle/meta/_journal.json`, so `db migrate` will skip them.
|
||||
|
||||
4. **Verify migrate is a clean no-op.** This proves the seeding worked:
|
||||
|
||||
```bash
|
||||
bun db migrate --env=<env>
|
||||
```
|
||||
|
||||
Expected: drizzle-kit reports "applied successfully" with no DDL run, and `drizzle.__drizzle_migrations` has the same row count as before.
|
||||
|
||||
### Ongoing — moving the apply step from TablePlus to the CLI / CI
|
||||
|
||||
Once the bootstrap above is done for an env, you have two ways to apply new migrations:
|
||||
|
||||
- **Manual command**, same shape as dev:
|
||||
```bash
|
||||
bun db migrate --env=staging
|
||||
bun db migrate --env=prod
|
||||
```
|
||||
|
||||
- **CI-based** — call the same command from a deploy step. Two things to wire up in the pipeline:
|
||||
|
||||
1. The CI runner needs `infisical` installed and authenticated with credentials that can read the relevant env. Existing workflows that use `infisical run --env=…` are the precedent; copy that auth setup.
|
||||
2. Add a step like:
|
||||
```yaml
|
||||
- name: Apply DB migrations
|
||||
run: bun db migrate --env=prod
|
||||
```
|
||||
after the build step and before traffic is shifted to the new revision. If the migration fails, the deploy should halt — `bun db migrate` exits non-zero on any DDL failure.
|
||||
|
||||
Recommendation: **start with staging-only CI migration first**, run it for a week or two, and only then enable prod. Prod migration failures during a deploy are high-blast-radius and you want to be confident the pipeline works before you bet a deploy on it.
|
||||
|
||||
---
|
||||
|
||||
## File layout
|
||||
|
||||
```
|
||||
scripts/db/
|
||||
├── README.md # this file
|
||||
├── index.ts # subcommand dispatch
|
||||
├── commands/
|
||||
│ ├── help.ts
|
||||
│ ├── generate.ts # passthrough to `bun -F @autumn/shared db:generate`
|
||||
│ ├── migrate.ts # passthrough to `bun -F @autumn/shared db:migrate`
|
||||
│ ├── markApplied.ts # seeds drizzle.__drizzle_migrations
|
||||
│ └── rebase.ts # auto-resolves duplicate-idx conflicts
|
||||
├── helpers/
|
||||
│ ├── env.ts # --env parsing + infisical wrap + DATABASE_URL host extraction
|
||||
│ ├── paths.ts # canonical paths to shared/drizzle/ and meta/
|
||||
│ └── spawn.ts # thin child_process.spawn wrapper
|
||||
└── pull.ts # unrelated — customer data pull (legacy)
|
||||
```
|
||||
|
||||
`shared/package.json` still owns the implementation of `db:generate` and `db:migrate` (which are what the CLI shells out to under the hood). The unified `bun db` interface lives at the repo root.
|
||||
|
||||
---
|
||||
|
||||
## Edge cases
|
||||
|
||||
### `bun db rebase` bailed with "drizzle-kit needs interactive input"
|
||||
|
||||
This happens when the regeneration would prompt for a rename decision (column renamed, enum value reordered, etc.). The script restored your original files from a temp backup and exited non-zero. Recovery:
|
||||
|
||||
1. `bun db generate` directly in a terminal — answer the prompts.
|
||||
2. Drizzle will produce a new migration. If it has a duplicate idx with `origin/dev`, manually rename the `.sql` file and update the `idx` + `tag` in `meta/_journal.json`.
|
||||
3. Re-run `bun db rebase` to confirm the journal is now clean.
|
||||
|
||||
This is rare. ~95% of migrations (ADD COLUMN, DROP COLUMN, CREATE INDEX) auto-resolve cleanly.
|
||||
|
||||
### CI says "migration idx N already exists"
|
||||
|
||||
Someone else's PR with the same migration idx merged first. Run `bun db rebase` on your branch, push, re-run CI.
|
||||
|
||||
### "I deleted shared/drizzle/ by accident"
|
||||
|
||||
Pull from `origin/dev` to get it back. Your in-flight schema changes in TS are still intact; run `bun db generate` and it'll regenerate the migration.
|
||||
11
scripts/db/commands/generate.ts
Normal file
11
scripts/db/commands/generate.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { run } from "../helpers/spawn.ts";
|
||||
import { REPO_ROOT } from "../helpers/paths.ts";
|
||||
|
||||
export async function cmdGenerate(): Promise<void> {
|
||||
const { code } = await run(
|
||||
"bun",
|
||||
["-F", "@autumn/shared", "db:generate"],
|
||||
{ cwd: REPO_ROOT },
|
||||
);
|
||||
process.exit(code);
|
||||
}
|
||||
19
scripts/db/commands/help.ts
Normal file
19
scripts/db/commands/help.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export function cmdHelp(): void {
|
||||
const lines = [
|
||||
"",
|
||||
" bun db <subcommand> [--env=dev|staging|prod]",
|
||||
"",
|
||||
" Subcommands:",
|
||||
" help print this message",
|
||||
" generate write a new migration .sql file from schema changes",
|
||||
" migrate apply pending migrations to the target DB",
|
||||
" migrate:dry preview pending migrations (SQL + safety checks), don't apply",
|
||||
" mark-applied bootstrap drizzle.__drizzle_migrations on an existing DB",
|
||||
" rebase resolve a local migration that collided with one on origin/dev",
|
||||
"",
|
||||
" --env defaults to dev. migrate and mark-applied auto-wrap themselves",
|
||||
" in `infisical run` so DATABASE_URL is injected automatically.",
|
||||
"",
|
||||
];
|
||||
process.stdout.write(`${lines.join("\n")}\n`);
|
||||
}
|
||||
64
scripts/db/commands/markApplied.ts
Normal file
64
scripts/db/commands/markApplied.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { readMigrationFiles } from "drizzle-orm/migrator";
|
||||
import pg from "pg";
|
||||
import { MIGRATIONS_DIR } from "../helpers/paths.ts";
|
||||
import { type Env, targetHost, wrapInInfisical } from "../helpers/env.ts";
|
||||
|
||||
export async function cmdMarkApplied(env: Env): Promise<void> {
|
||||
await wrapInInfisical(env);
|
||||
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
if (!databaseUrl) {
|
||||
console.error("DATABASE_URL not set after infisical wrap");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[db:mark-applied] env=${env} host=${targetHost(databaseUrl)} migrations=${MIGRATIONS_DIR}`,
|
||||
);
|
||||
|
||||
const migrations = readMigrationFiles({ migrationsFolder: MIGRATIONS_DIR });
|
||||
if (migrations.length === 0) {
|
||||
console.log("no migrations on disk — nothing to mark");
|
||||
return;
|
||||
}
|
||||
|
||||
const client = new pg.Client({ connectionString: databaseUrl });
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
await client.query(`CREATE SCHEMA IF NOT EXISTS "drizzle"`);
|
||||
await client.query(`
|
||||
CREATE TABLE IF NOT EXISTS "drizzle"."__drizzle_migrations" (
|
||||
id SERIAL PRIMARY KEY,
|
||||
hash text NOT NULL,
|
||||
created_at bigint
|
||||
)
|
||||
`);
|
||||
|
||||
let marked = 0;
|
||||
let already = 0;
|
||||
for (const migration of migrations) {
|
||||
const existing = await client.query<{ id: number }>(
|
||||
`SELECT id FROM "drizzle"."__drizzle_migrations" WHERE hash = $1 LIMIT 1`,
|
||||
[migration.hash],
|
||||
);
|
||||
|
||||
if (existing.rowCount && existing.rowCount > 0) {
|
||||
console.log(` already applied hash=${migration.hash.slice(0, 12)}…`);
|
||||
already++;
|
||||
continue;
|
||||
}
|
||||
|
||||
await client.query(
|
||||
`INSERT INTO "drizzle"."__drizzle_migrations" ("hash", "created_at") VALUES ($1, $2)`,
|
||||
[migration.hash, migration.folderMillis],
|
||||
);
|
||||
console.log(` marked hash=${migration.hash.slice(0, 12)}… when=${migration.folderMillis}`);
|
||||
marked++;
|
||||
}
|
||||
|
||||
console.log(`done — marked=${marked} already=${already} total=${migrations.length}`);
|
||||
} finally {
|
||||
await client.end();
|
||||
}
|
||||
}
|
||||
132
scripts/db/commands/migrate.ts
Normal file
132
scripts/db/commands/migrate.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import pg from "pg";
|
||||
import { run } from "../helpers/spawn.ts";
|
||||
import { REPO_ROOT } from "../helpers/paths.ts";
|
||||
import { type Env, targetHost, wrapInInfisical } from "../helpers/env.ts";
|
||||
import {
|
||||
getPendingMigrations,
|
||||
type PendingMigration,
|
||||
} from "../helpers/pendingMigrations.ts";
|
||||
import {
|
||||
type BlockingStatement,
|
||||
findBlockingIndexStatements,
|
||||
} from "../helpers/safetyCheck.ts";
|
||||
|
||||
export async function cmdMigrate(
|
||||
env: Env,
|
||||
opts: { dryRun: boolean; bootstrap: boolean },
|
||||
): Promise<void> {
|
||||
await wrapInInfisical(env);
|
||||
|
||||
const databaseUrl = process.env.DATABASE_URL;
|
||||
if (!databaseUrl) {
|
||||
console.error("DATABASE_URL not set after infisical wrap");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const tags = [
|
||||
opts.dryRun ? "DRY" : null,
|
||||
opts.bootstrap ? "BOOTSTRAP" : null,
|
||||
].filter(Boolean);
|
||||
const tagStr = tags.length > 0 ? ` (${tags.join(" ")})` : "";
|
||||
console.log(`[db:migrate${tagStr}] env=${env} host=${targetHost(databaseUrl)}`);
|
||||
|
||||
if (opts.bootstrap) {
|
||||
console.log(
|
||||
"bootstrap mode: skipping index-DDL safety check (use only for fresh DBs)",
|
||||
);
|
||||
}
|
||||
|
||||
const client = new pg.Client({ connectionString: databaseUrl });
|
||||
await client.connect();
|
||||
let pending: PendingMigration[];
|
||||
try {
|
||||
pending = await getPendingMigrations(client);
|
||||
} finally {
|
||||
await client.end();
|
||||
}
|
||||
|
||||
if (pending.length === 0) {
|
||||
console.log("no pending migrations");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`${pending.length} pending migration(s):`);
|
||||
for (const migration of pending) {
|
||||
console.log(` ${migration.tag}`);
|
||||
}
|
||||
|
||||
const blockers = opts.bootstrap ? [] : collectBlockers(pending);
|
||||
|
||||
if (opts.dryRun) {
|
||||
console.log("");
|
||||
console.log("--- SQL preview ---");
|
||||
for (const migration of pending) {
|
||||
console.log("");
|
||||
console.log(`-- ${migration.tag}.sql --`);
|
||||
console.log(migration.sql);
|
||||
}
|
||||
console.log("");
|
||||
if (blockers.length > 0) {
|
||||
printBlockerError(blockers);
|
||||
console.log("dry-run: would refuse to apply.");
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(
|
||||
`dry-run: ok — \`bun db migrate --env=${env}\` would apply these.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockers.length > 0) {
|
||||
printBlockerError(blockers);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { code } = await run("bun", ["-F", "@autumn/shared", "db:migrate"], {
|
||||
cwd: REPO_ROOT,
|
||||
});
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
type FlaggedBlocker = {
|
||||
migration: PendingMigration;
|
||||
blocker: BlockingStatement;
|
||||
};
|
||||
|
||||
function collectBlockers(pending: PendingMigration[]): FlaggedBlocker[] {
|
||||
const all: FlaggedBlocker[] = [];
|
||||
for (const migration of pending) {
|
||||
for (const blocker of findBlockingIndexStatements(migration.sql)) {
|
||||
all.push({ migration, blocker });
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
function printBlockerError(blockers: FlaggedBlocker[]): void {
|
||||
console.error("");
|
||||
console.error(
|
||||
`refusing to apply ${blockers.length} index DDL statement(s) without CONCURRENTLY:`,
|
||||
);
|
||||
for (const { migration, blocker } of blockers) {
|
||||
console.error("");
|
||||
console.error(` in ${migration.tag}.sql [${blocker.kind}]`);
|
||||
const indented = blocker.statement
|
||||
.split("\n")
|
||||
.map((line) => ` ${line}`)
|
||||
.join("\n");
|
||||
console.error(indented);
|
||||
}
|
||||
console.error("");
|
||||
console.error(
|
||||
"Index DDL without CONCURRENTLY takes an ACCESS EXCLUSIVE lock that blocks reads/writes on the table.",
|
||||
);
|
||||
console.error("");
|
||||
console.error("Options:");
|
||||
console.error(
|
||||
" 1. Apply this migration manually (psql / TablePlus) with CONCURRENTLY, then `bun db mark-applied --env=<env>` to record it.",
|
||||
);
|
||||
console.error(
|
||||
" 2. If the table is fresh or empty, add `.concurrently()` to the index in shared/db schema, `bun db generate`, and re-try.",
|
||||
);
|
||||
}
|
||||
180
scripts/db/commands/rebase.ts
Normal file
180
scripts/db/commands/rebase.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import { mkdtempSync, copyFileSync, existsSync, rmSync, writeFileSync, readFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { run } from "../helpers/spawn.ts";
|
||||
import { REPO_ROOT, MIGRATIONS_DIR, META_DIR, JOURNAL_PATH } from "../helpers/paths.ts";
|
||||
|
||||
type JournalEntry = {
|
||||
idx: number;
|
||||
version: string;
|
||||
when: number;
|
||||
tag: string;
|
||||
breakpoints: boolean;
|
||||
};
|
||||
|
||||
type Journal = {
|
||||
version: string;
|
||||
dialect: string;
|
||||
entries: JournalEntry[];
|
||||
};
|
||||
|
||||
const REMOTE_REF = "origin/dev";
|
||||
|
||||
export async function cmdRebase(): Promise<void> {
|
||||
// 1. Bail on unresolved schema conflicts.
|
||||
const unmerged = await run("git", ["diff", "--name-only", "--diff-filter=U"], {
|
||||
cwd: REPO_ROOT,
|
||||
stdio: "pipe",
|
||||
});
|
||||
if (unmerged.code !== 0) {
|
||||
console.error(`git diff failed:\n${unmerged.stderr}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const schemaConflicts = unmerged.stdout
|
||||
.split("\n")
|
||||
.filter((line) => line.startsWith("shared/db/"));
|
||||
if (schemaConflicts.length > 0) {
|
||||
console.error(
|
||||
`unresolved schema conflicts — resolve these first:\n${schemaConflicts.map((f) => ` ${f}`).join("\n")}`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 2. Read local + remote journals.
|
||||
const localJournal = readLocalJournal();
|
||||
const remoteJournal = await readRemoteJournal();
|
||||
|
||||
if (!remoteJournal) {
|
||||
console.log(`nothing to rebase — could not read ${REMOTE_REF}:shared/drizzle/meta/_journal.json (no remote yet?)`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Find orphaned local entries — same idx as remote, but different tag/when.
|
||||
const remoteByIdx = new Map<number, JournalEntry>();
|
||||
for (const entry of remoteJournal.entries) remoteByIdx.set(entry.idx, entry);
|
||||
|
||||
const orphans: JournalEntry[] = [];
|
||||
for (const entry of localJournal.entries) {
|
||||
const remoteEntry = remoteByIdx.get(entry.idx);
|
||||
if (!remoteEntry) continue;
|
||||
if (remoteEntry.tag !== entry.tag || remoteEntry.when !== entry.when) {
|
||||
orphans.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (orphans.length === 0) {
|
||||
console.log("no migration conflicts — nothing to rebase");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`found ${orphans.length} orphaned local migration(s):`);
|
||||
for (const orphan of orphans) {
|
||||
console.log(` idx=${orphan.idx} tag=${orphan.tag}`);
|
||||
}
|
||||
|
||||
// 4. Back up the orphaned files.
|
||||
const backupDir = mkdtempSync(join(tmpdir(), "autumn-db-rebase-"));
|
||||
console.log(`backup dir: ${backupDir}`);
|
||||
|
||||
const backups: Array<{ src: string; backup: string }> = [];
|
||||
for (const orphan of orphans) {
|
||||
const sql = join(MIGRATIONS_DIR, `${orphan.tag}.sql`);
|
||||
const snapshot = join(META_DIR, `${formatIdx(orphan.idx)}_snapshot.json`);
|
||||
for (const src of [sql, snapshot]) {
|
||||
if (!existsSync(src)) continue;
|
||||
const backup = join(backupDir, src.replace(/[/\\]/g, "_"));
|
||||
copyFileSync(src, backup);
|
||||
backups.push({ src, backup });
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Delete orphans, then restore canonical journal + snapshots from origin/dev.
|
||||
for (const orphan of orphans) {
|
||||
const sql = join(MIGRATIONS_DIR, `${orphan.tag}.sql`);
|
||||
const snapshot = join(META_DIR, `${formatIdx(orphan.idx)}_snapshot.json`);
|
||||
if (existsSync(sql)) rmSync(sql);
|
||||
if (existsSync(snapshot)) rmSync(snapshot);
|
||||
}
|
||||
|
||||
const remoteJournalRaw = await gitShow(`${REMOTE_REF}:shared/drizzle/meta/_journal.json`);
|
||||
if (remoteJournalRaw === null) {
|
||||
restoreBackups(backups);
|
||||
console.error("failed to fetch remote journal — aborted, backups restored");
|
||||
process.exit(1);
|
||||
}
|
||||
writeFileSync(JOURNAL_PATH, remoteJournalRaw);
|
||||
|
||||
for (const orphan of orphans) {
|
||||
const snapshotPath = `${REMOTE_REF}:shared/drizzle/meta/${formatIdx(orphan.idx)}_snapshot.json`;
|
||||
const remoteEntry = remoteByIdx.get(orphan.idx);
|
||||
if (!remoteEntry) continue;
|
||||
const snapshotRaw = await gitShow(snapshotPath);
|
||||
if (snapshotRaw === null) {
|
||||
restoreBackups(backups);
|
||||
console.error(`failed to fetch ${snapshotPath} — aborted, backups restored`);
|
||||
process.exit(1);
|
||||
}
|
||||
writeFileSync(join(META_DIR, `${formatIdx(orphan.idx)}_snapshot.json`), snapshotRaw);
|
||||
}
|
||||
|
||||
// 6. Regenerate non-interactively. drizzle-kit reads stdin for rename prompts;
|
||||
// closing stdin makes it fail fast rather than hang.
|
||||
const generate = await run("bun", ["-F", "@autumn/shared", "db:generate"], {
|
||||
cwd: REPO_ROOT,
|
||||
stdio: "pipe",
|
||||
});
|
||||
|
||||
if (generate.code !== 0) {
|
||||
restoreBackups(backups);
|
||||
console.error("`db:generate` failed during rebase — backups restored.");
|
||||
console.error("");
|
||||
console.error("Likely cause: drizzle-kit needs interactive input (e.g. column rename detection).");
|
||||
console.error("Resolve manually:");
|
||||
console.error(" 1. Run `bun db:generate` directly in a terminal and answer prompts.");
|
||||
console.error(" 2. If a duplicate-idx file is produced, delete it and re-run.");
|
||||
console.error("");
|
||||
console.error("drizzle-kit stderr:");
|
||||
console.error(generate.stderr);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(generate.stdout);
|
||||
|
||||
// 7. Stage everything for the engineer.
|
||||
await run("git", ["add", "shared/drizzle/"], { cwd: REPO_ROOT });
|
||||
|
||||
console.log("");
|
||||
console.log("rebase complete — review the regenerated migration and commit.");
|
||||
console.log(`backup retained at: ${backupDir}`);
|
||||
}
|
||||
|
||||
function readLocalJournal(): Journal {
|
||||
const raw = readFileSync(JOURNAL_PATH, "utf8");
|
||||
return JSON.parse(raw) as Journal;
|
||||
}
|
||||
|
||||
async function readRemoteJournal(): Promise<Journal | null> {
|
||||
const raw = await gitShow(`${REMOTE_REF}:shared/drizzle/meta/_journal.json`);
|
||||
if (raw === null) return null;
|
||||
return JSON.parse(raw) as Journal;
|
||||
}
|
||||
|
||||
async function gitShow(ref: string): Promise<string | null> {
|
||||
const result = await run("git", ["show", ref], { cwd: REPO_ROOT, stdio: "pipe" });
|
||||
if (result.code !== 0) return null;
|
||||
return result.stdout;
|
||||
}
|
||||
|
||||
function restoreBackups(backups: Array<{ src: string; backup: string }>): void {
|
||||
for (const { src, backup } of backups) {
|
||||
try {
|
||||
copyFileSync(backup, src);
|
||||
} catch {
|
||||
// best-effort restore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function formatIdx(idx: number): string {
|
||||
return idx.toString().padStart(4, "0");
|
||||
}
|
||||
84
scripts/db/helpers/env.ts
Normal file
84
scripts/db/helpers/env.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
export type Env = "dev" | "staging" | "prod";
|
||||
|
||||
const VALID_ENVS: readonly Env[] = ["dev", "staging", "prod"] as const;
|
||||
|
||||
export function parseEnv(argv: readonly string[]): Env {
|
||||
for (const arg of argv) {
|
||||
if (arg.startsWith("--env=")) {
|
||||
const value = arg.slice("--env=".length);
|
||||
if (!VALID_ENVS.includes(value as Env)) {
|
||||
console.error(
|
||||
`invalid --env=${value}, must be one of: ${VALID_ENVS.join(", ")}`,
|
||||
);
|
||||
process.exit(2);
|
||||
}
|
||||
return value as Env;
|
||||
}
|
||||
}
|
||||
return "dev";
|
||||
}
|
||||
|
||||
const ENV_FILE: Record<Env, string> = {
|
||||
dev: ".env",
|
||||
staging: ".env.staging",
|
||||
prod: ".env.prod",
|
||||
};
|
||||
|
||||
/**
|
||||
* If not already inside an infisical-wrapped context, re-exec this process
|
||||
* wrapped in `infisical run --env=<env> --recursive --` so DATABASE_URL is
|
||||
* injected from the right secret environment. Returns true if we re-exec'd
|
||||
* (caller should exit); false if already wrapped (caller should proceed).
|
||||
*/
|
||||
export async function wrapInInfisical(env: Env): Promise<boolean> {
|
||||
if (process.env.AUTUMN_DB_WRAPPED === "1") return false;
|
||||
|
||||
if (process.env.AUTUMN_DB_DIRECT === "1") {
|
||||
if (!process.env.DATABASE_URL) {
|
||||
console.error(
|
||||
"AUTUMN_DB_DIRECT=1 but DATABASE_URL not set — caller must inject the URL when bypassing infisical",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const args = [
|
||||
"run",
|
||||
`--env=${env}`,
|
||||
"--recursive",
|
||||
"--",
|
||||
"bun",
|
||||
...process.argv.slice(1),
|
||||
];
|
||||
|
||||
const child = spawn("infisical", args, {
|
||||
stdio: "inherit",
|
||||
env: {
|
||||
...process.env,
|
||||
AUTUMN_DB_WRAPPED: "1",
|
||||
ENV_FILE: ENV_FILE[env],
|
||||
},
|
||||
});
|
||||
|
||||
const code: number = await new Promise((resolve) => {
|
||||
child.on("close", (c) => resolve(c ?? 1));
|
||||
child.on("error", (err) => {
|
||||
console.error(`failed to spawn infisical: ${err.message}`);
|
||||
resolve(1);
|
||||
});
|
||||
});
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
export function targetHost(databaseUrl: string | undefined): string {
|
||||
if (!databaseUrl) return "<DATABASE_URL not set>";
|
||||
try {
|
||||
const url = new URL(databaseUrl);
|
||||
return url.host;
|
||||
} catch {
|
||||
return "<unparseable DATABASE_URL>";
|
||||
}
|
||||
}
|
||||
9
scripts/db/helpers/paths.ts
Normal file
9
scripts/db/helpers/paths.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export const REPO_ROOT = resolve(here, "../../..");
|
||||
export const MIGRATIONS_DIR = resolve(REPO_ROOT, "shared/drizzle");
|
||||
export const META_DIR = resolve(MIGRATIONS_DIR, "meta");
|
||||
export const JOURNAL_PATH = resolve(META_DIR, "_journal.json");
|
||||
55
scripts/db/helpers/pendingMigrations.ts
Normal file
55
scripts/db/helpers/pendingMigrations.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import type pg from "pg";
|
||||
import { JOURNAL_PATH, MIGRATIONS_DIR } from "./paths.ts";
|
||||
|
||||
export type JournalEntry = {
|
||||
idx: number;
|
||||
version: string;
|
||||
when: number;
|
||||
tag: string;
|
||||
breakpoints: boolean;
|
||||
};
|
||||
|
||||
export type PendingMigration = JournalEntry & {
|
||||
sql: string;
|
||||
sqlPath: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns migrations on disk that haven't been recorded in drizzle.__drizzle_migrations yet.
|
||||
* Mirrors drizzle-kit's filter: anything in _journal.json whose `when` is greater than the
|
||||
* largest `created_at` already in the tracking table.
|
||||
*/
|
||||
export async function getPendingMigrations(
|
||||
client: pg.Client,
|
||||
): Promise<PendingMigration[]> {
|
||||
await client.query(`CREATE SCHEMA IF NOT EXISTS "drizzle"`);
|
||||
await client.query(`
|
||||
CREATE TABLE IF NOT EXISTS "drizzle"."__drizzle_migrations" (
|
||||
id SERIAL PRIMARY KEY,
|
||||
hash text NOT NULL,
|
||||
created_at bigint
|
||||
)
|
||||
`);
|
||||
|
||||
const result = await client.query<{ created_at: string | null }>(
|
||||
`SELECT created_at FROM "drizzle"."__drizzle_migrations" ORDER BY created_at DESC LIMIT 1`,
|
||||
);
|
||||
const lastApplied =
|
||||
result.rowCount && result.rowCount > 0 && result.rows[0].created_at !== null
|
||||
? Number(result.rows[0].created_at)
|
||||
: null;
|
||||
|
||||
const journal = JSON.parse(readFileSync(JOURNAL_PATH, "utf8")) as {
|
||||
entries: JournalEntry[];
|
||||
};
|
||||
|
||||
return journal.entries
|
||||
.filter((entry) => lastApplied === null || entry.when > lastApplied)
|
||||
.map((entry) => {
|
||||
const sqlPath = join(MIGRATIONS_DIR, `${entry.tag}.sql`);
|
||||
const sql = readFileSync(sqlPath, "utf8");
|
||||
return { ...entry, sql, sqlPath };
|
||||
});
|
||||
}
|
||||
26
scripts/db/helpers/safetyCheck.ts
Normal file
26
scripts/db/helpers/safetyCheck.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
const INDEX_DDL = /^\s*(CREATE\s+(UNIQUE\s+)?INDEX|DROP\s+INDEX|REINDEX)\b/i;
|
||||
const HAS_CONCURRENTLY = /\bCONCURRENTLY\b/i;
|
||||
|
||||
export type BlockingStatement = {
|
||||
kind: "CREATE INDEX" | "DROP INDEX" | "REINDEX";
|
||||
statement: string;
|
||||
};
|
||||
|
||||
export function findBlockingIndexStatements(sql: string): BlockingStatement[] {
|
||||
const blockers: BlockingStatement[] = [];
|
||||
const statements = sql.split("--> statement-breakpoint");
|
||||
for (const raw of statements) {
|
||||
const trimmed = raw.trim();
|
||||
if (!trimmed) continue;
|
||||
if (!INDEX_DDL.test(trimmed)) continue;
|
||||
if (HAS_CONCURRENTLY.test(trimmed)) continue;
|
||||
const upper = trimmed.toUpperCase();
|
||||
const kind: BlockingStatement["kind"] = upper.startsWith("CREATE")
|
||||
? "CREATE INDEX"
|
||||
: upper.startsWith("DROP")
|
||||
? "DROP INDEX"
|
||||
: "REINDEX";
|
||||
blockers.push({ kind, statement: trimmed });
|
||||
}
|
||||
return blockers;
|
||||
}
|
||||
46
scripts/db/helpers/spawn.ts
Normal file
46
scripts/db/helpers/spawn.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
export type RunOptions = {
|
||||
cwd?: string;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
stdio?: "inherit" | "pipe";
|
||||
};
|
||||
|
||||
export type RunResult = {
|
||||
code: number;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
};
|
||||
|
||||
export function run(
|
||||
cmd: string,
|
||||
args: readonly string[],
|
||||
options: RunOptions = {},
|
||||
): Promise<RunResult> {
|
||||
const { cwd, env, stdio = "inherit" } = options;
|
||||
return new Promise((resolve) => {
|
||||
const child = spawn(cmd, [...args], {
|
||||
cwd,
|
||||
env: env ?? process.env,
|
||||
stdio: stdio === "inherit" ? "inherit" : ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
if (stdio === "pipe") {
|
||||
child.stdout?.on("data", (chunk: Buffer) => {
|
||||
stdout += chunk.toString();
|
||||
});
|
||||
child.stderr?.on("data", (chunk: Buffer) => {
|
||||
stderr += chunk.toString();
|
||||
});
|
||||
}
|
||||
|
||||
child.on("close", (code) => {
|
||||
resolve({ code: code ?? 1, stdout, stderr });
|
||||
});
|
||||
child.on("error", (err) => {
|
||||
resolve({ code: 1, stdout, stderr: stderr + err.message });
|
||||
});
|
||||
});
|
||||
}
|
||||
46
scripts/db/index.ts
Normal file
46
scripts/db/index.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { cmdHelp } from "./commands/help.ts";
|
||||
import { cmdGenerate } from "./commands/generate.ts";
|
||||
import { cmdMigrate } from "./commands/migrate.ts";
|
||||
import { cmdMarkApplied } from "./commands/markApplied.ts";
|
||||
import { cmdRebase } from "./commands/rebase.ts";
|
||||
import { parseEnv } from "./helpers/env.ts";
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const sub = process.argv[2];
|
||||
const rest = process.argv.slice(3);
|
||||
|
||||
if (!sub || sub === "help" || sub === "--help" || sub === "-h") {
|
||||
cmdHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (sub) {
|
||||
case "generate":
|
||||
await cmdGenerate();
|
||||
return;
|
||||
case "migrate":
|
||||
await cmdMigrate(parseEnv(rest), {
|
||||
dryRun: false,
|
||||
bootstrap: rest.includes("--bootstrap"),
|
||||
});
|
||||
return;
|
||||
case "migrate:dry":
|
||||
await cmdMigrate(parseEnv(rest), {
|
||||
dryRun: true,
|
||||
bootstrap: rest.includes("--bootstrap"),
|
||||
});
|
||||
return;
|
||||
case "mark-applied":
|
||||
await cmdMarkApplied(parseEnv(rest));
|
||||
return;
|
||||
case "rebase":
|
||||
await cmdRebase();
|
||||
return;
|
||||
default:
|
||||
console.error(`unknown subcommand: ${sub}`);
|
||||
cmdHelp();
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
await main();
|
||||
@@ -1,71 +1,33 @@
|
||||
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { sh, fatal, log } from "./shell.ts";
|
||||
import { SHARED_DIR, PROJECT_ROOT } from "../constants.ts";
|
||||
import { sh, shInherit, fatal, log } from "./shell.ts";
|
||||
import { PROJECT_ROOT } from "../constants.ts";
|
||||
|
||||
export function listSqlFiles(dir: string): string[] {
|
||||
if (!existsSync(dir)) return [];
|
||||
return readdirSync(dir).filter((f) => f.endsWith(".sql"));
|
||||
}
|
||||
|
||||
export function writeTempDrizzleConfig(outDir: string): string {
|
||||
const tmp = join(SHARED_DIR, `.dw-${process.pid}.config.ts`);
|
||||
const content = `import { defineConfig } from "drizzle-kit";\nexport default defineConfig({\n\tdialect: "postgresql",\n\tout: ${JSON.stringify(outDir)},\n\tschema: "./db/schema.ts",\n\tdbCredentials: { url: process.env.DATABASE_URL! },\n});\n`;
|
||||
writeFileSync(tmp, content);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
export function generateAndApplyMigration(
|
||||
/**
|
||||
* Brings a freshly-provisioned Neon branch up to the canonical schema.
|
||||
*
|
||||
* Strategy: invoke the shared `bun db migrate --bootstrap` CLI with the new
|
||||
* branch's DATABASE_URL injected directly (bypassing infisical). `--bootstrap`
|
||||
* skips the index-DDL safety check, which is safe here because the DB is empty
|
||||
* and has no concurrent traffic.
|
||||
*/
|
||||
export function applyCommittedMigrations(
|
||||
branchName: string,
|
||||
databaseUrl: string,
|
||||
): void {
|
||||
// Use the worktree's own shared/drizzle/ as the migration dir (matches
|
||||
// drizzle.config.ts out: "./drizzle"). Empty it first so the baseline
|
||||
// generated for this fresh Neon branch isn't a diff against the canonical
|
||||
// repo's migration history — subsequent `bun db:generate` runs then emit
|
||||
// clean incrementals against this worktree's actual DB state.
|
||||
const outDir = join(SHARED_DIR, "drizzle");
|
||||
if (existsSync(outDir)) rmSync(outDir, { recursive: true, force: true });
|
||||
mkdirSync(outDir, { recursive: true });
|
||||
log(`applying committed migrations to ${branchName}`);
|
||||
|
||||
const drizzleConfigPath = writeTempDrizzleConfig(outDir);
|
||||
try {
|
||||
log(`generating initial migration for ${branchName}`);
|
||||
const gen = sh(
|
||||
"bunx",
|
||||
["drizzle-kit", "generate", "--config", drizzleConfigPath],
|
||||
{
|
||||
cwd: SHARED_DIR,
|
||||
env: {
|
||||
...(process.env as Record<string, string>),
|
||||
NODE_OPTIONS: "--import tsx",
|
||||
},
|
||||
},
|
||||
);
|
||||
if (gen.code !== 0) {
|
||||
fatal(`drizzle-kit generate failed:\n${gen.stdout}\n${gen.stderr}`);
|
||||
}
|
||||
const code = shInherit("bun", ["db", "migrate", "--bootstrap"], {
|
||||
cwd: PROJECT_ROOT,
|
||||
env: {
|
||||
...(process.env as Record<string, string>),
|
||||
DATABASE_URL: databaseUrl,
|
||||
AUTUMN_DB_DIRECT: "1",
|
||||
},
|
||||
});
|
||||
|
||||
const sqlFiles = listSqlFiles(outDir);
|
||||
if (sqlFiles.length === 0) {
|
||||
fatal(`no .sql files generated in ${outDir}`);
|
||||
}
|
||||
|
||||
log(`applying ${sqlFiles.length} migration file(s) to ${branchName}`);
|
||||
for (const f of sqlFiles) {
|
||||
const p = join(outDir, f);
|
||||
const sqlBody = readFileSync(p, "utf-8");
|
||||
const mig = sh("psql", [databaseUrl, "-v", "ON_ERROR_STOP=1"], {
|
||||
stdin: sqlBody,
|
||||
});
|
||||
if (mig.code !== 0) {
|
||||
fatal(
|
||||
`applying migration ${f} failed:\n${mig.stdout}\n${mig.stderr}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (existsSync(drizzleConfigPath)) rmSync(drizzleConfigPath);
|
||||
if (code !== 0) {
|
||||
fatal(`bun db migrate --bootstrap failed for ${branchName} (exit ${code})`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
connectionString,
|
||||
findBranchByName,
|
||||
} from "./neon.ts";
|
||||
import { generateAndApplyMigration, loadDbFunctions } from "./migration.ts";
|
||||
import { applyCommittedMigrations, loadDbFunctions } from "./migration.ts";
|
||||
import { loadRegistry, saveRegistry } from "./registry.ts";
|
||||
import { PROJECT_ROOT, NEON_TEMPLATE_BRANCH } from "../constants.ts";
|
||||
import type { RegistryEntry } from "../types.ts";
|
||||
@@ -36,7 +36,7 @@ export async function setupAgentWorktree(
|
||||
const branch = createBranch(branchName, NEON_TEMPLATE_BRANCH);
|
||||
// Use direct (non-pooled) URL for DDL; pooler can interfere with some DDL paths.
|
||||
const directUrl = connectionString(branchName, { pooled: false });
|
||||
generateAndApplyMigration(branchName, directUrl);
|
||||
applyCommittedMigrations(branchName, directUrl);
|
||||
loadDbFunctions(branchName, directUrl);
|
||||
// Pooled URL for runtime.
|
||||
const pooledUrl = connectionString(branchName, { pooled: true });
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
"ioredis": "^5.10.0",
|
||||
"inquirer": "^12.6.3",
|
||||
"p-limit": "^7.2.0",
|
||||
"pg": "8.20.0",
|
||||
"react": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.3.11",
|
||||
"@types/pg": "8.11.10",
|
||||
"@types/react": "^18.3.1",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "^5.7.3"
|
||||
|
||||
882
shared/drizzle/0000_bumpy_tinkerer.sql
Normal file
882
shared/drizzle/0000_bumpy_tinkerer.sql
Normal file
@@ -0,0 +1,882 @@
|
||||
CREATE TABLE "account" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"account_id" text NOT NULL,
|
||||
"provider_id" text NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"access_token" text,
|
||||
"refresh_token" text,
|
||||
"id_token" text,
|
||||
"access_token_expires_at" timestamp,
|
||||
"refresh_token_expires_at" timestamp,
|
||||
"scope" text,
|
||||
"password" text,
|
||||
"created_at" timestamp with time zone NOT NULL,
|
||||
"updated_at" timestamp with time zone NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "account" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "actions" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"request_id" text NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"org_slug" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"customer_id" text,
|
||||
"internal_customer_id" text,
|
||||
"entity_id" text,
|
||||
"internal_entity_id" text,
|
||||
"type" text NOT NULL,
|
||||
"auth_type" text NOT NULL,
|
||||
"method" text NOT NULL,
|
||||
"path" text NOT NULL,
|
||||
"timestamp" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"properties" jsonb
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "actions" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "api_keys" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"name" text,
|
||||
"prefix" text,
|
||||
"org_id" text,
|
||||
"user_id" text,
|
||||
"env" text,
|
||||
"hashed_key" text,
|
||||
"meta" jsonb,
|
||||
"scopes" jsonb,
|
||||
CONSTRAINT "api_keys_hashed_key_key" UNIQUE("hashed_key")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "auto_topup_limit_states" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"customer_id" text NOT NULL,
|
||||
"feature_id" text NOT NULL,
|
||||
"purchase_window_ends_at" numeric NOT NULL,
|
||||
"purchase_count" numeric DEFAULT 0 NOT NULL,
|
||||
"attempt_window_ends_at" numeric NOT NULL,
|
||||
"attempt_count" numeric DEFAULT 0 NOT NULL,
|
||||
"failed_attempt_window_ends_at" numeric NOT NULL,
|
||||
"failed_attempt_count" numeric DEFAULT 0 NOT NULL,
|
||||
"last_attempt_at" numeric,
|
||||
"last_failed_attempt_at" numeric,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"updated_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "chat_results" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric,
|
||||
"data" jsonb NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "chat_results" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "checkouts" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"customer_id" text NOT NULL,
|
||||
"action" text NOT NULL,
|
||||
"params" jsonb NOT NULL,
|
||||
"params_version" integer DEFAULT 0 NOT NULL,
|
||||
"status" text DEFAULT 'pending' NOT NULL,
|
||||
"response" jsonb,
|
||||
"stripe_invoice_id" text,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"expires_at" numeric NOT NULL,
|
||||
"completed_at" numeric
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customer_entitlements" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"customer_product_id" text,
|
||||
"entitlement_id" text NOT NULL,
|
||||
"internal_customer_id" text COLLATE "C" NOT NULL,
|
||||
"internal_entity_id" text,
|
||||
"internal_feature_id" text NOT NULL,
|
||||
"unlimited" boolean DEFAULT false,
|
||||
"balance" numeric DEFAULT 0 NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"next_reset_at" numeric,
|
||||
"usage_allowed" boolean DEFAULT false,
|
||||
"adjustment" numeric,
|
||||
"additional_balance" numeric DEFAULT 0 NOT NULL,
|
||||
"entities" jsonb,
|
||||
"expires_at" numeric,
|
||||
"cache_version" integer DEFAULT 0,
|
||||
"customer_id" text,
|
||||
"feature_id" text,
|
||||
"external_id" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customer_prices" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"price_id" text,
|
||||
"options" jsonb,
|
||||
"internal_customer_id" text,
|
||||
"customer_product_id" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customer_products" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"internal_product_id" text NOT NULL,
|
||||
"internal_entity_id" text,
|
||||
"created_at" numeric,
|
||||
"updated_at" numeric,
|
||||
"status" text,
|
||||
"processor" jsonb,
|
||||
"canceled" boolean DEFAULT false,
|
||||
"canceled_at" numeric,
|
||||
"ended_at" numeric,
|
||||
"starts_at" numeric,
|
||||
"access_starts_at" numeric,
|
||||
"options" jsonb[],
|
||||
"product_id" text,
|
||||
"free_trial_id" text,
|
||||
"trial_ends_at" numeric,
|
||||
"billing_cycle_anchor_resets_at" numeric,
|
||||
"collection_method" text DEFAULT 'charge_automatically',
|
||||
"subscription_ids" text[],
|
||||
"scheduled_ids" text[],
|
||||
"quantity" numeric DEFAULT 1,
|
||||
"is_custom" boolean DEFAULT false NOT NULL,
|
||||
"customer_id" text,
|
||||
"entity_id" text,
|
||||
"billing_version" text,
|
||||
"api_version" numeric,
|
||||
"api_semver" text,
|
||||
"external_id" text,
|
||||
"stripe_checkout_session_id" text,
|
||||
"previous_customer_product_id" text,
|
||||
"on_trial_end" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "customers" (
|
||||
"internal_id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"name" text,
|
||||
"id" text,
|
||||
"email" text,
|
||||
"fingerprint" text DEFAULT null,
|
||||
"metadata" jsonb,
|
||||
"env" text NOT NULL,
|
||||
"processor" jsonb,
|
||||
"processors" jsonb DEFAULT '{}'::jsonb,
|
||||
"send_email_receipts" boolean DEFAULT false,
|
||||
"auto_topups" jsonb,
|
||||
"spend_limits" jsonb,
|
||||
"usage_alerts" jsonb,
|
||||
"overage_allowed" jsonb,
|
||||
"config" jsonb DEFAULT '{}'::jsonb,
|
||||
CONSTRAINT "cus_id_constraint" UNIQUE("org_id","id","env")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "customers" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "entities" (
|
||||
"id" text,
|
||||
"org_id" text,
|
||||
"created_at" numeric NOT NULL,
|
||||
"internal_id" text PRIMARY KEY NOT NULL,
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"env" text,
|
||||
"name" text,
|
||||
"deleted" boolean DEFAULT false NOT NULL,
|
||||
"internal_feature_id" text,
|
||||
"spend_limits" jsonb,
|
||||
"usage_alerts" jsonb,
|
||||
"overage_allowed" jsonb,
|
||||
"feature_id" text,
|
||||
CONSTRAINT "entity_id_constraint" UNIQUE("org_id","env","internal_customer_id","id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "entitlements" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"internal_feature_id" text NOT NULL,
|
||||
"internal_product_id" text,
|
||||
"internal_reward_id" text,
|
||||
"is_custom" boolean DEFAULT false,
|
||||
"allowance_type" text,
|
||||
"allowance" numeric,
|
||||
"interval" text,
|
||||
"interval_count" numeric DEFAULT 1,
|
||||
"carry_from_previous" boolean DEFAULT false,
|
||||
"entity_feature_id" text DEFAULT null,
|
||||
"org_id" text,
|
||||
"feature_id" text,
|
||||
"usage_limit" numeric,
|
||||
"expiry_duration" text,
|
||||
"expiry_length" numeric,
|
||||
"rollover" jsonb,
|
||||
CONSTRAINT "entitlements_id_key" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "events" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"org_slug" text NOT NULL,
|
||||
"internal_customer_id" text,
|
||||
"env" text NOT NULL,
|
||||
"created_at" bigint,
|
||||
"timestamp" timestamp with time zone,
|
||||
"event_name" text NOT NULL,
|
||||
"idempotency_key" text DEFAULT null,
|
||||
"value" numeric,
|
||||
"set_usage" boolean DEFAULT false,
|
||||
"entity_id" text,
|
||||
"internal_entity_id" text,
|
||||
"internal_product_id" text,
|
||||
"customer_id" text NOT NULL,
|
||||
"properties" jsonb,
|
||||
"deductions" jsonb,
|
||||
CONSTRAINT "unique_event_constraint" UNIQUE("org_id","env","customer_id","event_name","idempotency_key")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "features" (
|
||||
"internal_id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"created_at" numeric,
|
||||
"env" text,
|
||||
"id" text NOT NULL,
|
||||
"name" text,
|
||||
"type" text NOT NULL,
|
||||
"config" jsonb,
|
||||
"display" jsonb DEFAULT null,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"event_names" text[] DEFAULT '{}',
|
||||
CONSTRAINT "feature_id_constraint" UNIQUE("org_id","id","env")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "free_trials" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"internal_product_id" text,
|
||||
"duration" text DEFAULT 'day',
|
||||
"length" numeric,
|
||||
"unique_fingerprint" boolean,
|
||||
"is_custom" boolean DEFAULT false,
|
||||
"card_required" boolean DEFAULT false,
|
||||
"on_end" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "invitation" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"organization_id" text NOT NULL,
|
||||
"email" text NOT NULL,
|
||||
"role" text,
|
||||
"status" text DEFAULT 'pending' NOT NULL,
|
||||
"created_at" timestamp with time zone NOT NULL,
|
||||
"expires_at" timestamp with time zone NOT NULL,
|
||||
"inviter_id" text NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "invitation" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "invoice_line_items" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"invoice_id" text,
|
||||
"stripe_id" text,
|
||||
"stripe_invoice_id" text,
|
||||
"stripe_invoice_item_id" text,
|
||||
"stripe_subscription_item_id" text,
|
||||
"stripe_product_id" text,
|
||||
"stripe_price_id" text,
|
||||
"stripe_discountable" boolean DEFAULT true NOT NULL,
|
||||
"amount" numeric NOT NULL,
|
||||
"amount_after_discounts" numeric NOT NULL,
|
||||
"currency" text DEFAULT 'usd' NOT NULL,
|
||||
"stripe_quantity" numeric,
|
||||
"total_quantity" numeric,
|
||||
"paid_quantity" numeric,
|
||||
"description" text NOT NULL,
|
||||
"description_source" text,
|
||||
"direction" text NOT NULL,
|
||||
"billing_timing" text,
|
||||
"prorated" boolean DEFAULT false NOT NULL,
|
||||
"price_id" text,
|
||||
"customer_product_ids" jsonb DEFAULT '[]'::jsonb NOT NULL,
|
||||
"customer_price_ids" jsonb DEFAULT '[]'::jsonb NOT NULL,
|
||||
"customer_entitlement_ids" jsonb DEFAULT '[]'::jsonb NOT NULL,
|
||||
"internal_product_id" text,
|
||||
"product_id" text,
|
||||
"internal_feature_id" text,
|
||||
"feature_id" text,
|
||||
"effective_period_start" numeric,
|
||||
"effective_period_end" numeric,
|
||||
"discounts" jsonb[] DEFAULT '{}',
|
||||
CONSTRAINT "invoice_line_items_stripe_id_unique" UNIQUE("stripe_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "invoices" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"product_ids" text[] DEFAULT '{}',
|
||||
"internal_product_ids" text[] DEFAULT '{}',
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"internal_entity_id" text,
|
||||
"stripe_id" text NOT NULL,
|
||||
"processor_type" text,
|
||||
"status" text DEFAULT 'draft' NOT NULL,
|
||||
"hosted_invoice_url" text,
|
||||
"total" numeric DEFAULT 0 NOT NULL,
|
||||
"amount_paid" numeric,
|
||||
"refunded_amount" numeric DEFAULT 0 NOT NULL,
|
||||
"currency" text DEFAULT 'usd' NOT NULL,
|
||||
"discounts" jsonb[] DEFAULT '{}',
|
||||
"items" jsonb[] DEFAULT '{}',
|
||||
CONSTRAINT "invoices_stripe_id_key" UNIQUE("stripe_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "jwks" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"public_key" text NOT NULL,
|
||||
"private_key" text NOT NULL,
|
||||
"created_at" timestamp with time zone NOT NULL,
|
||||
"expires_at" timestamp with time zone
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "jwks" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "member" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"organization_id" text NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"role" text DEFAULT 'member' NOT NULL,
|
||||
"created_at" timestamp with time zone NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "member" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "metadata" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"expires_at" numeric,
|
||||
"data" jsonb,
|
||||
"type" text,
|
||||
"stripe_invoice_id" text,
|
||||
"stripe_checkout_session_id" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "migration_errors" (
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"migration_job_id" text NOT NULL,
|
||||
"created_at" numeric,
|
||||
"updated_at" numeric,
|
||||
"data" jsonb,
|
||||
"message" text,
|
||||
"code" text,
|
||||
CONSTRAINT "migration_errors_pkey" PRIMARY KEY("internal_customer_id","migration_job_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "migration_item_runs" (
|
||||
"migration_item_run_id" text PRIMARY KEY NOT NULL,
|
||||
"migration_internal_id" text NOT NULL,
|
||||
"migration_run_id" text,
|
||||
"dry_run" boolean DEFAULT false NOT NULL,
|
||||
"item_kind" text NOT NULL,
|
||||
"item_id" text NOT NULL,
|
||||
"status" text NOT NULL,
|
||||
"timestamp" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"updated_at" numeric
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "migration_jobs" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"updated_at" numeric,
|
||||
"current_step" text,
|
||||
"from_internal_product_id" text,
|
||||
"to_internal_product_id" text,
|
||||
"step_details" jsonb
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "migration_runs" (
|
||||
"internal_id" text PRIMARY KEY NOT NULL,
|
||||
"migration_internal_id" text NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"status" text NOT NULL,
|
||||
"dry_run" boolean NOT NULL,
|
||||
"lazy_run" boolean DEFAULT false NOT NULL,
|
||||
"trigger_run_id" text,
|
||||
"error_message" text,
|
||||
"only_ids" text[],
|
||||
"created_at" numeric NOT NULL,
|
||||
"updated_at" numeric,
|
||||
"started_at" numeric,
|
||||
"finished_at" numeric
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "migrations" (
|
||||
"internal_id" text PRIMARY KEY NOT NULL,
|
||||
"id" text NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"filter" jsonb,
|
||||
"operations" jsonb,
|
||||
"prepared_state" jsonb,
|
||||
"no_billing_changes" boolean,
|
||||
"retry_failed" boolean DEFAULT false NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
"updated_at" numeric
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "oauth_access_token" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"token" text,
|
||||
"client_id" text NOT NULL,
|
||||
"session_id" text,
|
||||
"user_id" text,
|
||||
"reference_id" text,
|
||||
"refresh_id" text,
|
||||
"expires_at" timestamp with time zone,
|
||||
"created_at" timestamp with time zone,
|
||||
"scopes" text[] NOT NULL,
|
||||
CONSTRAINT "oauth_access_token_token_unique" UNIQUE("token")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "oauth_access_token" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "oauth_client" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"client_id" text NOT NULL,
|
||||
"client_secret" text,
|
||||
"disabled" boolean DEFAULT false,
|
||||
"skip_consent" boolean,
|
||||
"enable_end_session" boolean,
|
||||
"scopes" text[],
|
||||
"user_id" text,
|
||||
"created_at" timestamp with time zone,
|
||||
"updated_at" timestamp with time zone,
|
||||
"name" text,
|
||||
"uri" text,
|
||||
"icon" text,
|
||||
"contacts" text[],
|
||||
"tos" text,
|
||||
"policy" text,
|
||||
"software_id" text,
|
||||
"software_version" text,
|
||||
"software_statement" text,
|
||||
"redirect_uris" text[] NOT NULL,
|
||||
"post_logout_redirect_uris" text[],
|
||||
"token_endpoint_auth_method" text,
|
||||
"grant_types" text[],
|
||||
"response_types" text[],
|
||||
"public" boolean,
|
||||
"type" text,
|
||||
"reference_id" text,
|
||||
"metadata" jsonb,
|
||||
CONSTRAINT "oauth_client_client_id_unique" UNIQUE("client_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "oauth_client" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "oauth_consent" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"client_id" text NOT NULL,
|
||||
"user_id" text,
|
||||
"reference_id" text,
|
||||
"scopes" text[] NOT NULL,
|
||||
"created_at" timestamp with time zone,
|
||||
"updated_at" timestamp with time zone
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "oauth_consent" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "oauth_refresh_token" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"token" text NOT NULL,
|
||||
"client_id" text NOT NULL,
|
||||
"session_id" text,
|
||||
"user_id" text NOT NULL,
|
||||
"reference_id" text,
|
||||
"expires_at" timestamp with time zone,
|
||||
"created_at" timestamp with time zone,
|
||||
"revoked" timestamp with time zone,
|
||||
"scopes" text[] NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "oauth_refresh_token" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "organizations" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"slug" text NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"logo" text,
|
||||
"createdAt" timestamp with time zone NOT NULL,
|
||||
"metadata" text,
|
||||
"default_currency" text DEFAULT 'usd',
|
||||
"stripe_connected" boolean DEFAULT false,
|
||||
"stripe_config" jsonb,
|
||||
"test_stripe_connect" jsonb DEFAULT '{}'::jsonb,
|
||||
"live_stripe_connect" jsonb DEFAULT '{}'::jsonb,
|
||||
"processor_configs" jsonb,
|
||||
"test_pkey" text,
|
||||
"live_pkey" text,
|
||||
"svix_config" jsonb DEFAULT '{}'::jsonb,
|
||||
"created_at" numeric,
|
||||
"config" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
"created_by" text,
|
||||
"onboarded" boolean DEFAULT false,
|
||||
"deployed" boolean DEFAULT false,
|
||||
"redis_config" jsonb,
|
||||
CONSTRAINT "organizations_slug_unique" UNIQUE("slug"),
|
||||
CONSTRAINT "organizations_test_pkey_key" UNIQUE("test_pkey"),
|
||||
CONSTRAINT "organizations_live_pkey_key" UNIQUE("live_pkey")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "prices" (
|
||||
"id" text COLLATE "C" PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"internal_product_id" text NOT NULL,
|
||||
"config" jsonb,
|
||||
"created_at" numeric NOT NULL,
|
||||
"billing_type" text,
|
||||
"tier_behavior" text DEFAULT null,
|
||||
"is_custom" boolean DEFAULT false,
|
||||
"entitlement_id" text DEFAULT null,
|
||||
"proration_config" jsonb DEFAULT null,
|
||||
CONSTRAINT "prices_id_key" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "products" (
|
||||
"internal_id" text PRIMARY KEY NOT NULL,
|
||||
"id" text NOT NULL,
|
||||
"name" text,
|
||||
"description" text,
|
||||
"org_id" text NOT NULL,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"is_add_on" boolean DEFAULT false NOT NULL,
|
||||
"is_default" boolean DEFAULT false NOT NULL,
|
||||
"group" text DEFAULT '',
|
||||
"version" numeric DEFAULT 1 NOT NULL,
|
||||
"processor" jsonb DEFAULT null,
|
||||
"base_variant_id" text,
|
||||
"archived" boolean DEFAULT false NOT NULL,
|
||||
"config" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
CONSTRAINT "unique_product" UNIQUE("org_id","id","env","version")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "referral_codes" (
|
||||
"code" text NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"internal_customer_id" text COLLATE "C",
|
||||
"internal_reward_program_id" text,
|
||||
"id" text NOT NULL,
|
||||
"created_at" numeric,
|
||||
CONSTRAINT "referral_codes_pkey" PRIMARY KEY("code","org_id","env"),
|
||||
CONSTRAINT "referral_codes_id_key" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "replaceables" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"cus_ent_id" text NOT NULL,
|
||||
"created_at" bigint NOT NULL,
|
||||
"from_entity_id" text,
|
||||
"delete_next_cycle" boolean DEFAULT false NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "replaceables" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "revenuecat_mappings" (
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"autumn_product_id" text NOT NULL,
|
||||
"revenuecat_product_ids" text[] DEFAULT '{}' NOT NULL,
|
||||
CONSTRAINT "revenuecat_mappings_pkey" PRIMARY KEY("org_id","env","autumn_product_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "reward_programs" (
|
||||
"internal_id" text PRIMARY KEY NOT NULL,
|
||||
"id" text,
|
||||
"created_at" numeric,
|
||||
"internal_reward_id" text,
|
||||
"max_redemptions" numeric,
|
||||
"unlimited_redemptions" boolean DEFAULT false,
|
||||
"org_id" text,
|
||||
"env" text,
|
||||
"when" text DEFAULT 'immediately',
|
||||
"product_ids" text[] DEFAULT '{""}',
|
||||
"exclude_trial" boolean DEFAULT false,
|
||||
"received_by" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "reward_redemptions" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"created_at" numeric,
|
||||
"updated_at" numeric,
|
||||
"internal_customer_id" text COLLATE "C",
|
||||
"triggered" boolean,
|
||||
"internal_reward_program_id" text,
|
||||
"applied" boolean DEFAULT false,
|
||||
"redeemer_applied" boolean DEFAULT false,
|
||||
"referral_code_id" text,
|
||||
"reward_internal_id" text,
|
||||
"promo_code" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "rewards" (
|
||||
"internal_id" text PRIMARY KEY NOT NULL,
|
||||
"id" text,
|
||||
"org_id" text,
|
||||
"env" text,
|
||||
"created_at" numeric,
|
||||
"name" text,
|
||||
"discount_config" jsonb,
|
||||
"free_product_config" jsonb,
|
||||
"free_product_id" text,
|
||||
"promo_codes" jsonb[],
|
||||
"type" text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "rollovers" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"cus_ent_id" text NOT NULL,
|
||||
"balance" numeric NOT NULL,
|
||||
"expires_at" numeric,
|
||||
"usage" numeric DEFAULT 0 NOT NULL,
|
||||
"entities" jsonb DEFAULT '{}'::jsonb NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "rollovers" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "phases" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"schedule_id" text NOT NULL,
|
||||
"starts_at" numeric NOT NULL,
|
||||
"customer_product_ids" text[] DEFAULT '{}' NOT NULL,
|
||||
"created_at" numeric NOT NULL,
|
||||
CONSTRAINT "phases_schedule_id_starts_at_key" UNIQUE("schedule_id","starts_at")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "schedules" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"internal_customer_id" text NOT NULL,
|
||||
"customer_id" text NOT NULL,
|
||||
"internal_entity_id" text,
|
||||
"entity_id" text,
|
||||
"created_at" numeric NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "session" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"expires_at" timestamp with time zone NOT NULL,
|
||||
"token" text NOT NULL,
|
||||
"created_at" timestamp with time zone NOT NULL,
|
||||
"updated_at" timestamp with time zone NOT NULL,
|
||||
"ip_address" text,
|
||||
"user_agent" text,
|
||||
"user_id" text NOT NULL,
|
||||
"impersonated_by" text,
|
||||
"active_organization_id" text,
|
||||
"city" text,
|
||||
"country" text,
|
||||
CONSTRAINT "session_token_unique" UNIQUE("token")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "session" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
CREATE TABLE "subscriptions" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"stripe_id" text,
|
||||
"stripe_schedule_id" text,
|
||||
"created_at" numeric DEFAULT ROUND(date_part('epoch', NOW()) * 1000)::BIGINT NOT NULL,
|
||||
"metadata" jsonb DEFAULT '{}'::jsonb,
|
||||
"usage_features" text[] DEFAULT '{}',
|
||||
"env" text,
|
||||
"current_period_start" numeric,
|
||||
"current_period_end" numeric,
|
||||
CONSTRAINT "subscriptions_stripe_id_key" UNIQUE("stripe_id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "user" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"email" text NOT NULL,
|
||||
"email_verified" boolean NOT NULL,
|
||||
"image" text,
|
||||
"created_at" timestamp with time zone NOT NULL,
|
||||
"updated_at" timestamp with time zone NOT NULL,
|
||||
"role" text,
|
||||
"banned" boolean,
|
||||
"ban_reason" text,
|
||||
"ban_expires" timestamp with time zone,
|
||||
"created_by" text,
|
||||
"last_active_at" timestamp with time zone,
|
||||
CONSTRAINT "user_email_unique" UNIQUE("email")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "vercel_resources" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"org_id" text NOT NULL,
|
||||
"env" text NOT NULL,
|
||||
"installation_id" text NOT NULL,
|
||||
"name" text NOT NULL,
|
||||
"status" text NOT NULL,
|
||||
"metadata" jsonb DEFAULT '{}'::jsonb NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "verification" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"identifier" text NOT NULL,
|
||||
"value" text NOT NULL,
|
||||
"expires_at" timestamp with time zone NOT NULL,
|
||||
"created_at" timestamp with time zone,
|
||||
"updated_at" timestamp with time zone
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "verification" ENABLE ROW LEVEL SECURITY;--> statement-breakpoint
|
||||
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "actions" ADD CONSTRAINT "actions_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "actions" ADD CONSTRAINT "actions_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "actions" ADD CONSTRAINT "actions_entity_id_fkey" FOREIGN KEY ("internal_entity_id") REFERENCES "public"."entities"("internal_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "api_keys" ADD CONSTRAINT "api_keys_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "auto_topup_limit_states" ADD CONSTRAINT "auto_topup_limits_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "auto_topup_limit_states" ADD CONSTRAINT "auto_topup_limits_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_entitlements" ADD CONSTRAINT "entitlements_internal_feature_id_fkey" FOREIGN KEY ("internal_feature_id") REFERENCES "public"."features"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_entitlements" ADD CONSTRAINT "customer_entitlements_internal_entity_id_fkey" FOREIGN KEY ("internal_entity_id") REFERENCES "public"."entities"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_entitlements" ADD CONSTRAINT "customer_entitlements_customer_product_id_fkey" FOREIGN KEY ("customer_product_id") REFERENCES "public"."customer_products"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "customer_entitlements" ADD CONSTRAINT "customer_entitlements_entitlement_id_fkey" FOREIGN KEY ("entitlement_id") REFERENCES "public"."entitlements"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "customer_prices" ADD CONSTRAINT "customer_prices_customer_product_id_fkey" FOREIGN KEY ("customer_product_id") REFERENCES "public"."customer_products"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_prices" ADD CONSTRAINT "customer_prices_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_prices" ADD CONSTRAINT "customer_prices_price_id_fkey" FOREIGN KEY ("price_id") REFERENCES "public"."prices"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_products" ADD CONSTRAINT "customer_products_free_trial_id_fkey" FOREIGN KEY ("free_trial_id") REFERENCES "public"."free_trials"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_products" ADD CONSTRAINT "customer_products_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "customer_products" ADD CONSTRAINT "customer_products_internal_product_id_fkey" FOREIGN KEY ("internal_product_id") REFERENCES "public"."products"("internal_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customer_products" ADD CONSTRAINT "customer_products_internal_entity_id_fkey" FOREIGN KEY ("internal_entity_id") REFERENCES "public"."entities"("internal_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "customers" ADD CONSTRAINT "customers_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entities" ADD CONSTRAINT "entities_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entities" ADD CONSTRAINT "entities_internal_feature_id_fkey" FOREIGN KEY ("internal_feature_id") REFERENCES "public"."features"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entities" ADD CONSTRAINT "entities_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entitlements" ADD CONSTRAINT "entitlements_internal_feature_id_fkey" FOREIGN KEY ("internal_feature_id") REFERENCES "public"."features"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "entitlements" ADD CONSTRAINT "entitlements_internal_product_id_fkey" FOREIGN KEY ("internal_product_id") REFERENCES "public"."products"("internal_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "entitlements" ADD CONSTRAINT "entitlements_internal_reward_id_fkey" FOREIGN KEY ("internal_reward_id") REFERENCES "public"."rewards"("internal_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "events" ADD CONSTRAINT "events_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "features" ADD CONSTRAINT "features_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "free_trials" ADD CONSTRAINT "free_trials_internal_product_id_fkey" FOREIGN KEY ("internal_product_id") REFERENCES "public"."products"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invitation" ADD CONSTRAINT "invitation_inviter_id_user_id_fk" FOREIGN KEY ("inviter_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invoice_line_items" ADD CONSTRAINT "invoice_line_items_invoice_id_fkey" FOREIGN KEY ("invoice_id") REFERENCES "public"."invoices"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invoices" ADD CONSTRAINT "invoices_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "invoices" ADD CONSTRAINT "invoices_internal_entity_id_fkey" FOREIGN KEY ("internal_entity_id") REFERENCES "public"."entities"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "member" ADD CONSTRAINT "member_organization_id_organizations_id_fk" FOREIGN KEY ("organization_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "member" ADD CONSTRAINT "member_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_errors" ADD CONSTRAINT "migration_customers_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_errors" ADD CONSTRAINT "migration_customers_migration_job_id_fkey" FOREIGN KEY ("migration_job_id") REFERENCES "public"."migration_jobs"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_jobs" ADD CONSTRAINT "migration_jobs_from_internal_product_id_fkey" FOREIGN KEY ("from_internal_product_id") REFERENCES "public"."products"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_jobs" ADD CONSTRAINT "migration_jobs_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_jobs" ADD CONSTRAINT "migration_jobs_to_internal_product_id_fkey" FOREIGN KEY ("to_internal_product_id") REFERENCES "public"."products"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_runs" ADD CONSTRAINT "migration_runs_migration_internal_id_fkey" FOREIGN KEY ("migration_internal_id") REFERENCES "public"."migrations"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migration_runs" ADD CONSTRAINT "migration_runs_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "migrations" ADD CONSTRAINT "migrations_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_access_token" ADD CONSTRAINT "oauth_access_token_client_id_oauth_client_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauth_client"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_access_token" ADD CONSTRAINT "oauth_access_token_session_id_session_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."session"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_access_token" ADD CONSTRAINT "oauth_access_token_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_access_token" ADD CONSTRAINT "oauth_access_token_refresh_id_oauth_refresh_token_id_fk" FOREIGN KEY ("refresh_id") REFERENCES "public"."oauth_refresh_token"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_client" ADD CONSTRAINT "oauth_client_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_consent" ADD CONSTRAINT "oauth_consent_client_id_oauth_client_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauth_client"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_consent" ADD CONSTRAINT "oauth_consent_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_refresh_token" ADD CONSTRAINT "oauth_refresh_token_client_id_oauth_client_client_id_fk" FOREIGN KEY ("client_id") REFERENCES "public"."oauth_client"("client_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_refresh_token" ADD CONSTRAINT "oauth_refresh_token_session_id_session_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."session"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "oauth_refresh_token" ADD CONSTRAINT "oauth_refresh_token_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "prices" ADD CONSTRAINT "prices_entitlement_id_fkey" FOREIGN KEY ("entitlement_id") REFERENCES "public"."entitlements"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "prices" ADD CONSTRAINT "prices_internal_product_id_fkey" FOREIGN KEY ("internal_product_id") REFERENCES "public"."products"("internal_id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "products" ADD CONSTRAINT "products_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "referral_codes" ADD CONSTRAINT "referral_codes_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "referral_codes" ADD CONSTRAINT "referral_codes_internal_reward_program_id_fkey" FOREIGN KEY ("internal_reward_program_id") REFERENCES "public"."reward_programs"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "referral_codes" ADD CONSTRAINT "referral_codes_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "replaceables" ADD CONSTRAINT "replaceables_cus_ent_id_fkey" FOREIGN KEY ("cus_ent_id") REFERENCES "public"."customer_entitlements"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "revenuecat_mappings" ADD CONSTRAINT "revenuecat_mappings_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "reward_programs" ADD CONSTRAINT "reward_triggers_internal_reward_id_fkey" FOREIGN KEY ("internal_reward_id") REFERENCES "public"."rewards"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "reward_programs" ADD CONSTRAINT "reward_triggers_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "reward_redemptions" ADD CONSTRAINT "reward_redemptions_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "reward_redemptions" ADD CONSTRAINT "reward_redemptions_internal_reward_program_id_fkey" FOREIGN KEY ("internal_reward_program_id") REFERENCES "public"."reward_programs"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "reward_redemptions" ADD CONSTRAINT "reward_redemptions_referral_code_id_fkey" FOREIGN KEY ("referral_code_id") REFERENCES "public"."referral_codes"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "rewards" ADD CONSTRAINT "coupons_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "rollovers" ADD CONSTRAINT "rollover_cus_ent_id_fkey" FOREIGN KEY ("cus_ent_id") REFERENCES "public"."customer_entitlements"("id") ON DELETE cascade ON UPDATE cascade;--> statement-breakpoint
|
||||
ALTER TABLE "phases" ADD CONSTRAINT "phases_schedule_id_fkey" FOREIGN KEY ("schedule_id") REFERENCES "public"."schedules"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "schedules" ADD CONSTRAINT "schedules_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "schedules" ADD CONSTRAINT "schedules_internal_customer_id_fkey" FOREIGN KEY ("internal_customer_id") REFERENCES "public"."customers"("internal_id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "schedules" ADD CONSTRAINT "schedules_internal_entity_id_fkey" FOREIGN KEY ("internal_entity_id") REFERENCES "public"."entities"("internal_id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "subscriptions" ADD CONSTRAINT "subscriptions_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "user" ADD CONSTRAINT "user_created_by_fkey" FOREIGN KEY ("created_by") REFERENCES "public"."organizations"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "vercel_resources" ADD CONSTRAINT "vercel_resources_org_id_fkey" FOREIGN KEY ("org_id") REFERENCES "public"."organizations"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "account_userId_idx" ON "account" USING btree ("user_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_actions_on_internal_entity_id" ON "actions" USING btree ("internal_entity_id");--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "auto_topup_limits_org_env_internal_customer_feature_unique" ON "auto_topup_limit_states" USING btree ("org_id","env","internal_customer_id","feature_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_checkouts_stripe_invoice_id" ON "checkouts" USING btree ("stripe_invoice_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_product_id" ON "customer_entitlements" USING btree ("customer_product_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_internal_customer_id" ON "customer_entitlements" USING hash ("internal_customer_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_internal_customer_id_btree" ON "customer_entitlements" USING btree ("internal_customer_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_entitlement_id" ON "customer_entitlements" USING btree ("entitlement_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_internal_entity_id" ON "customer_entitlements" USING hash ("internal_entity_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_on_next_reset_at" ON "customer_entitlements" USING btree ("next_reset_at");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_entitlements_loose_customer_expires" ON "customer_entitlements" USING btree ("internal_customer_id","expires_at") WHERE "customer_entitlements"."customer_product_id" IS NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_prices_product_id" ON "customer_prices" USING btree ("customer_product_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_prices_price_id" ON "customer_prices" USING btree ("price_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_products_customer_status" ON "customer_products" USING btree ("internal_customer_id","status");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_products_on_internal_entity_id" ON "customer_products" USING btree ("internal_entity_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_products_on_internal_product_id" ON "customer_products" USING btree ("internal_product_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_products_subscription_ids" ON "customer_products" USING gin ("subscription_ids");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_products_scheduled_ids" ON "customer_products" USING gin ("scheduled_ids");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customer_products_stripe_checkout_session_id" ON "customer_products" USING btree ("stripe_checkout_session_id");--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "customers_email_null_id_unique" ON "customers" USING btree ("org_id","env",lower("email")) WHERE "customers"."id" IS NULL AND "customers"."email" IS NOT NULL AND "customers"."email" != '';--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_org_env_fingerprint" ON "customers" USING btree ("org_id","env","fingerprint") WHERE "customers"."fingerprint" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_processor_id" ON "customers" USING btree (("processor" ->> 'id'));--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_composite" ON "customers" USING btree ("org_id","env","id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_org_env_internal_id" ON "customers" USING btree ("org_id","env","internal_id" DESC);--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_email_trgm" ON "customers" USING gin ("email" gin_trgm_ops) WHERE "customers"."email" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_name_trgm" ON "customers" USING gin ("name" gin_trgm_ops) WHERE "customers"."name" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_id_trgm" ON "customers" USING gin ("id" gin_trgm_ops) WHERE "customers"."id" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_org_id_env_created_at" ON "customers" USING btree ("org_id","env","created_at" DESC);--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_processors_revenuecat" ON "customers" USING btree (("processors" ->> 'revenuecat'));--> statement-breakpoint
|
||||
CREATE INDEX "idx_customers_processors_vercel" ON "customers" USING btree (("processors" ->> 'vercel'));--> statement-breakpoint
|
||||
CREATE INDEX "idx_entities_internal_customer_id" ON "entities" USING btree ("internal_customer_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_entities_customer_internal_desc" ON "entities" USING btree ("internal_customer_id","internal_id" DESC);--> statement-breakpoint
|
||||
CREATE INDEX "idx_entities_org_env_id" ON "entities" USING btree ("org_id","env","id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_entitlements_internal_product_id" ON "entitlements" USING btree ("internal_product_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_entitlements_internal_reward_id" ON "entitlements" USING btree ("internal_reward_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_entitlements_reward_feature" ON "entitlements" USING btree ("internal_reward_id","internal_feature_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_events_internal_customer_id" ON "events" USING btree ("internal_customer_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_events_internal_entity_id" ON "events" USING btree ("internal_entity_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_events_customer_non_usage_ts" ON "events" USING btree ("internal_customer_id","timestamp" DESC,"id" DESC) WHERE "events"."set_usage" = false;--> statement-breakpoint
|
||||
CREATE INDEX "idx_free_trials_internal_product_id" ON "free_trials" USING btree ("internal_product_id");--> statement-breakpoint
|
||||
CREATE INDEX "invitation_organizationId_idx" ON "invitation" USING btree ("organization_id");--> statement-breakpoint
|
||||
CREATE INDEX "invitation_email_idx" ON "invitation" USING btree ("email");--> statement-breakpoint
|
||||
CREATE INDEX "idx_invoices_customer_created" ON "invoices" USING btree ("internal_customer_id","created_at" DESC,"id" DESC);--> statement-breakpoint
|
||||
CREATE INDEX "member_organizationId_idx" ON "member" USING btree ("organization_id");--> statement-breakpoint
|
||||
CREATE INDEX "member_userId_idx" ON "member" USING btree ("user_id");--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "migration_item_runs_live_unique" ON "migration_item_runs" USING btree ("migration_internal_id","item_kind","item_id") WHERE "migration_item_runs"."dry_run" = false;--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "migration_item_runs_dry_run_unique" ON "migration_item_runs" USING btree ("migration_internal_id","migration_run_id","item_kind","item_id") WHERE "migration_item_runs"."dry_run" = true;--> statement-breakpoint
|
||||
CREATE INDEX "migration_item_runs_customer_recent_idx" ON "migration_item_runs" USING btree ("item_id","updated_at" DESC) WHERE "migration_item_runs"."item_kind" = 'customer';--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "migration_runs_active_per_migration_unique" ON "migration_runs" USING btree ("migration_internal_id") WHERE "migration_runs"."status" IN ('queued', 'running');--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "migrations_org_env_id_unique" ON "migrations" USING btree ("org_id","env","id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_organizations_name_trgm" ON "organizations" USING gin ("name" gin_trgm_ops) WHERE "organizations"."name" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_organizations_slug_trgm" ON "organizations" USING gin ("slug" gin_trgm_ops) WHERE "organizations"."slug" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_organizations_created_at_id" ON "organizations" USING btree ("createdAt" DESC,"id" DESC);--> statement-breakpoint
|
||||
CREATE INDEX "idx_prices_internal_product_id" ON "prices" USING btree ("internal_product_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_prices_entitlement_id" ON "prices" USING btree ("entitlement_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_products_org_env_id_version" ON "products" USING btree ("org_id","env","id","version");--> statement-breakpoint
|
||||
CREATE INDEX "idx_referral_codes_internal_customer_id" ON "referral_codes" USING btree ("internal_customer_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_replaceables_cus_ent_id" ON "replaceables" USING btree ("cus_ent_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_reward_redemptions_referral_code_id" ON "reward_redemptions" USING btree ("referral_code_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_reward_redemptions_reward_internal_id" ON "reward_redemptions" USING btree ("reward_internal_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_reward_redemptions_customer_reward" ON "reward_redemptions" USING btree ("internal_customer_id","reward_internal_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_rollovers_cus_ent_id" ON "rollovers" USING btree ("cus_ent_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_rollovers_cus_ent_expires" ON "rollovers" USING btree ("cus_ent_id","expires_at");--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "schedules_customer_scope_unique" ON "schedules" USING btree ("org_id","env","internal_customer_id") WHERE "schedules"."internal_entity_id" IS NULL;--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX "schedules_entity_scope_unique" ON "schedules" USING btree ("org_id","env","internal_customer_id","internal_entity_id") WHERE "schedules"."internal_entity_id" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_schedules_internal_customer_id" ON "schedules" USING btree ("internal_customer_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_schedules_internal_entity_id" ON "schedules" USING btree ("internal_entity_id");--> statement-breakpoint
|
||||
CREATE INDEX "session_userId_idx" ON "session" USING btree ("user_id");--> statement-breakpoint
|
||||
CREATE INDEX "idx_user_name_trgm" ON "user" USING gin ("name" gin_trgm_ops) WHERE "user"."name" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_user_email_trgm" ON "user" USING gin ("email" gin_trgm_ops) WHERE "user"."email" IS NOT NULL;--> statement-breakpoint
|
||||
CREATE INDEX "idx_user_created_at_id" ON "user" USING btree ("created_at" DESC,"id" DESC);--> statement-breakpoint
|
||||
CREATE INDEX "verification_identifier_idx" ON "verification" USING btree ("identifier");
|
||||
6667
shared/drizzle/meta/0000_snapshot.json
Normal file
6667
shared/drizzle/meta/0000_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
13
shared/drizzle/meta/_journal.json
Normal file
13
shared/drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "7",
|
||||
"when": 1779096275848,
|
||||
"tag": "0000_bumpy_tinkerer",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user