@synopackageland/sdk 0.9.9 → 0.10.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/README.md +121 -0
- package/dist/i18n/bridge/de.json +6 -0
- package/dist/i18n/bridge/en.json +6 -0
- package/dist/i18n/bridge/es.json +6 -0
- package/dist/i18n/bridge/fr.json +6 -0
- package/dist/i18n/bridge/it.json +6 -0
- package/dist/i18n/bridge/ja.json +6 -0
- package/dist/i18n/bridge/ko.json +6 -0
- package/dist/i18n/bridge/zh-CN.json +6 -0
- package/dist/i18n/bridge/zh-TW.json +6 -0
- package/dist/i18n/shell/de.json +5 -1
- package/dist/i18n/shell/en.json +5 -1
- package/dist/i18n/shell/es.json +5 -1
- package/dist/i18n/shell/fr.json +5 -1
- package/dist/i18n/shell/it.json +5 -1
- package/dist/i18n/shell/ja.json +5 -1
- package/dist/i18n/shell/ko.json +5 -1
- package/dist/i18n/shell/zh-CN.json +5 -1
- package/dist/i18n/shell/zh-TW.json +5 -1
- package/dist/index.js +2492 -2338
- package/dist/src/bridge/i18n.d.ts +5 -0
- package/dist/src/context.d.ts +23 -2
- package/dist/src/delegate/root.d.ts +40 -0
- package/dist/src/index.d.ts +5 -2
- package/dist/src/protocol/v1.d.ts +49 -4
- package/dist/src/shell/AppShell.vue.d.ts +31 -10
- package/dist/src/shell/app-pages.d.ts +37 -0
- package/dist/src/shell/i18n.d.ts +4 -0
- package/dist/src/shell/pages.d.ts +7 -2
- package/dist/src/shell/slot-content.d.ts +2 -0
- package/dist/src/standalone.d.ts +5 -0
- package/dist/src/vue.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/vue.js +1639 -1510
- package/package.json +4 -4
- package/spec/protocol/v1/README.md +154 -3
- package/spec/protocol/v1/errors.json +36 -4
- package/spec/protocol/v1/schema/root.jobs.get.json +19 -0
- package/spec/protocol/v1/schema/root.jobs.list.json +11 -0
- package/spec/protocol/v1/schema/root.jobs.stop.json +19 -0
- package/spec/protocol/v1/schema/root.run.json +6 -2
- package/spec/protocol/v1/schema/root.start.json +23 -0
- package/spec/protocol/v1/vectors/files.jsonl +11 -0
package/README.md
CHANGED
|
@@ -34,6 +34,117 @@ and passes it to `PortalSettings`. `call` reaches the package backend's
|
|
|
34
34
|
Its `messages` are `portalMessages(locale)`, the panel text from
|
|
35
35
|
`i18n/portal/<locale>.json` (`portalCatalogs`). It has no plain `mountPanel`.
|
|
36
36
|
|
|
37
|
+
## Full page
|
|
38
|
+
|
|
39
|
+
A Portal or standalone launch gives the App the whole page; the DSM window
|
|
40
|
+
passes `ctx.fullPage`, `ctx.displayName` and `ctx.appIcon`. `isFullPage(ctx)`
|
|
41
|
+
reads it, and with an older CLI that passes no `fullPage` treats everything
|
|
42
|
+
but a DSM desktop window as a full page. Pass `ctx` to `AppShell` and a full
|
|
43
|
+
page takes the web layout and a device-width viewport, names the App in the
|
|
44
|
+
sidebar and shows the signed-in user, administrator or DSM user, at its foot;
|
|
45
|
+
a DSM window keeps its window layout and title bar. `AppShell` reads only
|
|
46
|
+
`fullPage` (or `host`), `displayName`, `appIcon` and `user` (`ShellContext`),
|
|
47
|
+
so the DSM window's ctx works as it is.
|
|
48
|
+
|
|
49
|
+
```vue
|
|
50
|
+
<AppShell v-model="page" :ctx="ctx" :locale="ctx.locale" :pages="pages" sidebar-storage-key="HelloGo" />
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Outside DSM
|
|
54
|
+
|
|
55
|
+
A development page, a preview or a test owns the browser page and has no DSM
|
|
56
|
+
window. `createStandaloneContext({call})` gives it a full-page `Context`
|
|
57
|
+
(`locale: 'en'`, `fullPage: true`, a no-op `reopen`) around the App's own
|
|
58
|
+
`call`; any other field overrides. `createStandaloneHost(platform?)` is its
|
|
59
|
+
`HostAdapter`: `setTitle` titles the document, `openURL` opens an http(s)
|
|
60
|
+
URL in a new tab, `subscribe('window-resize')` follows the browser window,
|
|
61
|
+
and the DSM desktop actions answer `{status: 'unsupported'}`. Platform fields
|
|
62
|
+
override the snapshot, so a test can stand in for a DSM window
|
|
63
|
+
(`createStandaloneHost({host: 'dsm', dsmStandalone: false})`).
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const ctx = createStandaloneContext({locale: 'zh-TW', call: (method, params) => post('/api', {method, params})})
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## App pages
|
|
70
|
+
|
|
71
|
+
`AppShell` lays out the App's own pages too. Each `AppShellPage` has an `id`,
|
|
72
|
+
a `title` the App has already translated, and optionally an `icon`, a `group`
|
|
73
|
+
label (pages with the same label sit together), a `badge`, a `component` to
|
|
74
|
+
render while it is the current page, `hidden` (reachable through `v-model`
|
|
75
|
+
but not in the sidebar), its own `description`, and `header: false` for a
|
|
76
|
+
page that draws its own header. `fill: true` gives the page's body the height under
|
|
77
|
+
its header and notices; the page does not scroll, so the content scrolls
|
|
78
|
+
itself (a treemap, a table paged by height, a log viewer). The shell then
|
|
79
|
+
holds to `100dvh`, so a phone's address bar does not leave a gap. The built-in `'status'` and `'background'`
|
|
80
|
+
may sit in the same list.
|
|
81
|
+
|
|
82
|
+
```vue
|
|
83
|
+
<AppShell v-model="page" :ctx="ctx" :locale="ctx.locale" :pages="[
|
|
84
|
+
{id: 'downloads', title: t('downloads'), icon: Download, badge: running || undefined, component: DownloadsPage},
|
|
85
|
+
{id: 'settings', title: t('settings'), icon: Settings, group: t('admin')},
|
|
86
|
+
'background',
|
|
87
|
+
]" page-width="fill">
|
|
88
|
+
<template #actions="{page}"><Button v-if="page === 'downloads'" @click="add">{{ t('add') }}</Button></template>
|
|
89
|
+
<template #notices><JobStrip v-for="job in jobs" :key="job.id" :job="job" /></template>
|
|
90
|
+
<template #default="{page}"><SettingsPage v-show="page === 'settings'" /></template>
|
|
91
|
+
</AppShell>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Moving to another page starts it at the top; `keep-scroll` keeps the
|
|
95
|
+
position. The `toolbar` slot sits above the page (in `AppLayout`'s toolbar)
|
|
96
|
+
and `notices` in the page, under its header and inside the same padding, and
|
|
97
|
+
scrolls with it. `activePage(current, pages)` keeps a selection that still exists and
|
|
98
|
+
otherwise picks the first page the sidebar shows. A router drives the shell
|
|
99
|
+
through `v-model`:
|
|
100
|
+
`:model-value="route.name" @update:model-value="name => router.push({name})"`.
|
|
101
|
+
|
|
102
|
+
## App root
|
|
103
|
+
|
|
104
|
+
`app-root` wraps the shell in an app-local `AppRoot`
|
|
105
|
+
(`modal-scope="app"`, `height: 100%`) and a `ConfigProvider` with the
|
|
106
|
+
shell's `locale`, so the UI components' own text follows it. In a DSM desktop window (a `ctx` that
|
|
107
|
+
is not a full page) its dialogs may leave the window (`dialog-bounds=
|
|
108
|
+
"viewport"`), and a press on a floating dialog calls
|
|
109
|
+
`ctx.host.activateWindow()`, which brings the window to the front; a full
|
|
110
|
+
page and a shell without `ctx` keep dialogs in the App. Use it in place of
|
|
111
|
+
the App's own `AppRoot`: app-local roots do not nest.
|
|
112
|
+
|
|
113
|
+
```vue
|
|
114
|
+
<AppShell app-root v-model="page" :ctx="ctx" :locale="ctx.locale" :pages="pages" />
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Denied access
|
|
118
|
+
|
|
119
|
+
`denied` replaces the App's pages with one page that says the account may
|
|
120
|
+
not use the App: a `No access` header and a message pointing to DSM
|
|
121
|
+
Application Privileges, in every UI locale (`shellCopy`'s `deniedTitle` and
|
|
122
|
+
`deniedMessage`). `denied` is `true` or an `AppShellDenied` (`title`,
|
|
123
|
+
`message`, `header: false`); the `denied` slot replaces the message, for
|
|
124
|
+
example with a sign-in form. The sidebar, the notices and the default slot
|
|
125
|
+
are not rendered meanwhile.
|
|
126
|
+
|
|
127
|
+
```vue
|
|
128
|
+
<AppShell v-model="page" :ctx="ctx" :locale="ctx.locale" :pages="pages" :denied="!authorized && {title: t('privilegeTitle')}" />
|
|
129
|
+
<AppShell v-model="page" :ctx="ctx" :locale="ctx.locale" :pages="pages" :denied="signInNeeded && {header: false}">
|
|
130
|
+
<template #denied><LoginPage :session="login" :locale="ctx.locale" /></template>
|
|
131
|
+
</AppShell>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Calling the backend
|
|
135
|
+
|
|
136
|
+
`ctx.call(method, params, {signal})` posts to the package backend. An abort of
|
|
137
|
+
`signal` rejects it with `{code: 'request_canceled'}`, for a page the user
|
|
138
|
+
leaves; past `clientTimeout(ctx.requestTimeout)` it rejects with `{code:
|
|
139
|
+
'request_timeout'}`.
|
|
140
|
+
Without `ctx.requestTimeout` the deadline is `DEFAULT_REQUEST_TIMEOUT`, 60
|
|
141
|
+
seconds like the backend's, and the client waits 62.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
const controller = new AbortController()
|
|
145
|
+
const items = await ctx.call<Item[]>('items.list', {}, {signal: controller.signal})
|
|
146
|
+
```
|
|
147
|
+
|
|
37
148
|
## Localized copy
|
|
38
149
|
|
|
39
150
|
`format(message, values, locale)` fills `{key}` placeholders from `values`; a
|
|
@@ -52,6 +163,12 @@ format(copy[locale].files, {count: 3, folder: 'photo'}, locale) // {"one": "{cou
|
|
|
52
163
|
`mergeCatalogs` layers the App's catalogs over the SDK's, key by key; for each
|
|
53
164
|
key the order is the App's locale, the SDK's locale, then `en`.
|
|
54
165
|
|
|
166
|
+
`bridgeErrorCopy(error, locale)` is the text of a code that the bridge runtime
|
|
167
|
+
adds for Python, Node and Rust Apps: `app_unavailable`, and the services'
|
|
168
|
+
`limit_exceeded`, `read_failed` and `identity_unavailable`. For any other code
|
|
169
|
+
it returns `undefined`, so the App falls back to its own text. Its catalogs,
|
|
170
|
+
`i18n/bridge/<locale>.json`, are generated from `spec/bridge/v1/errors.json`.
|
|
171
|
+
|
|
55
172
|
The Vue entry needs the peer dependencies `vue`, `@synopackageland/ui` and
|
|
56
173
|
`@lucide/vue`. The headless entry needs none.
|
|
57
174
|
|
|
@@ -64,6 +181,10 @@ npm run typecheck
|
|
|
64
181
|
npm run build
|
|
65
182
|
```
|
|
66
183
|
|
|
184
|
+
After a change to `../spec/bridge/v1/errors.json`, run `node
|
|
185
|
+
scripts/gen-bridge-i18n.mjs`; `npm test` fails while `i18n/bridge/` differs
|
|
186
|
+
from it.
|
|
187
|
+
|
|
67
188
|
`npm run build` also copies `../spec` into `spec/`. Run `npm ci` before
|
|
68
189
|
`npm pack`: `prepack` builds and needs `node_modules`. `npm install
|
|
69
190
|
--install-links` from a checkout does not run `prepack`, so build first.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_unavailable": "Die App ist derzeit nicht verfügbar. Versuchen Sie es später erneut.",
|
|
3
|
+
"limit_exceeded": "Die Datei ist größer als zulässig.",
|
|
4
|
+
"read_failed": "Die Datei kann nicht gelesen werden. Bitte versuchen Sie es später erneut.",
|
|
5
|
+
"identity_unavailable": "Dieses Benutzerkonto kann nicht ermittelt werden. Bitte versuchen Sie es später erneut."
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_unavailable": "The App is not available right now. Try again later.",
|
|
3
|
+
"limit_exceeded": "The file is larger than allowed.",
|
|
4
|
+
"read_failed": "Unable to read the file. Please try again later.",
|
|
5
|
+
"identity_unavailable": "Unable to identify this user account. Please try again later."
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_unavailable": "La App no está disponible en este momento. Vuelva a intentarlo más tarde.",
|
|
3
|
+
"limit_exceeded": "El archivo supera el tamaño permitido.",
|
|
4
|
+
"read_failed": "No se puede leer el archivo. Vuelva a intentarlo más tarde.",
|
|
5
|
+
"identity_unavailable": "No se puede identificar esta cuenta de usuario. Vuelva a intentarlo más tarde."
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_unavailable": "L’App n’est pas disponible pour le moment. Réessayez plus tard.",
|
|
3
|
+
"limit_exceeded": "Le fichier dépasse la taille autorisée.",
|
|
4
|
+
"read_failed": "Impossible de lire le fichier. Veuillez réessayer ultérieurement.",
|
|
5
|
+
"identity_unavailable": "Impossible d'identifier ce compte utilisateur. Veuillez réessayer ultérieurement."
|
|
6
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_unavailable": "L’App non è al momento disponibile. Riprovare più tardi.",
|
|
3
|
+
"limit_exceeded": "Il file supera le dimensioni consentite.",
|
|
4
|
+
"read_failed": "Impossibile leggere il file. Riprovare più tardi.",
|
|
5
|
+
"identity_unavailable": "Impossibile identificare questo account utente. Riprovare più tardi."
|
|
6
|
+
}
|
package/dist/i18n/shell/de.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"status": "Status",
|
|
3
|
-
"background": "Hintergrundaufträge"
|
|
3
|
+
"background": "Hintergrundaufträge",
|
|
4
|
+
"administrator": "Administrator",
|
|
5
|
+
"dsmUser": "DSM-Benutzer",
|
|
6
|
+
"deniedTitle": "Kein Zugriff",
|
|
7
|
+
"deniedMessage": "Ihr DSM-Konto darf diese App nicht verwenden. Bitten Sie einen Administrator, sie in den DSM-Anwendungsberechtigungen freizugeben."
|
|
4
8
|
}
|
package/dist/i18n/shell/en.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"status": "Status",
|
|
3
|
-
"background": "Background jobs"
|
|
3
|
+
"background": "Background jobs",
|
|
4
|
+
"administrator": "Administrator",
|
|
5
|
+
"dsmUser": "DSM user",
|
|
6
|
+
"deniedTitle": "No access",
|
|
7
|
+
"deniedMessage": "Your DSM account is not allowed to use this app. Ask an administrator to allow it in DSM Application Privileges."
|
|
4
8
|
}
|
package/dist/i18n/shell/es.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"status": "Estado",
|
|
3
|
-
"background": "Tareas en segundo plano"
|
|
3
|
+
"background": "Tareas en segundo plano",
|
|
4
|
+
"administrator": "Administrador",
|
|
5
|
+
"dsmUser": "Usuario DSM",
|
|
6
|
+
"deniedTitle": "Sin acceso",
|
|
7
|
+
"deniedMessage": "Su cuenta de DSM no tiene permiso para usar esta aplicación. Pida a un administrador que la permita en los privilegios de aplicaciones de DSM."
|
|
4
8
|
}
|
package/dist/i18n/shell/fr.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"status": "Statut",
|
|
3
|
-
"background": "Tâches en arrière-plan"
|
|
3
|
+
"background": "Tâches en arrière-plan",
|
|
4
|
+
"administrator": "Administrateur",
|
|
5
|
+
"dsmUser": "Utilisateur DSM",
|
|
6
|
+
"deniedTitle": "Accès refusé",
|
|
7
|
+
"deniedMessage": "Votre compte DSM n’est pas autorisé à utiliser cette application. Demandez à un administrateur de l’autoriser dans les privilèges d’application de DSM."
|
|
4
8
|
}
|
package/dist/i18n/shell/it.json
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"status": "Stato",
|
|
3
|
-
"background": "Attività in background"
|
|
3
|
+
"background": "Attività in background",
|
|
4
|
+
"administrator": "Amministratore",
|
|
5
|
+
"dsmUser": "Utente DSM",
|
|
6
|
+
"deniedTitle": "Accesso negato",
|
|
7
|
+
"deniedMessage": "L’account DSM non è autorizzato a usare questa app. Chiedere a un amministratore di consentirlo nei privilegi delle applicazioni DSM."
|
|
4
8
|
}
|
package/dist/i18n/shell/ja.json
CHANGED
package/dist/i18n/shell/ko.json
CHANGED