@ossy/app 1.40.3 → 3.0.2

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 (40) hide show
  1. package/README.md +6 -0
  2. package/cli/get-platform-files.task.js +4 -6
  3. package/cli/manifest-plugin.js +111 -36
  4. package/package.json +23 -14
  5. package/runtime/merge-shell-slots.js +148 -0
  6. package/runtime/page-runtime.js +32 -16
  7. package/runtime/resolve-app-slots.js +48 -11
  8. package/src/en.translations.json +8 -0
  9. package/src/manifest/build-actions-schema.js +1 -36
  10. package/src/manifest/build-capabilities.js +1 -190
  11. package/src/manifest/build-manifest-summary.js +1 -121
  12. package/src/manifest/discover-package-definitions.js +1 -100
  13. package/src/manifest/resolve-page-layout.js +51 -0
  14. package/src/manifest/serialize-package-definition.js +1 -30
  15. package/src/shell/App.jsx +13 -7
  16. package/src/shell/AppSettings.jsx +6 -0
  17. package/src/shell/DevPagesPanel.jsx +1 -1
  18. package/src/shell/HeaderAuthActions.jsx +49 -0
  19. package/src/shell/LanguageList.jsx +83 -0
  20. package/src/shell/LanguageSelect.jsx +73 -0
  21. package/src/shell/ThemeEditor.jsx +2 -2
  22. package/src/shell/ThemeSelect.jsx +101 -0
  23. package/src/shell/buildSidebarNav.js +86 -0
  24. package/src/shell/index.js +7 -0
  25. package/src/shell/languageCode.js +31 -0
  26. package/src/shell/resolvePackageHomePageId.js +14 -0
  27. package/src/shell/useCompactShellLayout.js +24 -0
  28. package/src/shell-registry/blank.layout.jsx +8 -0
  29. package/src/shell-registry/default.layout.jsx +101 -0
  30. package/src/shell-registry/footer-default.component.jsx +39 -0
  31. package/src/shell-registry/head-default.component.jsx +17 -0
  32. package/src/shell-registry/header-default.component.jsx +50 -0
  33. package/src/shell-registry/logo-logomark.component.jsx +8 -0
  34. package/src/shell-registry/logo-logotype.component.jsx +15 -0
  35. package/src/shell-registry/minimal.layout.jsx +58 -0
  36. package/src/shell-registry/sidebar-default.component.jsx +281 -0
  37. package/src/sv.translations.json +8 -0
  38. package/src/manifest/action-id-to-tool-name.js +0 -29
  39. package/src/manifest/build-action-input-schema.js +0 -220
  40. package/src/manifest/template-to-json-schema.js +0 -103
