nomkit 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE.txt +21 -0
  2. package/dist/_virtual/_rolldown/runtime.js +27 -0
  3. package/dist/adapters/index.d.ts +15 -0
  4. package/dist/adapters/index.js +6 -0
  5. package/dist/cli/commands/push.d.ts +6 -0
  6. package/dist/cli/commands/push.js +143 -0
  7. package/dist/cli/index.d.ts +4 -0
  8. package/dist/cli/index.js +18 -0
  9. package/dist/cli/lib/collection_sync.d.ts +107 -0
  10. package/dist/cli/lib/collection_sync.js +158 -0
  11. package/dist/cli/lib/config_loader.d.ts +15 -0
  12. package/dist/cli/lib/config_loader.js +43 -0
  13. package/dist/cli/lib/hash.d.ts +22 -0
  14. package/dist/cli/lib/hash.js +63 -0
  15. package/dist/cli/lib/migrations.d.ts +6 -0
  16. package/dist/cli/lib/migrations.js +17 -0
  17. package/dist/client/index.d.ts +13 -0
  18. package/dist/client/index.js +34 -0
  19. package/dist/core/nomba_api/banks.d.ts +14 -0
  20. package/dist/core/nomba_api/banks.js +0 -0
  21. package/dist/core/nomba_api/charge-tokenized-card.d.ts +33 -0
  22. package/dist/core/nomba_api/charge-tokenized-card.js +0 -0
  23. package/dist/core/nomba_api/checkout.d.ts +44 -0
  24. package/dist/core/nomba_api/checkout.js +0 -0
  25. package/dist/core/nomba_api/get_checkout.d.ts +57 -0
  26. package/dist/core/nomba_api/get_checkout.js +0 -0
  27. package/dist/core/nomba_api/index.d.ts +313 -0
  28. package/dist/core/nomba_api/index.js +179 -0
  29. package/dist/core/nomba_api/lib/utils.d.ts +235 -0
  30. package/dist/core/nomba_api/lib/utils.js +313 -0
  31. package/dist/core/nomba_api/list-tokenized-cards.d.ts +24 -0
  32. package/dist/core/nomba_api/list-tokenized-cards.js +0 -0
  33. package/dist/core/nomba_api/token-manager/index.d.ts +51 -0
  34. package/dist/core/nomba_api/token-manager/index.js +109 -0
  35. package/dist/core/pg_db/index.d.ts +108 -0
  36. package/dist/core/pg_db/index.js +76 -0
  37. package/dist/core/pg_db/migrations/20260703085901_wealthy_blacklash/migration.sql +120 -0
  38. package/dist/core/pg_db/migrations/20260703085901_wealthy_blacklash/snapshot.json +1616 -0
  39. package/dist/core/pg_db/relations.d.ts +46 -0
  40. package/dist/core/pg_db/relations.js +83 -0
  41. package/dist/core/pg_db/schema.d.ts +1138 -0
  42. package/dist/core/pg_db/schema.js +124 -0
  43. package/dist/endpoints/customers/api.js +51 -0
  44. package/dist/endpoints/entitlements/api.js +42 -0
  45. package/dist/endpoints/routes.d.ts +15 -0
  46. package/dist/endpoints/routes.js +15 -0
  47. package/dist/endpoints/subscriptions/api.js +263 -0
  48. package/dist/endpoints/subscriptions/utils.js +105 -0
  49. package/dist/endpoints/webhooks/invoice/api.js +28 -0
  50. package/dist/endpoints/webhooks/nomba/api.js +76 -0
  51. package/dist/endpoints/webhooks/nomba/utils.js +36 -0
  52. package/dist/index.d.ts +204 -0
  53. package/dist/index.js +175 -0
  54. package/dist/lib/utils.d.ts +21 -0
  55. package/dist/lib/utils.js +41 -0
  56. package/dist/node_modules/.pnpm/@better-fetch_fetch@1.3.1/node_modules/@better-fetch/fetch/dist/index.js +475 -0
  57. package/dist/package.js +4 -0
  58. package/dist/queue/backends/pglite/backend.d.ts +43 -0
  59. package/dist/queue/backends/pglite/backend.js +33 -0
  60. package/dist/queue/backends/pglite/index.d.ts +4 -0
  61. package/dist/queue/backends/pglite/index.js +4 -0
  62. package/dist/queue/backends/pglite/migrations/schema.d.ts +4 -0
  63. package/dist/queue/backends/pglite/migrations/schema.js +37 -0
  64. package/dist/queue/backends/pglite/notification-channel.d.ts +17 -0
  65. package/dist/queue/backends/pglite/notification-channel.js +61 -0
  66. package/dist/queue/backends/pglite/repository.d.ts +38 -0
  67. package/dist/queue/backends/pglite/repository.js +299 -0
  68. package/dist/queue/backends/redis/index.d.ts +7 -0
  69. package/dist/queue/backends/redis/index.js +1 -0
  70. package/dist/queue/client/index.d.ts +12 -0
  71. package/dist/queue/client/index.js +31 -0
  72. package/dist/queue/endpoints/api.d.ts +53 -0
  73. package/dist/queue/endpoints/api.js +45 -0
  74. package/dist/queue/endpoints/routes.d.ts +32 -0
  75. package/dist/queue/endpoints/routes.js +5 -0
  76. package/dist/queue/init.d.ts +27 -0
  77. package/dist/queue/init.js +31 -0
  78. package/dist/queue/lib/billing.d.ts +25 -0
  79. package/dist/queue/lib/billing.js +87 -0
  80. package/dist/queue/lib/utils.d.ts +30 -0
  81. package/dist/queue/lib/utils.js +35 -0
  82. package/package.json +71 -0
