@cosmicdrift/kumiko-bundled-features 0.3.0 → 0.4.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/package.json +7 -5
  3. package/src/auth-email-password/i18n.ts +8 -0
  4. package/src/auth-email-password/web/__tests__/login-screen.test.tsx +128 -1
  5. package/src/auth-email-password/web/login-screen.tsx +73 -8
  6. package/src/config/__tests__/cascade.integration.ts +419 -0
  7. package/src/config/__tests__/config.integration.ts +109 -2
  8. package/src/config/constants.ts +1 -0
  9. package/src/config/feature.ts +2 -0
  10. package/src/config/handlers/cascade.query.ts +70 -0
  11. package/src/config/handlers/values.query.ts +14 -4
  12. package/src/config/index.ts +17 -0
  13. package/src/config/resolver.ts +273 -1
  14. package/src/delivery/__tests__/delivery.integration.ts +6 -0
  15. package/src/delivery/delivery-service.ts +4 -12
  16. package/src/delivery/feature.ts +6 -4
  17. package/src/delivery/index.ts +0 -1
  18. package/src/legal-pages/web/client-plugin.ts +50 -10
  19. package/src/renderer-foundation/README.md +86 -0
  20. package/src/renderer-foundation/__tests__/api.test.ts +188 -0
  21. package/src/renderer-foundation/__tests__/collect-plugins.integration.ts +101 -0
  22. package/src/renderer-foundation/api.ts +106 -0
  23. package/src/renderer-foundation/constants.ts +21 -0
  24. package/src/renderer-foundation/feature.ts +47 -0
  25. package/src/renderer-foundation/index.ts +25 -0
  26. package/src/renderer-foundation/types.ts +109 -0
  27. package/src/renderer-simple/__tests__/adapter.test.ts +50 -0
  28. package/src/renderer-simple/feature.ts +28 -3
  29. package/src/template-resolver/README.md +89 -0
  30. package/src/template-resolver/__tests__/handlers.integration.ts +403 -0
  31. package/src/template-resolver/__tests__/template-resolver.integration.ts +570 -0
  32. package/src/template-resolver/api.ts +205 -0
  33. package/src/template-resolver/constants.ts +28 -0
  34. package/src/template-resolver/feature.ts +36 -0
  35. package/src/template-resolver/handlers/archive.write.ts +42 -0
  36. package/src/template-resolver/handlers/find-by-id.query.ts +45 -0
  37. package/src/template-resolver/handlers/list.query.ts +71 -0
  38. package/src/template-resolver/handlers/publish.write.ts +45 -0
  39. package/src/template-resolver/handlers/shared.ts +41 -0
  40. package/src/template-resolver/handlers/upsert-system.write.ts +81 -0
  41. package/src/template-resolver/handlers/upsert-tenant.write.ts +105 -0
  42. package/src/template-resolver/index.ts +28 -0
  43. package/src/template-resolver/qualified-names.ts +24 -0
  44. package/src/template-resolver/table.ts +67 -0
  45. package/src/text-content/__tests__/text-content.integration.ts +54 -0
  46. package/src/text-content/handlers/by-slug.query.ts +1 -0
  47. package/src/text-content/handlers/by-tenant.query.ts +2 -0
  48. package/src/text-content/handlers/set.write.ts +23 -0
  49. package/src/text-content/seeding.ts +9 -1
  50. package/src/text-content/table.ts +6 -0
  51. package/src/text-content/web/__tests__/editor-read-only.test.tsx +125 -0
  52. package/src/text-content/web/__tests__/group-blocks.test.ts +221 -0
  53. package/src/text-content/web/client-plugin.tsx +378 -0
  54. package/src/text-content/web/client-plugin.ts +0 -113