@@ -1,220 +0,0 @@
1
- import { templatesContentOneOf } from './template-to-json-schema.js'
2
-
3
- const workspaceIdProp = {
4
- workspaceId: {
5
- type: 'string',
6
- description: 'Workspace id (defaults to request workspace header)',
7
- },
8
- }
9
-
10
- /** @type {Record<string, (ctx: { schemas: object[] }) => object>} */
11
- const ENVELOPES = {
12
- '@ossy/resources/actions/list': () => ({
13
- type: 'object',
14
- properties: {
15
- ...workspaceIdProp,
16
- location: { type: 'string', description: 'Folder path, e.g. /test/' },
17
- query: { type: 'object', description: 'Optional query filters merged with location' },
18
- },
19
- }),
20
-
21
- '@ossy/resources/actions/get': () => ({
22
- type: 'object',
23
- required: ['resourceId'],
24
- properties: {
25
- ...workspaceIdProp,
26
- resourceId: { type: 'string' },
27
- },
28
- }),
29
-
30
- '@ossy/resources/actions/search': () => ({
31
- type: 'object',
32
- properties: {
33
- ...workspaceIdProp,
34
- location: { type: 'string' },
35
- name: { type: 'string' },
36
- type: { type: 'string', description: 'Resource template id or mime type' },
37
- },
38
- }),
39
-
40
- '@ossy/resources/actions/create': ({ schemas }) => {
41
- const contentSchema = templatesContentOneOf(schemas)
42
- return {
43
- type: 'object',
44
- required: ['location', 'name', 'type'],
45
- properties: {
46
- ...workspaceIdProp,
47
- location: { type: 'string', description: 'Parent folder path, e.g. /test/' },
48
- name: { type: 'string' },
49
- type: {
50
- type: 'string',
51
- description: 'directory | mime type (binary) | registered resource template id',
52
- },
53
- size: {
54
- type: 'number',
55
- description: 'Byte size — required when type is a mime type (binary upload)',
56
- },
57
- ...(contentSchema
58
- ? {
59
- content: {
60
- description: 'Document payload when type is a resource template id',
61
- ...contentSchema,
62
- },
63
- }
64
- : {}),
65
- },
66
- }
67
- },
68
-
69
- '@ossy/resources/actions/update-content': ({ schemas }) => {
70
- const contentSchema = templatesContentOneOf(schemas)
71
- return {
72
- type: 'object',
73
- required: ['resourceId', 'content'],
74
- properties: {
75
- ...workspaceIdProp,
76
- resourceId: { type: 'string' },
77
- ...(contentSchema
78
- ? { content: contentSchema }
79
- : { content: { type: 'object' } }),
80
- },
81
- }
82
- },
83
-
84
- '@ossy/resources/actions/delete': () => ({
85
- type: 'object',
86
- required: ['resourceId'],
87
- properties: {
88
- ...workspaceIdProp,
89
- resourceId: { type: 'string' },
90
- },
91
- }),
92
-
93
- '@ossy/resources/actions/upload-named-version': () => ({
94
- type: 'object',
95
- required: ['resourceId', 'namedVersion', 'type', 'size'],
96
- properties: {
97
- ...workspaceIdProp,
98
- resourceId: { type: 'string' },
99
- namedVersion: { type: 'string', description: 'Version label, e.g. thumbnail' },
100
- type: { type: 'string', description: 'Mime type' },
101
- size: { type: 'number' },
102
- },
103
- }),
104
-
105
- '@ossy/resources/actions/update-name': () => ({
106
- type: 'object',
107
- required: ['resourceId', 'name'],
108
- properties: {
109
- ...workspaceIdProp,
110
- resourceId: { type: 'string' },
111
- name: { type: 'string' },
112
- },
113
- }),
114
-
115
- '@ossy/resources/actions/update-location': () => ({
116
- type: 'object',
117
- required: ['resourceId', 'target'],
118
- properties: {
119
- ...workspaceIdProp,
120
- resourceId: { type: 'string' },
121
- target: { type: 'string', description: 'Destination folder path' },
122
- },
123
- }),
124
-
125
- '@ossy/resources/actions/update-access': () => ({
126
- type: 'object',
127
- required: ['resourceId', 'access'],
128
- properties: {
129
- ...workspaceIdProp,
130
- resourceId: { type: 'string' },
131
- access: { type: 'string', enum: ['public', 'workspace', 'restricted'] },
132
- },
133
- }),
134
-
135
- '@ossy/booking/actions/get-services': () => ({
136
- type: 'object',
137
- properties: {
138
- providerSlug: { type: 'string' },
139
- workspaceId: { type: 'string' },
140
- includeInactive: { type: 'boolean' },
141
- includeContact: { type: 'boolean' },
142
- },
143
- }),
144
-
145
- '@ossy/booking/actions/get-available-slots': () => ({
146
- type: 'object',
147
- properties: {
148
- providerSlug: { type: 'string' },
149
- workspaceId: { type: 'string' },
150
- serviceId: { type: 'string' },
151
- duration: { type: 'number', description: 'Slot duration in minutes' },
152
- from: { type: 'number', description: 'Range start (Unix ms)' },
153
- to: { type: 'number', description: 'Range end (Unix ms)' },
154
- },
155
- }),
156
-
157
- '@ossy/booking/actions/create': () => ({
158
- type: 'object',
159
- required: ['startAt', 'duration', 'clientName', 'clientEmail'],
160
- properties: {
161
- providerSlug: { type: 'string' },
162
- workspaceId: { type: 'string' },
163
- serviceId: { type: 'string' },
164
- startAt: { type: 'number', description: 'Slot start (Unix ms)' },
165
- duration: { type: 'number', description: 'Duration in minutes' },
166
- clientName: { type: 'string' },
167
- clientEmail: { type: 'string', format: 'email' },
168
- clientMessage: { type: 'string' },
169
- },
170
- }),
171
-
172
- '@ossy/workspaces/actions/get-schemas': () => ({
173
- type: 'object',
174
- properties: { ...workspaceIdProp },
175
- }),
176
-
177
- '@ossy/workspaces/actions/import-schemas': () => ({
178
- type: 'object',
179
- required: ['schemas'],
180
- properties: {
181
- ...workspaceIdProp,
182
- schemas: {
183
- type: 'array',
184
- items: { type: 'object' },
185
- description: 'Workspace-imported schema definitions',
186
- },
187
- },
188
- }),
189
-
190
- '@ossy/users/actions/create-api-token': () => ({
191
- type: 'object',
192
- required: ['name', 'description'],
193
- properties: {
194
- name: { type: 'string' },
195
- description: { type: 'string' },
196
- },
197
- }),
198
- }
199
-
200
- /**
201
- * @param {string} actionId
202
- * @param {{ schemas?: object[] }} [ctx]
203
- * @returns {object}
204
- */
205
- export function buildActionInputSchema (actionId, ctx = {}) {
206
- const schemas = ctx.schemas || []
207
- const builder = ENVELOPES[actionId]
208
- if (builder) {
209
- return builder({ schemas })
210
- }
211
-
212
- return {
213
- type: 'object',
214
- properties: {
215
- ...workspaceIdProp,
216
- payload: { type: 'object', description: 'Action-specific payload' },
217
- },
218
- additionalProperties: true,
219
- }
220
- }
@@ -1,103 +0,0 @@
1
- /**
2
- * Map resource template field types to JSON Schema (draft-07 subset).
3
- *
4
- * @param {{ name: string, type: string, options?: string[] }} field
5
- * @returns {object}
6
- */
7
- export function fieldToJsonSchema (field) {
8
- const type = field?.type?.trim?.() || 'text'
9
-
10
- switch (type) {
11
- case 'number':
12
- case 'timestamp':
13
- return { type: 'number', description: `${field.name} (Unix ms for timestamp)` }
14
- case 'boolean':
15
- return { type: 'boolean' }
16
- case 'select':
17
- return {
18
- type: 'string',
19
- ...(Array.isArray(field.options) && field.options.length
20
- ? { enum: field.options }
21
- : {}),
22
- }
23
- case 'multiselect':
24
- return {
25
- type: 'array',
26
- items: {
27
- type: 'string',
28
- ...(Array.isArray(field.options) && field.options.length
29
- ? { enum: field.options }
30
- : {}),
31
- },
32
- }
33
- case 'file':
34
- case 'image':
35
- return {
36
- type: 'object',
37
- properties: { resourceId: { type: 'string' } },
38
- required: ['resourceId'],
39
- description: 'Reference to an uploaded binary resource',
40
- }
41
- case 'date-range':
42
- return {
43
- type: 'object',
44
- properties: {
45
- start: { type: 'number' },
46
- end: { type: 'number' },
47
- },
48
- required: ['start', 'end'],
49
- }
50
- case 'date-ranges':
51
- return {
52
- type: 'array',
53
- items: {
54
- type: 'object',
55
- properties: {
56
- start: { type: 'number' },
57
- end: { type: 'number' },
58
- },
59
- required: ['start', 'end'],
60
- },
61
- }
62
- case 'email':
63
- return { type: 'string', format: 'email' }
64
- case 'textarea':
65
- case 'richtext':
66
- case 'text':
67
- case 'date':
68
- default:
69
- return { type: 'string' }
70
- }
71
- }
72
-
73
- /**
74
- * @param {{ id: string, name?: string, fields?: Array<object> }} template
75
- * @returns {object}
76
- */
77
- export function templateToJsonSchema (template) {
78
- const properties = {}
79
- for (const field of template.fields || []) {
80
- if (!field?.name) continue
81
- properties[field.name] = fieldToJsonSchema(field)
82
- }
83
-
84
- return {
85
- title: template.id,
86
- type: 'object',
87
- properties,
88
- }
89
- }
90
-
91
- /**
92
- * @param {Array<{ id: string, fields?: Array<object> }>} templates
93
- * @returns {object | undefined}
94
- */
95
- export function templatesContentOneOf (templates) {
96
- const branches = (templates || [])
97
- .filter(t => t?.id && Array.isArray(t.fields))
98
- .map(templateToJsonSchema)
99
-
100
- if (!branches.length) return undefined
101
-
102
- return { oneOf: branches }
103
- }