@cosmicdrift/kumiko-samples 0.398.0 → 0.400.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 (60) hide show
  1. package/package.json +1 -1
  2. package/packages/bundled-features/package.json +6 -1
  3. package/packages/bundled-features/src/billing-foundation/changes.json +6 -0
  4. package/packages/bundled-features/src/billing-foundation/consumer-protection/consent-text.ts +4 -6
  5. package/packages/bundled-features/src/channel-in-app/changes.json +6 -0
  6. package/packages/bundled-features/src/channel-in-app/constants.ts +9 -9
  7. package/packages/bundled-features/src/channel-in-app/feature.ts +1 -1
  8. package/packages/bundled-features/src/channel-in-app/handlers/inbox.query.ts +31 -7
  9. package/packages/bundled-features/src/channel-in-app/handlers/unread-count.query.ts +6 -9
  10. package/packages/bundled-features/src/channel-in-app/in-app-channel.ts +25 -11
  11. package/packages/bundled-features/src/channel-in-app/in-app-target.ts +37 -0
  12. package/packages/bundled-features/src/channel-in-app/index.ts +1 -0
  13. package/packages/bundled-features/src/documents/aggregate-id.ts +20 -0
  14. package/packages/bundled-features/src/documents/capture.ts +125 -0
  15. package/packages/bundled-features/src/documents/constants.ts +31 -0
  16. package/packages/bundled-features/src/documents/ensure-link.ts +35 -0
  17. package/packages/bundled-features/src/documents/entity.ts +103 -0
  18. package/packages/bundled-features/src/documents/executor.ts +13 -0
  19. package/packages/bundled-features/src/documents/expiry.ts +32 -0
  20. package/packages/bundled-features/src/documents/feature.ts +197 -0
  21. package/packages/bundled-features/src/documents/handlers/import.write.ts +157 -0
  22. package/packages/bundled-features/src/documents/handlers/link.write.ts +103 -0
  23. package/packages/bundled-features/src/documents/i18n.ts +35 -0
  24. package/packages/bundled-features/src/documents/index.ts +22 -0
  25. package/packages/bundled-features/src/documents/pending-file-guard.ts +36 -0
  26. package/packages/bundled-features/src/documents/queries/expiry-overview.query.ts +46 -0
  27. package/packages/bundled-features/src/documents/queries/for-record.query.ts +74 -0
  28. package/packages/bundled-features/src/documents/queries/list-page.ts +51 -0
  29. package/packages/bundled-features/src/documents/queries/overview.query.ts +45 -0
  30. package/packages/bundled-features/src/documents/schemas.ts +66 -0
  31. package/packages/bundled-features/src/documents/screens.ts +86 -0
  32. package/packages/bundled-features/src/documents/tab.ts +46 -0
  33. package/packages/bundled-features/src/documents/target-write-check.ts +41 -0
  34. package/packages/bundled-features/src/documents/write-guard.ts +59 -0
  35. package/packages/bundled-features/src/metrics/changes.json +6 -0
  36. package/packages/bundled-features/src/metrics/compute.ts +19 -2
  37. package/packages/bundled-features/src/metrics/feature.ts +14 -1
  38. package/packages/bundled-features/src/metrics/types.ts +3 -1
  39. package/packages/bundled-features/src/metrics/validate.ts +3 -0
  40. package/packages/bundled-features/src/shared/purge-row-file-refs.ts +5 -4
  41. package/samples/apps/styleguide/src/app/seed.ts +102 -1
  42. package/samples/apps/styleguide/src/app/server.ts +2 -2
  43. package/samples/apps/styleguide/src/features/examples/feature.ts +97 -0
  44. package/samples/apps/styleguide/src/features/examples/i18n.ts +47 -0
  45. package/samples/apps/use-all-bundled/feature-manifest.json +31 -2
  46. package/samples/apps/use-all-bundled/kumiko/migrations/0058_documents.rebuild.json +4 -0
  47. package/samples/apps/use-all-bundled/src/app/dev-app-options.ts +11 -2
  48. package/samples/apps/use-all-bundled/src/run-config.ts +7 -0
  49. package/samples/recipes/derived-fields-sql/README.md +27 -0
  50. package/samples/recipes/derived-fields-sql/package.json +11 -0
  51. package/samples/recipes/derived-fields-sql/src/feature.ts +98 -0
  52. package/samples/recipes/documents/package.json +12 -0
  53. package/samples/recipes/documents/src/feature.ts +66 -0
  54. package/samples/recipes/inspection-checklist/README.md +27 -0
  55. package/samples/recipes/inspection-checklist/package.json +12 -0
  56. package/samples/recipes/inspection-checklist/src/entities/inspection-plan.ts +24 -0
  57. package/samples/recipes/inspection-checklist/src/entities/inspection-protocol.ts +72 -0
  58. package/samples/recipes/inspection-checklist/src/feature.ts +33 -0
  59. package/samples/recipes/inspection-checklist/src/handlers/create-from-plan.write.ts +38 -0
  60. package/samples/recipes/inspection-checklist/src/screens/inspection-protocol-edit.screen.ts +27 -0
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@cosmicdrift/kumiko-sample-inspection-checklist",
3
+ "description": "Embedded list as a phone inspection checklist: conditional fields, derived pass/fail, photos per row.",
4
+ "private": true,
5
+ "dependencies": {
6
+ "@cosmicdrift/kumiko-bundled-features": "workspace:*",
7
+ "@cosmicdrift/kumiko-framework": "workspace:*"
8
+ },
9
+ "devDependencies": {
10
+ "@cosmicdrift/kumiko-testing": "workspace:*"
11
+ }
12
+ }
@@ -0,0 +1,24 @@
1
+ import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
2
+ import {
3
+ createEmbeddedListField,
4
+ createEntity,
5
+ createTextField,
6
+ } from "@cosmicdrift/kumiko-framework/engine";
7
+
8
+ export const inspectionPlanEntity = createEntity({
9
+ table: "read_sample_inspection_plans",
10
+ fields: {
11
+ name: createTextField({ personal: false, reason: "is_business_data", required: true }),
12
+ checkpoints: createEmbeddedListField(
13
+ {
14
+ label: { type: "text", required: true },
15
+ kind: { type: "select", options: ["check", "measurement"], required: true },
16
+ min: { type: "number" },
17
+ max: { type: "number" },
18
+ },
19
+ { personal: false, reason: "is_business_data" },
20
+ ),
21
+ },
22
+ });
23
+
24
+ export const inspectionPlanTable = buildEntityTable("inspection-plan", inspectionPlanEntity);
@@ -0,0 +1,72 @@
1
+ import { buildEntityTable } from "@cosmicdrift/kumiko-framework/db";
2
+ import {
3
+ createEmbeddedListField,
4
+ createEntity,
5
+ createSelectField,
6
+ createTextField,
7
+ } from "@cosmicdrift/kumiko-framework/engine";
8
+
9
+ const isMeasurement = { field: "kind", eq: "measurement" } as const;
10
+ const isNotOk = { field: "result", eq: "not_ok" } as const;
11
+
12
+ export const inspectionProtocolEntity = createEntity({
13
+ table: "read_sample_inspection_protocols",
14
+ fields: {
15
+ measuringDevice: createTextField({ personal: false, reason: "is_business_data" }),
16
+ checkpoints: createEmbeddedListField(
17
+ {
18
+ label: { type: "text", required: true },
19
+ kind: { type: "select", options: ["check", "measurement"], required: true },
20
+ min: { type: "number", visibleWhen: isMeasurement },
21
+ max: { type: "number", visibleWhen: isMeasurement },
22
+ measured: { type: "number", visibleWhen: isMeasurement },
23
+ result: {
24
+ type: "select",
25
+ options: ["ok", "not_ok"],
26
+ display: "radio",
27
+ optionTones: { ok: "ok", not_ok: "bad" },
28
+ },
29
+ finding: { type: "text", visibleWhen: isNotOk, requiredWhen: isNotOk },
30
+ photos: {
31
+ type: "images",
32
+ capture: "environment",
33
+ maxCount: 5,
34
+ accept: ["jpg", "jpeg", "png"],
35
+ visibleWhen: isNotOk,
36
+ requiredWhen: isNotOk,
37
+ },
38
+ documents: { type: "files", maxCount: 3 },
39
+ approvedBy: { type: "text", access: { write: ["Admin"] } },
40
+ },
41
+ {
42
+ personal: false,
43
+ reason: "is_business_data",
44
+ derived: {
45
+ result: {
46
+ op: "inRange",
47
+ from: ["measured", "min", "max"],
48
+ inside: "ok",
49
+ outside: "not_ok",
50
+ when: isMeasurement,
51
+ },
52
+ },
53
+ },
54
+ ),
55
+ continuedOperation: createSelectField({
56
+ options: ["yes", "with_condition", "no"],
57
+ display: "radio",
58
+ optionTones: { yes: "ok", with_condition: "warn", no: "bad" },
59
+ }),
60
+ condition: createTextField({
61
+ personal: false,
62
+ reason: "is_business_data",
63
+ visibleWhen: { field: "continuedOperation", eq: "with_condition" },
64
+ requiredWhen: { field: "continuedOperation", eq: "with_condition" },
65
+ }),
66
+ },
67
+ });
68
+
69
+ export const inspectionProtocolTable = buildEntityTable(
70
+ "inspection-protocol",
71
+ inspectionProtocolEntity,
72
+ );
@@ -0,0 +1,33 @@
1
+ // Inspection Checklist Sample
2
+ // Shows: an embedded list as a phone inspection checklist.
3
+ // - visibleWhen / requiredWhen on cells and top-level fields (server-enforced)
4
+ // - a derived pass/fail cell (inRange) that the server recomputes
5
+ // - an images cell per row, uploaded with the `subField` multipart part
6
+ // - fixed rows copied from a plan, only the result cells stay editable
7
+
8
+ import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
9
+ import { inspectionPlanEntity } from "./entities/inspection-plan";
10
+ import { inspectionProtocolEntity } from "./entities/inspection-protocol";
11
+ import { createFromPlan } from "./handlers/create-from-plan.write";
12
+ import { inspectionProtocolEditScreen } from "./screens/inspection-protocol-edit.screen";
13
+
14
+ export { inspectionPlanEntity } from "./entities/inspection-plan";
15
+ export { inspectionProtocolEntity } from "./entities/inspection-protocol";
16
+
17
+ const inspectorAccess = { access: { roles: ["Admin", "Inspector"] } } as const;
18
+
19
+ export const inspectionChecklistFeature = defineFeature("inspection-checklist", (r) => {
20
+ r.requires({ features: ["files"] });
21
+
22
+ r.crud("inspection-plan", inspectionPlanEntity, {
23
+ write: inspectorAccess,
24
+ read: inspectorAccess,
25
+ });
26
+ r.crud("inspection-protocol", inspectionProtocolEntity, {
27
+ write: inspectorAccess,
28
+ read: inspectorAccess,
29
+ });
30
+ r.writeHandler(createFromPlan);
31
+
32
+ r.screen(inspectionProtocolEditScreen);
33
+ });
@@ -0,0 +1,38 @@
1
+ import { createEntityExecutor, defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
2
+ import { failNotFound } from "@cosmicdrift/kumiko-framework/errors";
3
+ import { z } from "zod";
4
+ import { inspectionPlanEntity } from "../entities/inspection-plan";
5
+ import { inspectionProtocolEntity } from "../entities/inspection-protocol";
6
+
7
+ const { executor: planExecutor } = createEntityExecutor("inspection-plan", inspectionPlanEntity);
8
+ const { executor: protocolExecutor } = createEntityExecutor(
9
+ "inspection-protocol",
10
+ inspectionProtocolEntity,
11
+ );
12
+
13
+ const planRows = z.array(
14
+ z.object({
15
+ label: z.string(),
16
+ kind: z.enum(["check", "measurement"]),
17
+ min: z.number().optional(),
18
+ max: z.number().optional(),
19
+ }),
20
+ );
21
+
22
+ // Copies only the plan's fixed columns; result, finding and photos stay empty for the inspector.
23
+ export const createFromPlan = defineWriteHandler({
24
+ name: "inspection-protocol:create-from-plan",
25
+ schema: z.object({ planId: z.uuid() }),
26
+ access: { roles: ["Admin", "Inspector"] },
27
+ handler: async (event, ctx) => {
28
+ const plan = await planExecutor.detail({ id: event.payload.planId }, event.user, ctx.db);
29
+ if (!plan) return failNotFound("inspection-plan", event.payload.planId);
30
+ const checkpoints = planRows.parse(plan["checkpoints"]).map(({ label, kind, min, max }) => ({
31
+ label,
32
+ kind,
33
+ ...(min !== undefined ? { min } : {}),
34
+ ...(max !== undefined ? { max } : {}),
35
+ }));
36
+ return protocolExecutor.create({ checkpoints }, event.user, ctx.db);
37
+ },
38
+ });
@@ -0,0 +1,27 @@
1
+ import type { EntityEditScreenDefinition } from "@cosmicdrift/kumiko-framework/engine";
2
+
3
+ export const inspectionProtocolEditScreen: EntityEditScreenDefinition = {
4
+ id: "inspection-protocol-edit",
5
+ type: "entityEdit",
6
+ entity: "inspection-protocol",
7
+ layout: {
8
+ width: "full",
9
+ sections: [
10
+ {
11
+ columns: 1,
12
+ fields: [
13
+ "measuringDevice",
14
+ {
15
+ field: "checkpoints",
16
+ embeddedList: {
17
+ readOnlyCells: ["label", "kind", "min", "max"],
18
+ cardHiddenCells: ["kind"],
19
+ fixedRows: true,
20
+ },
21
+ },
22
+ ],
23
+ },
24
+ { columns: 1, fields: ["continuedOperation", "condition"] },
25
+ ],
26
+ },
27
+ };