@fayz-ai/plugin-forms 0.2.0 → 0.8.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/README.md +2 -0
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/tables.d.ts +7 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/index.cjs +27 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -19
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +8 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -4
- package/src/data/supabase.ts +20 -19
- package/src/data/tables.ts +7 -0
- package/src/index.ts +2 -1
- package/src/migrations/000_plg_rename.sql +21 -0
- package/src/migrations/001_frm_base.sql +92 -56
- package/src/migrations/002_document_archetype.sql +130 -42
- package/src/migrations/index.ts +433 -0
- package/src/types.ts +4 -4
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@fayz-ai/plugin-forms)
|
|
6
6
|
[](https://github.com/FayaLabs/fayz-sdk/blob/main/LICENSE)
|
|
7
7
|
|
|
8
|
+
**Status:** beta — pre-1.0. Core surface is stable; some backend facets (see `PLUGIN_PATTERNS.md`) are still landing. APIs may change before 1.0.
|
|
9
|
+
|
|
8
10
|
Every real business runs on forms it never wanted to build: anamnesis sheets, evolution notes, consent contracts, intake docs. plugin-forms kills that busywork. Define a template once, attach a filled document to a person, and the data lives in your tenant — not in a PDF nobody can query.
|
|
9
11
|
|
|
10
12
|
It snaps into a `defineSaas` app as the document engine. A clinic fills health anamnesis, a salon collects consent forms, a studio signs contracts — same plugin, same `frm_*` tables, different templates. Documents surface right inside the person record via a detail-tab widget, and the AI assistant can list templates and a client's documents on demand.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAiGtD,wBAAgB,2BAA2B,IAAI,uBAAuB,CAmTrE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../src/data/tables.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,CAAC;;;;;CAKJ,CAAA"}
|
package/dist/index.cjs
CHANGED
|
@@ -13,6 +13,14 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
13
13
|
|
|
14
14
|
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
15
15
|
|
|
16
|
+
// src/data/tables.ts
|
|
17
|
+
var T = {
|
|
18
|
+
documents: "plg_forms_documents",
|
|
19
|
+
templates: "plg_forms_templates",
|
|
20
|
+
documentFiles: "plg_forms_document_files",
|
|
21
|
+
categories: "plg_forms_categories"
|
|
22
|
+
};
|
|
23
|
+
|
|
16
24
|
// src/data/mock.ts
|
|
17
25
|
function uuid() {
|
|
18
26
|
return crypto.randomUUID();
|
|
@@ -261,7 +269,7 @@ function createSupabaseFormsProvider() {
|
|
|
261
269
|
// ── Templates ──────────────────────────────────────────
|
|
262
270
|
async getTemplates(query) {
|
|
263
271
|
const db = getClient();
|
|
264
|
-
let qb = db.from(
|
|
272
|
+
let qb = db.from(T.templates).select("*", { count: "exact" }).eq("tenant_id", getTenantId()).eq("is_current", true).eq("is_deleted", false);
|
|
265
273
|
if (query.category) qb = qb.eq("category", query.category);
|
|
266
274
|
if (query.search) qb = qb.ilike("name", `%${query.search}%`);
|
|
267
275
|
const page = query.page ?? 1;
|
|
@@ -273,14 +281,14 @@ function createSupabaseFormsProvider() {
|
|
|
273
281
|
},
|
|
274
282
|
async getTemplateById(id) {
|
|
275
283
|
const db = getClient();
|
|
276
|
-
const { data, error } = await db.from(
|
|
284
|
+
const { data, error } = await db.from(T.templates).select("*").eq("id", id).eq("is_deleted", false).single();
|
|
277
285
|
if (error || !data) return null;
|
|
278
286
|
return mapTemplate(data);
|
|
279
287
|
},
|
|
280
288
|
async createTemplate(input) {
|
|
281
289
|
const db = getClient();
|
|
282
290
|
const tenantId = getTenantId();
|
|
283
|
-
const { data, error } = await db.from(
|
|
291
|
+
const { data, error } = await db.from(T.templates).insert({
|
|
284
292
|
tenant_id: tenantId,
|
|
285
293
|
name: input.name,
|
|
286
294
|
description: input.description,
|
|
@@ -296,12 +304,12 @@ function createSupabaseFormsProvider() {
|
|
|
296
304
|
async updateTemplate(id, input) {
|
|
297
305
|
const db = getClient();
|
|
298
306
|
const tenantId = getTenantId();
|
|
299
|
-
const { count } = await db.from(
|
|
307
|
+
const { count } = await db.from(T.documents).select("document_id", { count: "exact", head: true }).eq("template_id", id);
|
|
300
308
|
const hasDocuments = (count ?? 0) > 0;
|
|
301
309
|
if (hasDocuments && input.schema) {
|
|
302
310
|
const existing = await this.getTemplateById(id);
|
|
303
311
|
if (!existing) throw new Error("Template not found");
|
|
304
|
-
const { data: newRow, error: insertError } = await db.from(
|
|
312
|
+
const { data: newRow, error: insertError } = await db.from(T.templates).insert({
|
|
305
313
|
tenant_id: tenantId,
|
|
306
314
|
name: input.name ?? existing.name,
|
|
307
315
|
description: input.description ?? existing.description,
|
|
@@ -316,7 +324,7 @@ function createSupabaseFormsProvider() {
|
|
|
316
324
|
parent_id: existing.parentId ?? existing.id
|
|
317
325
|
}).select().single();
|
|
318
326
|
if (insertError) throw new Error(insertError.message);
|
|
319
|
-
await db.from(
|
|
327
|
+
await db.from(T.templates).update({ is_current: false, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
|
|
320
328
|
return mapTemplate(newRow);
|
|
321
329
|
}
|
|
322
330
|
const updates = { updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
@@ -328,16 +336,16 @@ function createSupabaseFormsProvider() {
|
|
|
328
336
|
if (input.tags !== void 0) updates.tags = input.tags;
|
|
329
337
|
if (input.metadata !== void 0) updates.metadata = input.metadata;
|
|
330
338
|
if (input.isActive !== void 0) updates.is_active = input.isActive;
|
|
331
|
-
const { data, error } = await db.from(
|
|
339
|
+
const { data, error } = await db.from(T.templates).update(updates).eq("id", id).select().single();
|
|
332
340
|
if (error) throw new Error(error.message);
|
|
333
341
|
return mapTemplate(data);
|
|
334
342
|
},
|
|
335
343
|
async deleteTemplate(id) {
|
|
336
344
|
const db = getClient();
|
|
337
|
-
const { error } = await db.from(
|
|
345
|
+
const { error } = await db.from(T.templates).update({ is_deleted: true, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
|
|
338
346
|
if (error) throw new Error(error.message);
|
|
339
347
|
},
|
|
340
|
-
// ── Documents (
|
|
348
|
+
// ── Documents (public.documents + plg_forms_documents extension) ──
|
|
341
349
|
async getDocuments(query) {
|
|
342
350
|
const db = getClient();
|
|
343
351
|
let qb = db.from("v_documents").select("*", { count: "exact" }).eq("tenant_id", getTenantId()).eq("is_active", true);
|
|
@@ -364,7 +372,7 @@ function createSupabaseFormsProvider() {
|
|
|
364
372
|
async createDocument(input) {
|
|
365
373
|
const tenantId = getTenantId();
|
|
366
374
|
const isForm = !!input.templateId;
|
|
367
|
-
const { data: coreDoc, error: coreError } = await getClient().from("
|
|
375
|
+
const { data: coreDoc, error: coreError } = await getClient().from("documents").insert({
|
|
368
376
|
tenant_id: tenantId,
|
|
369
377
|
kind: input.kind ?? (isForm ? "form" : "attachment"),
|
|
370
378
|
person_id: input.personId,
|
|
@@ -379,14 +387,14 @@ function createSupabaseFormsProvider() {
|
|
|
379
387
|
if (coreError) throw new Error(coreError.message);
|
|
380
388
|
if (isForm && input.templateId) {
|
|
381
389
|
const db = getClient();
|
|
382
|
-
const { error: extError } = await db.from(
|
|
390
|
+
const { error: extError } = await db.from(T.documents).insert({
|
|
383
391
|
document_id: coreDoc.id,
|
|
384
392
|
tenant_id: tenantId,
|
|
385
393
|
template_id: input.templateId,
|
|
386
394
|
data: input.data ?? {}
|
|
387
395
|
});
|
|
388
396
|
if (extError) {
|
|
389
|
-
await getClient().from("
|
|
397
|
+
await getClient().from("documents").delete().eq("id", coreDoc.id);
|
|
390
398
|
throw new Error(extError.message);
|
|
391
399
|
}
|
|
392
400
|
}
|
|
@@ -399,23 +407,23 @@ function createSupabaseFormsProvider() {
|
|
|
399
407
|
if (input.status !== void 0) coreUpdates.status = input.status;
|
|
400
408
|
if (input.title !== void 0) coreUpdates.title = input.title;
|
|
401
409
|
if (input.notes !== void 0) coreUpdates.notes = input.notes;
|
|
402
|
-
const { error: coreError } = await getClient().from("
|
|
410
|
+
const { error: coreError } = await getClient().from("documents").update(coreUpdates).eq("id", id);
|
|
403
411
|
if (coreError) throw new Error(coreError.message);
|
|
404
412
|
if (input.data !== void 0) {
|
|
405
413
|
const db = getClient();
|
|
406
|
-
await db.from(
|
|
414
|
+
await db.from(T.documents).update({ data: input.data, updated_at: now2 }).eq("document_id", id);
|
|
407
415
|
}
|
|
408
416
|
const doc = await this.getDocumentById(id);
|
|
409
417
|
return doc;
|
|
410
418
|
},
|
|
411
419
|
async deleteDocument(id) {
|
|
412
|
-
const { error } = await getClient().from("
|
|
420
|
+
const { error } = await getClient().from("documents").update({ is_active: false, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
|
|
413
421
|
if (error) throw new Error(error.message);
|
|
414
422
|
},
|
|
415
423
|
// ── Files ──────────────────────────────────────────────
|
|
416
424
|
async getDocumentFiles(documentId) {
|
|
417
425
|
const db = getClient();
|
|
418
|
-
const { data, error } = await db.from(
|
|
426
|
+
const { data, error } = await db.from(T.documentFiles).select("*").eq("document_id", documentId).order("sort_order");
|
|
419
427
|
if (error) throw new Error(error.message);
|
|
420
428
|
return (data ?? []).map(mapFile);
|
|
421
429
|
},
|
|
@@ -427,7 +435,7 @@ function createSupabaseFormsProvider() {
|
|
|
427
435
|
const { error: uploadError } = await db.storage.from("documents").upload(storagePath, file, { contentType: file.type });
|
|
428
436
|
if (uploadError) throw new Error(uploadError.message);
|
|
429
437
|
const { data: urlData } = db.storage.from("documents").getPublicUrl(storagePath);
|
|
430
|
-
const { data, error } = await db.from(
|
|
438
|
+
const { data, error } = await db.from(T.documentFiles).insert({
|
|
431
439
|
tenant_id: tenantId,
|
|
432
440
|
document_id: documentId,
|
|
433
441
|
field_key: fieldKey,
|
|
@@ -441,7 +449,7 @@ function createSupabaseFormsProvider() {
|
|
|
441
449
|
},
|
|
442
450
|
async deleteFile(fileId) {
|
|
443
451
|
const db = getClient();
|
|
444
|
-
const { error } = await db.from(
|
|
452
|
+
const { error } = await db.from(T.documentFiles).delete().eq("id", fileId);
|
|
445
453
|
if (error) throw new Error(error.message);
|
|
446
454
|
}
|
|
447
455
|
};
|
|
@@ -1499,7 +1507,7 @@ function createCustomFormsPlugin(options) {
|
|
|
1499
1507
|
{ key: "isActive", label: "Active", type: "boolean", showInTable: true, defaultValue: true, inlineToggle: true }
|
|
1500
1508
|
],
|
|
1501
1509
|
data: {
|
|
1502
|
-
table:
|
|
1510
|
+
table: T.categories,
|
|
1503
1511
|
tenantScoped: true
|
|
1504
1512
|
}
|
|
1505
1513
|
},
|