@specverse/runtime 4.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/runtime/views/core/entity-display.d.ts +31 -0
- package/dist/runtime/views/core/entity-display.d.ts.map +1 -0
- package/dist/runtime/views/core/entity-display.js +123 -0
- package/dist/runtime/views/core/entity-display.js.map +1 -0
- package/dist/runtime/views/core/field-classification.d.ts +65 -0
- package/dist/runtime/views/core/field-classification.d.ts.map +1 -0
- package/dist/runtime/views/core/field-classification.js +142 -0
- package/dist/runtime/views/core/field-classification.js.map +1 -0
- package/dist/runtime/views/core/index.d.ts +5 -0
- package/dist/runtime/views/core/index.d.ts.map +1 -0
- package/dist/runtime/views/core/index.js +5 -0
- package/dist/runtime/views/core/index.js.map +1 -0
- package/dist/runtime/views/core/pattern-engine.d.ts +54 -0
- package/dist/runtime/views/core/pattern-engine.d.ts.map +1 -0
- package/dist/runtime/views/core/pattern-engine.js +125 -0
- package/dist/runtime/views/core/pattern-engine.js.map +1 -0
- package/dist/runtime/views/core/types.d.ts +82 -0
- package/dist/runtime/views/core/types.d.ts.map +1 -0
- package/dist/runtime/views/core/types.js +10 -0
- package/dist/runtime/views/core/types.js.map +1 -0
- package/dist/runtime/views/index.d.ts +11 -0
- package/dist/runtime/views/index.d.ts.map +1 -0
- package/dist/runtime/views/index.js +11 -0
- package/dist/runtime/views/index.js.map +1 -0
- package/dist/runtime/views/react/components/DevShell.d.ts +26 -0
- package/dist/runtime/views/react/components/DevShell.d.ts.map +1 -0
- package/dist/runtime/views/react/components/DevShell.js +55 -0
- package/dist/runtime/views/react/components/DevShell.js.map +1 -0
- package/dist/runtime/views/react/components/ModelManager.d.ts +15 -0
- package/dist/runtime/views/react/components/ModelManager.d.ts.map +1 -0
- package/dist/runtime/views/react/components/ModelManager.js +182 -0
- package/dist/runtime/views/react/components/ModelManager.js.map +1 -0
- package/dist/runtime/views/react/components/ModelSelector.d.ts +13 -0
- package/dist/runtime/views/react/components/ModelSelector.d.ts.map +1 -0
- package/dist/runtime/views/react/components/ModelSelector.js +43 -0
- package/dist/runtime/views/react/components/ModelSelector.js.map +1 -0
- package/dist/runtime/views/react/components/RelationshipField.d.ts +20 -0
- package/dist/runtime/views/react/components/RelationshipField.d.ts.map +1 -0
- package/dist/runtime/views/react/components/RelationshipField.js +31 -0
- package/dist/runtime/views/react/components/RelationshipField.js.map +1 -0
- package/dist/runtime/views/react/components/RuntimeView.d.ts +20 -0
- package/dist/runtime/views/react/components/RuntimeView.d.ts.map +1 -0
- package/dist/runtime/views/react/components/RuntimeView.js +284 -0
- package/dist/runtime/views/react/components/RuntimeView.js.map +1 -0
- package/dist/runtime/views/react/components/ViewRouter.d.ts +22 -0
- package/dist/runtime/views/react/components/ViewRouter.d.ts.map +1 -0
- package/dist/runtime/views/react/components/ViewRouter.js +70 -0
- package/dist/runtime/views/react/components/ViewRouter.js.map +1 -0
- package/dist/runtime/views/react/components/ViewSidebar.d.ts +14 -0
- package/dist/runtime/views/react/components/ViewSidebar.d.ts.map +1 -0
- package/dist/runtime/views/react/components/ViewSidebar.js +11 -0
- package/dist/runtime/views/react/components/ViewSidebar.js.map +1 -0
- package/dist/runtime/views/react/components/ui/ResizeHandle.d.ts +13 -0
- package/dist/runtime/views/react/components/ui/ResizeHandle.d.ts.map +1 -0
- package/dist/runtime/views/react/components/ui/ResizeHandle.js +11 -0
- package/dist/runtime/views/react/components/ui/ResizeHandle.js.map +1 -0
- package/dist/runtime/views/react/context.d.ts +24 -0
- package/dist/runtime/views/react/context.d.ts.map +1 -0
- package/dist/runtime/views/react/context.js +32 -0
- package/dist/runtime/views/react/context.js.map +1 -0
- package/dist/runtime/views/react/hooks/useEntityHelpers.d.ts +25 -0
- package/dist/runtime/views/react/hooks/useEntityHelpers.d.ts.map +1 -0
- package/dist/runtime/views/react/hooks/useEntityHelpers.js +49 -0
- package/dist/runtime/views/react/hooks/useEntityHelpers.js.map +1 -0
- package/dist/runtime/views/react/hooks/useResizableSidebar.d.ts +18 -0
- package/dist/runtime/views/react/hooks/useResizableSidebar.d.ts.map +1 -0
- package/dist/runtime/views/react/hooks/useResizableSidebar.js +37 -0
- package/dist/runtime/views/react/hooks/useResizableSidebar.js.map +1 -0
- package/dist/runtime/views/react/hooks/useTheme.d.ts +15 -0
- package/dist/runtime/views/react/hooks/useTheme.d.ts.map +1 -0
- package/dist/runtime/views/react/hooks/useTheme.js +32 -0
- package/dist/runtime/views/react/hooks/useTheme.js.map +1 -0
- package/dist/runtime/views/react/index.d.ts +20 -0
- package/dist/runtime/views/react/index.d.ts.map +1 -0
- package/dist/runtime/views/react/index.js +23 -0
- package/dist/runtime/views/react/index.js.map +1 -0
- package/dist/runtime/views/tailwind/index.d.ts +8 -0
- package/dist/runtime/views/tailwind/index.d.ts.map +1 -0
- package/dist/runtime/views/tailwind/index.js +8 -0
- package/dist/runtime/views/tailwind/index.js.map +1 -0
- package/dist/runtime/views/tailwind/universal-adapter.d.ts +37 -0
- package/dist/runtime/views/tailwind/universal-adapter.d.ts.map +1 -0
- package/dist/runtime/views/tailwind/universal-adapter.js +616 -0
- package/dist/runtime/views/tailwind/universal-adapter.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity Display Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized logic for generating human-readable display names for entities.
|
|
5
|
+
* Framework-agnostic — works with any frontend or backend context.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from specverse-app-demo/frontend-react/src/lib/utils/entity-display.ts
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Get a human-readable display name for an entity.
|
|
11
|
+
*
|
|
12
|
+
* Resolution order:
|
|
13
|
+
* 1. Standard fields: name, title, label
|
|
14
|
+
* 2. Fields ending with Name, Title, Label
|
|
15
|
+
* 3. Relationship resolution via foreign keys
|
|
16
|
+
* 4. Fallback fields: email, location, description
|
|
17
|
+
* 5. Date formatting for temporal entities
|
|
18
|
+
* 6. Truncated ID as last resort
|
|
19
|
+
*/
|
|
20
|
+
export declare function getEntityDisplayName(entity: any, allEntities?: Record<string, any[]>): string;
|
|
21
|
+
/**
|
|
22
|
+
* Humanize a field name for display.
|
|
23
|
+
* Converts camelCase/snake_case to human-readable format.
|
|
24
|
+
*
|
|
25
|
+
* Examples:
|
|
26
|
+
* 'firstName' → 'First Name'
|
|
27
|
+
* 'authorId' → 'Author'
|
|
28
|
+
* 'created_at' → 'Created at'
|
|
29
|
+
*/
|
|
30
|
+
export declare function humanizeFieldName(fieldName: string): string;
|
|
31
|
+
//# sourceMappingURL=entity-display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-display.d.ts","sourceRoot":"","sources":["../../../../src/runtime/views/core/entity-display.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,GAAG,EACX,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAM,GACtC,MAAM,CAiGR;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAO3D"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity Display Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized logic for generating human-readable display names for entities.
|
|
5
|
+
* Framework-agnostic — works with any frontend or backend context.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from specverse-app-demo/frontend-react/src/lib/utils/entity-display.ts
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Get a human-readable display name for an entity.
|
|
11
|
+
*
|
|
12
|
+
* Resolution order:
|
|
13
|
+
* 1. Standard fields: name, title, label
|
|
14
|
+
* 2. Fields ending with Name, Title, Label
|
|
15
|
+
* 3. Relationship resolution via foreign keys
|
|
16
|
+
* 4. Fallback fields: email, location, description
|
|
17
|
+
* 5. Date formatting for temporal entities
|
|
18
|
+
* 6. Truncated ID as last resort
|
|
19
|
+
*/
|
|
20
|
+
export function getEntityDisplayName(entity, allEntities = {}) {
|
|
21
|
+
const data = entity?.data || entity || {};
|
|
22
|
+
// Try standard name/title/label fields first
|
|
23
|
+
if (data.name)
|
|
24
|
+
return data.name;
|
|
25
|
+
if (data.title)
|
|
26
|
+
return data.title;
|
|
27
|
+
if (data.label)
|
|
28
|
+
return data.label;
|
|
29
|
+
// Try fields ending with Name (e.g., roomName, houseName, guestName)
|
|
30
|
+
for (const key in data) {
|
|
31
|
+
if (key.endsWith('Name') && typeof data[key] === 'string' && data[key]) {
|
|
32
|
+
return data[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Try fields ending with Title
|
|
36
|
+
for (const key in data) {
|
|
37
|
+
if (key.endsWith('Title') && typeof data[key] === 'string' && data[key]) {
|
|
38
|
+
return data[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Try fields ending with Label
|
|
42
|
+
for (const key in data) {
|
|
43
|
+
if (key.endsWith('Label') && typeof data[key] === 'string' && data[key]) {
|
|
44
|
+
return data[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// Helper to resolve a relationship by foreign key
|
|
48
|
+
const resolveRelation = (relName) => {
|
|
49
|
+
// First check if already populated
|
|
50
|
+
if (data[relName]?.name) {
|
|
51
|
+
return data[relName].name;
|
|
52
|
+
}
|
|
53
|
+
if (data[relName]?.title) {
|
|
54
|
+
return data[relName].title;
|
|
55
|
+
}
|
|
56
|
+
// Try to resolve using foreign key
|
|
57
|
+
const foreignKey = `${relName}Id`;
|
|
58
|
+
const foreignKeyValue = data[foreignKey];
|
|
59
|
+
if (foreignKeyValue) {
|
|
60
|
+
const targetModel = relName.charAt(0).toUpperCase() + relName.slice(1);
|
|
61
|
+
const targetEntities = allEntities[targetModel] || [];
|
|
62
|
+
const targetEntity = targetEntities.find((e) => e.data?.id === foreignKeyValue || e.id === foreignKeyValue);
|
|
63
|
+
if (targetEntity) {
|
|
64
|
+
return getEntityDisplayName(targetEntity, allEntities);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
};
|
|
69
|
+
// For junction tables or entities without names, construct from relationships
|
|
70
|
+
const relatedNames = [];
|
|
71
|
+
// Check all keys in data that end with 'Id' (foreign keys)
|
|
72
|
+
for (const key in data) {
|
|
73
|
+
if (key.endsWith('Id')) {
|
|
74
|
+
const relName = key.slice(0, -2);
|
|
75
|
+
const relValue = resolveRelation(relName);
|
|
76
|
+
if (relValue) {
|
|
77
|
+
relatedNames.push(relValue);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (relatedNames.length > 0) {
|
|
82
|
+
return relatedNames.join(' - ');
|
|
83
|
+
}
|
|
84
|
+
// Try other useful fields (generic)
|
|
85
|
+
if (data.email)
|
|
86
|
+
return data.email;
|
|
87
|
+
if (data.location)
|
|
88
|
+
return data.location;
|
|
89
|
+
if (data.description)
|
|
90
|
+
return data.description;
|
|
91
|
+
// Format date fields nicely (include time for uniqueness)
|
|
92
|
+
if (data.appliedAt) {
|
|
93
|
+
const date = new Date(data.appliedAt);
|
|
94
|
+
return `Applied ${date.toLocaleString()}`;
|
|
95
|
+
}
|
|
96
|
+
if (data.dateTime) {
|
|
97
|
+
const date = new Date(data.dateTime);
|
|
98
|
+
return date.toLocaleString();
|
|
99
|
+
}
|
|
100
|
+
// Last resort: use UUID with truncation for readability
|
|
101
|
+
if (data.id) {
|
|
102
|
+
return `${data.id.slice(0, 8)}...`;
|
|
103
|
+
}
|
|
104
|
+
return entity.id || 'Unknown';
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Humanize a field name for display.
|
|
108
|
+
* Converts camelCase/snake_case to human-readable format.
|
|
109
|
+
*
|
|
110
|
+
* Examples:
|
|
111
|
+
* 'firstName' → 'First Name'
|
|
112
|
+
* 'authorId' → 'Author'
|
|
113
|
+
* 'created_at' → 'Created at'
|
|
114
|
+
*/
|
|
115
|
+
export function humanizeFieldName(fieldName) {
|
|
116
|
+
return fieldName
|
|
117
|
+
.replace(/Id$/, '')
|
|
118
|
+
.replace(/([A-Z])/g, ' $1')
|
|
119
|
+
.replace(/_/g, ' ')
|
|
120
|
+
.replace(/^./, (str) => str.toUpperCase())
|
|
121
|
+
.trim();
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=entity-display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-display.js","sourceRoot":"","sources":["../../../../src/runtime/views/core/entity-display.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field Classification
|
|
3
|
+
*
|
|
4
|
+
* Pure functions for classifying spec fields into categories:
|
|
5
|
+
* business, relationship, lifecycle, metadata, auto-generated.
|
|
6
|
+
*
|
|
7
|
+
* Framework-agnostic — no React or DOM dependencies.
|
|
8
|
+
*
|
|
9
|
+
* Consolidated from:
|
|
10
|
+
* - app-demo useEntityHelpers.ts (field separation, metadata detection)
|
|
11
|
+
* - engines field-helpers-generator.ts (auto-generated detection, defaults)
|
|
12
|
+
*/
|
|
13
|
+
/** Result of classifying a model's fields */
|
|
14
|
+
export interface FieldClassification {
|
|
15
|
+
/** Business logic fields (displayed prominently) */
|
|
16
|
+
regularFields: string[];
|
|
17
|
+
/** Metadata fields (id, timestamps — displayed at end, muted) */
|
|
18
|
+
metadataFields: string[];
|
|
19
|
+
}
|
|
20
|
+
/** Fields always treated as metadata (displayed last, muted styling) */
|
|
21
|
+
export declare const METADATA_FIELDS: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Classify fields into regular (business) vs metadata categories.
|
|
24
|
+
*
|
|
25
|
+
* Column order in views:
|
|
26
|
+
* 1. Regular business fields
|
|
27
|
+
* 2. Relationship fields (blue)
|
|
28
|
+
* 3. Lifecycle fields (purple badges)
|
|
29
|
+
* 4. Metadata fields (gray, italic)
|
|
30
|
+
*/
|
|
31
|
+
export declare function classifyFields(attributes: Record<string, unknown>): FieldClassification;
|
|
32
|
+
/**
|
|
33
|
+
* Check if a field is auto-generated (should be hidden in forms).
|
|
34
|
+
*
|
|
35
|
+
* Detection:
|
|
36
|
+
* - Has `auto` property in schema (auto=now, auto=uuid4, etc.)
|
|
37
|
+
* - String format contains `auto=`
|
|
38
|
+
* - Common auto-generated DateTime fields (createdAt, updatedAt, etc.)
|
|
39
|
+
* - UUID id field
|
|
40
|
+
*/
|
|
41
|
+
export declare function isAutoField(attrName: string, attrDef: unknown): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Check if a field is a metadata field (id, timestamps).
|
|
44
|
+
*/
|
|
45
|
+
export declare function isMetadataField(name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Check if a field represents a relationship (foreign key).
|
|
48
|
+
*/
|
|
49
|
+
export declare function isRelationshipField(name: string): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Check if a field is required.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isFieldRequired(attrDef: unknown): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Get default value for a field based on its type.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getFieldDefaultValue(attrDef: unknown): unknown;
|
|
58
|
+
/**
|
|
59
|
+
* Initialize form data from schema attributes.
|
|
60
|
+
* Skips auto-generated fields by default.
|
|
61
|
+
*/
|
|
62
|
+
export declare function initializeFormData(attributes: Record<string, unknown>, options?: {
|
|
63
|
+
includeAutoGenerated?: boolean;
|
|
64
|
+
}): Record<string, unknown>;
|
|
65
|
+
//# sourceMappingURL=field-classification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-classification.d.ts","sourceRoot":"","sources":["../../../../src/runtime/views/core/field-classification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iEAAiE;IACjE,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wEAAwE;AACxE,eAAO,MAAM,eAAe,UAE3B,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,mBAAmB,CAiBrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAqBvE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAMzD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAgC9D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,OAAO,GAAE;IAAE,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field Classification
|
|
3
|
+
*
|
|
4
|
+
* Pure functions for classifying spec fields into categories:
|
|
5
|
+
* business, relationship, lifecycle, metadata, auto-generated.
|
|
6
|
+
*
|
|
7
|
+
* Framework-agnostic — no React or DOM dependencies.
|
|
8
|
+
*
|
|
9
|
+
* Consolidated from:
|
|
10
|
+
* - app-demo useEntityHelpers.ts (field separation, metadata detection)
|
|
11
|
+
* - engines field-helpers-generator.ts (auto-generated detection, defaults)
|
|
12
|
+
*/
|
|
13
|
+
/** Fields always treated as metadata (displayed last, muted styling) */
|
|
14
|
+
export const METADATA_FIELDS = [
|
|
15
|
+
'id', 'createdAt', 'updatedAt', 'appliedAt', 'joinedAt', 'publishedAt',
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Classify fields into regular (business) vs metadata categories.
|
|
19
|
+
*
|
|
20
|
+
* Column order in views:
|
|
21
|
+
* 1. Regular business fields
|
|
22
|
+
* 2. Relationship fields (blue)
|
|
23
|
+
* 3. Lifecycle fields (purple badges)
|
|
24
|
+
* 4. Metadata fields (gray, italic)
|
|
25
|
+
*/
|
|
26
|
+
export function classifyFields(attributes) {
|
|
27
|
+
if (!attributes || Object.keys(attributes).length === 0) {
|
|
28
|
+
return { regularFields: [], metadataFields: [] };
|
|
29
|
+
}
|
|
30
|
+
const regular = [];
|
|
31
|
+
const metadata = [];
|
|
32
|
+
for (const key of Object.keys(attributes)) {
|
|
33
|
+
if (METADATA_FIELDS.includes(key)) {
|
|
34
|
+
metadata.push(key);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
regular.push(key);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return { regularFields: regular, metadataFields: metadata };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if a field is auto-generated (should be hidden in forms).
|
|
44
|
+
*
|
|
45
|
+
* Detection:
|
|
46
|
+
* - Has `auto` property in schema (auto=now, auto=uuid4, etc.)
|
|
47
|
+
* - String format contains `auto=`
|
|
48
|
+
* - Common auto-generated DateTime fields (createdAt, updatedAt, etc.)
|
|
49
|
+
* - UUID id field
|
|
50
|
+
*/
|
|
51
|
+
export function isAutoField(attrName, attrDef) {
|
|
52
|
+
// Object format with auto property
|
|
53
|
+
if (attrDef && typeof attrDef === 'object' && attrDef.auto) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
const typeStr = typeof attrDef === 'string'
|
|
57
|
+
? attrDef
|
|
58
|
+
: attrDef?.type || '';
|
|
59
|
+
// String format with auto= modifier
|
|
60
|
+
if (typeStr.includes('auto='))
|
|
61
|
+
return true;
|
|
62
|
+
// UUID id field
|
|
63
|
+
if (attrName === 'id' && typeStr.includes('UUID'))
|
|
64
|
+
return true;
|
|
65
|
+
// Common auto-generated DateTime fields
|
|
66
|
+
const autoDateFields = ['createdAt', 'updatedAt', 'joinedAt', 'publishedAt'];
|
|
67
|
+
if (autoDateFields.includes(attrName) && typeStr.includes('DateTime'))
|
|
68
|
+
return true;
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if a field is a metadata field (id, timestamps).
|
|
73
|
+
*/
|
|
74
|
+
export function isMetadataField(name) {
|
|
75
|
+
return METADATA_FIELDS.includes(name);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if a field represents a relationship (foreign key).
|
|
79
|
+
*/
|
|
80
|
+
export function isRelationshipField(name) {
|
|
81
|
+
return name.endsWith('Id') && name !== 'id';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if a field is required.
|
|
85
|
+
*/
|
|
86
|
+
export function isFieldRequired(attrDef) {
|
|
87
|
+
if (!attrDef)
|
|
88
|
+
return false;
|
|
89
|
+
if (typeof attrDef === 'string') {
|
|
90
|
+
return attrDef.toLowerCase().includes('required');
|
|
91
|
+
}
|
|
92
|
+
return attrDef.required === true;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get default value for a field based on its type.
|
|
96
|
+
*/
|
|
97
|
+
export function getFieldDefaultValue(attrDef) {
|
|
98
|
+
if (!attrDef)
|
|
99
|
+
return '';
|
|
100
|
+
const typeStr = typeof attrDef === 'string'
|
|
101
|
+
? attrDef
|
|
102
|
+
: attrDef?.type || '';
|
|
103
|
+
// Check if schema has an explicit default
|
|
104
|
+
if (attrDef && typeof attrDef === 'object' && attrDef.default !== undefined) {
|
|
105
|
+
const defaultVal = attrDef.default;
|
|
106
|
+
if (typeStr.toLowerCase().includes('bool')) {
|
|
107
|
+
return defaultVal === 'true' || defaultVal === true;
|
|
108
|
+
}
|
|
109
|
+
else if (typeStr.toLowerCase().includes('int') ||
|
|
110
|
+
typeStr.toLowerCase().includes('number')) {
|
|
111
|
+
return typeof defaultVal === 'number' ? defaultVal : parseInt(defaultVal) || 0;
|
|
112
|
+
}
|
|
113
|
+
else if (typeStr.toLowerCase().includes('string')) {
|
|
114
|
+
return typeof defaultVal === 'string'
|
|
115
|
+
? defaultVal.replace(/^"|"$/g, '')
|
|
116
|
+
: defaultVal;
|
|
117
|
+
}
|
|
118
|
+
return defaultVal;
|
|
119
|
+
}
|
|
120
|
+
// Type-based defaults
|
|
121
|
+
if (typeStr.toLowerCase().includes('bool'))
|
|
122
|
+
return false;
|
|
123
|
+
if (typeStr.toLowerCase().includes('int') ||
|
|
124
|
+
typeStr.toLowerCase().includes('number'))
|
|
125
|
+
return 0;
|
|
126
|
+
return '';
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Initialize form data from schema attributes.
|
|
130
|
+
* Skips auto-generated fields by default.
|
|
131
|
+
*/
|
|
132
|
+
export function initializeFormData(attributes, options = {}) {
|
|
133
|
+
const data = {};
|
|
134
|
+
for (const [attrName, attrDef] of Object.entries(attributes)) {
|
|
135
|
+
if (!options.includeAutoGenerated && isAutoField(attrName, attrDef)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
data[attrName] = getFieldDefaultValue(attrDef);
|
|
139
|
+
}
|
|
140
|
+
return data;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=field-classification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-classification.js","sourceRoot":"","sources":["../../../../src/runtime/views/core/field-classification.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/runtime/views/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/runtime/views/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AACpC,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Engine — Framework-Agnostic
|
|
3
|
+
*
|
|
4
|
+
* Core logic for detecting view patterns and mapping CURVED operations
|
|
5
|
+
* to protocol (HTTP) endpoints. No React, no DOM, no Tailwind.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from react-pattern-adapter.tsx — the framework-agnostic parts.
|
|
8
|
+
*/
|
|
9
|
+
/** CURVED operation names */
|
|
10
|
+
export type CURVEDOperation = 'create' | 'update' | 'retrieve' | 'retrieve_many' | 'validate' | 'evolve' | 'delete';
|
|
11
|
+
/** Protocol mapping for a CURVED operation */
|
|
12
|
+
export interface ProtocolMapping {
|
|
13
|
+
method: string;
|
|
14
|
+
pathPattern: string;
|
|
15
|
+
}
|
|
16
|
+
/** Result of detecting a pattern from a view spec */
|
|
17
|
+
export interface PatternDetectionResult {
|
|
18
|
+
/** Pattern ID (e.g., 'list-view', 'detail-view') */
|
|
19
|
+
patternId: string;
|
|
20
|
+
/** View category */
|
|
21
|
+
category: 'data-entry' | 'data-display' | 'dashboard';
|
|
22
|
+
/** Original view type from spec */
|
|
23
|
+
viewType: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default CURVED → HTTP protocol mapping.
|
|
27
|
+
*
|
|
28
|
+
* Maps semantic CRUD operations to REST endpoints.
|
|
29
|
+
* Can be overridden per-instance for different backend patterns.
|
|
30
|
+
*/
|
|
31
|
+
export declare const CURVED_PROTOCOL_MAPPING: Record<CURVEDOperation, ProtocolMapping>;
|
|
32
|
+
/**
|
|
33
|
+
* Detect the pattern type from a view specification.
|
|
34
|
+
*
|
|
35
|
+
* Maps view.type to a pattern ID and category.
|
|
36
|
+
* Returns null if the view type is unrecognized.
|
|
37
|
+
*/
|
|
38
|
+
export declare function detectPattern(viewSpec: {
|
|
39
|
+
type?: string;
|
|
40
|
+
}): PatternDetectionResult | null;
|
|
41
|
+
/**
|
|
42
|
+
* Infer displayable fields from a model schema.
|
|
43
|
+
*
|
|
44
|
+
* Returns field names suitable for rendering, excluding
|
|
45
|
+
* auto-generated and internal fields.
|
|
46
|
+
*/
|
|
47
|
+
export declare function inferFieldsFromSchema(modelSchemas: Record<string, any> | undefined, modelName: string): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Infer fields from actual entity data when schema is not available.
|
|
50
|
+
*
|
|
51
|
+
* Examines the first entity to determine field names.
|
|
52
|
+
*/
|
|
53
|
+
export declare function inferFieldsFromModel(entities: any[]): string[];
|
|
54
|
+
//# sourceMappingURL=pattern-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-engine.d.ts","sourceRoot":"","sources":["../../../../src/runtime/views/core/pattern-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,6BAA6B;AAC7B,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,eAAe,GACf,UAAU,GACV,QAAQ,GACR,QAAQ,CAAC;AAEb,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qDAAqD;AACrD,MAAM,WAAW,sBAAsB;IACrC,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB;IACpB,QAAQ,EAAE,YAAY,GAAG,cAAc,GAAG,WAAW,CAAC;IACtD,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,eAAe,EAAE,eAAe,CA6B5E,CAAC;AAmBF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,sBAAsB,GAAG,IAAI,CAYxF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,EAC7C,SAAS,EAAE,MAAM,GAChB,MAAM,EAAE,CAiBV;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,MAAM,EAAE,CAc9D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern Engine — Framework-Agnostic
|
|
3
|
+
*
|
|
4
|
+
* Core logic for detecting view patterns and mapping CURVED operations
|
|
5
|
+
* to protocol (HTTP) endpoints. No React, no DOM, no Tailwind.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from react-pattern-adapter.tsx — the framework-agnostic parts.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Default CURVED → HTTP protocol mapping.
|
|
11
|
+
*
|
|
12
|
+
* Maps semantic CRUD operations to REST endpoints.
|
|
13
|
+
* Can be overridden per-instance for different backend patterns.
|
|
14
|
+
*/
|
|
15
|
+
export const CURVED_PROTOCOL_MAPPING = {
|
|
16
|
+
create: {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
pathPattern: '/api/{resource}',
|
|
19
|
+
},
|
|
20
|
+
update: {
|
|
21
|
+
method: 'PUT',
|
|
22
|
+
pathPattern: '/api/{resource}/{id}',
|
|
23
|
+
},
|
|
24
|
+
retrieve: {
|
|
25
|
+
method: 'GET',
|
|
26
|
+
pathPattern: '/api/{resource}/{id}',
|
|
27
|
+
},
|
|
28
|
+
retrieve_many: {
|
|
29
|
+
method: 'GET',
|
|
30
|
+
pathPattern: '/api/{resource}',
|
|
31
|
+
},
|
|
32
|
+
validate: {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
pathPattern: '/api/{resource}/validate',
|
|
35
|
+
},
|
|
36
|
+
evolve: {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
pathPattern: '/api/{resource}/{id}/evolve',
|
|
39
|
+
},
|
|
40
|
+
delete: {
|
|
41
|
+
method: 'DELETE',
|
|
42
|
+
pathPattern: '/api/{resource}/{id}',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
/** Map from view type string to pattern ID */
|
|
46
|
+
const VIEW_TYPE_TO_PATTERN = {
|
|
47
|
+
'form': { patternId: 'form-view', category: 'data-entry' },
|
|
48
|
+
'create': { patternId: 'form-view', category: 'data-entry' },
|
|
49
|
+
'edit': { patternId: 'form-view', category: 'data-entry' },
|
|
50
|
+
'create-form': { patternId: 'form-view', category: 'data-entry' },
|
|
51
|
+
'edit-form': { patternId: 'form-view', category: 'data-entry' },
|
|
52
|
+
'list': { patternId: 'list-view', category: 'data-display' },
|
|
53
|
+
'table': { patternId: 'list-view', category: 'data-display' },
|
|
54
|
+
'detail': { patternId: 'detail-view', category: 'data-display' },
|
|
55
|
+
'master-detail': { patternId: 'detail-view', category: 'data-display' },
|
|
56
|
+
'dashboard': { patternId: 'dashboard-view', category: 'dashboard' },
|
|
57
|
+
'board': { patternId: 'board-view', category: 'data-display' },
|
|
58
|
+
'timeline': { patternId: 'timeline-view', category: 'data-display' },
|
|
59
|
+
'calendar': { patternId: 'calendar-view', category: 'data-display' },
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Detect the pattern type from a view specification.
|
|
63
|
+
*
|
|
64
|
+
* Maps view.type to a pattern ID and category.
|
|
65
|
+
* Returns null if the view type is unrecognized.
|
|
66
|
+
*/
|
|
67
|
+
export function detectPattern(viewSpec) {
|
|
68
|
+
const viewType = viewSpec.type?.toLowerCase();
|
|
69
|
+
if (!viewType)
|
|
70
|
+
return null;
|
|
71
|
+
const mapping = VIEW_TYPE_TO_PATTERN[viewType];
|
|
72
|
+
if (!mapping)
|
|
73
|
+
return null;
|
|
74
|
+
return {
|
|
75
|
+
patternId: mapping.patternId,
|
|
76
|
+
category: mapping.category,
|
|
77
|
+
viewType,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Infer displayable fields from a model schema.
|
|
82
|
+
*
|
|
83
|
+
* Returns field names suitable for rendering, excluding
|
|
84
|
+
* auto-generated and internal fields.
|
|
85
|
+
*/
|
|
86
|
+
export function inferFieldsFromSchema(modelSchemas, modelName) {
|
|
87
|
+
if (!modelSchemas || !modelSchemas[modelName])
|
|
88
|
+
return [];
|
|
89
|
+
const schema = modelSchemas[modelName];
|
|
90
|
+
const attributes = schema.attributes || {};
|
|
91
|
+
const fields = [];
|
|
92
|
+
for (const [name, def] of Object.entries(attributes)) {
|
|
93
|
+
// Skip internal/auto fields
|
|
94
|
+
if (name === 'id')
|
|
95
|
+
continue;
|
|
96
|
+
if (name === 'createdAt' || name === 'updatedAt')
|
|
97
|
+
continue;
|
|
98
|
+
const typeDef = def;
|
|
99
|
+
if (typeDef?.auto)
|
|
100
|
+
continue;
|
|
101
|
+
fields.push(name);
|
|
102
|
+
}
|
|
103
|
+
return fields;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Infer fields from actual entity data when schema is not available.
|
|
107
|
+
*
|
|
108
|
+
* Examines the first entity to determine field names.
|
|
109
|
+
*/
|
|
110
|
+
export function inferFieldsFromModel(entities) {
|
|
111
|
+
if (!entities || entities.length === 0)
|
|
112
|
+
return [];
|
|
113
|
+
const firstEntity = entities[0];
|
|
114
|
+
const data = firstEntity?.data || firstEntity || {};
|
|
115
|
+
const fields = [];
|
|
116
|
+
for (const key of Object.keys(data)) {
|
|
117
|
+
if (key === 'id')
|
|
118
|
+
continue;
|
|
119
|
+
if (key === 'createdAt' || key === 'updatedAt')
|
|
120
|
+
continue;
|
|
121
|
+
fields.push(key);
|
|
122
|
+
}
|
|
123
|
+
return fields;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=pattern-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-engine.js","sourceRoot":"","sources":["../../../../src/runtime/views/core/pattern-engine.ts"],"names":[],"mappings":"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"}
|