@synopackageland/sdk 0.10.2 → 0.10.4
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 +77 -5
- package/dist/i18n/background/zh-CN.json +7 -7
- package/dist/i18n/bridge/de.json +3 -1
- package/dist/i18n/bridge/en.json +3 -1
- package/dist/i18n/bridge/es.json +3 -1
- package/dist/i18n/bridge/fr.json +3 -1
- package/dist/i18n/bridge/it.json +3 -1
- package/dist/i18n/bridge/ja.json +3 -1
- package/dist/i18n/bridge/ko.json +3 -1
- package/dist/i18n/bridge/zh-CN.json +3 -1
- package/dist/i18n/bridge/zh-TW.json +3 -1
- package/dist/i18n/delegate/de.json +5 -3
- package/dist/i18n/delegate/en.json +5 -3
- package/dist/i18n/delegate/es.json +5 -3
- package/dist/i18n/delegate/fr.json +5 -3
- package/dist/i18n/delegate/it.json +5 -3
- package/dist/i18n/delegate/ja.json +5 -3
- package/dist/i18n/delegate/ko.json +5 -3
- package/dist/i18n/delegate/zh-CN.json +5 -3
- package/dist/i18n/delegate/zh-TW.json +5 -3
- package/dist/i18n/identity/zh-CN.json +5 -5
- package/dist/i18n/save/de.json +16 -17
- package/dist/i18n/save/en.json +16 -17
- package/dist/i18n/save/es.json +16 -17
- package/dist/i18n/save/fr.json +16 -17
- package/dist/i18n/save/it.json +16 -17
- package/dist/i18n/save/ja.json +16 -17
- package/dist/i18n/save/ko.json +16 -17
- package/dist/i18n/save/zh-CN.json +16 -17
- package/dist/i18n/save/zh-TW.json +16 -17
- package/dist/index.js +2334 -2296
- package/dist/native.js +350 -0
- package/dist/src/delegate/BackgroundSavePanel.vue.d.ts +3 -0
- package/dist/src/delegate/BackgroundSaveSettings.vue.d.ts +42 -0
- package/dist/src/delegate/ExecutorSettings.vue.d.ts +1 -2
- package/dist/src/delegate/SaveOperations.vue.d.ts +23 -0
- package/dist/src/delegate/copy.d.ts +10 -6
- package/dist/src/delegate/executor-setup.d.ts +2 -0
- package/dist/src/delegate/save-copy.d.ts +33 -36
- package/dist/src/delegate/use-executor-setup.d.ts +5 -1
- package/dist/src/delegate/use-scope-approval.d.ts +50 -0
- package/dist/src/dsm/file-station.d.ts +1 -1
- package/dist/src/native/authorization-runtime.d.ts +2 -0
- package/dist/src/native/dsm-version.d.ts +6 -0
- package/dist/src/native/root-runtime.d.ts +34 -0
- package/dist/src/native.d.ts +2 -0
- package/dist/src/protocol/v1.d.ts +20 -2
- package/dist/src/shell/AppShell.vue.d.ts +3 -0
- package/dist/src/shell/PageActions.vue.d.ts +13 -0
- package/dist/src/shell/app-pages.d.ts +2 -0
- package/dist/src/shell/page-actions.d.ts +3 -0
- package/dist/src/vue.d.ts +3 -0
- package/dist/style.css +1 -1
- package/dist/vue.js +2128 -1809
- package/package.json +7 -3
- package/spec/protocol/v1/README.md +99 -5
- package/spec/protocol/v1/errors.json +24 -0
- package/spec/protocol/v1/timeouts.json +21 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synopackageland/sdk",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
4
4
|
"description": "Frontend SDK for DSM packages built with synopkgland: headless client and Vue components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/synopackageland/syno-pkg-land-sdk/tree/main/ts#readme",
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"import": "./dist/vue.js"
|
|
27
27
|
},
|
|
28
28
|
"./vue/style.css": "./dist/style.css",
|
|
29
|
+
"./native": {
|
|
30
|
+
"types": "./dist/src/native.d.ts",
|
|
31
|
+
"import": "./dist/native.js"
|
|
32
|
+
},
|
|
29
33
|
"./i18n/*": "./dist/i18n/*"
|
|
30
34
|
},
|
|
31
35
|
"files": [
|
|
@@ -40,7 +44,7 @@
|
|
|
40
44
|
},
|
|
41
45
|
"peerDependencies": {
|
|
42
46
|
"@lucide/vue": "^1.48.0",
|
|
43
|
-
"@synopackageland/ui": "^0.9.
|
|
47
|
+
"@synopackageland/ui": "^0.9.5",
|
|
44
48
|
"vue": "^3.5.0"
|
|
45
49
|
},
|
|
46
50
|
"peerDependenciesMeta": {
|
|
@@ -53,7 +57,7 @@
|
|
|
53
57
|
},
|
|
54
58
|
"devDependencies": {
|
|
55
59
|
"@lucide/vue": "1.48.0",
|
|
56
|
-
"@synopackageland/ui": "0.9.
|
|
60
|
+
"@synopackageland/ui": "0.9.6",
|
|
57
61
|
"@types/node": "24.19.2",
|
|
58
62
|
"@vitejs/plugin-vue": "6.0.9",
|
|
59
63
|
"jsdom": "27.4.0",
|
|
@@ -15,6 +15,7 @@ the executor against the vectors here.
|
|
|
15
15
|
| `schema/<op>.json` | JSON Schema (draft 2020-12) of the `params` of each op, with `since` |
|
|
16
16
|
| `errors.json` | Every code: `code`, `kind`, `retryable`, `httpStatus`, `en`, `zh-TW`. The only source of codes; the Go constants are generated from it |
|
|
17
17
|
| `vectors/*.jsonl` | One request per line: `{name, request, policy, state, expect}` |
|
|
18
|
+
| `timeouts.json` | The timeouts of the section Timeouts, in seconds; the SDK's constants and tests read it |
|
|
18
19
|
|
|
19
20
|
## Transport
|
|
20
21
|
|
|
@@ -27,6 +28,38 @@ the executor against the vectors here.
|
|
|
27
28
|
4. The executor MUST answer one line of JSON ending in `\n` and close.
|
|
28
29
|
5. The executor SHOULD close a connection that sends nothing for 15 seconds.
|
|
29
30
|
|
|
31
|
+
## Timeouts
|
|
32
|
+
|
|
33
|
+
Since 0.10.3. Every layer between the browser and a root program waits
|
|
34
|
+
longer than the layer it calls, so the inner answer, or the inner refusal,
|
|
35
|
+
arrives before the outer layer gives up. The margin is 10 seconds between
|
|
36
|
+
the executor and its client and between the client and the request; the
|
|
37
|
+
browser waits 2 seconds past the request (`timeouts.json` holds the values).
|
|
38
|
+
|
|
39
|
+
| Layer | Waits for | Bound |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Root program (`run.timeout_s`) | its own work | 1–120 s, default 20; the process group is then killed |
|
|
42
|
+
| Executor, `root.run` | the program, then its reply | answers within 130 s (120 + 10) |
|
|
43
|
+
| Executor, every other op | its DSM calls | answers within 30 s |
|
|
44
|
+
| Executor client (Go `delegate.Client`, the bridge runtime's `root.*` and `delegate.*`) | the executor | `root.run` 140 s (`delegate.RootRunTimeout`), every other op 40 s (`delegate.ExecutorTimeout`) |
|
|
45
|
+
| Request (`api.Timeout`, manifest `timeout_seconds`) | the App's backend | default 60 s (`api.DefaultRequestTimeout`), 1–3600 |
|
|
46
|
+
| Browser (`clientTimeout`, the CLI window's `call`) | the request | the request's deadline + 2 s |
|
|
47
|
+
|
|
48
|
+
- The request's deadline ends every inner wait: a client never waits past it.
|
|
49
|
+
An App whose backend awaits `root.run` therefore needs a deadline of at
|
|
50
|
+
least the program's `run.timeout_s` + 20 seconds (the executor's 10 and the
|
|
51
|
+
client's 10), so a 120-second program needs `timeout_seconds` 140; a build
|
|
52
|
+
tool SHOULD refuse less. The default 60 covers programs of up to 40 seconds.
|
|
53
|
+
- A client that gave up does not stop the work: `root.run` runs on (it cannot
|
|
54
|
+
be canceled), and `portal.register` and `portal.unregister` finish their
|
|
55
|
+
steps within 2 minutes. The client reads the result again (`status`,
|
|
56
|
+
`root.jobs.get`) instead of repeating the work.
|
|
57
|
+
- The start step (Package start step) is waited on by no request: while it
|
|
58
|
+
runs (at most 60 seconds) every op but `status` is refused at once with
|
|
59
|
+
`EXECUTOR_STARTING` (retryable). A window that waits for the executor to
|
|
60
|
+
become ready polls `status` for longer than 60 seconds before it reports
|
|
61
|
+
the start step as still running.
|
|
62
|
+
|
|
30
63
|
## Request
|
|
31
64
|
|
|
32
65
|
```json
|
|
@@ -70,6 +103,19 @@ the executor against the vectors here.
|
|
|
70
103
|
as `EXECUTOR_PROTOCOL`, and an unreachable socket as
|
|
71
104
|
`EXECUTOR_UNAVAILABLE`. Codes of kind `client` are never sent by the
|
|
72
105
|
executor.
|
|
106
|
+
- A client that knows the package's lifecycle mailbox (`<data
|
|
107
|
+
dir>/executor/control`) answers an unreachable socket with `APP_STOPPED`
|
|
108
|
+
when its last request is `stop`; within 10 seconds of a `start` it waits
|
|
109
|
+
for the socket and ends with `APP_STARTING`. Neither sends a byte, so the
|
|
110
|
+
caller MAY repeat the request.
|
|
111
|
+
- Such a client answers `EXECUTOR_UNAVAILABLE` only for a package that runs
|
|
112
|
+
and was not started in the last 10 seconds, yet whose executor does not
|
|
113
|
+
listen: it is not approved, awaits approval after an upgrade, or failed.
|
|
114
|
+
`retryable` says that nothing was sent, not that waiting helps: a browser
|
|
115
|
+
client repeats `APP_STOPPED`, `APP_STARTING` and `EXECUTOR_STARTING` on its
|
|
116
|
+
own, but shows `EXECUTOR_UNAVAILABLE` as the approval state at once, since
|
|
117
|
+
only an administrator's approval (which also restarts the executor) changes
|
|
118
|
+
it.
|
|
73
119
|
|
|
74
120
|
## Status
|
|
75
121
|
|
|
@@ -78,7 +124,9 @@ and `policy_digest`. With `auth` (since 0.9.6) it also answers `allowed`:
|
|
|
78
124
|
whether DSM's Application Privileges let the caller use the App and File
|
|
79
125
|
Station from `remote_addr`, the check `delegate.create` makes; an invalid
|
|
80
126
|
session is `AUTH_DENIED`. A CGI sends the caller's `auth` so an App the
|
|
81
|
-
executor would refuse is never shown as ready.
|
|
127
|
+
executor would refuse is never shown as ready. While a due start step runs
|
|
128
|
+
(see Package start step), `status` answers `ready: false` with `state`
|
|
129
|
+
`"starting"` and both digests. The executor MUST NOT report the SDK version; the binary
|
|
82
130
|
digest MUST change only when the executor source changes.
|
|
83
131
|
|
|
84
132
|
## Application Portal
|
|
@@ -136,7 +184,7 @@ Every root program, whatever starts it:
|
|
|
136
184
|
| Variable | Set for | Value |
|
|
137
185
|
|---|---|---|
|
|
138
186
|
| `SYNOPKGLAND_PACKAGE` | all | the package name |
|
|
139
|
-
| `SYNOPKGLAND_ROOT_MODE` | all | `run`, `job`, `stop` or `purge` |
|
|
187
|
+
| `SYNOPKGLAND_ROOT_MODE` | all | `run`, `job`, `start`, `stop` or `purge` |
|
|
140
188
|
| `SYNOPKGLAND_REQUESTED_BY` | run, job | the verified DSM user name |
|
|
141
189
|
| `SYNOPKGLAND_REQUEST_ID` | run | 64 hex digits, unique per call |
|
|
142
190
|
| `SYNOPKGLAND_JOB_ID` | job | the job's `job_id` |
|
|
@@ -155,11 +203,16 @@ Every root program, whatever starts it:
|
|
|
155
203
|
- A program that exits, whatever its status, is a result: `request_id`,
|
|
156
204
|
`exit_code`, `stderr` and either `output` (UTF-8, in a reply under 64 KiB)
|
|
157
205
|
or `staging` and `size`, a package-owned staging file the client reads and
|
|
158
|
-
removes.
|
|
206
|
+
removes. `staging` is a bare file name, `root-` and 32 lowercase hex
|
|
207
|
+
digits, never a path: the client joins it to the package staging folder,
|
|
208
|
+
`/var/packages/<package>/var/executor-staging`. The executor MUST create
|
|
209
|
+
that folder, owned by the package account with mode 0700, when it is
|
|
210
|
+
missing; a staging folder it cannot use is `ROOT_FAILED` with the message
|
|
211
|
+
`root output staging unavailable`. Past the timeout the process group is killed (`ROOT_TIMEOUT`);
|
|
159
212
|
output past `max_output` is `limit-exceeded`; a full staging quota is
|
|
160
213
|
`ROOT_STAGING_FULL`; two running programs make a third `ROOT_BUSY`.
|
|
161
214
|
- A `root.run` request MAY be up to 1 MiB; the executor answers within 130
|
|
162
|
-
seconds and a client SHOULD wait 140.
|
|
215
|
+
seconds and a client SHOULD wait 140 (Timeouts).
|
|
163
216
|
- `root.run` cannot be canceled: a closed connection does not stop the
|
|
164
217
|
program, which runs until it exits or its timeout. Work that may be stopped
|
|
165
218
|
is a root job (`root.start`, `root.jobs.stop`).
|
|
@@ -250,7 +303,48 @@ use it), and `stop` otherwise; jobs are canceled with `upgrade` or `stop`
|
|
|
250
303
|
accordingly. It runs for at most 30 seconds, only while the approval is live
|
|
251
304
|
(as for the purge step), its exit and output go to the executor log, and a
|
|
252
305
|
failure does not stop the stop. `root.run` and `root.start` refuse it with
|
|
253
|
-
`POLICY_DENIED
|
|
306
|
+
`POLICY_DENIED`, so a policy whose stop or purge entry declares `run` or
|
|
307
|
+
`job` is invalid; the entry is a lifecycle step only, either
|
|
308
|
+
with neither member or as the shorthand digest. Session work takes another
|
|
309
|
+
entry, which may pin the same digest under another name.
|
|
310
|
+
|
|
311
|
+
## Package start step
|
|
312
|
+
|
|
313
|
+
Since 0.10.3. A policy MAY carry `"start": "<name>"`, naming a `root` entry
|
|
314
|
+
the executor runs once after each install or upgrade, with no session:
|
|
315
|
+
|
|
316
|
+
- The executor MUST run it at the first start of a package version (the
|
|
317
|
+
`version` of the package INFO), after the pins matched. The socket opens first
|
|
318
|
+
and the step runs once the executor has read the
|
|
319
|
+
approval tasks back; until the step ends, `status` answers `ready: false`
|
|
320
|
+
and `state` `"starting"`, and every other request is refused with
|
|
321
|
+
`EXECUTOR_STARTING` (retryable), so no session reaches the App's root work
|
|
322
|
+
while the step runs. Its
|
|
323
|
+
arguments are `install` when the executor has recorded no earlier start,
|
|
324
|
+
and `upgrade` followed by the version recorded before otherwise. Every
|
|
325
|
+
start records its version, also for a policy without the step; a package
|
|
326
|
+
that adds the step in an upgrade therefore gets `upgrade`, except on the
|
|
327
|
+
first start under an executor that predates the record, which is `install`.
|
|
328
|
+
- It runs only while the approval is live (as for the purge step); otherwise
|
|
329
|
+
it MUST log `start root step skipped: not approved` and run at the next
|
|
330
|
+
start. A step cut short because the executor ended also runs again.
|
|
331
|
+
- It runs for at most 60 seconds; its exit and output go to the executor log,
|
|
332
|
+
and the executor MUST become ready whatever it answers. A failure is the result of
|
|
333
|
+
that version: the step does not run again until the next upgrade or
|
|
334
|
+
reinstall, so the program should be idempotent.
|
|
335
|
+
- `status` answers `start_step` for such a policy: `{"state": "pending"}`
|
|
336
|
+
until the step ran for the version being served, then `state` `ok` (exit
|
|
337
|
+
`0`) or `failed`, `reason` (`install` or `upgrade`), `previous_version` for
|
|
338
|
+
an upgrade, `exit` (an exit code, `timeout`, `signal` or `refused`),
|
|
339
|
+
`output` (at most 4 KiB, which the package account can read) and
|
|
340
|
+
`finished_at` (RFC 3339).
|
|
341
|
+
- As for stop and purge, `root.run` and `root.start` refuse it with
|
|
342
|
+
`POLICY_DENIED`, and an entry that declares `run` or `job` makes the policy
|
|
343
|
+
invalid.
|
|
344
|
+
|
|
345
|
+
Because DSM's package start only writes the start request, `postinst`,
|
|
346
|
+
`postupgrade` and `start` scripts run before or while the step runs; they
|
|
347
|
+
MUST NOT expect its result. The App reads it from `status`.
|
|
254
348
|
|
|
255
349
|
## Root state directory
|
|
256
350
|
|
|
@@ -106,6 +106,14 @@
|
|
|
106
106
|
"en": "The executor is paused, for example while the package stops or upgrades.",
|
|
107
107
|
"zh-TW": "executor 已暫停,例如套件停止或升級期間。"
|
|
108
108
|
},
|
|
109
|
+
{
|
|
110
|
+
"code": "EXECUTOR_STARTING",
|
|
111
|
+
"kind": "refusal",
|
|
112
|
+
"retryable": true,
|
|
113
|
+
"httpStatus": 503,
|
|
114
|
+
"en": "The executor is running the App's start step after an install or upgrade; status answers state starting until it ends.",
|
|
115
|
+
"zh-TW": "executor 正在執行安裝或升級後的 App start 步驟;結束前 status 回報 state starting。"
|
|
116
|
+
},
|
|
109
117
|
{
|
|
110
118
|
"code": "STORAGE_ERROR",
|
|
111
119
|
"kind": "refusal",
|
|
@@ -466,6 +474,22 @@
|
|
|
466
474
|
"en": "The client could not connect to the executor socket.",
|
|
467
475
|
"zh-TW": "用戶端無法連到 executor socket。"
|
|
468
476
|
},
|
|
477
|
+
{
|
|
478
|
+
"code": "APP_STOPPED",
|
|
479
|
+
"kind": "client",
|
|
480
|
+
"retryable": true,
|
|
481
|
+
"httpStatus": 503,
|
|
482
|
+
"en": "The package is stopped: its lifecycle mailbox asks the executor to stop. The client sent nothing.",
|
|
483
|
+
"zh-TW": "套件已停止:生命週期信箱要求 executor 停止。用戶端沒有送出任何內容。"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"code": "APP_STARTING",
|
|
487
|
+
"kind": "client",
|
|
488
|
+
"retryable": true,
|
|
489
|
+
"httpStatus": 503,
|
|
490
|
+
"en": "The package was just started and its executor is not listening yet. The client sent nothing.",
|
|
491
|
+
"zh-TW": "套件剛啟動,executor 尚未開始接聽。用戶端沒有送出任何內容。"
|
|
492
|
+
},
|
|
469
493
|
{
|
|
470
494
|
"code": "EXECUTOR_TIMEOUT",
|
|
471
495
|
"kind": "client",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Timeouts on the call chain to the executor, in seconds unless the name says ms. Each layer waits margin_s longer than the layer it calls, so the inner answer arrives first; README.md, Timeouts.",
|
|
3
|
+
"margin_s": 10,
|
|
4
|
+
"executor": {
|
|
5
|
+
"op_s": 30,
|
|
6
|
+
"root_run_program_default_s": 20,
|
|
7
|
+
"root_run_program_max_s": 120,
|
|
8
|
+
"root_run_answer_s": 130,
|
|
9
|
+
"start_step_s": 60
|
|
10
|
+
},
|
|
11
|
+
"client": {
|
|
12
|
+
"op_s": 40,
|
|
13
|
+
"root_run_s": 140
|
|
14
|
+
},
|
|
15
|
+
"request": {
|
|
16
|
+
"default_s": 60
|
|
17
|
+
},
|
|
18
|
+
"browser": {
|
|
19
|
+
"margin_ms": 2000
|
|
20
|
+
}
|
|
21
|
+
}
|