@cosmicdrift/kumiko-samples 0.359.0 → 0.361.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +9 -2
  3. package/packages/bundled-features/src/audit/changes.json +6 -0
  4. package/packages/bundled-features/src/audit/handlers/details.query.ts +2 -1
  5. package/packages/bundled-features/src/audit/handlers/list.query.ts +4 -5
  6. package/packages/bundled-features/src/auth-email-password/web/auth-client.ts +6 -0
  7. package/packages/bundled-features/src/auth-email-password/web/session.tsx +39 -3
  8. package/packages/bundled-features/src/billing-foundation/consumer-protection/termination-pages.ts +4 -4
  9. package/packages/bundled-features/src/cap-counter/changes.json +6 -0
  10. package/packages/bundled-features/src/cap-counter/index.ts +1 -0
  11. package/packages/bundled-features/src/data-retention/run-retention-cleanup.ts +11 -6
  12. package/packages/bundled-features/src/folders-user-data/hooks.ts +4 -2
  13. package/packages/bundled-features/src/form-draft-user-data/hooks.ts +4 -1
  14. package/packages/bundled-features/src/jobs/changes.json +6 -0
  15. package/packages/bundled-features/src/jobs/job-run-logger.ts +23 -10
  16. package/packages/bundled-features/src/renderer-pdf/README.md +27 -0
  17. package/packages/bundled-features/src/renderer-pdf/changes.json +8 -0
  18. package/packages/bundled-features/src/renderer-pdf/feature.ts +48 -0
  19. package/packages/bundled-features/src/renderer-pdf/index.ts +9 -0
  20. package/packages/bundled-features/src/renderer-pdf/render-table-pdf.ts +433 -0
  21. package/packages/bundled-features/src/shared/encrypt-for-direct-write.ts +2 -2
  22. package/packages/bundled-features/src/shared/index.ts +1 -0
  23. package/packages/bundled-features/src/shared/redact-pii-ciphertext.ts +16 -0
  24. package/packages/bundled-features/src/tenant-lifecycle/run-tenant-destroy.ts +7 -2
  25. package/packages/bundled-features/src/tenant-lifecycle/stages.ts +2 -1
  26. package/packages/bundled-features/src/user/changes.json +6 -0
  27. package/packages/bundled-features/src/user/handlers/me.query.ts +5 -1
  28. package/packages/bundled-features/src/user-data-rights/handlers/my-audit-log.query.ts +2 -1
  29. package/packages/bundled-features/src/user-data-rights-defaults/hooks/file-ref.userdata-hook.ts +6 -1
  30. package/packages/bundled-features/src/user-data-rights-defaults/hooks/tenant-invitation.userdata-hook.ts +3 -2
  31. package/packages/bundled-features/src/user-data-rights-defaults/hooks/user.userdata-hook.ts +3 -3
  32. package/packages/bundled-features/src/user-profile/changes.json +6 -0
  33. package/packages/bundled-features/src/user-profile/feature.ts +21 -11
  34. package/packages/bundled-features/src/user-profile/index.ts +1 -1
  35. package/samples/apps/styleguide/src/features/examples/feature.ts +52 -3
  36. package/samples/apps/styleguide/src/features/examples/i18n.ts +3 -0
  37. package/samples/apps/ui-walkthrough/src/app/seed-rental.ts +3 -2
  38. package/samples/apps/ui-walkthrough/src/features/rental/feature.ts +11 -2
  39. package/samples/apps/ui-walkthrough/src/features/rental/i18n.ts +17 -5
  40. package/samples/apps/ui-walkthrough/src/features/rental/lease-support.ts +12 -1
  41. package/samples/apps/ui-walkthrough/src/features/rental/screens.ts +46 -1
  42. package/samples/apps/ui-walkthrough/src/features/vehicles/feature.ts +2 -0
  43. package/samples/apps/ui-walkthrough/src/features/vehicles/i18n.ts +3 -1
  44. package/samples/apps/ui-walkthrough/src/features/vehicles/screens.ts +18 -0
  45. package/samples/apps/use-all-bundled/feature-manifest.json +28 -2
  46. package/samples/apps/use-all-bundled/schema/generate.ts +5 -0
  47. package/samples/apps/use-all-bundled/src/run-config.ts +2 -0
  48. package/samples/recipes/files-post-processing/src/feature.ts +11 -1
  49. package/samples/recipes/pdf-audit-export/README.md +22 -0
  50. package/samples/recipes/pdf-audit-export/package.json +12 -0
  51. package/samples/recipes/pdf-audit-export/src/feature.ts +114 -0
