@supacloud/lite 0.32.0 → 0.33.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +37 -0
- package/dist/cli.js +2459 -161
- package/dist/index.js +2459 -161
- package/dist/runtime/auth/handler.d.ts +33 -1
- package/dist/runtime/auth/handler.d.ts.map +1 -1
- package/dist/runtime/auth/oauth.d.ts +28 -2
- package/dist/runtime/auth/oauth.d.ts.map +1 -1
- package/dist/runtime/auth/settings.d.ts +14 -0
- package/dist/runtime/auth/settings.d.ts.map +1 -1
- package/dist/runtime/auth/web3.d.ts +14 -0
- package/dist/runtime/auth/web3.d.ts.map +1 -0
- package/dist/runtime/db/bootstrap.d.ts +2 -2
- package/dist/runtime/db/bootstrap.d.ts.map +1 -1
- package/package.json +14 -14
|
@@ -61,6 +61,11 @@ interface UserRow {
|
|
|
61
61
|
email: string | null;
|
|
62
62
|
encrypted_password: string | null;
|
|
63
63
|
email_confirmed_at: Date | string | null;
|
|
64
|
+
email_change_token_new: string | null;
|
|
65
|
+
email_change: string | null;
|
|
66
|
+
email_change_sent_at: Date | string | null;
|
|
67
|
+
email_change_token_current: string | null;
|
|
68
|
+
email_change_confirm_status: number | null;
|
|
64
69
|
last_sign_in_at: Date | string | null;
|
|
65
70
|
raw_app_meta_data: Record<string, unknown> | null;
|
|
66
71
|
raw_user_meta_data: Record<string, unknown> | null;
|
|
@@ -68,6 +73,11 @@ interface UserRow {
|
|
|
68
73
|
updated_at: Date | string | null;
|
|
69
74
|
phone: string | null;
|
|
70
75
|
phone_confirmed_at: Date | string | null;
|
|
76
|
+
phone_change: string | null;
|
|
77
|
+
phone_change_token: string | null;
|
|
78
|
+
phone_change_sent_at: Date | string | null;
|
|
79
|
+
reauthentication_token: string | null;
|
|
80
|
+
reauthentication_sent_at: Date | string | null;
|
|
71
81
|
is_anonymous: boolean | null;
|
|
72
82
|
banned_until: Date | string | null;
|
|
73
83
|
deleted_at: Date | string | null;
|
|
@@ -99,17 +109,24 @@ export declare class AuthHandler {
|
|
|
99
109
|
handle(req: Request, ctx: RequestContext, url: URL): Promise<Response>;
|
|
100
110
|
private oauthCallbackUrl;
|
|
101
111
|
private signup;
|
|
112
|
+
private sso;
|
|
102
113
|
private token;
|
|
103
114
|
private getUser;
|
|
115
|
+
private unlinkIdentity;
|
|
104
116
|
private updateUser;
|
|
117
|
+
private reauthenticate;
|
|
118
|
+
private sessionRequiresReauthentication;
|
|
119
|
+
private consumeReauthentication;
|
|
120
|
+
private requestEmailChange;
|
|
105
121
|
private logout;
|
|
106
122
|
private issueToken;
|
|
107
123
|
private sendOtp;
|
|
124
|
+
private resendEmailChange;
|
|
125
|
+
private requestPhoneChange;
|
|
108
126
|
private issuePhoneToken;
|
|
109
127
|
private preparePhoneOtp;
|
|
110
128
|
private phoneUser;
|
|
111
129
|
private phoneUserForUpdate;
|
|
112
|
-
private createPhoneIdentity;
|
|
113
130
|
private deliverPhoneOtp;
|
|
114
131
|
private sendPhoneOtp;
|
|
115
132
|
private cleanupFailedPhoneOtp;
|
|
@@ -120,6 +137,7 @@ export declare class AuthHandler {
|
|
|
120
137
|
/** Max wrong guesses for a one-time code before its tokens are invalidated. */
|
|
121
138
|
private static readonly MAX_OTP_ATTEMPTS;
|
|
122
139
|
private redeem;
|
|
140
|
+
private redeemUser;
|
|
123
141
|
private claimEmailToken;
|
|
124
142
|
private lockAndDeleteEmailToken;
|
|
125
143
|
private confirmEmailTokenUser;
|
|
@@ -127,7 +145,13 @@ export declare class AuthHandler {
|
|
|
127
145
|
private recordFailedEmailTokenAttempt;
|
|
128
146
|
private verifyToken;
|
|
129
147
|
private redeemPhoneOtp;
|
|
148
|
+
private redeemPhoneChange;
|
|
130
149
|
private verifyLink;
|
|
150
|
+
private exchangeEmailPkce;
|
|
151
|
+
private redeemEmailChangeUser;
|
|
152
|
+
private redeemEmailChange;
|
|
153
|
+
private claimEmailChange;
|
|
154
|
+
private sessionForEmailPkce;
|
|
131
155
|
private admin;
|
|
132
156
|
private generateAdminMagicLink;
|
|
133
157
|
/**
|
|
@@ -156,11 +180,19 @@ export declare class AuthHandler {
|
|
|
156
180
|
private enrollFactor;
|
|
157
181
|
private challengeFactor;
|
|
158
182
|
private verifyFactor;
|
|
183
|
+
private recoveryCodesStatus;
|
|
184
|
+
private generateRecoveryCodes;
|
|
185
|
+
private regenerateRecoveryCodes;
|
|
186
|
+
private deleteRecoveryCodes;
|
|
187
|
+
private verifyRecoveryCode;
|
|
188
|
+
private requireAal2;
|
|
159
189
|
private unenrollFactor;
|
|
160
190
|
private getUserFactors;
|
|
161
191
|
/** GoTrue-shaped identities for a user (linked providers), from auth.identities. */
|
|
162
192
|
private getUserIdentities;
|
|
163
193
|
private ensureEmailIdentity;
|
|
194
|
+
private ensurePhoneIdentity;
|
|
195
|
+
private syncUserProviders;
|
|
164
196
|
private userJsonWithRelations;
|
|
165
197
|
private rotateRefreshToken;
|
|
166
198
|
private findAvailableRefreshToken;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,mBAAmB,CAAA;AAE1D,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAc,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhF,OAAO,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,10 @@ export declare class OAuthAccountIneligibleError extends Error {
|
|
|
16
16
|
readonly code: 'user_banned' | 'user_not_found';
|
|
17
17
|
constructor(code: 'user_banned' | 'user_not_found');
|
|
18
18
|
}
|
|
19
|
+
export declare class OAuthIdentityLinkError extends Error {
|
|
20
|
+
readonly code: 'identity_already_exists';
|
|
21
|
+
constructor(code: 'identity_already_exists');
|
|
22
|
+
}
|
|
19
23
|
/** Operator-supplied config for one OAuth provider. Endpoint URLs are optional for presets (google, github). */
|
|
20
24
|
export interface OAuthProviderConfig {
|
|
21
25
|
/** OAuth client id issued by the provider */
|
|
@@ -32,6 +36,14 @@ export interface OAuthProviderConfig {
|
|
|
32
36
|
scopes?: string;
|
|
33
37
|
/** Map the provider's raw userinfo JSON to a normalized profile. */
|
|
34
38
|
profileMap?: (raw: OAuthRawProfile) => OAuthProfile;
|
|
39
|
+
/** Exact issuer accepted for OIDC ID tokens. Defaults to a known provider preset. */
|
|
40
|
+
idTokenIssuer?: string;
|
|
41
|
+
/** JWKS URL used to verify OIDC ID token signatures. Defaults to a known provider preset. */
|
|
42
|
+
idTokenJwksUrl?: string;
|
|
43
|
+
/** Additional audience accepted for OIDC ID tokens. Defaults to the OAuth client id. */
|
|
44
|
+
idTokenAudience?: string | string[];
|
|
45
|
+
/** Email domains that may resolve this provider through POST /sso. */
|
|
46
|
+
ssoDomains?: string[];
|
|
35
47
|
}
|
|
36
48
|
/** Normalized profile extracted from a provider's userinfo response. */
|
|
37
49
|
export interface OAuthProfile {
|
|
@@ -46,8 +58,12 @@ export interface OAuthProfile {
|
|
|
46
58
|
/** extra provider fields (avatar, username, …) merged into identity_data */
|
|
47
59
|
metadata?: Record<string, unknown>;
|
|
48
60
|
}
|
|
49
|
-
interface ResolvedProvider extends
|
|
61
|
+
interface ResolvedProvider extends OAuthProviderConfig {
|
|
50
62
|
name: string;
|
|
63
|
+
authorizeUrl: string;
|
|
64
|
+
tokenUrl: string;
|
|
65
|
+
userInfoUrl: string;
|
|
66
|
+
scopes: string;
|
|
51
67
|
profileMap: (raw: OAuthRawProfile) => OAuthProfile;
|
|
52
68
|
}
|
|
53
69
|
/**
|
|
@@ -66,12 +82,20 @@ export declare class OAuthService {
|
|
|
66
82
|
private uriAllowList;
|
|
67
83
|
private enforceRedirectAllowList;
|
|
68
84
|
private providers;
|
|
85
|
+
private idTokenKeySets;
|
|
69
86
|
constructor(db: Database, apiUrl: string, siteUrl: string, configs: Record<string, OAuthProviderConfig>, fetchImpl?: typeof fetch, uriAllowList?: string[], enforceRedirectAllowList?: boolean);
|
|
70
87
|
/** Whether a provider by this name is configured. */
|
|
71
88
|
has(name: string): boolean;
|
|
89
|
+
/** Verify an OIDC ID token and reuse the normal OAuth identity upsert path. */
|
|
90
|
+
signInWithIdToken(providerName: string, token: string, accessToken?: string, nonce?: string): Promise<string | null>;
|
|
91
|
+
/** Verify an OIDC ID token and attach its identity to an existing user. */
|
|
92
|
+
linkIdentityWithIdToken(providerName: string, token: string, userId: string, accessToken?: string, nonce?: string): Promise<boolean>;
|
|
93
|
+
/** Upsert an already verified non-OAuth identity through the shared path. */
|
|
94
|
+
signInWithProfile(provider: string, profile: OAuthProfile): Promise<string>;
|
|
95
|
+
private verifyIdToken;
|
|
72
96
|
private callbackUrl;
|
|
73
97
|
/** GET /authorize - persist state, redirect to the provider. */
|
|
74
|
-
authorize(url: URL): Promise<Response>;
|
|
98
|
+
authorize(url: URL, linkUserId?: string): Promise<Response>;
|
|
75
99
|
/** GET /callback - exchange code, upsert user+identity, redirect back. */
|
|
76
100
|
callback(url: URL, createSession: (userId: string) => Promise<OAuthSession>): Promise<Response>;
|
|
77
101
|
/** POST /token?grant_type=pkce - exchange an auth code + verifier for a session. */
|
|
@@ -79,7 +103,9 @@ export declare class OAuthService {
|
|
|
79
103
|
private exchangeCode;
|
|
80
104
|
private fetchProfile;
|
|
81
105
|
private upsertUser;
|
|
106
|
+
private linkIdentityToUser;
|
|
82
107
|
private upsertUserInTransaction;
|
|
108
|
+
private syncUserProviders;
|
|
83
109
|
private assertUserEligible;
|
|
84
110
|
}
|
|
85
111
|
/** The minimal session the callback puts in the redirect fragment for the implicit flow. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,8 @@ export interface AuthSettings {
|
|
|
19
19
|
autoconfirm: boolean;
|
|
20
20
|
/** Minimum accepted password length (signup, updateUser, admin create). */
|
|
21
21
|
minPasswordLength: number;
|
|
22
|
+
/** Require a recent email/phone OTP before changing an existing password. */
|
|
23
|
+
requirePasswordReauthentication: boolean;
|
|
22
24
|
/** Configured OAuth providers the operator has switched off at runtime. */
|
|
23
25
|
disabledProviders: string[];
|
|
24
26
|
/** Digits in emailed OTP codes (config.toml auth.email.otp_length; 6-10). */
|
|
@@ -39,6 +41,18 @@ export interface AuthSettings {
|
|
|
39
41
|
totpEnrollEnabled: boolean;
|
|
40
42
|
/** Allow TOTP verification/challenge (auth.mfa.totp.verify_enabled). */
|
|
41
43
|
totpVerifyEnabled: boolean;
|
|
44
|
+
/** Allow recovery-code enrollment and rotation (auth.mfa.recovery_codes.enroll_enabled). */
|
|
45
|
+
recoveryCodesEnrollEnabled: boolean;
|
|
46
|
+
/** Allow recovery-code verification (auth.mfa.recovery_codes.verify_enabled). */
|
|
47
|
+
recoveryCodesVerifyEnabled: boolean;
|
|
48
|
+
/** Number of recovery codes issued per set. */
|
|
49
|
+
recoveryCodesCount: number;
|
|
50
|
+
/** Length of each recovery code before display separators are added. */
|
|
51
|
+
recoveryCodeLength: number;
|
|
52
|
+
/** Failed recovery-code attempts before temporary lockout. */
|
|
53
|
+
recoveryCodesMaxVerifyAttempts: number;
|
|
54
|
+
/** Recovery-code lockout duration in seconds. */
|
|
55
|
+
recoveryCodesLockoutSeconds: number;
|
|
42
56
|
}
|
|
43
57
|
/** Built-in defaults, matching `supabase start`'s permissive local posture (autoconfirm on, anonymous users on). */
|
|
44
58
|
export declare const DEFAULT_AUTH_SETTINGS: AuthSettings;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/settings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,6FAA6F;IAC7F,aAAa,EAAE,OAAO,CAAA;IACtB,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAA;IACvB,6HAA6H;IAC7H,WAAW,EAAE,OAAO,CAAA;IACpB,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,CAAA;IACzB,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,gBAAgB,EAAE,MAAM,CAAA;IACxB,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAA;IACnB,0DAA0D;IAC1D,gBAAgB,EAAE,OAAO,CAAA;IACzB,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAA;IAC7B,uFAAuF;IACvF,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,4DAA4D;IAC5D,iBAAiB,EAAE,OAAO,CAAA;IAC1B,wEAAwE;IACxE,iBAAiB,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/settings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,6FAA6F;IAC7F,aAAa,EAAE,OAAO,CAAA;IACtB,yDAAyD;IACzD,cAAc,EAAE,OAAO,CAAA;IACvB,6HAA6H;IAC7H,WAAW,EAAE,OAAO,CAAA;IACpB,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,CAAA;IACzB,6EAA6E;IAC7E,+BAA+B,EAAE,OAAO,CAAA;IACxC,2EAA2E;IAC3E,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAA;IACjB,oEAAoE;IACpE,gBAAgB,EAAE,MAAM,CAAA;IACxB,oEAAoE;IACpE,UAAU,EAAE,OAAO,CAAA;IACnB,0DAA0D;IAC1D,gBAAgB,EAAE,OAAO,CAAA;IACzB,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAA;IAC7B,uFAAuF;IACvF,WAAW,EAAE,MAAM,CAAA;IACnB,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,4DAA4D;IAC5D,iBAAiB,EAAE,OAAO,CAAA;IAC1B,wEAAwE;IACxE,iBAAiB,EAAE,OAAO,CAAA;IAC1B,4FAA4F;IAC5F,0BAA0B,EAAE,OAAO,CAAA;IACnC,iFAAiF;IACjF,0BAA0B,EAAE,OAAO,CAAA;IACnC,+CAA+C;IAC/C,kBAAkB,EAAE,MAAM,CAAA;IAC1B,wEAAwE;IACxE,kBAAkB,EAAE,MAAM,CAAA;IAC1B,8DAA8D;IAC9D,8BAA8B,EAAE,MAAM,CAAA;IACtC,iDAAiD;IACjD,2BAA2B,EAAE,MAAM,CAAA;CACpC;AAED,oHAAoH;AACpH,eAAO,MAAM,qBAAqB,EAAE,YAsBnC,CAAA;AA0DD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,GAAE,OAAO,CAAC,YAAY,CAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAShH;AAED,kDAAkD;AAClD,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAM1F;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CA8D1G"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SolanaSignInMessage {
|
|
2
|
+
address: string;
|
|
3
|
+
domain: string;
|
|
4
|
+
uri: string;
|
|
5
|
+
issuedAt: number;
|
|
6
|
+
expirationTime?: number;
|
|
7
|
+
notBefore?: number;
|
|
8
|
+
nonce?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Parse and validate the non-cryptographic part of a Sign in with Solana message. */
|
|
11
|
+
export declare function parseSolanaSignInMessage(message: string): SolanaSignInMessage | null;
|
|
12
|
+
/** Verify an auth-js Sign in with Solana payload and return its wallet address. */
|
|
13
|
+
export declare function verifySolanaSignIn(message: string, signature: string): Promise<SolanaSignInMessage | null>;
|
|
14
|
+
//# sourceMappingURL=web3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web3.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/web3.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAwDD,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAuCpF;AAED,mFAAmF;AACnF,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CA+BhH"}
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
* SQL-language auth helpers needed for the REST + auth CRUD surface. No RLS is
|
|
11
11
|
* enforced here - this path is for local-dev/preview only.
|
|
12
12
|
*/
|
|
13
|
-
export declare const MINIMAL_BOOTSTRAP_SQL = "\ncreate schema if not exists auth;\ncreate schema if not exists storage;\ncreate schema if not exists supabase_migrations;\n\ncreate table if not exists auth.users (\n id uuid primary key default gen_random_uuid(),\n aud text default 'authenticated',\n role text default 'authenticated',\n email text unique,\n encrypted_password text,\n email_confirmed_at timestamptz,\n last_sign_in_at timestamptz,\n raw_app_meta_data jsonb default '{}'::jsonb,\n raw_user_meta_data jsonb default '{}'::jsonb,\n is_super_admin boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n phone text unique,\n phone_confirmed_at timestamptz,\n banned_until timestamptz,\n deleted_at timestamptz,\n is_anonymous boolean default false\n);\n\ncreate table if not exists auth.refresh_tokens (\n id bigserial primary key,\n token text unique not null,\n user_id uuid not null,\n parent text,\n session_id uuid,\n revoked boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists auth.one_time_tokens (\n id uuid primary key default gen_random_uuid(),\n user_id uuid,\n email text,\n phone text,\n token_type text not null,\n token text not null,\n attempts int not null default 0,\n created_at timestamptz default now(),\n expires_at timestamptz not null,\n constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n )\n);\n\n-- Minimal engines can persist a database created by an older Lite version.\n-- Standard ALTER statements keep that path compatible without requiring plpgsql.\nalter table auth.one_time_tokens add column if not exists phone text;\nalter table auth.one_time_tokens alter column email drop not null;\nalter table auth.one_time_tokens drop constraint if exists one_time_tokens_contact_check;\nalter table auth.one_time_tokens add constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n);\n\ncreate unique index if not exists one_time_tokens_phone_type_idx\n on auth.one_time_tokens(phone, token_type) where phone is not null;\n\ncreate table if not exists auth.phone_otp_cooldowns (\n phone_fingerprint text primary key,\n issuance_id uuid not null,\n last_sent_at timestamptz not null default now()\n);\n\ncreate table if not exists auth.identities (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null,\n provider text not null,\n provider_id text not null,\n identity_data jsonb default '{}'::jsonb,\n last_sign_in_at timestamptz default now(),\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n unique (provider, provider_id)\n);\n\ncreate table if not exists auth.flow_state (\n id uuid primary key default gen_random_uuid(),\n provider text not null,\n provider_state text not null unique,\n redirect_to text,\n code_challenge text,\n code_challenge_method text,\n auth_code text unique,\n user_id uuid,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\n\ncreate table if not exists auth.mfa_factors (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null,\n friendly_name text,\n factor_type text not null default 'totp',\n status text not null default 'unverified',\n secret text,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists auth.mfa_challenges (\n id uuid primary key default gen_random_uuid(),\n factor_id uuid not null,\n verified_at timestamptz,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\n\ncreate table if not exists auth.audit_log_entries (\n id uuid primary key default gen_random_uuid(),\n payload jsonb,\n created_at timestamptz default now(),\n ip_address varchar(64) not null default ''\n);\n\n-- runtime-mutable instance settings (Studio auth toggles)\ncreate table if not exists auth.config (\n key text primary key,\n value jsonb not null,\n updated_at timestamptz default now()\n);\n\ncreate table if not exists storage.buckets (\n id text primary key,\n name text not null unique,\n owner uuid,\n owner_id text,\n public boolean default false,\n file_size_limit bigint,\n allowed_mime_types text[],\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\nalter table storage.buckets add column if not exists owner_id text;\nupdate storage.buckets\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate table if not exists storage.objects (\n id uuid primary key default gen_random_uuid(),\n bucket_id text not null,\n name text not null,\n owner uuid,\n owner_id text,\n version text,\n metadata jsonb default '{}'::jsonb,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n last_accessed_at timestamptz default now(),\n unique (bucket_id, name)\n);\n\nalter table storage.objects add column if not exists owner_id text;\nupdate storage.objects\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate table if not exists supabase_migrations.schema_migrations (\n version text primary key,\n name text,\n statements text[],\n applied_at timestamptz default now()\n);\n\ncreate table if not exists supabase_migrations.seed_files (\n path text primary key,\n hash text,\n applied_at timestamptz default now()\n);\n";
|
|
13
|
+
export declare const MINIMAL_BOOTSTRAP_SQL = "\ncreate schema if not exists auth;\ncreate schema if not exists storage;\ncreate schema if not exists supabase_migrations;\n\ncreate table if not exists auth.users (\n id uuid primary key default gen_random_uuid(),\n aud text default 'authenticated',\n role text default 'authenticated',\n email text unique,\n encrypted_password text,\n email_confirmed_at timestamptz,\n email_change_token_new text default '',\n email_change text,\n email_change_sent_at timestamptz,\n email_change_token_current text default '',\n email_change_confirm_status smallint default 0,\n last_sign_in_at timestamptz,\n raw_app_meta_data jsonb default '{}'::jsonb,\n raw_user_meta_data jsonb default '{}'::jsonb,\n is_super_admin boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n phone text unique,\n phone_confirmed_at timestamptz,\n phone_change text default '',\n phone_change_token text default '',\n phone_change_sent_at timestamptz,\n banned_until timestamptz,\n deleted_at timestamptz,\n is_anonymous boolean default false\n);\n\nalter table auth.users add column if not exists email_change text;\nalter table auth.users add column if not exists email_change_sent_at timestamptz;\nalter table auth.users add column if not exists email_change_token_new text default '';\nalter table auth.users add column if not exists email_change_token_current text default '';\nalter table auth.users add column if not exists email_change_confirm_status smallint default 0;\nalter table auth.users add column if not exists phone_change text default '';\nalter table auth.users add column if not exists phone_change_token text default '';\nalter table auth.users add column if not exists phone_change_sent_at timestamptz;\n\ncreate table if not exists auth.refresh_tokens (\n id bigserial primary key,\n token text unique not null,\n user_id uuid not null,\n parent text,\n session_id uuid,\n revoked boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists auth.one_time_tokens (\n id uuid primary key default gen_random_uuid(),\n user_id uuid,\n email text,\n phone text,\n token_type text not null,\n token text not null,\n attempts int not null default 0,\n created_at timestamptz default now(),\n expires_at timestamptz not null,\n constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n )\n);\n\n-- Minimal engines can persist a database created by an older Lite version.\n-- Standard ALTER statements keep that path compatible without requiring plpgsql.\nalter table auth.one_time_tokens add column if not exists phone text;\nalter table auth.one_time_tokens alter column email drop not null;\nalter table auth.one_time_tokens drop constraint if exists one_time_tokens_contact_check;\nalter table auth.one_time_tokens add constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n);\n\ncreate unique index if not exists one_time_tokens_phone_type_idx\n on auth.one_time_tokens(phone, token_type) where phone is not null;\n\ncreate table if not exists auth.phone_otp_cooldowns (\n phone_fingerprint text primary key,\n issuance_id uuid not null,\n last_sent_at timestamptz not null default now()\n);\n\ncreate table if not exists auth.identities (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null,\n provider text not null,\n provider_id text not null,\n identity_data jsonb default '{}'::jsonb,\n last_sign_in_at timestamptz default now(),\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n unique (provider, provider_id)\n);\n\ncreate table if not exists auth.flow_state (\n id uuid primary key default gen_random_uuid(),\n provider text not null,\n provider_state text not null unique,\n redirect_to text,\n code_challenge text,\n code_challenge_method text,\n auth_code text unique,\n user_id uuid,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\nalter table auth.flow_state add column if not exists link_user_id uuid;\n\ncreate table if not exists auth.mfa_factors (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null,\n friendly_name text,\n factor_type text not null default 'totp',\n status text not null default 'unverified',\n secret text,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists auth.mfa_challenges (\n id uuid primary key default gen_random_uuid(),\n factor_id uuid not null,\n verified_at timestamptz,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\n\ncreate table if not exists auth.mfa_recovery_code_sets (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null,\n mfa_factor_id uuid not null unique,\n failed_verification_count int not null default 0,\n verification_locked_until timestamptz,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n unique (user_id)\n);\n\ncreate table if not exists auth.mfa_recovery_codes (\n id uuid primary key default gen_random_uuid(),\n mfa_recovery_code_set_id uuid not null references auth.mfa_recovery_code_sets(id) on delete cascade,\n code_hash text not null,\n consumed_at timestamptz,\n created_at timestamptz default now()\n);\n\ncreate table if not exists auth.audit_log_entries (\n id uuid primary key default gen_random_uuid(),\n payload jsonb,\n created_at timestamptz default now(),\n ip_address varchar(64) not null default ''\n);\n\n-- runtime-mutable instance settings (Studio auth toggles)\ncreate table if not exists auth.config (\n key text primary key,\n value jsonb not null,\n updated_at timestamptz default now()\n);\n\ncreate table if not exists storage.buckets (\n id text primary key,\n name text not null unique,\n owner uuid,\n owner_id text,\n public boolean default false,\n file_size_limit bigint,\n allowed_mime_types text[],\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\nalter table storage.buckets add column if not exists owner_id text;\nupdate storage.buckets\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate table if not exists storage.objects (\n id uuid primary key default gen_random_uuid(),\n bucket_id text not null,\n name text not null,\n owner uuid,\n owner_id text,\n version text,\n metadata jsonb default '{}'::jsonb,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n last_accessed_at timestamptz default now(),\n unique (bucket_id, name)\n);\n\nalter table storage.objects add column if not exists owner_id text;\nupdate storage.objects\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate table if not exists supabase_migrations.schema_migrations (\n version text primary key,\n name text,\n statements text[],\n applied_at timestamptz default now()\n);\n\ncreate table if not exists supabase_migrations.seed_files (\n path text primary key,\n hash text,\n applied_at timestamptz default now()\n);\n";
|
|
14
14
|
/**
|
|
15
15
|
* Full bootstrap for the real engines (PGlite / native embedded Postgres):
|
|
16
16
|
* extensions, the anon/authenticated/service_role roles, GoTrue-compatible auth
|
|
17
17
|
* schema, storage schema with default RLS policies, migration bookkeeping, and
|
|
18
18
|
* the realtime CDC + broadcast plumbing.
|
|
19
19
|
*/
|
|
20
|
-
export declare const BOOTSTRAP_SQL = "\n-- \u2500\u2500 Extensions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n-- Supabase enables these by default and migrations lean on them\n-- (uuid_generate_v4(), crypt(), citext, pg_trgm, \u2026). Each is created into the\n-- 'extensions' schema like hosted Supabase; any not available in this engine\n-- build is skipped rather than aborting the whole bootstrap.\ncreate schema if not exists extensions;\ndo $$\ndeclare ext text;\nbegin\n foreach ext in array array[\n 'uuid-ossp','pgcrypto','citext','pg_trgm','ltree','hstore','fuzzystrmatch',\n 'vector','postgis','pg_textsearch'\n ] loop\n begin\n execute format('create extension if not exists %I with schema extensions', ext);\n exception when others then\n -- extension not bundled in this engine build; continue\n end;\n end loop;\nend $$;\n\n-- The official pgmq extension owns its required pgmq schema. PGlite and\n-- native PostgreSQL builds that do not provide it simply continue to Lite's\n-- SQL fallback during database initialization.\ncreate schema if not exists pgmq;\ndo $$\nbegin\n begin\n create extension if not exists pgmq with schema pgmq;\n exception when others then\n null;\n end;\nend $$;\n\n-- uuid-ossp isn't in every Postgres build (it needs an external UUID lib at\n-- build time - e.g. the theseus Linux binaries omit it). uuid_generate_v4() is\n-- the single most-used function from it, so shim it onto core gen_random_uuid()\n-- (also a v4 UUID) whenever the real extension isn't present, so migrations\n-- that call it work identically on every engine and platform.\ndo $$\nbegin\n if not exists (\n select 1 from pg_proc p join pg_namespace n on n.oid = p.pronamespace\n where p.proname = 'uuid_generate_v4' and n.nspname in ('public', 'extensions')\n ) then\n create function extensions.uuid_generate_v4() returns uuid\n language sql volatile as 'select gen_random_uuid()';\n end if;\nend $$;\n\n-- Make extension functions resolvable unqualified (uuid_generate_v4(), \u2026) on\n-- the current session (migrations run here) and for future connections.\ndo $$\nbegin\n execute 'alter database ' || quote_ident(current_database()) ||\n ' set search_path to \"$user\", public, extensions';\nexception when others then\n -- some engines disallow altering the current database; session SET below still applies\nend $$;\nset search_path to \"$user\", public, extensions;\n\n-- \u2500\u2500 Roles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndo $$\nbegin\n if not exists (select from pg_roles where rolname = 'anon') then\n create role anon nologin noinherit;\n end if;\n if not exists (select from pg_roles where rolname = 'authenticated') then\n create role authenticated nologin noinherit;\n end if;\n if not exists (select from pg_roles where rolname = 'service_role') then\n create role service_role nologin noinherit bypassrls;\n end if;\nend $$;\n\ngrant usage on schema extensions to anon, authenticated, service_role;\nalter role anon set search_path to \"$user\", public, extensions;\nalter role authenticated set search_path to \"$user\", public, extensions;\nalter role service_role set search_path to \"$user\", public, extensions;\n\n-- Initialize defaults once. Restart/maintenance must not undo application ACLs.\ndo $$\nbegin\n if to_regclass('supabase_migrations.schema_migrations') is null then\n grant usage on schema public to anon, authenticated, service_role;\n alter default privileges in schema public\n grant all on tables to anon, authenticated, service_role;\n alter default privileges in schema public\n grant all on sequences to anon, authenticated, service_role;\n end if;\nend $$;\n\n-- PostgreSQL already grants EXECUTE on new functions to PUBLIC. Keep that\n-- default so project migrations can revoke PUBLIC and grant only selected\n-- roles without hidden direct grants from Lite. Existing ACLs are left intact.\n\n-- \u2500\u2500 Auth schema (GoTrue-compatible subset) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists auth;\n\ncreate table if not exists auth.users (\n instance_id uuid default '00000000-0000-0000-0000-000000000000',\n id uuid primary key default gen_random_uuid(),\n aud text default 'authenticated',\n role text default 'authenticated',\n email text unique,\n encrypted_password text,\n email_confirmed_at timestamptz,\n invited_at timestamptz,\n confirmation_token text default '',\n confirmation_sent_at timestamptz,\n recovery_token text default '',\n recovery_sent_at timestamptz,\n email_change_token_new text default '',\n email_change text default '',\n email_change_sent_at timestamptz,\n email_change_token_current text default '',\n email_change_confirm_status smallint default 0,\n last_sign_in_at timestamptz,\n raw_app_meta_data jsonb default '{}'::jsonb,\n raw_user_meta_data jsonb default '{}'::jsonb,\n is_super_admin boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n phone text unique,\n phone_confirmed_at timestamptz,\n phone_change text default '',\n phone_change_token text default '',\n phone_change_sent_at timestamptz,\n reauthentication_token text default '',\n reauthentication_sent_at timestamptz,\n banned_until timestamptz,\n deleted_at timestamptz,\n is_anonymous boolean default false\n);\n\ncreate table if not exists auth.refresh_tokens (\n id bigint generated by default as identity primary key,\n token text unique not null,\n user_id uuid not null references auth.users(id) on delete cascade,\n parent text,\n session_id uuid,\n revoked boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate index if not exists refresh_tokens_user_id_idx on auth.refresh_tokens(user_id);\n\ncreate table if not exists auth.one_time_tokens (\n id uuid primary key default gen_random_uuid(),\n user_id uuid references auth.users(id) on delete cascade,\n email text,\n phone text,\n token_type text not null, -- otp | magiclink | recovery | sms\n token text not null,\n attempts int not null default 0,\n created_at timestamptz default now(),\n expires_at timestamptz not null,\n constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n )\n);\n\n-- Upgrade databases created by Lite <=0.5.9 without touching existing email tokens.\nalter table auth.one_time_tokens add column if not exists phone text;\nalter table auth.one_time_tokens alter column email drop not null;\ndo $phone_otp_contact_constraint$\nbegin\n if not exists (\n select 1 from pg_constraint\n where conrelid = 'auth.one_time_tokens'::regclass\n and conname = 'one_time_tokens_contact_check'\n ) then\n alter table auth.one_time_tokens add constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n );\n end if;\nend $phone_otp_contact_constraint$;\n\ncreate unique index if not exists one_time_tokens_phone_type_idx\n on auth.one_time_tokens(phone, token_type) where phone is not null;\n\n-- Only a keyed phone fingerprint is persisted for cooldown enforcement; the\n-- normalized phone number never enters this table.\ncreate table if not exists auth.phone_otp_cooldowns (\n phone_fingerprint text primary key,\n issuance_id uuid not null,\n last_sent_at timestamptz not null default now()\n);\n\ncreate table if not exists auth.identities (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null references auth.users(id) on delete cascade,\n provider text not null,\n provider_id text not null,\n identity_data jsonb default '{}'::jsonb,\n last_sign_in_at timestamptz default now(),\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n unique (provider, provider_id)\n);\n\n-- OAuth / PKCE flow state, bridging /authorize \u2192 provider \u2192 /callback \u2192 exchange\ncreate table if not exists auth.flow_state (\n id uuid primary key default gen_random_uuid(),\n provider text not null,\n provider_state text not null unique,\n redirect_to text,\n code_challenge text,\n code_challenge_method text,\n auth_code text unique,\n user_id uuid references auth.users(id) on delete cascade,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\n\ncreate table if not exists auth.mfa_factors (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null references auth.users(id) on delete cascade,\n friendly_name text,\n factor_type text not null default 'totp',\n status text not null default 'unverified', -- unverified | verified\n secret text,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists auth.mfa_challenges (\n id uuid primary key default gen_random_uuid(),\n factor_id uuid not null references auth.mfa_factors(id) on delete cascade,\n verified_at timestamptz,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\n\n-- append-only security audit trail (GoTrue-compatible shape)\ncreate table if not exists auth.audit_log_entries (\n instance_id uuid default '00000000-0000-0000-0000-000000000000',\n id uuid primary key default gen_random_uuid(),\n payload jsonb,\n created_at timestamptz default now(),\n ip_address varchar(64) not null default ''\n);\ncreate index if not exists audit_logs_instance_id_idx on auth.audit_log_entries(created_at);\n\n-- runtime-mutable instance settings (Studio auth toggles)\ncreate table if not exists auth.config (\n key text primary key,\n value jsonb not null,\n updated_at timestamptz default now()\n);\n\ngrant usage on schema auth to anon, authenticated, service_role;\n\ncreate or replace function auth.jwt() returns jsonb\nlanguage sql stable as $$\n select coalesce(\n nullif(current_setting('request.jwt.claims', true), ''),\n '{}'\n )::jsonb\n$$;\n\ncreate or replace function auth.uid() returns uuid\nlanguage sql stable as $$\n select nullif(auth.jwt() ->> 'sub', '')::uuid\n$$;\n\ncreate or replace function auth.role() returns text\nlanguage sql stable as $$\n select coalesce(auth.jwt() ->> 'role', 'anon')\n$$;\n\ncreate or replace function auth.email() returns text\nlanguage sql stable as $$\n select auth.jwt() ->> 'email'\n$$;\n\ngrant execute on function auth.jwt(), auth.uid(), auth.role(), auth.email()\n to anon, authenticated, service_role;\n\n-- \u2500\u2500 Storage schema (storage-api-compatible subset) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists storage;\n\ncreate table if not exists storage.buckets (\n id text primary key,\n name text not null unique,\n owner uuid,\n owner_id text,\n public boolean default false,\n file_size_limit bigint,\n allowed_mime_types text[],\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\nalter table storage.buckets add column if not exists owner_id text;\nupdate storage.buckets\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate table if not exists storage.objects (\n id uuid primary key default gen_random_uuid(),\n bucket_id text not null references storage.buckets(id),\n name text not null,\n owner uuid,\n owner_id text,\n version text,\n metadata jsonb default '{}'::jsonb,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n last_accessed_at timestamptz default now(),\n unique (bucket_id, name)\n);\n\n-- storage-api keeps the legacy UUID owner and the current text owner_id in\n-- parallel. Re-running bootstrap upgrades existing Lite databases and retains\n-- object ownership for rows created before owner_id support was added.\nalter table storage.objects add column if not exists owner_id text;\nupdate storage.objects\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate index if not exists objects_bucket_name_idx on storage.objects(bucket_id, name);\n\ngrant usage on schema storage to anon, authenticated, service_role;\ngrant select on storage.buckets to anon, authenticated, service_role;\ngrant all on storage.buckets to service_role;\ngrant all on storage.objects to anon, authenticated, service_role;\n\ncreate or replace function storage.foldername(name text) returns text[]\nlanguage sql immutable as $$\n select (string_to_array(name, '/'))[1 : array_length(string_to_array(name, '/'), 1) - 1]\n$$;\n\ncreate or replace function storage.filename(name text) returns text\nlanguage sql immutable as $$\n select (string_to_array(name, '/'))[array_length(string_to_array(name, '/'), 1)]\n$$;\n\ncreate or replace function storage.extension(name text) returns text\nlanguage sql immutable as $$\n select reverse(split_part(reverse(storage.filename(name)), '.', 1))\n$$;\n\nalter table storage.objects enable row level security;\n\ndrop policy if exists supacloud_lite_authenticated_all on storage.objects;\ndrop policy if exists supacloud_lite_public_read on storage.objects;\n\ndo $legacy_policy_cleanup$\ndeclare\n legacy_prefix constant text := 'tin' || 'base';\nbegin\n execute format(\n 'drop policy if exists %I on storage.objects',\n legacy_prefix || '_authenticated_all'\n );\n execute format(\n 'drop policy if exists %I on storage.objects',\n legacy_prefix || '_public_read'\n );\nend $legacy_policy_cleanup$;\n\n-- \u2500\u2500 Migration bookkeeping (same table the Supabase CLI uses) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists supabase_migrations;\n\ncreate table if not exists supabase_migrations.schema_migrations (\n version text primary key,\n name text,\n statements text[],\n applied_at timestamptz default now()\n);\n\ncreate table if not exists supabase_migrations.seed_files (\n path text primary key,\n hash text,\n applied_at timestamptz default now()\n);\n\n-- \u2500\u2500 Realtime CDC plumbing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndo $legacy_schema_upgrade$\ndeclare\n legacy_schema constant text := 'tin' || 'base';\nbegin\n if exists (select 1 from pg_namespace where nspname = legacy_schema)\n and not exists (select 1 from pg_namespace where nspname = 'supacloud_lite') then\n execute format('alter schema %I rename to supacloud_lite', legacy_schema);\n end if;\nend $legacy_schema_upgrade$;\n\ncreate schema if not exists supacloud_lite;\n\ncreate or replace function supacloud_lite.cdc_notify() returns trigger\nlanguage plpgsql security definer as $$\ndeclare\n payload text;\nbegin\n payload := json_build_object(\n 'schema', TG_TABLE_SCHEMA,\n 'table', TG_TABLE_NAME,\n 'type', TG_OP,\n 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'),\n 'record', case when TG_OP in ('INSERT', 'UPDATE') then row_to_json(NEW) else null end,\n 'old_record', case when TG_OP in ('UPDATE', 'DELETE') then row_to_json(OLD) else null end\n )::text;\n -- pg_notify payloads are capped at ~8kB; degrade like Supabase does.\n if octet_length(payload) > 7500 then\n payload := json_build_object(\n 'schema', TG_TABLE_SCHEMA,\n 'table', TG_TABLE_NAME,\n 'type', TG_OP,\n 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'),\n 'record', null,\n 'old_record', null,\n 'errors', json_build_array('Payload too large')\n )::text;\n end if;\n perform pg_notify('supacloud_lite_cdc', payload);\n return coalesce(NEW, OLD);\nend $$;\n\ndo $legacy_trigger_upgrade$\ndeclare\n legacy_schema constant text := 'tin' || 'base';\n legacy_trigger constant text := ('tin' || 'base') || '_cdc';\n trigger_record record;\n target_exists boolean;\nbegin\n for trigger_record in\n select c.oid as relation_oid, n.nspname as schema_name, c.relname as table_name\n from pg_trigger tg\n join pg_class c on c.oid = tg.tgrelid\n join pg_namespace n on n.oid = c.relnamespace\n join pg_proc p on p.oid = tg.tgfoid\n join pg_namespace pn on pn.oid = p.pronamespace\n where not tg.tgisinternal\n and tg.tgname = legacy_trigger\n and p.proname = 'cdc_notify'\n and pn.nspname in (legacy_schema, 'supacloud_lite')\n loop\n select exists (\n select 1\n from pg_trigger\n where not tgisinternal\n and tgrelid = trigger_record.relation_oid\n and tgname = 'supacloud_lite_cdc'\n ) into target_exists;\n\n execute format(\n 'drop trigger %I on %I.%I',\n legacy_trigger,\n trigger_record.schema_name,\n trigger_record.table_name\n );\n\n if not target_exists then\n execute format(\n 'create trigger supacloud_lite_cdc after insert or update or delete on %I.%I for each row execute function supacloud_lite.cdc_notify()',\n trigger_record.schema_name,\n trigger_record.table_name\n );\n end if;\n end loop;\nend $legacy_trigger_upgrade$;\n\ndo $legacy_schema_cleanup$\ndeclare\n legacy_schema constant text := 'tin' || 'base';\nbegin\n if exists (\n select 1\n from pg_proc p\n join pg_namespace n on n.oid = p.pronamespace\n where n.nspname = legacy_schema\n and p.proname = 'cdc_notify'\n and p.pronargs = 0\n ) then\n execute format('drop function %I.cdc_notify()', legacy_schema);\n end if;\n\n if exists (select 1 from pg_namespace where nspname = legacy_schema) then\n begin\n execute format('drop schema %I', legacy_schema);\n exception when dependent_objects_still_exist then\n raise notice 'SupaCloud Lite: retained non-empty legacy runtime schema';\n end;\n end if;\nend $legacy_schema_cleanup$;\n\n-- \u2500\u2500 Realtime Authorization + broadcast-from-database \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n-- Mirrors Supabase Realtime: developers write RLS policies on\n-- realtime.messages using realtime.topic(); a SELECT policy grants a private\n-- channel's subscribers the right to *receive*, an INSERT policy the right to\n-- *broadcast*. realtime.send() lets the database push a broadcast to a topic.\ncreate schema if not exists realtime;\n\ncreate table if not exists realtime.messages (\n id uuid not null default gen_random_uuid(),\n topic text not null,\n extension text not null,\n event text,\n payload jsonb,\n private boolean default false,\n inserted_at timestamptz not null default now(),\n updated_at timestamptz not null default now(),\n primary key (id)\n);\nalter table realtime.messages enable row level security;\n\ngrant usage on schema realtime to anon, authenticated, service_role;\ngrant all on realtime.messages to anon, authenticated, service_role;\n\n-- the topic currently being authorized/broadcast (set per operation)\ncreate or replace function realtime.topic() returns text\n language sql stable as $$ select nullif(current_setting('realtime.topic', true), '') $$;\n\n-- push a broadcast message to all subscribers of <topic> from SQL / triggers.\n-- Delivered over the websocket by the in-process realtime engine, which listens\n-- on the 'supacloud_lite_realtime_broadcast' channel.\ncreate or replace function realtime.send(payload jsonb, event text, topic text, private boolean default true)\n returns void language plpgsql security definer as $$\nbegin\n perform pg_notify(\n 'supacloud_lite_realtime_broadcast',\n json_build_object('topic', topic, 'event', event, 'payload', payload, 'private', private)::text\n );\nexception when others then\n -- never let a notify failure abort the caller's transaction\n null;\nend $$;\n\ngrant execute on function realtime.topic() to anon, authenticated, service_role;\ngrant execute on function realtime.send(jsonb, text, text, boolean) to anon, authenticated, service_role;\n";
|
|
20
|
+
export declare const BOOTSTRAP_SQL = "\n-- \u2500\u2500 Extensions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n-- Supabase enables these by default and migrations lean on them\n-- (uuid_generate_v4(), crypt(), citext, pg_trgm, \u2026). Each is created into the\n-- 'extensions' schema like hosted Supabase; any not available in this engine\n-- build is skipped rather than aborting the whole bootstrap.\ncreate schema if not exists extensions;\ndo $$\ndeclare ext text;\nbegin\n foreach ext in array array[\n 'uuid-ossp','pgcrypto','citext','pg_trgm','ltree','hstore','fuzzystrmatch',\n 'vector','postgis','pg_textsearch'\n ] loop\n begin\n execute format('create extension if not exists %I with schema extensions', ext);\n exception when others then\n -- extension not bundled in this engine build; continue\n end;\n end loop;\nend $$;\n\n-- The official pgmq extension owns its required pgmq schema. PGlite and\n-- native PostgreSQL builds that do not provide it simply continue to Lite's\n-- SQL fallback during database initialization.\ncreate schema if not exists pgmq;\ndo $$\nbegin\n begin\n create extension if not exists pgmq with schema pgmq;\n exception when others then\n null;\n end;\nend $$;\n\n-- uuid-ossp isn't in every Postgres build (it needs an external UUID lib at\n-- build time - e.g. the theseus Linux binaries omit it). uuid_generate_v4() is\n-- the single most-used function from it, so shim it onto core gen_random_uuid()\n-- (also a v4 UUID) whenever the real extension isn't present, so migrations\n-- that call it work identically on every engine and platform.\ndo $$\nbegin\n if not exists (\n select 1 from pg_proc p join pg_namespace n on n.oid = p.pronamespace\n where p.proname = 'uuid_generate_v4' and n.nspname in ('public', 'extensions')\n ) then\n create function extensions.uuid_generate_v4() returns uuid\n language sql volatile as 'select gen_random_uuid()';\n end if;\nend $$;\n\n-- Make extension functions resolvable unqualified (uuid_generate_v4(), \u2026) on\n-- the current session (migrations run here) and for future connections.\ndo $$\nbegin\n execute 'alter database ' || quote_ident(current_database()) ||\n ' set search_path to \"$user\", public, extensions';\nexception when others then\n -- some engines disallow altering the current database; session SET below still applies\nend $$;\nset search_path to \"$user\", public, extensions;\n\n-- \u2500\u2500 Roles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndo $$\nbegin\n if not exists (select from pg_roles where rolname = 'anon') then\n create role anon nologin noinherit;\n end if;\n if not exists (select from pg_roles where rolname = 'authenticated') then\n create role authenticated nologin noinherit;\n end if;\n if not exists (select from pg_roles where rolname = 'service_role') then\n create role service_role nologin noinherit bypassrls;\n end if;\nend $$;\n\ngrant usage on schema extensions to anon, authenticated, service_role;\nalter role anon set search_path to \"$user\", public, extensions;\nalter role authenticated set search_path to \"$user\", public, extensions;\nalter role service_role set search_path to \"$user\", public, extensions;\n\n-- Initialize defaults once. Restart/maintenance must not undo application ACLs.\ndo $$\nbegin\n if to_regclass('supabase_migrations.schema_migrations') is null then\n grant usage on schema public to anon, authenticated, service_role;\n alter default privileges in schema public\n grant all on tables to anon, authenticated, service_role;\n alter default privileges in schema public\n grant all on sequences to anon, authenticated, service_role;\n end if;\nend $$;\n\n-- PostgreSQL already grants EXECUTE on new functions to PUBLIC. Keep that\n-- default so project migrations can revoke PUBLIC and grant only selected\n-- roles without hidden direct grants from Lite. Existing ACLs are left intact.\n\n-- \u2500\u2500 Auth schema (GoTrue-compatible subset) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists auth;\n\ncreate table if not exists auth.users (\n instance_id uuid default '00000000-0000-0000-0000-000000000000',\n id uuid primary key default gen_random_uuid(),\n aud text default 'authenticated',\n role text default 'authenticated',\n email text unique,\n encrypted_password text,\n email_confirmed_at timestamptz,\n invited_at timestamptz,\n confirmation_token text default '',\n confirmation_sent_at timestamptz,\n recovery_token text default '',\n recovery_sent_at timestamptz,\n email_change_token_new text default '',\n email_change text default '',\n email_change_sent_at timestamptz,\n email_change_token_current text default '',\n email_change_confirm_status smallint default 0,\n last_sign_in_at timestamptz,\n raw_app_meta_data jsonb default '{}'::jsonb,\n raw_user_meta_data jsonb default '{}'::jsonb,\n is_super_admin boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n phone text unique,\n phone_confirmed_at timestamptz,\n phone_change text default '',\n phone_change_token text default '',\n phone_change_sent_at timestamptz,\n reauthentication_token text default '',\n reauthentication_sent_at timestamptz,\n banned_until timestamptz,\n deleted_at timestamptz,\n is_anonymous boolean default false\n);\n\nalter table auth.users add column if not exists email_change text;\nalter table auth.users add column if not exists email_change_sent_at timestamptz;\nalter table auth.users add column if not exists email_change_token_new text default '';\nalter table auth.users add column if not exists email_change_token_current text default '';\nalter table auth.users add column if not exists email_change_confirm_status smallint default 0;\n\ncreate table if not exists auth.refresh_tokens (\n id bigint generated by default as identity primary key,\n token text unique not null,\n user_id uuid not null references auth.users(id) on delete cascade,\n parent text,\n session_id uuid,\n revoked boolean default false,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate index if not exists refresh_tokens_user_id_idx on auth.refresh_tokens(user_id);\n\ncreate table if not exists auth.one_time_tokens (\n id uuid primary key default gen_random_uuid(),\n user_id uuid references auth.users(id) on delete cascade,\n email text,\n phone text,\n token_type text not null, -- otp | magiclink | recovery | sms\n token text not null,\n attempts int not null default 0,\n created_at timestamptz default now(),\n expires_at timestamptz not null,\n constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n )\n);\n\n-- Upgrade databases created by Lite <=0.5.9 without touching existing email tokens.\nalter table auth.one_time_tokens add column if not exists phone text;\nalter table auth.one_time_tokens alter column email drop not null;\ndo $phone_otp_contact_constraint$\nbegin\n if not exists (\n select 1 from pg_constraint\n where conrelid = 'auth.one_time_tokens'::regclass\n and conname = 'one_time_tokens_contact_check'\n ) then\n alter table auth.one_time_tokens add constraint one_time_tokens_contact_check check (\n (email is not null and phone is null) or (email is null and phone is not null)\n );\n end if;\nend $phone_otp_contact_constraint$;\n\ncreate unique index if not exists one_time_tokens_phone_type_idx\n on auth.one_time_tokens(phone, token_type) where phone is not null;\n\n-- Only a keyed phone fingerprint is persisted for cooldown enforcement; the\n-- normalized phone number never enters this table.\ncreate table if not exists auth.phone_otp_cooldowns (\n phone_fingerprint text primary key,\n issuance_id uuid not null,\n last_sent_at timestamptz not null default now()\n);\n\ncreate table if not exists auth.identities (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null references auth.users(id) on delete cascade,\n provider text not null,\n provider_id text not null,\n identity_data jsonb default '{}'::jsonb,\n last_sign_in_at timestamptz default now(),\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n unique (provider, provider_id)\n);\n\n-- OAuth / PKCE flow state, bridging /authorize \u2192 provider \u2192 /callback \u2192 exchange\ncreate table if not exists auth.flow_state (\n id uuid primary key default gen_random_uuid(),\n provider text not null,\n provider_state text not null unique,\n redirect_to text,\n code_challenge text,\n code_challenge_method text,\n auth_code text unique,\n user_id uuid references auth.users(id) on delete cascade,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\nalter table auth.flow_state add column if not exists link_user_id uuid;\n\ncreate table if not exists auth.mfa_factors (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null references auth.users(id) on delete cascade,\n friendly_name text,\n factor_type text not null default 'totp',\n status text not null default 'unverified', -- unverified | verified\n secret text,\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\ncreate table if not exists auth.mfa_challenges (\n id uuid primary key default gen_random_uuid(),\n factor_id uuid not null references auth.mfa_factors(id) on delete cascade,\n verified_at timestamptz,\n created_at timestamptz default now(),\n expires_at timestamptz not null\n);\n\ncreate table if not exists auth.mfa_recovery_code_sets (\n id uuid primary key default gen_random_uuid(),\n user_id uuid not null references auth.users(id) on delete cascade,\n mfa_factor_id uuid not null unique references auth.mfa_factors(id) on delete cascade,\n failed_verification_count int not null default 0,\n verification_locked_until timestamptz,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n unique (user_id)\n);\n\ncreate table if not exists auth.mfa_recovery_codes (\n id uuid primary key default gen_random_uuid(),\n mfa_recovery_code_set_id uuid not null references auth.mfa_recovery_code_sets(id) on delete cascade,\n code_hash text not null,\n consumed_at timestamptz,\n created_at timestamptz default now()\n);\n\n-- append-only security audit trail (GoTrue-compatible shape)\ncreate table if not exists auth.audit_log_entries (\n instance_id uuid default '00000000-0000-0000-0000-000000000000',\n id uuid primary key default gen_random_uuid(),\n payload jsonb,\n created_at timestamptz default now(),\n ip_address varchar(64) not null default ''\n);\ncreate index if not exists audit_logs_instance_id_idx on auth.audit_log_entries(created_at);\n\n-- runtime-mutable instance settings (Studio auth toggles)\ncreate table if not exists auth.config (\n key text primary key,\n value jsonb not null,\n updated_at timestamptz default now()\n);\n\ngrant usage on schema auth to anon, authenticated, service_role;\n\ncreate or replace function auth.jwt() returns jsonb\nlanguage sql stable as $$\n select coalesce(\n nullif(current_setting('request.jwt.claims', true), ''),\n '{}'\n )::jsonb\n$$;\n\ncreate or replace function auth.uid() returns uuid\nlanguage sql stable as $$\n select nullif(auth.jwt() ->> 'sub', '')::uuid\n$$;\n\ncreate or replace function auth.role() returns text\nlanguage sql stable as $$\n select coalesce(auth.jwt() ->> 'role', 'anon')\n$$;\n\ncreate or replace function auth.email() returns text\nlanguage sql stable as $$\n select auth.jwt() ->> 'email'\n$$;\n\ngrant execute on function auth.jwt(), auth.uid(), auth.role(), auth.email()\n to anon, authenticated, service_role;\n\n-- \u2500\u2500 Storage schema (storage-api-compatible subset) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists storage;\n\ncreate table if not exists storage.buckets (\n id text primary key,\n name text not null unique,\n owner uuid,\n owner_id text,\n public boolean default false,\n file_size_limit bigint,\n allowed_mime_types text[],\n created_at timestamptz default now(),\n updated_at timestamptz default now()\n);\n\nalter table storage.buckets add column if not exists owner_id text;\nupdate storage.buckets\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate table if not exists storage.objects (\n id uuid primary key default gen_random_uuid(),\n bucket_id text not null references storage.buckets(id),\n name text not null,\n owner uuid,\n owner_id text,\n version text,\n metadata jsonb default '{}'::jsonb,\n created_at timestamptz default now(),\n updated_at timestamptz default now(),\n last_accessed_at timestamptz default now(),\n unique (bucket_id, name)\n);\n\n-- storage-api keeps the legacy UUID owner and the current text owner_id in\n-- parallel. Re-running bootstrap upgrades existing Lite databases and retains\n-- object ownership for rows created before owner_id support was added.\nalter table storage.objects add column if not exists owner_id text;\nupdate storage.objects\nset owner_id = owner::text\nwhere owner_id is null and owner is not null;\n\ncreate index if not exists objects_bucket_name_idx on storage.objects(bucket_id, name);\n\ngrant usage on schema storage to anon, authenticated, service_role;\ngrant select on storage.buckets to anon, authenticated, service_role;\ngrant all on storage.buckets to service_role;\ngrant all on storage.objects to anon, authenticated, service_role;\n\ncreate or replace function storage.foldername(name text) returns text[]\nlanguage sql immutable as $$\n select (string_to_array(name, '/'))[1 : array_length(string_to_array(name, '/'), 1) - 1]\n$$;\n\ncreate or replace function storage.filename(name text) returns text\nlanguage sql immutable as $$\n select (string_to_array(name, '/'))[array_length(string_to_array(name, '/'), 1)]\n$$;\n\ncreate or replace function storage.extension(name text) returns text\nlanguage sql immutable as $$\n select reverse(split_part(reverse(storage.filename(name)), '.', 1))\n$$;\n\nalter table storage.objects enable row level security;\n\ndrop policy if exists supacloud_lite_authenticated_all on storage.objects;\ndrop policy if exists supacloud_lite_public_read on storage.objects;\n\ndo $legacy_policy_cleanup$\ndeclare\n legacy_prefix constant text := 'tin' || 'base';\nbegin\n execute format(\n 'drop policy if exists %I on storage.objects',\n legacy_prefix || '_authenticated_all'\n );\n execute format(\n 'drop policy if exists %I on storage.objects',\n legacy_prefix || '_public_read'\n );\nend $legacy_policy_cleanup$;\n\n-- \u2500\u2500 Migration bookkeeping (same table the Supabase CLI uses) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ncreate schema if not exists supabase_migrations;\n\ncreate table if not exists supabase_migrations.schema_migrations (\n version text primary key,\n name text,\n statements text[],\n applied_at timestamptz default now()\n);\n\ncreate table if not exists supabase_migrations.seed_files (\n path text primary key,\n hash text,\n applied_at timestamptz default now()\n);\n\n-- \u2500\u2500 Realtime CDC plumbing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndo $legacy_schema_upgrade$\ndeclare\n legacy_schema constant text := 'tin' || 'base';\nbegin\n if exists (select 1 from pg_namespace where nspname = legacy_schema)\n and not exists (select 1 from pg_namespace where nspname = 'supacloud_lite') then\n execute format('alter schema %I rename to supacloud_lite', legacy_schema);\n end if;\nend $legacy_schema_upgrade$;\n\ncreate schema if not exists supacloud_lite;\n\ncreate or replace function supacloud_lite.cdc_notify() returns trigger\nlanguage plpgsql security definer as $$\ndeclare\n payload text;\nbegin\n payload := json_build_object(\n 'schema', TG_TABLE_SCHEMA,\n 'table', TG_TABLE_NAME,\n 'type', TG_OP,\n 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'),\n 'record', case when TG_OP in ('INSERT', 'UPDATE') then row_to_json(NEW) else null end,\n 'old_record', case when TG_OP in ('UPDATE', 'DELETE') then row_to_json(OLD) else null end\n )::text;\n -- pg_notify payloads are capped at ~8kB; degrade like Supabase does.\n if octet_length(payload) > 7500 then\n payload := json_build_object(\n 'schema', TG_TABLE_SCHEMA,\n 'table', TG_TABLE_NAME,\n 'type', TG_OP,\n 'commit_timestamp', to_char(now() at time zone 'utc', 'YYYY-MM-DD\"T\"HH24:MI:SS.MS\"Z\"'),\n 'record', null,\n 'old_record', null,\n 'errors', json_build_array('Payload too large')\n )::text;\n end if;\n perform pg_notify('supacloud_lite_cdc', payload);\n return coalesce(NEW, OLD);\nend $$;\n\ndo $legacy_trigger_upgrade$\ndeclare\n legacy_schema constant text := 'tin' || 'base';\n legacy_trigger constant text := ('tin' || 'base') || '_cdc';\n trigger_record record;\n target_exists boolean;\nbegin\n for trigger_record in\n select c.oid as relation_oid, n.nspname as schema_name, c.relname as table_name\n from pg_trigger tg\n join pg_class c on c.oid = tg.tgrelid\n join pg_namespace n on n.oid = c.relnamespace\n join pg_proc p on p.oid = tg.tgfoid\n join pg_namespace pn on pn.oid = p.pronamespace\n where not tg.tgisinternal\n and tg.tgname = legacy_trigger\n and p.proname = 'cdc_notify'\n and pn.nspname in (legacy_schema, 'supacloud_lite')\n loop\n select exists (\n select 1\n from pg_trigger\n where not tgisinternal\n and tgrelid = trigger_record.relation_oid\n and tgname = 'supacloud_lite_cdc'\n ) into target_exists;\n\n execute format(\n 'drop trigger %I on %I.%I',\n legacy_trigger,\n trigger_record.schema_name,\n trigger_record.table_name\n );\n\n if not target_exists then\n execute format(\n 'create trigger supacloud_lite_cdc after insert or update or delete on %I.%I for each row execute function supacloud_lite.cdc_notify()',\n trigger_record.schema_name,\n trigger_record.table_name\n );\n end if;\n end loop;\nend $legacy_trigger_upgrade$;\n\ndo $legacy_schema_cleanup$\ndeclare\n legacy_schema constant text := 'tin' || 'base';\nbegin\n if exists (\n select 1\n from pg_proc p\n join pg_namespace n on n.oid = p.pronamespace\n where n.nspname = legacy_schema\n and p.proname = 'cdc_notify'\n and p.pronargs = 0\n ) then\n execute format('drop function %I.cdc_notify()', legacy_schema);\n end if;\n\n if exists (select 1 from pg_namespace where nspname = legacy_schema) then\n begin\n execute format('drop schema %I', legacy_schema);\n exception when dependent_objects_still_exist then\n raise notice 'SupaCloud Lite: retained non-empty legacy runtime schema';\n end;\n end if;\nend $legacy_schema_cleanup$;\n\n-- \u2500\u2500 Realtime Authorization + broadcast-from-database \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n-- Mirrors Supabase Realtime: developers write RLS policies on\n-- realtime.messages using realtime.topic(); a SELECT policy grants a private\n-- channel's subscribers the right to *receive*, an INSERT policy the right to\n-- *broadcast*. realtime.send() lets the database push a broadcast to a topic.\ncreate schema if not exists realtime;\n\ncreate table if not exists realtime.messages (\n id uuid not null default gen_random_uuid(),\n topic text not null,\n extension text not null,\n event text,\n payload jsonb,\n private boolean default false,\n inserted_at timestamptz not null default now(),\n updated_at timestamptz not null default now(),\n primary key (id)\n);\nalter table realtime.messages enable row level security;\n\ngrant usage on schema realtime to anon, authenticated, service_role;\ngrant all on realtime.messages to anon, authenticated, service_role;\n\n-- the topic currently being authorized/broadcast (set per operation)\ncreate or replace function realtime.topic() returns text\n language sql stable as $$ select nullif(current_setting('realtime.topic', true), '') $$;\n\n-- push a broadcast message to all subscribers of <topic> from SQL / triggers.\n-- Delivered over the websocket by the in-process realtime engine, which listens\n-- on the 'supacloud_lite_realtime_broadcast' channel.\ncreate or replace function realtime.send(payload jsonb, event text, topic text, private boolean default true)\n returns void language plpgsql security definer as $$\nbegin\n perform pg_notify(\n 'supacloud_lite_realtime_broadcast',\n json_build_object('topic', topic, 'event', event, 'payload', payload, 'private', private)::text\n );\nexception when others then\n -- never let a notify failure abort the caller's transaction\n null;\nend $$;\n\ngrant execute on function realtime.topic() to anon, authenticated, service_role;\ngrant execute on function realtime.send(jsonb, text, text, boolean) to anon, authenticated, service_role;\n";
|
|
21
21
|
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/runtime/db/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/runtime/db/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,goOAoNjC,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,+4rBAgjBzB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supacloud/lite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -59,17 +59,17 @@
|
|
|
59
59
|
"@electric-sql/pglite-pgmq": "0.0.8",
|
|
60
60
|
"@electric-sql/pglite-pgvector": "0.0.11",
|
|
61
61
|
"@electric-sql/pglite-postgis": "0.2.10",
|
|
62
|
-
"@supacloud/db": "0.
|
|
62
|
+
"@supacloud/db": "0.20.0",
|
|
63
63
|
"exact-mirror": "1.2.6",
|
|
64
64
|
"tar": "^7.5.22",
|
|
65
65
|
"typebox": "1.3.37"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@supacloud/app": "0.
|
|
69
|
-
"@supacloud/contracts": "0.
|
|
70
|
-
"@supacloud/compiler": "0.
|
|
71
|
-
"@supacloud/elysia": "0.
|
|
72
|
-
"@supabase/supabase-js": "^2.
|
|
68
|
+
"@supacloud/app": "0.31.0",
|
|
69
|
+
"@supacloud/contracts": "0.13.0",
|
|
70
|
+
"@supacloud/compiler": "0.50.0",
|
|
71
|
+
"@supacloud/elysia": "0.35.1",
|
|
72
|
+
"@supabase/supabase-js": "^2.118.0",
|
|
73
73
|
"@types/bun": "^1.4.3",
|
|
74
74
|
"effect": "4.0.5",
|
|
75
75
|
"elysia": "2.0.0-beta.32",
|
|
@@ -77,13 +77,13 @@
|
|
|
77
77
|
"typescript": "^7.0.2"
|
|
78
78
|
},
|
|
79
79
|
"overrides": {
|
|
80
|
-
"@supacloud/db": "0.
|
|
81
|
-
"@supacloud/app": "0.
|
|
82
|
-
"@supacloud/compiler": "0.
|
|
83
|
-
"@supacloud/elysia": "0.
|
|
84
|
-
"@supacloud/contracts": "0.
|
|
85
|
-
"@supacloud/commands": "0.
|
|
86
|
-
"@supacloud/delivery": "0.
|
|
80
|
+
"@supacloud/db": "0.20.0",
|
|
81
|
+
"@supacloud/app": "0.31.0",
|
|
82
|
+
"@supacloud/compiler": "0.50.0",
|
|
83
|
+
"@supacloud/elysia": "0.35.1",
|
|
84
|
+
"@supacloud/contracts": "0.13.0",
|
|
85
|
+
"@supacloud/commands": "0.11.0",
|
|
86
|
+
"@supacloud/delivery": "0.21.0",
|
|
87
87
|
"@graphql-tools/utils": "^12.0.4"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|