@object-ui/app-shell 6.1.0 → 6.2.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.
- package/CHANGELOG.md +129 -0
- package/README.md +10 -1
- package/dist/console/AppContent.js +53 -2
- package/dist/console/ai/AiChatPage.d.ts +8 -0
- package/dist/console/ai/AiChatPage.js +188 -0
- package/dist/console/ai/ConversationsSidebar.d.ts +7 -0
- package/dist/console/ai/ConversationsSidebar.js +111 -0
- package/dist/console/auth/LoginPage.js +19 -2
- package/dist/console/auth/RegisterPage.js +30 -1
- package/dist/console/marketplace/MarketplaceAccessDenied.js +3 -1
- package/dist/console/marketplace/MarketplaceInstalledPage.js +11 -3
- package/dist/console/marketplace/MarketplacePackagePage.js +57 -19
- package/dist/console/marketplace/MarketplacePage.js +55 -18
- package/dist/console/marketplace/marketplaceApi.d.ts +20 -0
- package/dist/console/marketplace/usePackageL10n.d.ts +38 -0
- package/dist/console/marketplace/usePackageL10n.js +110 -0
- package/dist/console/organizations/CreateWorkspaceDialog.js +29 -1
- package/dist/console/organizations/OrganizationsPage.js +24 -3
- package/dist/context/FavoritesProvider.d.ts +40 -2
- package/dist/context/FavoritesProvider.js +201 -20
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useChatConversation.d.ts +7 -0
- package/dist/hooks/useChatConversation.js +37 -5
- package/dist/hooks/useConversationList.d.ts +25 -0
- package/dist/hooks/useConversationList.js +131 -0
- package/dist/hooks/useNavPins.d.ts +11 -4
- package/dist/hooks/useNavPins.js +104 -53
- package/dist/index.d.ts +7 -0
- package/dist/index.js +14 -0
- package/dist/layout/AppHeader.js +2 -2
- package/dist/layout/AppSidebar.js +20 -1
- package/dist/layout/UnifiedSidebar.js +1 -1
- package/dist/providers/ExpressionProvider.d.ts +11 -1
- package/dist/providers/ExpressionProvider.js +11 -6
- package/dist/services/builtinComponents.d.ts +1 -0
- package/dist/services/builtinComponents.js +169 -0
- package/dist/services/componentRegistry.d.ts +63 -0
- package/dist/services/componentRegistry.js +36 -0
- package/dist/views/ComponentNavView.d.ts +6 -0
- package/dist/views/ComponentNavView.js +26 -0
- package/dist/views/RecordDetailView.js +66 -6
- package/dist/views/RecordFormPage.js +15 -3
- package/dist/views/SearchResultsPage.js +4 -0
- package/dist/views/metadata-admin/DesignerEditorWrapper.d.ts +68 -0
- package/dist/views/metadata-admin/DesignerEditorWrapper.js +158 -0
- package/dist/views/metadata-admin/DirectoryPage.d.ts +1 -0
- package/dist/views/metadata-admin/DirectoryPage.js +135 -0
- package/dist/views/metadata-admin/LayeredDiff.d.ts +6 -0
- package/dist/views/metadata-admin/LayeredDiff.js +26 -0
- package/dist/views/metadata-admin/MetadataDetailDrawer.d.ts +13 -0
- package/dist/views/metadata-admin/MetadataDetailDrawer.js +52 -0
- package/dist/views/metadata-admin/PageShell.d.ts +34 -0
- package/dist/views/metadata-admin/PageShell.js +40 -0
- package/dist/views/metadata-admin/PermissionMatrixEditor.d.ts +5 -0
- package/dist/views/metadata-admin/PermissionMatrixEditor.js +288 -0
- package/dist/views/metadata-admin/QuickFind.d.ts +5 -0
- package/dist/views/metadata-admin/QuickFind.js +152 -0
- package/dist/views/metadata-admin/RelatedPanel.d.ts +33 -0
- package/dist/views/metadata-admin/RelatedPanel.js +171 -0
- package/dist/views/metadata-admin/ResourceEditPage.d.ts +13 -0
- package/dist/views/metadata-admin/ResourceEditPage.js +302 -0
- package/dist/views/metadata-admin/ResourceHistoryPage.d.ts +5 -0
- package/dist/views/metadata-admin/ResourceHistoryPage.js +100 -0
- package/dist/views/metadata-admin/ResourceListPage.d.ts +4 -0
- package/dist/views/metadata-admin/ResourceListPage.js +146 -0
- package/dist/views/metadata-admin/ResourceRouter.d.ts +10 -0
- package/dist/views/metadata-admin/ResourceRouter.js +47 -0
- package/dist/views/metadata-admin/SchemaForm.d.ts +99 -0
- package/dist/views/metadata-admin/SchemaForm.js +565 -0
- package/dist/views/metadata-admin/anchors.d.ts +1 -0
- package/dist/views/metadata-admin/anchors.js +229 -0
- package/dist/views/metadata-admin/default-schemas.d.ts +6 -0
- package/dist/views/metadata-admin/default-schemas.js +207 -0
- package/dist/views/metadata-admin/i18n.d.ts +33 -0
- package/dist/views/metadata-admin/i18n.js +303 -0
- package/dist/views/metadata-admin/index.d.ts +33 -0
- package/dist/views/metadata-admin/index.js +39 -0
- package/dist/views/metadata-admin/predicate.d.ts +31 -0
- package/dist/views/metadata-admin/predicate.js +150 -0
- package/dist/views/metadata-admin/registry.d.ts +232 -0
- package/dist/views/metadata-admin/registry.js +106 -0
- package/dist/views/metadata-admin/useMetadata.d.ts +37 -0
- package/dist/views/metadata-admin/useMetadata.js +96 -0
- package/dist/views/metadata-admin/widgets.d.ts +68 -0
- package/dist/views/metadata-admin/widgets.js +287 -0
- package/package.json +27 -26
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
const TYPE_LABELS_EN = {
|
|
3
|
+
// Data
|
|
4
|
+
object: 'Object',
|
|
5
|
+
field: 'Field',
|
|
6
|
+
trigger: 'Trigger',
|
|
7
|
+
validation: 'Validation Rule',
|
|
8
|
+
hook: 'Hook',
|
|
9
|
+
// UI
|
|
10
|
+
view: 'View',
|
|
11
|
+
page: 'Page',
|
|
12
|
+
dashboard: 'Dashboard',
|
|
13
|
+
app: 'Application',
|
|
14
|
+
action: 'Action',
|
|
15
|
+
report: 'Report',
|
|
16
|
+
// Automation
|
|
17
|
+
flow: 'Flow',
|
|
18
|
+
workflow: 'Workflow',
|
|
19
|
+
approval: 'Approval Process',
|
|
20
|
+
// System
|
|
21
|
+
datasource: 'Datasource',
|
|
22
|
+
translation: 'Translation',
|
|
23
|
+
router: 'Router',
|
|
24
|
+
function: 'Function',
|
|
25
|
+
service: 'Service',
|
|
26
|
+
email_template: 'Email Template',
|
|
27
|
+
// Security
|
|
28
|
+
permission: 'Permission Set',
|
|
29
|
+
profile: 'Profile',
|
|
30
|
+
role: 'Role',
|
|
31
|
+
// AI
|
|
32
|
+
agent: 'AI Agent',
|
|
33
|
+
tool: 'AI Tool',
|
|
34
|
+
skill: 'AI Skill',
|
|
35
|
+
// Platform
|
|
36
|
+
package: 'Package',
|
|
37
|
+
data: 'Dataset',
|
|
38
|
+
};
|
|
39
|
+
const TYPE_LABELS_ZH = {
|
|
40
|
+
object: '对象',
|
|
41
|
+
field: '字段',
|
|
42
|
+
trigger: '触发器',
|
|
43
|
+
validation: '校验规则',
|
|
44
|
+
hook: '钩子',
|
|
45
|
+
view: '视图',
|
|
46
|
+
page: '页面',
|
|
47
|
+
dashboard: '仪表板',
|
|
48
|
+
app: '应用',
|
|
49
|
+
action: '操作',
|
|
50
|
+
report: '报表',
|
|
51
|
+
flow: '流程',
|
|
52
|
+
workflow: '工作流',
|
|
53
|
+
approval: '审批流程',
|
|
54
|
+
datasource: '数据源',
|
|
55
|
+
translation: '翻译',
|
|
56
|
+
router: '路由',
|
|
57
|
+
function: '函数',
|
|
58
|
+
service: '服务',
|
|
59
|
+
email_template: '邮件模板',
|
|
60
|
+
permission: '权限集',
|
|
61
|
+
profile: '配置文件',
|
|
62
|
+
role: '角色',
|
|
63
|
+
agent: 'AI 智能体',
|
|
64
|
+
tool: 'AI 工具',
|
|
65
|
+
skill: 'AI 技能',
|
|
66
|
+
package: '包',
|
|
67
|
+
data: '数据集',
|
|
68
|
+
};
|
|
69
|
+
const DOMAIN_LABELS_EN = {
|
|
70
|
+
data: 'Data',
|
|
71
|
+
ui: 'UI',
|
|
72
|
+
automation: 'Automation',
|
|
73
|
+
ai: 'AI',
|
|
74
|
+
system: 'System',
|
|
75
|
+
platform: 'Platform',
|
|
76
|
+
identity: 'Identity',
|
|
77
|
+
security: 'Security',
|
|
78
|
+
other: 'Other',
|
|
79
|
+
};
|
|
80
|
+
const DOMAIN_LABELS_ZH = {
|
|
81
|
+
data: '数据',
|
|
82
|
+
ui: '界面',
|
|
83
|
+
automation: '自动化',
|
|
84
|
+
ai: 'AI',
|
|
85
|
+
system: '系统',
|
|
86
|
+
platform: '平台',
|
|
87
|
+
identity: '身份',
|
|
88
|
+
security: '安全',
|
|
89
|
+
other: '其他',
|
|
90
|
+
};
|
|
91
|
+
const ENGINE_STRINGS_EN = {
|
|
92
|
+
'engine.directory.title': 'All Metadata Types',
|
|
93
|
+
'engine.directory.description': 'The platform protocol exposes {count} metadata types ({writable} writable at runtime). Click any tile to browse, override, or create instances.',
|
|
94
|
+
'engine.directory.search': 'Search metadata types…',
|
|
95
|
+
'engine.directory.writableOnly': 'Writable only',
|
|
96
|
+
'engine.directory.quickFind': 'Quick Find',
|
|
97
|
+
'engine.directory.noMatches': 'No matches',
|
|
98
|
+
'engine.directory.noMatchesHint': 'Adjust your search or filters to see more metadata types.',
|
|
99
|
+
'engine.directory.loading': 'Loading metadata types…',
|
|
100
|
+
'engine.directory.loadFailed': 'Failed to load metadata types',
|
|
101
|
+
'engine.directory.all': 'All',
|
|
102
|
+
'engine.list.create': 'New',
|
|
103
|
+
'engine.list.refresh': 'Refresh',
|
|
104
|
+
'engine.list.search': 'Search name, label, description…',
|
|
105
|
+
'engine.list.empty': 'No items yet.',
|
|
106
|
+
'engine.list.items': 'Items',
|
|
107
|
+
'engine.list.filtered': 'Filtered',
|
|
108
|
+
'engine.list.allSources': 'All sources',
|
|
109
|
+
'engine.list.col.name': 'Name',
|
|
110
|
+
'engine.list.col.label': 'Label',
|
|
111
|
+
'engine.list.col.source': 'Source',
|
|
112
|
+
'engine.list.col.object': 'Object',
|
|
113
|
+
'engine.list.col.type': 'Type',
|
|
114
|
+
'engine.edit.save': 'Save',
|
|
115
|
+
'engine.edit.reset': 'Reset overlay',
|
|
116
|
+
'engine.edit.resetConfirm': 'Reset overlay for {type}/{name}?',
|
|
117
|
+
'engine.edit.history': 'History',
|
|
118
|
+
'engine.edit.layers': 'Layers',
|
|
119
|
+
'engine.edit.references': 'References',
|
|
120
|
+
'engine.edit.form': 'Form',
|
|
121
|
+
'engine.edit.readOnly': 'Read-only (runtime overrides disabled).',
|
|
122
|
+
'engine.edit.loading': 'Loading',
|
|
123
|
+
'engine.edit.bespokeDesigner': 'Designer',
|
|
124
|
+
'engine.edit.readOnlyHint': 'Read-only — this metadata type does not allow runtime overrides. Edit the source in the package and redeploy.',
|
|
125
|
+
'engine.edit.unsaved': 'Unsaved',
|
|
126
|
+
'engine.edit.unsavedHint': 'You have unsaved changes.',
|
|
127
|
+
'engine.edit.destructive': 'Destructive change',
|
|
128
|
+
'engine.edit.destructiveHint': 'The change would break existing references. Review the issues and confirm to force-save.',
|
|
129
|
+
'engine.edit.forceSave': 'Force save',
|
|
130
|
+
'engine.cancel': 'Cancel',
|
|
131
|
+
'engine.quickfind.placeholder': "Find metadata types or items… (try 'view', 'account')",
|
|
132
|
+
'engine.quickfind.empty': 'Type to search across all metadata types.',
|
|
133
|
+
'engine.quickfind.title': 'Quick Find',
|
|
134
|
+
'engine.quickfind.indexing': 'Indexing items across',
|
|
135
|
+
'engine.quickfind.noMatches': 'No matches.',
|
|
136
|
+
'engine.breadcrumb.allTypes': 'All Metadata Types',
|
|
137
|
+
// Permission matrix
|
|
138
|
+
'perm.action.create': 'Create',
|
|
139
|
+
'perm.action.read': 'Read',
|
|
140
|
+
'perm.action.edit': 'Edit',
|
|
141
|
+
'perm.action.delete': 'Delete',
|
|
142
|
+
'perm.action.transfer': 'Transfer ownership',
|
|
143
|
+
'perm.action.restore': 'Restore from trash',
|
|
144
|
+
'perm.action.purge': 'Hard delete (purge)',
|
|
145
|
+
'perm.action.viewAll': 'View All Records (bypass sharing)',
|
|
146
|
+
'perm.action.modifyAll': 'Modify All Records (bypass sharing)',
|
|
147
|
+
'perm.col.object': 'Object',
|
|
148
|
+
'perm.col.bulk': 'Bulk',
|
|
149
|
+
'perm.bulk.read': 'R',
|
|
150
|
+
'perm.bulk.crud': 'CRUD',
|
|
151
|
+
'perm.bulk.all': 'All',
|
|
152
|
+
'perm.bulk.none': 'None',
|
|
153
|
+
'perm.filter.placeholder': 'Filter objects…',
|
|
154
|
+
'perm.filter.onlyGranted': 'Only granted',
|
|
155
|
+
'perm.filter.empty': 'No objects match the filter.',
|
|
156
|
+
'perm.field.name': 'Name',
|
|
157
|
+
'perm.field.label': 'Label',
|
|
158
|
+
'perm.field.isProfile': 'Is profile',
|
|
159
|
+
'perm.field.loading': 'Loading fields…',
|
|
160
|
+
'perm.field.empty': 'No fields registered for this object.',
|
|
161
|
+
'perm.field.col.name': 'Field',
|
|
162
|
+
'perm.field.read': 'Read',
|
|
163
|
+
'perm.field.edit': 'Edit',
|
|
164
|
+
'perm.stat.objects': 'Objects granted',
|
|
165
|
+
'perm.stat.fields': 'Fields granted',
|
|
166
|
+
'perm.stat.objectsGranted': 'Objects granted',
|
|
167
|
+
'perm.stat.fieldOverrides': 'Field overrides',
|
|
168
|
+
'perm.stat.objectsSuffix': 'objects',
|
|
169
|
+
'perm.subtitle.profile': 'Profile',
|
|
170
|
+
'perm.subtitle.set': 'Permission set',
|
|
171
|
+
'perm.loading': 'Loading permission set {name}…',
|
|
172
|
+
'perm.readOnly': 'Read-only (OS_METADATA_WRITABLE not enabled)',
|
|
173
|
+
// Designer wrapper
|
|
174
|
+
'designer.unsavedChanges': 'Unsaved changes',
|
|
175
|
+
'designer.editingOverlay': 'Editing overlay',
|
|
176
|
+
'designer.codeBaseline': 'Code baseline',
|
|
177
|
+
};
|
|
178
|
+
const ENGINE_STRINGS_ZH = {
|
|
179
|
+
'engine.directory.title': '元数据',
|
|
180
|
+
'engine.directory.description': '平台协议共暴露 {count} 个元数据类型(其中 {writable} 个支持运行时覆盖)。点击任意卡片即可浏览、覆盖或创建实例。',
|
|
181
|
+
'engine.directory.search': '搜索元数据类型…',
|
|
182
|
+
'engine.directory.writableOnly': '仅显示可写',
|
|
183
|
+
'engine.directory.quickFind': '快速查找',
|
|
184
|
+
'engine.directory.noMatches': '没有匹配项',
|
|
185
|
+
'engine.directory.noMatchesHint': '调整搜索或筛选条件以查看更多元数据类型。',
|
|
186
|
+
'engine.directory.loading': '正在加载元数据类型…',
|
|
187
|
+
'engine.directory.loadFailed': '加载元数据类型失败',
|
|
188
|
+
'engine.directory.all': '全部',
|
|
189
|
+
'engine.list.create': '新建',
|
|
190
|
+
'engine.list.refresh': '刷新',
|
|
191
|
+
'engine.list.search': '搜索名称、标签或描述…',
|
|
192
|
+
'engine.list.empty': '暂无数据。',
|
|
193
|
+
'engine.list.items': '条目',
|
|
194
|
+
'engine.list.filtered': '已筛选',
|
|
195
|
+
'engine.list.allSources': '全部来源',
|
|
196
|
+
'engine.list.col.name': '名称',
|
|
197
|
+
'engine.list.col.label': '标签',
|
|
198
|
+
'engine.list.col.source': '来源',
|
|
199
|
+
'engine.list.col.object': '对象',
|
|
200
|
+
'engine.list.col.type': '类型',
|
|
201
|
+
'engine.edit.save': '保存',
|
|
202
|
+
'engine.edit.reset': '重置覆盖',
|
|
203
|
+
'engine.edit.resetConfirm': '重置 {type}/{name} 的覆盖层?',
|
|
204
|
+
'engine.edit.history': '历史',
|
|
205
|
+
'engine.edit.layers': '层次',
|
|
206
|
+
'engine.edit.references': '引用关系',
|
|
207
|
+
'engine.edit.form': '表单',
|
|
208
|
+
'engine.edit.readOnly': '只读(运行时覆盖未启用)。',
|
|
209
|
+
'engine.edit.loading': '加载中',
|
|
210
|
+
'engine.edit.bespokeDesigner': '可视化编辑器',
|
|
211
|
+
'engine.edit.readOnlyHint': '只读 — 该元数据类型不支持运行时覆盖。请修改包内源代码并重新部署。',
|
|
212
|
+
'engine.edit.unsaved': '未保存',
|
|
213
|
+
'engine.edit.unsavedHint': '当前存在未保存的修改。',
|
|
214
|
+
'engine.edit.destructive': '破坏性变更',
|
|
215
|
+
'engine.edit.destructiveHint': '该修改会破坏现有引用关系。请检查问题清单后确认强制保存。',
|
|
216
|
+
'engine.edit.forceSave': '强制保存',
|
|
217
|
+
'engine.cancel': '取消',
|
|
218
|
+
'engine.quickfind.placeholder': '搜索元数据类型或条目…(如:view、account)',
|
|
219
|
+
'engine.quickfind.empty': '输入关键字以搜索所有元数据类型。',
|
|
220
|
+
'engine.quickfind.title': '快速查找',
|
|
221
|
+
'engine.quickfind.indexing': '正在索引所有类型,共',
|
|
222
|
+
'engine.quickfind.noMatches': '没有匹配项。',
|
|
223
|
+
'engine.breadcrumb.allTypes': '元数据',
|
|
224
|
+
// Permission matrix
|
|
225
|
+
'perm.action.create': '创建',
|
|
226
|
+
'perm.action.read': '读取',
|
|
227
|
+
'perm.action.edit': '编辑',
|
|
228
|
+
'perm.action.delete': '删除',
|
|
229
|
+
'perm.action.transfer': '转移所有者',
|
|
230
|
+
'perm.action.restore': '从回收站恢复',
|
|
231
|
+
'perm.action.purge': '彻底删除',
|
|
232
|
+
'perm.action.viewAll': '查看所有记录(绕过共享规则)',
|
|
233
|
+
'perm.action.modifyAll': '修改所有记录(绕过共享规则)',
|
|
234
|
+
'perm.col.object': '对象',
|
|
235
|
+
'perm.col.bulk': '批量',
|
|
236
|
+
'perm.bulk.read': '读',
|
|
237
|
+
'perm.bulk.crud': '增改删',
|
|
238
|
+
'perm.bulk.all': '全选',
|
|
239
|
+
'perm.bulk.none': '清空',
|
|
240
|
+
'perm.filter.placeholder': '筛选对象…',
|
|
241
|
+
'perm.filter.onlyGranted': '只看已授权',
|
|
242
|
+
'perm.filter.empty': '没有匹配的对象。',
|
|
243
|
+
'perm.field.name': '名称',
|
|
244
|
+
'perm.field.label': '标签',
|
|
245
|
+
'perm.field.isProfile': '作为 Profile',
|
|
246
|
+
'perm.field.loading': '加载字段中…',
|
|
247
|
+
'perm.field.empty': '该对象未注册字段。',
|
|
248
|
+
'perm.field.col.name': '字段',
|
|
249
|
+
'perm.field.read': '读',
|
|
250
|
+
'perm.field.edit': '改',
|
|
251
|
+
'perm.stat.objects': '已授权对象',
|
|
252
|
+
'perm.stat.fields': '已授权字段',
|
|
253
|
+
'perm.stat.objectsGranted': '已授权对象',
|
|
254
|
+
'perm.stat.fieldOverrides': '字段覆盖',
|
|
255
|
+
'perm.stat.objectsSuffix': '个对象',
|
|
256
|
+
'perm.subtitle.profile': 'Profile',
|
|
257
|
+
'perm.subtitle.set': '权限集',
|
|
258
|
+
'perm.loading': '加载权限集 {name}…',
|
|
259
|
+
'perm.readOnly': '只读(OS_METADATA_WRITABLE 未启用)',
|
|
260
|
+
// Designer wrapper
|
|
261
|
+
'designer.unsavedChanges': '未保存的修改',
|
|
262
|
+
'designer.editingOverlay': '编辑覆盖层',
|
|
263
|
+
'designer.codeBaseline': '代码基线',
|
|
264
|
+
};
|
|
265
|
+
function pickTable(locale) {
|
|
266
|
+
const lower = (locale ?? '').toLowerCase();
|
|
267
|
+
if (lower.startsWith('zh')) {
|
|
268
|
+
return { types: TYPE_LABELS_ZH, domains: DOMAIN_LABELS_ZH, strings: ENGINE_STRINGS_ZH };
|
|
269
|
+
}
|
|
270
|
+
return { types: TYPE_LABELS_EN, domains: DOMAIN_LABELS_EN, strings: ENGINE_STRINGS_EN };
|
|
271
|
+
}
|
|
272
|
+
export function translateMetadataType(type, locale, fallback) {
|
|
273
|
+
// Prefer locale table when the locale has a translation for this type.
|
|
274
|
+
// This ensures Chinese labels win over the English `label` baked into
|
|
275
|
+
// the server's metadata registry (which would otherwise show "Field"
|
|
276
|
+
// even when the user's locale is zh-CN).
|
|
277
|
+
const localized = pickTable(locale).types[type];
|
|
278
|
+
if (localized)
|
|
279
|
+
return localized;
|
|
280
|
+
// Fall back to caller-supplied label (typically the server's English one).
|
|
281
|
+
return fallback ?? type;
|
|
282
|
+
}
|
|
283
|
+
export function translateMetadataDomain(domain, locale) {
|
|
284
|
+
return pickTable(locale).domains[domain] ?? domain;
|
|
285
|
+
}
|
|
286
|
+
export function t(key, locale) {
|
|
287
|
+
return pickTable(locale).strings[key] ?? key;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Format a translated string with `{token}` placeholders.
|
|
291
|
+
*
|
|
292
|
+
* tFormat('engine.directory.description', 'zh-CN', { count: 28, writable: 4 })
|
|
293
|
+
*/
|
|
294
|
+
export function tFormat(key, locale, vars) {
|
|
295
|
+
const template = t(key, locale);
|
|
296
|
+
return template.replace(/\{(\w+)\}/g, (_m, name) => name in vars ? String(vars[name]) : `{${name}}`);
|
|
297
|
+
}
|
|
298
|
+
/** Returns the locale string most browsers report (matches navigator.language). */
|
|
299
|
+
export function detectLocale() {
|
|
300
|
+
if (typeof navigator !== 'undefined' && /^zh/i.test(navigator.language))
|
|
301
|
+
return 'zh-CN';
|
|
302
|
+
return 'en-US';
|
|
303
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface for the metadata-admin engine (Phase 3c).
|
|
3
|
+
*
|
|
4
|
+
* Pages are registered with the ComponentRegistry in
|
|
5
|
+
* `../../services/builtinComponents.ts`; consumers (and plugins) can
|
|
6
|
+
* still import directly to compose custom shells.
|
|
7
|
+
*
|
|
8
|
+
* The Registry export lets plugin authors opt their bespoke editors
|
|
9
|
+
* into the generic shell:
|
|
10
|
+
*
|
|
11
|
+
* import { registerMetadataResource } from '@object-ui/app-shell';
|
|
12
|
+
* registerMetadataResource({ type: 'view', EditPage: MyViewEditor });
|
|
13
|
+
*/
|
|
14
|
+
export { MetadataDirectoryPage } from './DirectoryPage';
|
|
15
|
+
export { MetadataResourceRouter } from './ResourceRouter';
|
|
16
|
+
export { MetadataResourceListPage } from './ResourceListPage';
|
|
17
|
+
export { MetadataResourceEditPage } from './ResourceEditPage';
|
|
18
|
+
export { RelatedPanel } from './RelatedPanel';
|
|
19
|
+
export { MetadataDetailDrawer } from './MetadataDetailDrawer';
|
|
20
|
+
export { MetadataResourceHistoryPage } from './ResourceHistoryPage';
|
|
21
|
+
export { MetadataQuickFind } from './QuickFind';
|
|
22
|
+
export { PageShell as MetadataPageShell } from './PageShell';
|
|
23
|
+
export { SchemaForm } from './SchemaForm';
|
|
24
|
+
export { LayeredDiff } from './LayeredDiff';
|
|
25
|
+
export { PermissionMatrixEditPage } from './PermissionMatrixEditor';
|
|
26
|
+
export { DesignerEditorWrapper, DesignerEditorBody } from './DesignerEditorWrapper';
|
|
27
|
+
export type { DesignerEditorWrapperProps } from './DesignerEditorWrapper';
|
|
28
|
+
export { translateMetadataType, translateMetadataDomain, t as translateMetadataAdmin, detectLocale, } from './i18n';
|
|
29
|
+
export type { SupportedLocale } from './i18n';
|
|
30
|
+
export { registerMetadataResource, getMetadataResource, listMetadataResources, listAnchorsFor, resolveResourceConfig, anchorByField, } from './registry';
|
|
31
|
+
export type { MetadataResourceConfig, MetadataDomain, MetadataAnchor, } from './registry';
|
|
32
|
+
export { useMetadataClient, useMetadataTypes, useTypesIndex, matchesQuery, } from './useMetadata';
|
|
33
|
+
export type { RichMetadataTypeEntry } from './useMetadata';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Public surface for the metadata-admin engine (Phase 3c).
|
|
4
|
+
*
|
|
5
|
+
* Pages are registered with the ComponentRegistry in
|
|
6
|
+
* `../../services/builtinComponents.ts`; consumers (and plugins) can
|
|
7
|
+
* still import directly to compose custom shells.
|
|
8
|
+
*
|
|
9
|
+
* The Registry export lets plugin authors opt their bespoke editors
|
|
10
|
+
* into the generic shell:
|
|
11
|
+
*
|
|
12
|
+
* import { registerMetadataResource } from '@object-ui/app-shell';
|
|
13
|
+
* registerMetadataResource({ type: 'view', EditPage: MyViewEditor });
|
|
14
|
+
*/
|
|
15
|
+
export { MetadataDirectoryPage } from './DirectoryPage';
|
|
16
|
+
export { MetadataResourceRouter } from './ResourceRouter';
|
|
17
|
+
export { MetadataResourceListPage } from './ResourceListPage';
|
|
18
|
+
export { MetadataResourceEditPage } from './ResourceEditPage';
|
|
19
|
+
export { RelatedPanel } from './RelatedPanel';
|
|
20
|
+
export { MetadataDetailDrawer } from './MetadataDetailDrawer';
|
|
21
|
+
export { MetadataResourceHistoryPage } from './ResourceHistoryPage';
|
|
22
|
+
export { MetadataQuickFind } from './QuickFind';
|
|
23
|
+
export { PageShell as MetadataPageShell } from './PageShell';
|
|
24
|
+
export { SchemaForm } from './SchemaForm';
|
|
25
|
+
export { LayeredDiff } from './LayeredDiff';
|
|
26
|
+
export { PermissionMatrixEditPage } from './PermissionMatrixEditor';
|
|
27
|
+
export { DesignerEditorWrapper, DesignerEditorBody } from './DesignerEditorWrapper';
|
|
28
|
+
export { translateMetadataType, translateMetadataDomain, t as translateMetadataAdmin, detectLocale, } from './i18n';
|
|
29
|
+
export { registerMetadataResource, getMetadataResource, listMetadataResources, listAnchorsFor, resolveResourceConfig, anchorByField, } from './registry';
|
|
30
|
+
// Side-effect: register the built-in anchor relationships so the Related
|
|
31
|
+
// tab works out of the box for objects (hooks, views, pages, …).
|
|
32
|
+
import { registerBuiltinAnchors } from './anchors';
|
|
33
|
+
registerBuiltinAnchors();
|
|
34
|
+
// Side-effect: register fallback JSONSchemas for the 12 writable types
|
|
35
|
+
// so the generic SchemaForm renders a real form (vs raw-JSON fallback)
|
|
36
|
+
// until the framework wires Zod→JSONSchema generation into /meta/types.
|
|
37
|
+
import { registerDefaultMetadataSchemas } from './default-schemas';
|
|
38
|
+
registerDefaultMetadataSchemas();
|
|
39
|
+
export { useMetadataClient, useMetadataTypes, useTypesIndex, matchesQuery, } from './useMetadata';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny predicate evaluator for FormView `visibleOn` expressions.
|
|
3
|
+
*
|
|
4
|
+
* This is an interim stand-in for the full CEL runtime
|
|
5
|
+
* (`@objectstack/formula`) — we keep it intentionally small so the
|
|
6
|
+
* Setup admin engine has zero new runtime dependencies. When CEL is
|
|
7
|
+
* unified across the platform (ROADMAP M9), swap `evaluatePredicate`
|
|
8
|
+
* for the real CEL evaluator without touching SchemaForm.tsx.
|
|
9
|
+
*
|
|
10
|
+
* Supported subset (covers everything used in spec `*.form.ts` today):
|
|
11
|
+
* - `path == 'literal'` string equality
|
|
12
|
+
* - `path != 'literal'` string inequality
|
|
13
|
+
* - `path == 123` number equality
|
|
14
|
+
* - `path == true|false` boolean equality
|
|
15
|
+
* - `path in ['a','b']` membership
|
|
16
|
+
* - `!path` negation (truthy)
|
|
17
|
+
* - `path` truthy check
|
|
18
|
+
* - `path && expr` conjunction
|
|
19
|
+
* - `path || expr` disjunction
|
|
20
|
+
*
|
|
21
|
+
* Paths support dot notation: `data.type`, `data.config.kind`.
|
|
22
|
+
*
|
|
23
|
+
* On any parse error → returns `true` (fail-open): better to show a
|
|
24
|
+
* field than to silently hide it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function evaluatePredicate(expr: string | {
|
|
27
|
+
dialect?: string;
|
|
28
|
+
source: string;
|
|
29
|
+
} | null | undefined, ctx: {
|
|
30
|
+
data: Record<string, unknown>;
|
|
31
|
+
}): boolean;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
/**
|
|
3
|
+
* Tiny predicate evaluator for FormView `visibleOn` expressions.
|
|
4
|
+
*
|
|
5
|
+
* This is an interim stand-in for the full CEL runtime
|
|
6
|
+
* (`@objectstack/formula`) — we keep it intentionally small so the
|
|
7
|
+
* Setup admin engine has zero new runtime dependencies. When CEL is
|
|
8
|
+
* unified across the platform (ROADMAP M9), swap `evaluatePredicate`
|
|
9
|
+
* for the real CEL evaluator without touching SchemaForm.tsx.
|
|
10
|
+
*
|
|
11
|
+
* Supported subset (covers everything used in spec `*.form.ts` today):
|
|
12
|
+
* - `path == 'literal'` string equality
|
|
13
|
+
* - `path != 'literal'` string inequality
|
|
14
|
+
* - `path == 123` number equality
|
|
15
|
+
* - `path == true|false` boolean equality
|
|
16
|
+
* - `path in ['a','b']` membership
|
|
17
|
+
* - `!path` negation (truthy)
|
|
18
|
+
* - `path` truthy check
|
|
19
|
+
* - `path && expr` conjunction
|
|
20
|
+
* - `path || expr` disjunction
|
|
21
|
+
*
|
|
22
|
+
* Paths support dot notation: `data.type`, `data.config.kind`.
|
|
23
|
+
*
|
|
24
|
+
* On any parse error → returns `true` (fail-open): better to show a
|
|
25
|
+
* field than to silently hide it.
|
|
26
|
+
*/
|
|
27
|
+
export function evaluatePredicate(expr, ctx) {
|
|
28
|
+
if (expr == null)
|
|
29
|
+
return true;
|
|
30
|
+
const source = typeof expr === 'string' ? expr : expr.source;
|
|
31
|
+
if (!source)
|
|
32
|
+
return true;
|
|
33
|
+
try {
|
|
34
|
+
return evalExpr(source.trim(), ctx);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function evalExpr(expr, ctx) {
|
|
41
|
+
// Handle || (lowest precedence)
|
|
42
|
+
const orParts = splitTopLevel(expr, '||');
|
|
43
|
+
if (orParts.length > 1) {
|
|
44
|
+
return orParts.some((p) => evalExpr(p.trim(), ctx));
|
|
45
|
+
}
|
|
46
|
+
// Handle &&
|
|
47
|
+
const andParts = splitTopLevel(expr, '&&');
|
|
48
|
+
if (andParts.length > 1) {
|
|
49
|
+
return andParts.every((p) => evalExpr(p.trim(), ctx));
|
|
50
|
+
}
|
|
51
|
+
// Handle negation
|
|
52
|
+
if (expr.startsWith('!')) {
|
|
53
|
+
return !evalExpr(expr.slice(1).trim(), ctx);
|
|
54
|
+
}
|
|
55
|
+
// Handle 'in'
|
|
56
|
+
const inMatch = expr.match(/^(.+?)\s+in\s+(\[.*\])$/);
|
|
57
|
+
if (inMatch) {
|
|
58
|
+
const left = resolveValue(inMatch[1].trim(), ctx);
|
|
59
|
+
const right = parseLiteral(inMatch[2]);
|
|
60
|
+
return Array.isArray(right) && right.includes(left);
|
|
61
|
+
}
|
|
62
|
+
// Handle == / != (CEL-style loose equality: null == undefined)
|
|
63
|
+
const eqMatch = expr.match(/^(.+?)\s*(==|!=)\s*(.+)$/);
|
|
64
|
+
if (eqMatch) {
|
|
65
|
+
const left = resolveValue(eqMatch[1].trim(), ctx);
|
|
66
|
+
const right = parseLiteral(eqMatch[3].trim());
|
|
67
|
+
const nullish = (v) => v === null || v === undefined;
|
|
68
|
+
const equal = nullish(left) && nullish(right) ? true : left === right;
|
|
69
|
+
return eqMatch[2] === '==' ? equal : !equal;
|
|
70
|
+
}
|
|
71
|
+
// Bare truthy check
|
|
72
|
+
return Boolean(resolveValue(expr, ctx));
|
|
73
|
+
}
|
|
74
|
+
function splitTopLevel(expr, op) {
|
|
75
|
+
const out = [];
|
|
76
|
+
let depth = 0;
|
|
77
|
+
let inStr = null;
|
|
78
|
+
let buf = '';
|
|
79
|
+
for (let i = 0; i < expr.length; i++) {
|
|
80
|
+
const ch = expr[i];
|
|
81
|
+
if (inStr) {
|
|
82
|
+
buf += ch;
|
|
83
|
+
if (ch === inStr && expr[i - 1] !== '\\')
|
|
84
|
+
inStr = null;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (ch === "'" || ch === '"') {
|
|
88
|
+
inStr = ch;
|
|
89
|
+
buf += ch;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (ch === '(' || ch === '[')
|
|
93
|
+
depth++;
|
|
94
|
+
else if (ch === ')' || ch === ']')
|
|
95
|
+
depth--;
|
|
96
|
+
if (depth === 0 &&
|
|
97
|
+
expr.slice(i, i + op.length) === op &&
|
|
98
|
+
// Not a sub-operator (e.g. == when looking for =)
|
|
99
|
+
expr[i + op.length] !== '=') {
|
|
100
|
+
out.push(buf);
|
|
101
|
+
buf = '';
|
|
102
|
+
i += op.length - 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
buf += ch;
|
|
106
|
+
}
|
|
107
|
+
if (buf)
|
|
108
|
+
out.push(buf);
|
|
109
|
+
return out;
|
|
110
|
+
}
|
|
111
|
+
function resolveValue(path, ctx) {
|
|
112
|
+
// Allow literals on the left side too.
|
|
113
|
+
if (/^['"]/.test(path) || /^-?\d/.test(path) || path === 'true' || path === 'false' || path === 'null') {
|
|
114
|
+
return parseLiteral(path);
|
|
115
|
+
}
|
|
116
|
+
const segs = path.split('.');
|
|
117
|
+
let cur = ctx;
|
|
118
|
+
for (const seg of segs) {
|
|
119
|
+
if (cur == null)
|
|
120
|
+
return undefined;
|
|
121
|
+
cur = cur[seg];
|
|
122
|
+
}
|
|
123
|
+
return cur;
|
|
124
|
+
}
|
|
125
|
+
function parseLiteral(raw) {
|
|
126
|
+
const s = raw.trim();
|
|
127
|
+
if (s === 'true')
|
|
128
|
+
return true;
|
|
129
|
+
if (s === 'false')
|
|
130
|
+
return false;
|
|
131
|
+
if (s === 'null')
|
|
132
|
+
return null;
|
|
133
|
+
if (/^-?\d+(\.\d+)?$/.test(s))
|
|
134
|
+
return Number(s);
|
|
135
|
+
if ((s.startsWith("'") && s.endsWith("'")) ||
|
|
136
|
+
(s.startsWith('"') && s.endsWith('"'))) {
|
|
137
|
+
return s.slice(1, -1);
|
|
138
|
+
}
|
|
139
|
+
if (s.startsWith('[') && s.endsWith(']')) {
|
|
140
|
+
try {
|
|
141
|
+
// JSON-parse after normalising single-quoted strings to double.
|
|
142
|
+
const json = s.replace(/'([^']*)'/g, (_, inner) => JSON.stringify(inner));
|
|
143
|
+
return JSON.parse(json);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return s;
|
|
150
|
+
}
|