@squaredr/fieldcraft-supabase 1.0.0 → 1.1.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.
- package/dist/index.d.mts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +82 -0
- package/dist/index.mjs +81 -0
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormResponse, SubmitAdapter, DraftAdapter } from '@squaredr/fieldcraft-core';
|
|
1
|
+
import { FormResponse, SubmitAdapter, DraftAdapter, SchemaAdapter } from '@squaredr/fieldcraft-core';
|
|
2
2
|
|
|
3
3
|
type SupabaseAdapterConfig = {
|
|
4
4
|
/** Supabase client instance from @supabase/supabase-js */
|
|
@@ -34,9 +34,22 @@ type SupabaseQueryBuilder = {
|
|
|
34
34
|
}): SupabaseFilterBuilder;
|
|
35
35
|
delete(): SupabaseFilterBuilder;
|
|
36
36
|
};
|
|
37
|
+
type SupabaseSchemaAdapterConfig = {
|
|
38
|
+
/** Supabase client instance */
|
|
39
|
+
client: SupabaseClient;
|
|
40
|
+
/** Table name for schemas (default: "formengine_schemas") */
|
|
41
|
+
table?: string;
|
|
42
|
+
/** Called on error */
|
|
43
|
+
onError?: (error: Error) => void;
|
|
44
|
+
};
|
|
37
45
|
type SupabaseFilterBuilder = {
|
|
38
46
|
eq(column: string, value: unknown): SupabaseFilterBuilder;
|
|
39
47
|
gt(column: string, value: unknown): SupabaseFilterBuilder;
|
|
48
|
+
ilike(column: string, pattern: string): SupabaseFilterBuilder;
|
|
49
|
+
order(column: string, options?: {
|
|
50
|
+
ascending?: boolean;
|
|
51
|
+
}): SupabaseFilterBuilder;
|
|
52
|
+
range(from: number, to: number): SupabaseFilterBuilder;
|
|
40
53
|
single(): Promise<{
|
|
41
54
|
data: Record<string, unknown> | null;
|
|
42
55
|
error: Error | null;
|
|
@@ -54,9 +67,28 @@ declare function createSupabaseAdapter(config: SupabaseAdapterConfig): SubmitAda
|
|
|
54
67
|
/** Create a Supabase draft adapter. */
|
|
55
68
|
declare function createSupabaseDraftAdapter(config: SupabaseDraftAdapterConfig): DraftAdapter;
|
|
56
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Create a Supabase schema adapter for persisting FormEngineSchema documents.
|
|
72
|
+
*
|
|
73
|
+
* Requires a `formengine_schemas` table (or custom name) with the following columns:
|
|
74
|
+
*
|
|
75
|
+
* ```sql
|
|
76
|
+
* create table formengine_schemas (
|
|
77
|
+
* id text primary key,
|
|
78
|
+
* title text not null default '',
|
|
79
|
+
* version text not null default '1.0.0',
|
|
80
|
+
* status text not null default 'draft',
|
|
81
|
+
* definition jsonb not null,
|
|
82
|
+
* created_at timestamptz not null default now(),
|
|
83
|
+
* updated_at timestamptz not null default now()
|
|
84
|
+
* );
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare function createSupabaseSchemaAdapter(config: SupabaseSchemaAdapterConfig): SchemaAdapter;
|
|
88
|
+
|
|
57
89
|
/** Encrypt specified fields in a values object. */
|
|
58
90
|
declare function encryptFields(values: Record<string, unknown>, fieldIds: string[], keyBase64: string): Record<string, unknown>;
|
|
59
91
|
/** Decrypt specified fields in a values object. */
|
|
60
92
|
declare function decryptFields(values: Record<string, unknown>, fieldIds: string[], keyBase64: string): Record<string, unknown>;
|
|
61
93
|
|
|
62
|
-
export { type SupabaseAdapterConfig, type SupabaseClient, type SupabaseDraftAdapterConfig, createSupabaseAdapter, createSupabaseDraftAdapter, decryptFields, encryptFields };
|
|
94
|
+
export { type SupabaseAdapterConfig, type SupabaseClient, type SupabaseDraftAdapterConfig, type SupabaseSchemaAdapterConfig, createSupabaseAdapter, createSupabaseDraftAdapter, createSupabaseSchemaAdapter, decryptFields, encryptFields };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormResponse, SubmitAdapter, DraftAdapter } from '@squaredr/fieldcraft-core';
|
|
1
|
+
import { FormResponse, SubmitAdapter, DraftAdapter, SchemaAdapter } from '@squaredr/fieldcraft-core';
|
|
2
2
|
|
|
3
3
|
type SupabaseAdapterConfig = {
|
|
4
4
|
/** Supabase client instance from @supabase/supabase-js */
|
|
@@ -34,9 +34,22 @@ type SupabaseQueryBuilder = {
|
|
|
34
34
|
}): SupabaseFilterBuilder;
|
|
35
35
|
delete(): SupabaseFilterBuilder;
|
|
36
36
|
};
|
|
37
|
+
type SupabaseSchemaAdapterConfig = {
|
|
38
|
+
/** Supabase client instance */
|
|
39
|
+
client: SupabaseClient;
|
|
40
|
+
/** Table name for schemas (default: "formengine_schemas") */
|
|
41
|
+
table?: string;
|
|
42
|
+
/** Called on error */
|
|
43
|
+
onError?: (error: Error) => void;
|
|
44
|
+
};
|
|
37
45
|
type SupabaseFilterBuilder = {
|
|
38
46
|
eq(column: string, value: unknown): SupabaseFilterBuilder;
|
|
39
47
|
gt(column: string, value: unknown): SupabaseFilterBuilder;
|
|
48
|
+
ilike(column: string, pattern: string): SupabaseFilterBuilder;
|
|
49
|
+
order(column: string, options?: {
|
|
50
|
+
ascending?: boolean;
|
|
51
|
+
}): SupabaseFilterBuilder;
|
|
52
|
+
range(from: number, to: number): SupabaseFilterBuilder;
|
|
40
53
|
single(): Promise<{
|
|
41
54
|
data: Record<string, unknown> | null;
|
|
42
55
|
error: Error | null;
|
|
@@ -54,9 +67,28 @@ declare function createSupabaseAdapter(config: SupabaseAdapterConfig): SubmitAda
|
|
|
54
67
|
/** Create a Supabase draft adapter. */
|
|
55
68
|
declare function createSupabaseDraftAdapter(config: SupabaseDraftAdapterConfig): DraftAdapter;
|
|
56
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Create a Supabase schema adapter for persisting FormEngineSchema documents.
|
|
72
|
+
*
|
|
73
|
+
* Requires a `formengine_schemas` table (or custom name) with the following columns:
|
|
74
|
+
*
|
|
75
|
+
* ```sql
|
|
76
|
+
* create table formengine_schemas (
|
|
77
|
+
* id text primary key,
|
|
78
|
+
* title text not null default '',
|
|
79
|
+
* version text not null default '1.0.0',
|
|
80
|
+
* status text not null default 'draft',
|
|
81
|
+
* definition jsonb not null,
|
|
82
|
+
* created_at timestamptz not null default now(),
|
|
83
|
+
* updated_at timestamptz not null default now()
|
|
84
|
+
* );
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare function createSupabaseSchemaAdapter(config: SupabaseSchemaAdapterConfig): SchemaAdapter;
|
|
88
|
+
|
|
57
89
|
/** Encrypt specified fields in a values object. */
|
|
58
90
|
declare function encryptFields(values: Record<string, unknown>, fieldIds: string[], keyBase64: string): Record<string, unknown>;
|
|
59
91
|
/** Decrypt specified fields in a values object. */
|
|
60
92
|
declare function decryptFields(values: Record<string, unknown>, fieldIds: string[], keyBase64: string): Record<string, unknown>;
|
|
61
93
|
|
|
62
|
-
export { type SupabaseAdapterConfig, type SupabaseClient, type SupabaseDraftAdapterConfig, createSupabaseAdapter, createSupabaseDraftAdapter, decryptFields, encryptFields };
|
|
94
|
+
export { type SupabaseAdapterConfig, type SupabaseClient, type SupabaseDraftAdapterConfig, type SupabaseSchemaAdapterConfig, createSupabaseAdapter, createSupabaseDraftAdapter, createSupabaseSchemaAdapter, decryptFields, encryptFields };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
createSupabaseAdapter: () => createSupabaseAdapter,
|
|
34
34
|
createSupabaseDraftAdapter: () => createSupabaseDraftAdapter,
|
|
35
|
+
createSupabaseSchemaAdapter: () => createSupabaseSchemaAdapter,
|
|
35
36
|
decryptFields: () => decryptFields,
|
|
36
37
|
encryptFields: () => encryptFields
|
|
37
38
|
});
|
|
@@ -166,10 +167,91 @@ function createSupabaseDraftAdapter(config) {
|
|
|
166
167
|
}
|
|
167
168
|
};
|
|
168
169
|
}
|
|
170
|
+
|
|
171
|
+
// src/supabase-schema-adapter.ts
|
|
172
|
+
function createSupabaseSchemaAdapter(config) {
|
|
173
|
+
const tableName = config.table ?? "formengine_schemas";
|
|
174
|
+
return {
|
|
175
|
+
name: "supabase-schema",
|
|
176
|
+
async save(schema) {
|
|
177
|
+
const { error } = await config.client.from(tableName).upsert(
|
|
178
|
+
{
|
|
179
|
+
id: schema.id,
|
|
180
|
+
title: schema.title ?? "",
|
|
181
|
+
version: schema.version ?? "1.0.0",
|
|
182
|
+
status: "draft",
|
|
183
|
+
definition: schema,
|
|
184
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
185
|
+
},
|
|
186
|
+
{ onConflict: "id" }
|
|
187
|
+
);
|
|
188
|
+
if (error) {
|
|
189
|
+
const err = new Error(`Supabase schema save failed: ${error.message}`);
|
|
190
|
+
config.onError?.(err);
|
|
191
|
+
throw err;
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
async load(schemaId) {
|
|
195
|
+
const { data, error } = await config.client.from(tableName).select("definition").eq("id", schemaId).single();
|
|
196
|
+
if (error || !data) return null;
|
|
197
|
+
return data.definition;
|
|
198
|
+
},
|
|
199
|
+
async delete(schemaId) {
|
|
200
|
+
const { error } = await config.client.from(tableName).delete().eq("id", schemaId);
|
|
201
|
+
if (error) {
|
|
202
|
+
const err = new Error(`Supabase schema delete failed: ${error.message}`);
|
|
203
|
+
config.onError?.(err);
|
|
204
|
+
throw err;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
async list(params) {
|
|
208
|
+
const page = params?.page ?? 1;
|
|
209
|
+
const pageSize = params?.pageSize ?? 20;
|
|
210
|
+
const from = (page - 1) * pageSize;
|
|
211
|
+
const to = from + pageSize - 1;
|
|
212
|
+
let query = config.client.from(tableName).select("id, title, version, status, created_at, updated_at");
|
|
213
|
+
if (params?.search) {
|
|
214
|
+
query = query.ilike("title", `%${params.search}%`);
|
|
215
|
+
}
|
|
216
|
+
if (params?.status) {
|
|
217
|
+
query = query.eq("status", params.status);
|
|
218
|
+
}
|
|
219
|
+
const sortBy = params?.sortBy ?? "updatedAt";
|
|
220
|
+
const sortOrder = params?.sortOrder ?? "desc";
|
|
221
|
+
const columnMap = {
|
|
222
|
+
title: "title",
|
|
223
|
+
updatedAt: "updated_at",
|
|
224
|
+
createdAt: "created_at"
|
|
225
|
+
};
|
|
226
|
+
const sortColumn = columnMap[sortBy] ?? "updated_at";
|
|
227
|
+
query = query.order(sortColumn, { ascending: sortOrder === "asc" }).range(from, to);
|
|
228
|
+
const { data, error } = await query.then((res) => res);
|
|
229
|
+
if (error || !data) {
|
|
230
|
+
return { items: [], total: 0, page, pageSize };
|
|
231
|
+
}
|
|
232
|
+
const items = data.map((row) => ({
|
|
233
|
+
id: row.id,
|
|
234
|
+
title: row.title,
|
|
235
|
+
version: row.version,
|
|
236
|
+
updatedAt: row.updated_at,
|
|
237
|
+
createdAt: row.created_at,
|
|
238
|
+
status: row.status
|
|
239
|
+
}));
|
|
240
|
+
return {
|
|
241
|
+
items,
|
|
242
|
+
total: items.length < pageSize ? from + items.length : from + pageSize + 1,
|
|
243
|
+
page,
|
|
244
|
+
pageSize
|
|
245
|
+
};
|
|
246
|
+
},
|
|
247
|
+
onError: config.onError
|
|
248
|
+
};
|
|
249
|
+
}
|
|
169
250
|
// Annotate the CommonJS export names for ESM import in node:
|
|
170
251
|
0 && (module.exports = {
|
|
171
252
|
createSupabaseAdapter,
|
|
172
253
|
createSupabaseDraftAdapter,
|
|
254
|
+
createSupabaseSchemaAdapter,
|
|
173
255
|
decryptFields,
|
|
174
256
|
encryptFields
|
|
175
257
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -127,9 +127,90 @@ function createSupabaseDraftAdapter(config) {
|
|
|
127
127
|
}
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
+
|
|
131
|
+
// src/supabase-schema-adapter.ts
|
|
132
|
+
function createSupabaseSchemaAdapter(config) {
|
|
133
|
+
const tableName = config.table ?? "formengine_schemas";
|
|
134
|
+
return {
|
|
135
|
+
name: "supabase-schema",
|
|
136
|
+
async save(schema) {
|
|
137
|
+
const { error } = await config.client.from(tableName).upsert(
|
|
138
|
+
{
|
|
139
|
+
id: schema.id,
|
|
140
|
+
title: schema.title ?? "",
|
|
141
|
+
version: schema.version ?? "1.0.0",
|
|
142
|
+
status: "draft",
|
|
143
|
+
definition: schema,
|
|
144
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
145
|
+
},
|
|
146
|
+
{ onConflict: "id" }
|
|
147
|
+
);
|
|
148
|
+
if (error) {
|
|
149
|
+
const err = new Error(`Supabase schema save failed: ${error.message}`);
|
|
150
|
+
config.onError?.(err);
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
async load(schemaId) {
|
|
155
|
+
const { data, error } = await config.client.from(tableName).select("definition").eq("id", schemaId).single();
|
|
156
|
+
if (error || !data) return null;
|
|
157
|
+
return data.definition;
|
|
158
|
+
},
|
|
159
|
+
async delete(schemaId) {
|
|
160
|
+
const { error } = await config.client.from(tableName).delete().eq("id", schemaId);
|
|
161
|
+
if (error) {
|
|
162
|
+
const err = new Error(`Supabase schema delete failed: ${error.message}`);
|
|
163
|
+
config.onError?.(err);
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
async list(params) {
|
|
168
|
+
const page = params?.page ?? 1;
|
|
169
|
+
const pageSize = params?.pageSize ?? 20;
|
|
170
|
+
const from = (page - 1) * pageSize;
|
|
171
|
+
const to = from + pageSize - 1;
|
|
172
|
+
let query = config.client.from(tableName).select("id, title, version, status, created_at, updated_at");
|
|
173
|
+
if (params?.search) {
|
|
174
|
+
query = query.ilike("title", `%${params.search}%`);
|
|
175
|
+
}
|
|
176
|
+
if (params?.status) {
|
|
177
|
+
query = query.eq("status", params.status);
|
|
178
|
+
}
|
|
179
|
+
const sortBy = params?.sortBy ?? "updatedAt";
|
|
180
|
+
const sortOrder = params?.sortOrder ?? "desc";
|
|
181
|
+
const columnMap = {
|
|
182
|
+
title: "title",
|
|
183
|
+
updatedAt: "updated_at",
|
|
184
|
+
createdAt: "created_at"
|
|
185
|
+
};
|
|
186
|
+
const sortColumn = columnMap[sortBy] ?? "updated_at";
|
|
187
|
+
query = query.order(sortColumn, { ascending: sortOrder === "asc" }).range(from, to);
|
|
188
|
+
const { data, error } = await query.then((res) => res);
|
|
189
|
+
if (error || !data) {
|
|
190
|
+
return { items: [], total: 0, page, pageSize };
|
|
191
|
+
}
|
|
192
|
+
const items = data.map((row) => ({
|
|
193
|
+
id: row.id,
|
|
194
|
+
title: row.title,
|
|
195
|
+
version: row.version,
|
|
196
|
+
updatedAt: row.updated_at,
|
|
197
|
+
createdAt: row.created_at,
|
|
198
|
+
status: row.status
|
|
199
|
+
}));
|
|
200
|
+
return {
|
|
201
|
+
items,
|
|
202
|
+
total: items.length < pageSize ? from + items.length : from + pageSize + 1,
|
|
203
|
+
page,
|
|
204
|
+
pageSize
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
onError: config.onError
|
|
208
|
+
};
|
|
209
|
+
}
|
|
130
210
|
export {
|
|
131
211
|
createSupabaseAdapter,
|
|
132
212
|
createSupabaseDraftAdapter,
|
|
213
|
+
createSupabaseSchemaAdapter,
|
|
133
214
|
decryptFields,
|
|
134
215
|
encryptFields
|
|
135
216
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squaredr/fieldcraft-supabase",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "FieldCraft Supabase storage adapter with field-level AES-256-GCM encryption",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"clean": "rm -rf dist"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@squaredr/fieldcraft-core": "^1.
|
|
24
|
+
"@squaredr/fieldcraft-core": "^1.2.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"@supabase/supabase-js": "^2.0"
|