@@ -0,0 +1,114 @@
1
+ // PDF Audit Export Sample
2
+ //
3
+ // A write handler turns tenant data into a PDF and keeps it as a regular
4
+ // FileRef: renderTablePdf draws the table (pure JS, no browser), then
5
+ // createFileRefFromBytes stores the bytes through the same validation,
6
+ // storage layout and fileRef.created event as an upload.
7
+
8
+ import { renderTablePdf } from "@cosmicdrift/kumiko-bundled-features/renderer-pdf";
9
+ import {
10
+ createDateField,
11
+ createEntity,
12
+ createEntityExecutor,
13
+ createSelectField,
14
+ createTextField,
15
+ defineFeature,
16
+ } from "@cosmicdrift/kumiko-framework/engine";
17
+ import { createFileRefFromBytes } from "@cosmicdrift/kumiko-framework/files";
18
+ import * as z from "zod";
19
+
20
+ export const INSPECTION_RESULTS = ["ok", "defect"] as const;
21
+
22
+ export const inspectionEntity = createEntity({
23
+ table: "read_sample_inspections",
24
+ fields: {
25
+ assetName: createTextField({ personal: false, reason: "is_business_data", required: true }),
26
+ inspectedOn: createDateField({ required: true }),
27
+ result: createSelectField({ options: INSPECTION_RESULTS, required: true }),
28
+ inspector: createTextField({ personal: "ref" }),
29
+ },
30
+ });
31
+
32
+ const RESULT_LABELS: Readonly<Record<(typeof INSPECTION_RESULTS)[number], string>> = {
33
+ ok: "In Ordnung",
34
+ defect: "Mangel",
35
+ };
36
+
37
+ // The renderer takes ready-formatted strings, so date formatting stays with the caller.
38
+ function formatGermanDate(isoDate: string): string {
39
+ const [year, month, day] = isoDate.split("-");
40
+ return `${day}.${month}.${year}`;
41
+ }
42
+
43
+ function toFileNameSegment(text: string): string {
44
+ return text.replaceAll(/[^A-Za-z0-9_-]+/g, "-");
45
+ }
46
+
47
+ const AUDIT_ROW_LIMIT = 200;
48
+
49
+ const access = { access: { roles: ["Admin", "User"] } } as const;
50
+
51
+ export const pdfAuditExportFeature = defineFeature("pdf-audit-export", (r) => {
52
+ r.entity("inspection", inspectionEntity);
53
+ const { executor: inspectionExecutor } = createEntityExecutor("inspection", inspectionEntity);
54
+
55
+ r.writeHandler(
56
+ "inspection:create",
57
+ z.object({
58
+ assetName: z.string().min(1),
59
+ inspectedOn: z.iso.date(),
60
+ result: z.enum(INSPECTION_RESULTS),
61
+ inspector: z.string().optional(),
62
+ }),
63
+ async (event, ctx) => inspectionExecutor.create(event.payload, event.user, ctx.db),
64
+ access,
65
+ );
66
+
67
+ r.writeHandler(
68
+ "export-audit",
69
+ z.object({ assetName: z.string().min(1), from: z.iso.date(), to: z.iso.date() }),
70
+ async (event, ctx) => {
71
+ const { assetName, from, to } = event.payload;
72
+ const inspections = await inspectionExecutor.list(
73
+ {
74
+ filters: [
75
+ { field: "assetName", op: "eq", value: assetName },
76
+ { field: "inspectedOn", op: "gte", value: from },
77
+ { field: "inspectedOn", op: "lte", value: to },
78
+ ],
79
+ sort: "inspectedOn",
80
+ sortDirection: "asc",
81
+ limit: AUDIT_ROW_LIMIT,
82
+ },
83
+ event.user,
84
+ ctx.db,
85
+ );
86
+
87
+ const { pdfBytes } = await renderTablePdf({
88
+ title: `Prüfprotokoll ${assetName}`,
89
+ meta: [
90
+ { label: "Zeitraum", value: `${formatGermanDate(from)} bis ${formatGermanDate(to)}` },
91
+ { label: "Prüfungen", value: String(inspections.rows.length) },
92
+ ],
93
+ columns: [{ header: "Datum" }, { header: "Ergebnis" }, { header: "Prüfer", weight: 2 }],
94
+ rows: inspections.rows.map((row) => [
95
+ formatGermanDate(String(row["inspectedOn"])),
96
+ RESULT_LABELS[z.enum(INSPECTION_RESULTS).parse(row["result"])],
97
+ String(row["inspector"] ?? ""),
98
+ ]),
99
+ emptyText: "Keine Prüfungen im Zeitraum",
100
+ footerText: `Prüfbericht ${assetName}`,
101
+ pageLabel: "Seite {page} von {pages}",
102
+ });
103
+
104
+ const created = await createFileRefFromBytes(ctx, {
105
+ fileName: `audit-${toFileNameSegment(assetName)}.pdf`,
106
+ mimeType: "application/pdf",
107
+ data: pdfBytes,
108
+ });
109
+ if (!created.isSuccess) return created;
110
+ return { isSuccess: true as const, data: { fileRefId: created.data.id } };
111
+ },
112
+ access,
113
+ );
114
+ });