@@ -0,0 +1,109 @@
1
+ import ms from "ms";
2
+ import { Temporal } from "temporal-polyfill";
3
+ //#region core/nomba_api/token-manager/index.ts
4
+ var TokenManager = class {
5
+ baseUrl;
6
+ accountId;
7
+ clientId;
8
+ clientSecret;
9
+ accessToken = null;
10
+ refreshToken = null;
11
+ expiresAt = null;
12
+ refreshTimer = null;
13
+ constructor(options) {
14
+ if (!options.baseUrl) throw new Error("Token manager requires a baseURL");
15
+ this.baseUrl = options.baseUrl;
16
+ this.accountId = options.accountId;
17
+ this.clientId = options.clientId;
18
+ this.clientSecret = options.clientSecret;
19
+ }
20
+ /**
21
+ * Initializes authentication.
22
+ * Call this once during application startup.
23
+ */
24
+ async initialize() {
25
+ await this.obtainAccessToken();
26
+ }
27
+ /**
28
+ * Returns the latest access token.
29
+ */
30
+ async getAccessToken() {
31
+ if (!this.accessToken) await this.initialize();
32
+ return this.accessToken;
33
+ }
34
+ /**
35
+ * Returns the latest refresh token.
36
+ */
37
+ async getRefreshToken() {
38
+ if (!this.refreshToken) await this.initialize();
39
+ return this.refreshToken;
40
+ }
41
+ /**
42
+ * Stops automatic refreshing.
43
+ */
44
+ dispose() {
45
+ if (this.refreshTimer) {
46
+ clearTimeout(this.refreshTimer);
47
+ this.refreshTimer = null;
48
+ }
49
+ }
50
+ async obtainAccessToken() {
51
+ const response = await fetch(`${this.baseUrl}/v1/auth/token/issue`, {
52
+ method: "POST",
53
+ headers: {
54
+ "Content-Type": "application/json",
55
+ accountId: this.accountId
56
+ },
57
+ body: JSON.stringify({
58
+ grant_type: "client_credentials",
59
+ client_id: this.clientId,
60
+ client_secret: this.clientSecret
61
+ })
62
+ });
63
+ if (!response.ok) throw new Error(`Failed to obtain token (${response.status})`);
64
+ const payload = await response.json();
65
+ this.updateTokens(payload.data);
66
+ }
67
+ async refreshAccessToken() {
68
+ if (!this.refreshToken || !this.accessToken) {
69
+ await this.obtainAccessToken();
70
+ return;
71
+ }
72
+ const response = await fetch(`${this.baseUrl}/v1/auth/token/refresh`, {
73
+ method: "POST",
74
+ headers: {
75
+ Authorization: `Bearer ${this.accessToken}`,
76
+ "Content-Type": "application/json",
77
+ accountId: this.accountId
78
+ },
79
+ body: JSON.stringify({
80
+ grant_type: "refresh_token",
81
+ refresh_token: this.refreshToken
82
+ })
83
+ });
84
+ if (!response.ok) {
85
+ await this.obtainAccessToken();
86
+ return;
87
+ }
88
+ const payload = await response.json();
89
+ this.updateTokens(payload.data);
90
+ }
91
+ updateTokens(data) {
92
+ this.accessToken = data.access_token;
93
+ this.refreshToken = data.refresh_token;
94
+ this.expiresAt = new Date(data.expiresAt);
95
+ this.scheduleRefresh();
96
+ }
97
+ scheduleRefresh() {
98
+ if (!this.expiresAt) return;
99
+ if (this.refreshTimer) clearTimeout(this.refreshTimer);
100
+ const refreshAt = Temporal.Instant.from(this.expiresAt.toISOString()).subtract({ milliseconds: ms("30m") });
101
+ const now = Temporal.Now.instant();
102
+ const delay = Math.max(Number(refreshAt.epochMilliseconds - now.epochMilliseconds), 0);
103
+ this.refreshTimer = setTimeout(() => {
104
+ this.refreshAccessToken();
105
+ }, delay);
106
+ }
107
+ };
108
+ //#endregion
109
+ export { TokenManager };
@@ -0,0 +1,108 @@
1
+ import { schema_d_exports } from "./schema.js";
2
+ import { Pool } from "pg";
3
+ import { PGlite } from "@electric-sql/pglite";
4
+
5
+ //#region core/pg_db/index.d.ts
6
+ declare function migratePGlite(client: PGlite): Promise<void | import("drizzle-orm/migrator").MigratorInitFailResponse>;
7
+ declare function migratePgNode(client: Pool): Promise<void>;
8
+ declare function isPgPool(db: any): db is Pool;
9
+ declare function isPGlite(db: any): db is PGlite;
10
+ type AdapterConfig = {
11
+ provider: "pg";
12
+ db: Pool;
13
+ } | {
14
+ provider: "pglite";
15
+ db: PGlite;
16
+ };
17
+ type DatabaseConfig = string | Pool | AdapterConfig;
18
+ declare function drizzleAdapter(args: AdapterConfig): AdapterConfig;
19
+ declare function getDrizzle(config: DatabaseConfig): (import("drizzle-orm/pglite").PgliteDatabase<import("drizzle-orm").ExtractTablesWithRelations<{
20
+ products: {
21
+ features: import("drizzle-orm").Many<"productFeatures">;
22
+ subscriptions: import("drizzle-orm").Many<"subscriptions">;
23
+ };
24
+ productFeatures: {
25
+ product: import("drizzle-orm").One<"products", true>;
26
+ feature: import("drizzle-orm").One<"features", true>;
27
+ };
28
+ features: {
29
+ products: import("drizzle-orm").Many<"productFeatures">;
30
+ entitlements: import("drizzle-orm").Many<"entitlements">;
31
+ };
32
+ customers: {
33
+ paymentMethods: import("drizzle-orm").Many<"paymentMethods">;
34
+ subscriptions: import("drizzle-orm").Many<"subscriptions">;
35
+ entitlements: import("drizzle-orm").Many<"entitlements">;
36
+ invoices: import("drizzle-orm").Many<"invoices">;
37
+ };
38
+ paymentMethods: {
39
+ customer: import("drizzle-orm").One<"customers", true>;
40
+ subscriptions: import("drizzle-orm").Many<"subscriptions">;
41
+ };
42
+ subscriptions: {
43
+ customer: import("drizzle-orm").One<"customers", true>;
44
+ product: import("drizzle-orm").One<"products", true>;
45
+ paymentMethod: import("drizzle-orm").One<"paymentMethods", true>;
46
+ entitlements: import("drizzle-orm").Many<"entitlements">;
47
+ invoices: import("drizzle-orm").Many<"invoices">;
48
+ nextSubscription: import("drizzle-orm").One<"subscriptions", true>;
49
+ };
50
+ entitlements: {
51
+ subscription: import("drizzle-orm").One<"subscriptions", true>;
52
+ customer: import("drizzle-orm").One<"customers", true>;
53
+ feature: import("drizzle-orm").One<"features", true>;
54
+ };
55
+ invoices: {
56
+ customer: import("drizzle-orm").One<"customers", true>;
57
+ subscription: import("drizzle-orm").One<"subscriptions", true>;
58
+ };
59
+ }, import("drizzle-orm").ExtractTablesFromSchema<typeof schema_d_exports>>> & {
60
+ $client: PGlite;
61
+ }) | (import("drizzle-orm/node-postgres").NodePgDatabase<import("drizzle-orm").ExtractTablesWithRelations<{
62
+ products: {
63
+ features: import("drizzle-orm").Many<"productFeatures">;
64
+ subscriptions: import("drizzle-orm").Many<"subscriptions">;
65
+ };
66
+ productFeatures: {
67
+ product: import("drizzle-orm").One<"products", true>;
68
+ feature: import("drizzle-orm").One<"features", true>;
69
+ };
70
+ features: {
71
+ products: import("drizzle-orm").Many<"productFeatures">;
72
+ entitlements: import("drizzle-orm").Many<"entitlements">;
73
+ };
74
+ customers: {
75
+ paymentMethods: import("drizzle-orm").Many<"paymentMethods">;
76
+ subscriptions: import("drizzle-orm").Many<"subscriptions">;
77
+ entitlements: import("drizzle-orm").Many<"entitlements">;
78
+ invoices: import("drizzle-orm").Many<"invoices">;
79
+ };
80
+ paymentMethods: {
81
+ customer: import("drizzle-orm").One<"customers", true>;
82
+ subscriptions: import("drizzle-orm").Many<"subscriptions">;
83
+ };
84
+ subscriptions: {
85
+ customer: import("drizzle-orm").One<"customers", true>;
86
+ product: import("drizzle-orm").One<"products", true>;
87
+ paymentMethod: import("drizzle-orm").One<"paymentMethods", true>;
88
+ entitlements: import("drizzle-orm").Many<"entitlements">;
89
+ invoices: import("drizzle-orm").Many<"invoices">;
90
+ nextSubscription: import("drizzle-orm").One<"subscriptions", true>;
91
+ };
92
+ entitlements: {
93
+ subscription: import("drizzle-orm").One<"subscriptions", true>;
94
+ customer: import("drizzle-orm").One<"customers", true>;
95
+ feature: import("drizzle-orm").One<"features", true>;
96
+ };
97
+ invoices: {
98
+ customer: import("drizzle-orm").One<"customers", true>;
99
+ subscription: import("drizzle-orm").One<"subscriptions", true>;
100
+ };
101
+ }, import("drizzle-orm").ExtractTablesFromSchema<typeof schema_d_exports>>> & {
102
+ $client: Pool;
103
+ });
104
+ declare function closeConnection(config: DatabaseConfig): Promise<void>;
105
+ type NomkitDB = ReturnType<typeof getDrizzle>;
106
+ declare function hasPendingMigrations(db: NomkitDB): Promise<boolean>;
107
+ //#endregion
108
+ export { AdapterConfig, DatabaseConfig, NomkitDB, closeConnection, drizzleAdapter, getDrizzle, hasPendingMigrations, isPGlite, isPgPool, migratePGlite, migratePgNode };
@@ -0,0 +1,76 @@
1
+ import { relations } from "./relations.js";
2
+ import { drizzle } from "drizzle-orm/node-postgres";
3
+ import { migrate } from "drizzle-orm/node-postgres/migrator";
4
+ import { drizzle as drizzle$1 } from "drizzle-orm/pglite";
5
+ import { migrate as migrate$1 } from "drizzle-orm/pglite/migrator";
6
+ import fs from "node:fs/promises";
7
+ import path from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { Pool } from "pg";
10
+ //#region core/pg_db/index.ts
11
+ const migrationsSchema = "public";
12
+ const migrationsTable = "nomkit_migrations";
13
+ const migrationsFolder = path.join(path.dirname(fileURLToPath(import.meta.url)), "migrations");
14
+ async function migratePGlite(client) {
15
+ if (!isPGlite(client)) return;
16
+ return migrate$1(drizzle$1({
17
+ client,
18
+ relations
19
+ }), {
20
+ migrationsFolder,
21
+ migrationsSchema,
22
+ migrationsTable
23
+ });
24
+ }
25
+ async function migratePgNode(client) {
26
+ if (!isPgPool(client)) return;
27
+ await migrate(drizzle({
28
+ client,
29
+ relations
30
+ }), {
31
+ migrationsFolder,
32
+ migrationsSchema,
33
+ migrationsTable
34
+ });
35
+ }
36
+ function isPgPool(db) {
37
+ return db instanceof Pool;
38
+ }
39
+ function isPGlite(db) {
40
+ return ("ENV" in db || "Module" in db) && "dataDir" in db;
41
+ }
42
+ function drizzleAdapter(args) {
43
+ return args;
44
+ }
45
+ function getDrizzle(config) {
46
+ if (typeof config === "string") return drizzle({
47
+ client: new Pool({ connectionString: config }),
48
+ relations
49
+ });
50
+ if (isPgPool(config)) return drizzle({
51
+ client: config,
52
+ relations
53
+ });
54
+ return config.provider === "pglite" ? drizzle$1({
55
+ client: config.db,
56
+ relations
57
+ }) : drizzle({
58
+ client: config.db,
59
+ relations
60
+ });
61
+ }
62
+ async function closeConnection(config) {
63
+ if (typeof config === "string") return;
64
+ if (isPgPool(config)) return await config.end();
65
+ return await (config.provider === "pglite" ? config.db.close() : config.db.end());
66
+ }
67
+ async function hasPendingMigrations(db) {
68
+ const totalMigrations = (await fs.readdir(migrationsFolder, { withFileTypes: true })).filter((item) => item.isDirectory()).length;
69
+ try {
70
+ return totalMigrations - ((await db.execute(`SELECT count(*)::int AS count FROM ${migrationsSchema}.${migrationsTable}`)).rows.at(0)?.count ?? 0) !== 0;
71
+ } catch {
72
+ return true;
73
+ }
74
+ }
75
+ //#endregion
76
+ export { closeConnection, drizzleAdapter, getDrizzle, hasPendingMigrations, isPGlite, isPgPool, migratePGlite, migratePgNode };
@@ -0,0 +1,120 @@
1
+ CREATE TYPE "feature_type" AS ENUM('boolean', 'metered');--> statement-breakpoint
2
+ CREATE TYPE "invoice_status" AS ENUM('paid', 'failed', 'void', 'pending');--> statement-breakpoint
3
+ CREATE TYPE "subscription_status" AS ENUM('active', 'cancelled', 'past_due', 'pending', 'scheduled');--> statement-breakpoint
4
+ CREATE TABLE "nomkit_customer" (
5
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
6
+ "name" text,
7
+ "email" text NOT NULL UNIQUE,
8
+ "metadata" jsonb,
9
+ "external_id" text UNIQUE,
10
+ "created_at" timestamp NOT NULL,
11
+ "updated_at" timestamp NOT NULL
12
+ );
13
+ --> statement-breakpoint
14
+ CREATE TABLE "nomkit_entitlement" (
15
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
16
+ "subscription_id" uuid NOT NULL,
17
+ "customer_id" uuid NOT NULL,
18
+ "feature_internal_id" uuid NOT NULL,
19
+ "limit" bigint,
20
+ "remaining" bigint,
21
+ "reset_at" timestamp,
22
+ "created_at" timestamp NOT NULL,
23
+ "updated_at" timestamp NOT NULL
24
+ );
25
+ --> statement-breakpoint
26
+ CREATE TABLE "nomkit_feature" (
27
+ "internal_id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
28
+ "id" text NOT NULL,
29
+ "label" text NOT NULL,
30
+ "created_at" timestamp NOT NULL,
31
+ "updated_at" timestamp NOT NULL
32
+ );
33
+ --> statement-breakpoint
34
+ CREATE TABLE "nomkit_invoice" (
35
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
36
+ "customer_id" uuid NOT NULL,
37
+ "subscription_id" uuid NOT NULL,
38
+ "status" "invoice_status" DEFAULT 'pending'::"invoice_status" NOT NULL,
39
+ "amount" integer NOT NULL,
40
+ "currency" text NOT NULL,
41
+ "period_start" timestamp,
42
+ "period_end" timestamp,
43
+ "created_at" timestamp NOT NULL,
44
+ "updated_at" timestamp NOT NULL
45
+ );
46
+ --> statement-breakpoint
47
+ CREATE TABLE "nomkit_payment_method" (
48
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
49
+ "customer_id" uuid NOT NULL,
50
+ "token_key" text NOT NULL UNIQUE,
51
+ "email" text NOT NULL,
52
+ "card_type" text NOT NULL,
53
+ "card_pan" text NOT NULL,
54
+ "token_expiration_date" text NOT NULL,
55
+ "created_at" timestamp NOT NULL,
56
+ "updated_at" timestamp NOT NULL
57
+ );
58
+ --> statement-breakpoint
59
+ CREATE TABLE "nomkit_product_features" (
60
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
61
+ "feature_internal_id" uuid NOT NULL,
62
+ "type" "feature_type" NOT NULL,
63
+ "limit" bigint,
64
+ "reset_interval" text,
65
+ "feature_hash" text NOT NULL,
66
+ "product_id" text NOT NULL,
67
+ "product_version" integer NOT NULL,
68
+ "created_at" timestamp NOT NULL,
69
+ "updated_at" timestamp NOT NULL
70
+ );
71
+ --> statement-breakpoint
72
+ CREATE TABLE "nomkit_product" (
73
+ "internal_id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
74
+ "id" text NOT NULL,
75
+ "label" text NOT NULL,
76
+ "product_hash" text NOT NULL,
77
+ "price_amount" integer,
78
+ "product_interval" text,
79
+ "version" integer DEFAULT 1 NOT NULL,
80
+ "created_at" timestamp NOT NULL,
81
+ "updated_at" timestamp NOT NULL
82
+ );
83
+ --> statement-breakpoint
84
+ CREATE TABLE "nomkit_subscription" (
85
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
86
+ "customer_id" uuid NOT NULL,
87
+ "product_internal_id" uuid NOT NULL,
88
+ "payment_method_id" uuid,
89
+ "next_subscription_id" uuid,
90
+ "status" "subscription_status" DEFAULT 'active'::"subscription_status" NOT NULL,
91
+ "current_period_start" timestamp,
92
+ "current_period_end" timestamp,
93
+ "created_at" timestamp NOT NULL,
94
+ "updated_at" timestamp NOT NULL,
95
+ "ended_at" timestamp
96
+ );
97
+ --> statement-breakpoint
98
+ CREATE INDEX "customer_created_at_id_idx" ON "nomkit_customer" ("created_at","id");--> statement-breakpoint
99
+ CREATE INDEX "entitlement_customer_idx" ON "nomkit_entitlement" ("customer_id");--> statement-breakpoint
100
+ CREATE INDEX "entitlement_subscription_idx" ON "nomkit_entitlement" ("subscription_id");--> statement-breakpoint
101
+ CREATE UNIQUE INDEX "subscription_feature_unique" ON "nomkit_entitlement" ("subscription_id","feature_internal_id");--> statement-breakpoint
102
+ CREATE INDEX "feature_idx" ON "nomkit_feature" ("internal_id");--> statement-breakpoint
103
+ CREATE UNIQUE INDEX "feature_unique" ON "nomkit_feature" ("id");--> statement-breakpoint
104
+ CREATE UNIQUE INDEX "invoice_period_unique" ON "nomkit_invoice" ("subscription_id","period_start","period_end");--> statement-breakpoint
105
+ CREATE INDEX "project_feature_idx" ON "nomkit_product_features" ("id");--> statement-breakpoint
106
+ CREATE UNIQUE INDEX "product_feature_unique_version" ON "nomkit_product_features" ("id","product_id","feature_internal_id","product_version");--> statement-breakpoint
107
+ CREATE INDEX "product_idx" ON "nomkit_product" ("id");--> statement-breakpoint
108
+ CREATE UNIQUE INDEX "product_hash_version_unique" ON "nomkit_product" ("id","product_hash","version");--> statement-breakpoint
109
+ CREATE INDEX "subscription_customer_idx" ON "nomkit_subscription" ("customer_id");--> statement-breakpoint
110
+ ALTER TABLE "nomkit_entitlement" ADD CONSTRAINT "nomkit_entitlement_subscription_id_nomkit_subscription_id_fkey" FOREIGN KEY ("subscription_id") REFERENCES "nomkit_subscription"("id") ON DELETE CASCADE;--> statement-breakpoint
111
+ ALTER TABLE "nomkit_entitlement" ADD CONSTRAINT "nomkit_entitlement_customer_id_nomkit_customer_id_fkey" FOREIGN KEY ("customer_id") REFERENCES "nomkit_customer"("id") ON DELETE CASCADE;--> statement-breakpoint
112
+ ALTER TABLE "nomkit_entitlement" ADD CONSTRAINT "nomkit_entitlement_qXkYoPL3C6xl_fkey" FOREIGN KEY ("feature_internal_id") REFERENCES "nomkit_feature"("internal_id") ON DELETE CASCADE;--> statement-breakpoint
113
+ ALTER TABLE "nomkit_invoice" ADD CONSTRAINT "nomkit_invoice_customer_id_nomkit_customer_id_fkey" FOREIGN KEY ("customer_id") REFERENCES "nomkit_customer"("id");--> statement-breakpoint
114
+ ALTER TABLE "nomkit_invoice" ADD CONSTRAINT "nomkit_invoice_subscription_id_nomkit_subscription_id_fkey" FOREIGN KEY ("subscription_id") REFERENCES "nomkit_subscription"("id");--> statement-breakpoint
115
+ ALTER TABLE "nomkit_payment_method" ADD CONSTRAINT "nomkit_payment_method_customer_id_nomkit_customer_id_fkey" FOREIGN KEY ("customer_id") REFERENCES "nomkit_customer"("id") ON DELETE CASCADE;--> statement-breakpoint
116
+ ALTER TABLE "nomkit_product_features" ADD CONSTRAINT "nomkit_product_features_fRzfjURvzgtv_fkey" FOREIGN KEY ("feature_internal_id") REFERENCES "nomkit_feature"("internal_id");--> statement-breakpoint
117
+ ALTER TABLE "nomkit_subscription" ADD CONSTRAINT "nomkit_subscription_customer_id_nomkit_customer_id_fkey" FOREIGN KEY ("customer_id") REFERENCES "nomkit_customer"("id") ON DELETE CASCADE;--> statement-breakpoint
118
+ ALTER TABLE "nomkit_subscription" ADD CONSTRAINT "nomkit_subscription_ojvUYQjCR2Ut_fkey" FOREIGN KEY ("product_internal_id") REFERENCES "nomkit_product"("internal_id") ON DELETE CASCADE;--> statement-breakpoint
119
+ ALTER TABLE "nomkit_subscription" ADD CONSTRAINT "nomkit_subscription_280q9WzMFyev_fkey" FOREIGN KEY ("payment_method_id") REFERENCES "nomkit_payment_method"("id");--> statement-breakpoint
120
+ ALTER TABLE "nomkit_subscription" ADD CONSTRAINT "nomkit_subscription_y7gGqXYjhQGH_fkey" FOREIGN KEY ("next_subscription_id") REFERENCES "nomkit_subscription"("id") ON DELETE SET NULL;