@@ -1,113 +0,0 @@
1
- // @runtime client
2
- // Client-Feature-Factory für text-content Visual-Tree. Wird vom App-Code
3
- // in createKumikoApp({ clientFeatures: [textContentClient()] }) eingehängt
4
- // und liefert den treeProvider der Text-Blocks aus der by-tenant Query
5
- // lädt, nach Slug-Prefix gruppiert und als TreeNode[] emitted.
6
- //
7
- // **Slug-Gruppierung**: Slugs der Form `<prefix>:<rest>` oder `<prefix>/<rest>`
8
- // werden unter einem `<prefix>`-Container-Knoten gruppiert. Slugs ohne
9
- // Trenner landen als Top-Level-Knoten. Beispiele:
10
- // - "page:index:hero.title" → folder "page", label "index:hero.title"
11
- // - "imprint" → root-node, label "imprint"
12
- // V.1.3+ kann mehrstufige Hierarchien einführen wenn realer Bedarf zeigt.
13
- //
14
- // **State**: TreeNode.state = "filled" wenn body gesetzt ist, sonst
15
- // "stub" (hellgrau, Designer-Hinweis dass Slug existiert aber leer ist).
16
- //
17
- // **Fetch statt Subscribe**: V.1.1 ist Fetch-once beim Mount. Unsubscribe
18
- // ist no-op. V.1.3+ kann SSE-driven Re-Emit einbauen wenn text-block-
19
- // updated-Events propagiert werden.
20
-
21
- import type { TreeChildrenSubscribe, TreeNode } from "@cosmicdrift/kumiko-framework/engine";
22
- import type { ClientFeatureDefinition } from "@cosmicdrift/kumiko-renderer-web";
23
- import { TextContentQueries } from "../constants";
24
-
25
- type BlockSummary = {
26
- readonly slug: string;
27
- readonly lang: string;
28
- readonly title: string;
29
- readonly body: string | null;
30
- readonly updatedAt: string;
31
- };
32
-
33
- type ByTenantResponse = {
34
- readonly data: { readonly blocks: readonly BlockSummary[] };
35
- };
36
-
37
- // Folder-Name = alles vor dem ersten ":" oder "/", oder undefined wenn
38
- // der Slug keinen Trenner enthält (dann landet er als Root-Node).
39
- function getFolderName(slug: string): string | undefined {
40
- const sepIdx = slug.search(/[:/]/);
41
- if (sepIdx === -1) return undefined;
42
- return slug.slice(0, sepIdx);
43
- }
44
-
45
- function groupBlocksBySlugPrefix(blocks: readonly BlockSummary[]): readonly TreeNode[] {
46
- const rootNodes: TreeNode[] = [];
47
- const folders = new Map<string, TreeNode[]>();
48
-
49
- for (const block of blocks) {
50
- const node: TreeNode = {
51
- label: block.title || block.slug,
52
- target: {
53
- featureId: "text-content",
54
- action: "edit",
55
- args: { slug: block.slug, lang: block.lang },
56
- },
57
- state: block.body ? "filled" : "stub",
58
- };
59
-
60
- const folderName = getFolderName(block.slug);
61
- if (folderName === undefined) {
62
- rootNodes.push(node);
63
- } else {
64
- const existing = folders.get(folderName) ?? [];
65
- existing.push(node);
66
- folders.set(folderName, existing);
67
- }
68
- }
69
-
70
- for (const [name, children] of folders) {
71
- rootNodes.push({
72
- label: name,
73
- icon: "folder",
74
- state: "filled",
75
- children,
76
- });
77
- }
78
-
79
- return rootNodes;
80
- }
81
-
82
- const treeProvider: TreeChildrenSubscribe = (_ctx) => (emit) => {
83
- fetch("/api/query", {
84
- method: "POST",
85
- headers: { "content-type": "application/json" },
86
- body: JSON.stringify({
87
- type: TextContentQueries.byTenant,
88
- payload: {},
89
- }),
90
- })
91
- .then((r) => r.json())
92
- .then((data: ByTenantResponse) => {
93
- const nodes = groupBlocksBySlugPrefix(data.data.blocks);
94
- emit(nodes);
95
- })
96
- .catch(() => {
97
- // V.1.3+ TODO: state="error"-Knoten + Reload-Action statt empty.
98
- emit([]);
99
- });
100
- return () => {};
101
- };
102
-
103
- export function textContentClient(): ClientFeatureDefinition {
104
- return {
105
- name: "text-content",
106
- treeProvider,
107
- treeActions: {
108
- edit: { args: { slug: "" as string, lang: "" as string } },
109
- list: {},
110
- create: { args: { folder: "" as string } },
111
- },
112
- };
113
- }