@webstudio-is/postgrest 0.252.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.
@@ -0,0 +1,16 @@
1
+ import type { Database } from "./__generated__/db-types";
2
+ import { PostgrestClient } from "@supabase/postgrest-js";
3
+ export type { Database } from "./__generated__/db-types";
4
+
5
+ export type Client = PostgrestClient<Database>;
6
+
7
+ export const createClient = (url: string, apiKey: string): Client => {
8
+ const client = new PostgrestClient<Database>(url, {
9
+ headers: {
10
+ apikey: apiKey,
11
+ Authorization: `Bearer ${apiKey}`,
12
+ },
13
+ });
14
+
15
+ return client;
16
+ };
@@ -0,0 +1,161 @@
1
+ # Sql Testing AI Helpers
2
+
3
+ Extract schema
4
+
5
+ ```bash
6
+ pnpx supabase db dump -s public --db-url postgresql://postgres:pass@localhost/webstudio > schema.sql
7
+ ```
8
+
9
+ Promt Examples
10
+
11
+ ---
12
+
13
+ Below is a partial dump of the SQL schema:
14
+
15
+ ```sql
16
+
17
+ CREATE TABLE IF NOT EXISTS "public"."User" (
18
+ "id" "text" NOT NULL,
19
+ "createdAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
20
+ "email" "text",
21
+ "image" "text",
22
+ "provider" "text",
23
+ "username" "text",
24
+ "teamId" "text"
25
+ );
26
+
27
+
28
+ CREATE TABLE IF NOT EXISTS "public"."Domain" (
29
+ "id" "text" NOT NULL,
30
+ "domain" "text" NOT NULL,
31
+ "createdAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
32
+ "txtRecord" "text",
33
+ "status" "public"."DomainStatus" DEFAULT 'INITIALIZING'::"public"."DomainStatus" NOT NULL,
34
+ "error" "text",
35
+ "updatedAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
36
+ );
37
+
38
+ CREATE TABLE IF NOT EXISTS "public"."Build" (
39
+ "id" "text" NOT NULL,
40
+ "createdAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
41
+ "pages" "text" NOT NULL,
42
+ "projectId" "text" NOT NULL,
43
+ "styleSources" "text" DEFAULT '[]'::"text" NOT NULL,
44
+ "styles" "text" DEFAULT '[]'::"text" NOT NULL,
45
+ "breakpoints" "text" DEFAULT '[]'::"text" NOT NULL,
46
+ "styleSourceSelections" "text" DEFAULT '[]'::"text" NOT NULL,
47
+ "props" "text" DEFAULT '[]'::"text" NOT NULL,
48
+ "instances" "text" DEFAULT '[]'::"text" NOT NULL,
49
+ "updatedAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
50
+ "version" integer DEFAULT 0 NOT NULL,
51
+ "deployment" "text",
52
+ "publishStatus" "public"."PublishStatus" DEFAULT 'PENDING'::"public"."PublishStatus" NOT NULL,
53
+ "dataSources" "text" DEFAULT '[]'::"text" NOT NULL,
54
+ "lastTransactionId" "text",
55
+ "resources" "text" DEFAULT '[]'::"text" NOT NULL,
56
+ "marketplaceProduct" "text" DEFAULT '{}'::"text" NOT NULL
57
+ );
58
+
59
+ CREATE TABLE IF NOT EXISTS "public"."Project" (
60
+ "id" "text" NOT NULL,
61
+ "title" "text" NOT NULL,
62
+ "domain" "text" NOT NULL,
63
+ "userId" "text",
64
+ "isDeleted" boolean DEFAULT false NOT NULL,
65
+ "createdAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
66
+ "previewImageAssetId" "text",
67
+ "marketplaceApprovalStatus" "public"."MarketplaceApprovalStatus" DEFAULT 'UNLISTED'::"public"."MarketplaceApprovalStatus" NOT NULL
68
+ );
69
+
70
+ CREATE TABLE IF NOT EXISTS "public"."ProjectDomain" (
71
+ "projectId" "text" NOT NULL,
72
+ "domainId" "text" NOT NULL,
73
+ "createdAt" timestamp(3) with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
74
+ "txtRecord" "text" NOT NULL,
75
+ "cname" "text" NOT NULL
76
+ );
77
+
78
+ CREATE OR REPLACE FUNCTION "public"."latestBuildVirtual"("public"."Project") RETURNS SETOF "public"."latestBuildVirtual"
79
+ LANGUAGE "sql" STABLE ROWS 1
80
+ AS $_$ -- The function is expected to return 1 row
81
+
82
+
83
+ SELECT
84
+ b.id AS "buildId",
85
+ b."projectId",
86
+ -- Use CASE to determine which domain to select based on conditions
87
+ CASE
88
+ WHEN (b.deployment::jsonb ->> 'projectDomain') = p.domain
89
+ OR (b.deployment::jsonb -> 'domains') @> to_jsonb(array[p.domain])
90
+ THEN p.domain
91
+ ELSE d.domain
92
+ END AS "domain",
93
+ b."createdAt",
94
+ b."publishStatus"
95
+ FROM "Build" b
96
+ JOIN "Project" p ON b."projectId" = p.id
97
+ LEFT JOIN "ProjectDomain" pd ON pd."projectId" = p.id
98
+ LEFT JOIN "Domain" d ON d.id = pd."domainId"
99
+ WHERE b."projectId" = $1.id
100
+ AND b.deployment IS NOT NULL
101
+ -- 'destination' IS NULL for backward compatibility; 'destination' = 'saas' for non-static builds
102
+ AND ((b.deployment::jsonb ->> 'destination') IS NULL OR (b.deployment::jsonb ->> 'destination') = 'saas')
103
+ AND (
104
+ -- Check if 'projectDomain' matches p.domain
105
+ (b.deployment::jsonb ->> 'projectDomain') = p.domain
106
+ -- Check if 'domains' contains p.domain or d.domain
107
+ OR (b.deployment::jsonb -> 'domains') @> to_jsonb(array[p.domain])
108
+ OR (b.deployment::jsonb -> 'domains') @> to_jsonb(array[d.domain])
109
+ )
110
+ ORDER BY b."createdAt" DESC
111
+ LIMIT 1;
112
+
113
+ $_$;
114
+
115
+ ```
116
+
117
+ Create a pgTAP test for the function "public"."latestBuildVirtual" that takes "public"."Project" as an argument.
118
+
119
+ ---
120
+
121
+ ## Additional Instructions
122
+
123
+ These instructions are sometimes necessary, while at other times they may not be required.
124
+
125
+ All fields, such as `projectId`, already reference their corresponding table columns (e.g., `"Project"."id"`), but foreign key constraints are omitted.
126
+
127
+ - **Data Integrity:** Do not create new tables for `"public"."Project"` or related entities. These tables already exist in the database. DO NOT TRUNCATE DROP or DELETE Existing tables.
128
+
129
+ - **Data Accuracy:** When inserting new data, adhere strictly to the NULL constraints. Ensure all fields without default values are filled correctly in every `INSERT` statement.
130
+ you may omit fields with default values if they are not directly relevant to the tests, except for `"createdAt"` and `"updatedAt"` fields, which should always be specified with explicit timestamp values.
131
+
132
+ - **Timestamp Fields:** For fields like `"createdAt"` and `"updatedAt"`, always use specific timestamp values rather than functions like `NOW()`.
133
+
134
+ - **Naming Conventions:** Since field and function names use camelCase, always wrap them in double quotes (`""`) to ensure proper referencing.
135
+
136
+ - **Test Coverage:** In addition to standard tests, cover additional cases to validate that the function returns the correct data in different scenarios:
137
+
138
+ 1. When a project has changed its domain.
139
+ 2. When builds with the new domain do not exist and when they do exist.
140
+ 3. When the domain is either in `Build.deployment.projectDomain` or included in `Build.deployment.domains`.
141
+
142
+ - **Function Calls:** Use precise casting for function calls, such as `(p.*)::Project`, to ensure accuracy in test execution.
143
+
144
+ Ensure the tests comprehensively validate the function’s behavior in all specified cases.
145
+
146
+ In addition to the specific test cases mentioned, any other test scenarios the model identifies would be highly appreciated.
147
+
148
+ Examples of calling the function:
149
+
150
+ ```sql
151
+
152
+ select "public"."latestBuildVirtual"((p.*)::"Project") from "public"."Project" p where p.id = '1';
153
+ ```
154
+
155
+ ---
156
+
157
+ ## PS
158
+
159
+ Initially, it may produce non-working examples. However, it seems that a multi-step improvement process can enhance the results. By incorporating the additions mentioned above, you can achieve better final outcomes. While not perfect, it serves as a good starting point.
160
+
161
+ Seems like the shorter the input the better the results. The models are seems to struggle with longer inputs.
@@ -0,0 +1,227 @@
1
+ BEGIN;
2
+ SET LOCAL search_path = pgtap, public;
3
+ -- Initialize the testing environment without planning any specific number of tests
4
+ -- We are using SELECT no_plan() because we don't specify the exact number of tests upfront.
5
+ SELECT no_plan();
6
+
7
+ -- =========================================
8
+ -- Setup: Insert initial data for Users, Projects, Domains, ProjectDomains, and Builds
9
+ -- =========================================
10
+
11
+ -- Insert a user into the "User" table
12
+ INSERT INTO "public"."User" ("id", "createdAt", "email", "username")
13
+ VALUES
14
+ ('user1', '2023-01-01 00:00:00+00', 'user1@517cce32-9af3-example.com', 'user1');
15
+
16
+ -- Insert projects associated with the user into the "Project" table
17
+ INSERT INTO "public"."Project" ("id", "title", "domain", "userId", "isDeleted", "createdAt")
18
+ VALUES
19
+ ('project1', 'Project One', '517cce32-9af3-project1-domain1', 'user1', false, '2023-01-01 00:00:00+00'),
20
+ ('project2', 'Project Two', '517cce32-9af3-project2-domain1', 'user1', false, '2023-01-01 00:00:00+00');
21
+
22
+ -- Insert custom domains into the "Domain" table
23
+ INSERT INTO "public"."Domain" ("id", "domain", "createdAt", "status", "updatedAt")
24
+ VALUES
25
+ ('project-1-custom-domain-1', '517cce32-9af3-project-1-custom-domain-1.com', '2023-01-01 00:00:00+00', 'INITIALIZING', '2023-01-01 00:00:00+00'),
26
+ ('project-1-custom-domain-2', '517cce32-9af3-project-1-custom-domain-2.com', '2023-01-01 00:00:00+00', 'INITIALIZING', '2023-01-01 00:00:00+00'),
27
+ ('project-2-custom-domain-1', '517cce32-9af3-project-2-custom-domain-1.com', '2023-01-01 00:00:00+00', 'INITIALIZING', '2023-01-01 00:00:00+00'),
28
+ ('project-2-custom-domain-2', '517cce32-9af3-project-2-custom-domain-2.com', '2023-01-01 00:00:00+00', 'INITIALIZING', '2023-01-01 00:00:00+00');
29
+
30
+ -- Establish relationships between projects and custom domains in the "ProjectDomain" table
31
+ INSERT INTO "public"."ProjectDomain" ("projectId", "domainId", "createdAt", "txtRecord", "cname")
32
+ VALUES
33
+ ('project1', 'project-1-custom-domain-1', '2023-01-01 00:00:00+00', 'txtRecord1', 'cname1'),
34
+ ('project1', 'project-1-custom-domain-2', '2023-01-01 00:00:00+00', 'txtRecord2', 'cname2'),
35
+ ('project2', 'project-2-custom-domain-1', '2023-01-01 00:00:00+00', 'p2-txtRecord1', 'cname1'),
36
+ ('project2', 'project-2-custom-domain-2', '2023-01-01 00:00:00+00', 'p2-txtRecord2', 'cname2');
37
+
38
+ -- Insert initial builds into the "Build" table
39
+ INSERT INTO "public"."Build" (
40
+ "id",
41
+ "createdAt",
42
+ "pages",
43
+ "projectId",
44
+ "deployment",
45
+ "updatedAt",
46
+ "publishStatus"
47
+ )
48
+ VALUES
49
+ -- Development Build for Project1
50
+ (
51
+ 'build1-development',
52
+ '1990-01-01 00:00:00+00',
53
+ 'home',
54
+ 'project1',
55
+ NULL,
56
+ '1990-01-01 00:00:00+00',
57
+ 'PENDING'
58
+ ),
59
+ -- Development Build for Project2
60
+ (
61
+ 'project2-build1-development',
62
+ '1990-01-01 00:00:00+00',
63
+ 'home',
64
+ 'project2',
65
+ NULL,
66
+ '1990-01-01 00:00:00+00',
67
+ 'PENDING'
68
+ ),
69
+ -- Custom Domain Build for Project2
70
+ (
71
+ 'project2-build1-for-custom-domain-1',
72
+ '1990-01-02 00:00:00+00',
73
+ 'home',
74
+ 'project2',
75
+ '{"domains": ["517cce32-9af3-project-2-custom-domain-1.com"]}'::text,
76
+ '1990-01-02 00:00:00+00',
77
+ 'PUBLISHED'
78
+ ),
79
+ -- Project Domain Build for Project2
80
+ (
81
+ 'project2-build1-for-project-domain-1',
82
+ '1990-01-01 00:00:00+00',
83
+ 'home',
84
+ 'project2',
85
+ '{"domains": ["517cce32-9af3-project2-domain1"]}'::text,
86
+ '1990-01-01 00:00:00+00',
87
+ 'PUBLISHED'
88
+ ),
89
+ -- Custom Domain Build for Project1
90
+ (
91
+ 'build1-for-custom-domain-1',
92
+ '1990-01-02 00:00:00+00',
93
+ 'home',
94
+ 'project1',
95
+ '{"domains": ["517cce32-9af3-project-1-custom-domain-1.com"]}'::text,
96
+ '1990-01-02 00:00:00+00',
97
+ 'PUBLISHED'
98
+ ),
99
+ -- Project Domain Build for Project1
100
+ (
101
+ 'build1-for-project-domain-1',
102
+ '1990-01-01 00:00:00+00',
103
+ 'home',
104
+ 'project1',
105
+ '{"domains": ["517cce32-9af3-project1-domain1"]}'::text,
106
+ '1990-01-01 00:00:00+00',
107
+ 'PUBLISHED'
108
+ );
109
+
110
+ -- =========================================
111
+ -- Test 1: Verify that initial cleanup does not clean any builds
112
+ -- =========================================
113
+
114
+ -- Run the database cleanup function for builds created in 1990
115
+ SELECT database_cleanup('1990-01-01 00:00:00', '1990-12-31 23:59:59');
116
+
117
+ -- Assert that no builds have been cleaned up initially
118
+ SELECT is(
119
+ (SELECT count(*)::integer FROM "Build" WHERE "createdAt" BETWEEN '1990-01-01' AND '1990-12-31' AND "isCleaned" = TRUE),
120
+ 0,
121
+ 'Test 1: No builds should be cleaned up on initial cleanup'
122
+ );
123
+
124
+ -- =========================================
125
+ -- Test 2: Insert a new project domain build and verify cleanup
126
+ -- =========================================
127
+
128
+ -- Insert a new build for the project domain
129
+ INSERT INTO "public"."Build" (
130
+ "id",
131
+ "createdAt",
132
+ "pages",
133
+ "projectId",
134
+ "deployment",
135
+ "updatedAt",
136
+ "publishStatus"
137
+ )
138
+ VALUES
139
+ -- New Project Domain Build for Project1
140
+ (
141
+ 'build2-for-project-domain-1',
142
+ '1990-01-02 00:00:00+00', -- A later date than the previous build
143
+ 'home',
144
+ 'project1',
145
+ '{"domains": ["517cce32-9af3-project1-domain1"]}'::text,
146
+ '1990-01-02 00:00:00+00',
147
+ 'PUBLISHED'
148
+ );
149
+
150
+ -- Run the database cleanup function again
151
+ SELECT database_cleanup('1990-01-01 00:00:00', '1990-12-31 23:59:59');
152
+
153
+ -- Assert that one build has been cleaned (the previous project domain build)
154
+ SELECT is(
155
+ (SELECT count(*)::integer FROM "Build" WHERE "createdAt" BETWEEN '1990-01-01' AND '1990-12-31' AND "isCleaned" = TRUE),
156
+ 1,
157
+ 'Test 2: Previous project domain build should be cleaned up after new build is published'
158
+ );
159
+
160
+ -- Assert that the specific build cleaned is 'build1-for-project-domain-1'
161
+ SELECT is(
162
+ (SELECT id FROM "Build" WHERE "createdAt" BETWEEN '1990-01-01' AND '1990-12-31' AND "isCleaned" = TRUE),
163
+ 'build1-for-project-domain-1',
164
+ 'Test 2: Build "build1-for-project-domain-1" should be marked as cleaned'
165
+ );
166
+
167
+ -- =========================================
168
+ -- Test 3: Insert a new custom domain build and verify cleanup
169
+ -- =========================================
170
+
171
+ -- Insert a new build for the custom domain
172
+ INSERT INTO "public"."Build" (
173
+ "id",
174
+ "createdAt",
175
+ "pages",
176
+ "projectId",
177
+ "deployment",
178
+ "updatedAt",
179
+ "publishStatus"
180
+ )
181
+ VALUES
182
+ -- New Custom Domain Build for Project1
183
+ (
184
+ 'build2-for-custom-domain-1',
185
+ '1990-01-03 00:00:00+00', -- A later date than the previous build
186
+ 'home',
187
+ 'project1',
188
+ '{"domains": ["517cce32-9af3-project-1-custom-domain-1.com"]}'::text,
189
+ '1990-01-03 00:00:00+00',
190
+ 'PUBLISHED'
191
+ );
192
+
193
+ -- Run the database cleanup function again
194
+ SELECT database_cleanup('1990-01-01 00:00:00', '1990-12-31 23:59:59');
195
+
196
+ -- Assert that two builds have been cleaned (the previous project domain and custom domain builds)
197
+ SELECT is(
198
+ (SELECT count(*)::integer FROM "Build" WHERE "createdAt" BETWEEN '1990-01-01' AND '1990-12-31' AND "isCleaned" = TRUE),
199
+ 2,
200
+ 'Test 3: Previous custom domain build should be cleaned up after new build is published'
201
+ );
202
+
203
+ -- Assert that the builds cleaned are 'build1-for-custom-domain-1' and 'build1-for-project-domain-1'
204
+ SELECT results_eq(
205
+ $$
206
+ SELECT id FROM "Build" WHERE "createdAt" BETWEEN '1990-01-01' AND '1990-12-31' AND "isCleaned" = TRUE ORDER BY id
207
+ $$,
208
+ $$
209
+ SELECT * FROM (
210
+ VALUES
211
+ ('build1-for-custom-domain-1'),
212
+ ('build1-for-project-domain-1')
213
+ ) AS expected(id)
214
+ ORDER BY "id"
215
+ $$,
216
+ 'Test 3: Builds "build1-for-custom-domain-1" and "build1-for-project-domain-1" should be marked as cleaned'
217
+ );
218
+
219
+ -- =========================================
220
+ -- Finish the test
221
+ -- =========================================
222
+
223
+ -- Finish the test by calling the finish() function, which outputs the test summary
224
+ SELECT finish();
225
+
226
+ -- Rollback the transaction to ensure no changes are persisted in the database
227
+ ROLLBACK;