@synopackageland/cli 0.10.7 → 0.10.9

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 CHANGED
@@ -1,5 +1,82 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.10.9 (2026-10-15)
4
+
5
+ Builds with SDK 0.10.9 and templates 0.10.10: `init` writes SDK v0.10.9,
6
+ `@synopackageland/sdk` 0.10.9 and `@synopackageland/ui` 0.9.8, and the root-ops
7
+ template's `ExecutorGate.vue` passes `preload`. The executor digest table adds
8
+ SDK 0.10.8 and 0.10.9 (equal to each other; the executor changed in 0.10.8).
9
+ **An App moved from SDK 0.10.7 or earlier and rebuilt is approved once more
10
+ by an administrator after the upgrade**, since its executor digest changes.
11
+ The CLI still needs SDK 0.10.5 or later: an executor without `tasks` (before
12
+ 0.10.8) is read back by the window as before. Use SDK 0.10.9, not 0.10.8:
13
+ 0.10.8's `ExecutorApproval` kept its loading text beside the pages without an
14
+ executor setup.
15
+
16
+ To upgrade an App: devDependency `@synopackageland/cli` 0.10.9 (exact) with
17
+ its lockfile; an App that depends on the SDK directly moves to 0.10.9 (Go
18
+ `require github.com/synopackageland/syno-pkg-land-sdk v0.10.9` with go.sum,
19
+ `@synopackageland/sdk` and `@synopackageland/app` 0.10.9, Cargo tag
20
+ `v0.10.9`, `backend.sdk: 0.10.9`); then rebuild, upgrade, and approve once.
21
+
22
+ 繁中摘要:搭配 SDK 0.10.9、templates 0.10.10(UI 0.9.8)。digest 表新增 SDK 0.10.8/0.10.9
23
+ (兩者相同,executor 在 0.10.8 改變)。自 SDK 0.10.7 以前升級並重建的 App,升級後要由管理員
24
+ 重新核准一次。SDK 下限維持 0.10.5(沒有 `tasks` 的舊 executor 照舊完整核對)。請用 SDK 0.10.9,
25
+ 不要用 0.10.8。App 要改:`@synopackageland/cli` 0.10.9+lock;直接依賴 SDK 的 App 升到 0.10.9。
26
+
27
+ - The DSM window shows an administrator the App without reading Task
28
+ Scheduler and EventScheduler when the pinned, running executor's status
29
+ says its own readback of the approval tasks is `ready` (`tasks`, SDK
30
+ 0.10.8 or later). That readback runs at the executor's start and
31
+ every 10 minutes; a task another administrator changes after it is seen at
32
+ the next one, up to 15 minutes later, instead of when the window opens.
33
+ Approval, the control task's start, stop and purge, and a scope selection
34
+ still read both tasks back first. An executor without `tasks`, or with a
35
+ readback that is not `ready`, is read back by the window as before, and
36
+ the first status request now also serves its health check.
37
+ 繁中:管理員開啟視窗時,若 executor 回報自己的排程核對為 ready,就不再呼叫兩個
38
+ 排程 API;核准、start/stop/purge 與範圍選擇仍先完整核對。舊 executor 照舊核對。
39
+
40
+ ## 0.10.8 (2026-10-15)
41
+
42
+ Builds with SDK 0.10.7 and templates 0.10.8, as 0.10.7 did: `init` still
43
+ writes SDK v0.10.7, `@synopackageland/sdk` 0.10.7 and `@synopackageland/ui`
44
+ 0.9.8, and the executor digest table is unchanged, so an App rebuilt on it
45
+ keeps its approval unless its executor or policy changes. Only the DSM
46
+ window's `ctx.call` changes. The CLI still needs SDK 0.10.5 or later: the
47
+ SDK's Gate, `useLifecycleRetry`, `appLifecycle` and `ExecutorApproval` already
48
+ read an `APP_STOPPED` that arrives at once and check again; SDK 0.10.7 changed
49
+ only its protocol README's wording, and nothing in the CLI depends on it.
50
+
51
+ 繁中摘要:搭配 SDK 0.10.7、templates 0.10.8(UI 0.9.8),digest 不變;SDK 下限維持 0.10.5
52
+ (SDK 的 Gate/`useLifecycleRetry`/`appLifecycle`/`ExecutorApproval` 本來就處理立即回的
53
+ `APP_STOPPED`)。只改 DSM window 的 `ctx.call`。
54
+
55
+ - `ctx.call` rejects `APP_STOPPED` at once: a stopped package waits for the
56
+ user to start it in Package Center, so the SDK's stopped copy shows within a
57
+ page's next read instead of 30 s later (Download Hub 29.3 s, t-0527; Reclaim
58
+ showed its old content or loading, t-0528). `APP_STARTING` and
59
+ `EXECUTOR_STARTING` repeat for 4 s of waiting (0.5, 1, 2, 0.5 s), so a short
60
+ start still shows the page nothing and the SDK's starting copy follows a
61
+ longer one within its own 4 s recheck. `executor.control`, which the window's
62
+ approval starts the executor with, still repeats a start for 30 s; the SDK's
63
+ status reads are still not repeated.
64
+ 繁中:套件停止時 `ctx.call` 立即回 `APP_STOPPED`;啟動中最多重試 4 s(`executor.control` 維持 30 s)。
65
+
66
+ ### Behavior changes
67
+
68
+ - An App rebuilt with CLI 0.10.8 shows a stopped package's copy within its
69
+ page's next read: `ctx.call` rejects `APP_STOPPED` at once instead of after
70
+ about 30 s, and repeats `APP_STARTING` and `EXECUTOR_STARTING` for at most
71
+ about 4 s. The App's code needs no change; only its devDependency
72
+ `@synopackageland/cli` 0.10.8 and its lockfile, then a rebuild.
73
+ - An e2e test that waits only for the Gate's stopped title
74
+ (`authorization.stopped.title`) can miss it: `ExecutorApproval` now takes
75
+ over first and shows its own stopped copy. Accept either of the SDK's stopped
76
+ copies.
77
+ 繁中:App 升到 CLI 0.10.8 重新 build 後,套件停止時頁面立即收到 `APP_STOPPED`(不再等 30 s),
78
+ 啟動中最多重試約 4 s;App 不需改程式。E2E 若只等 Gate 的停止標題,應接受 SDK 的任一停止文案。
79
+
3
80
  ## 0.10.7 (2026-10-15)
4
81
 
5
82
  Builds with SDK 0.10.7 and templates 0.10.8: `init` writes SDK v0.10.7 (Go
@@ -86,5 +86,27 @@
86
86
  "armv7": "cafc97c89f5645c14a8cf31d6d9f258394ed6f2d086478a7aebd04d57c274b4e"
87
87
  },
88
88
  "goToolchain": "go1.26.9"
89
+ },
90
+ "0.10.8": {
91
+ "x86_64": "ba38f5764d5f0510706afe39979eef18bf2b8a72421a3a495810c628db0c962d",
92
+ "aarch64": "b5129b26714c25c0eda83931f3a66961fa9ecd059074c534159db6a68aefd8f7",
93
+ "armv7": "359005fbab7714c29d0d0598f09f3b011aa643be26d0368726a023edbef53b8e",
94
+ "lifecycle": {
95
+ "x86_64": "d65500c4f04713a32b45d360059281391acfa5e00ee24895fdd2de7b82735372",
96
+ "aarch64": "94f6cd119186ff482b8aea56541dd1f9d53c147566bc1efdca6f5a1c86198331",
97
+ "armv7": "cafc97c89f5645c14a8cf31d6d9f258394ed6f2d086478a7aebd04d57c274b4e"
98
+ },
99
+ "goToolchain": "go1.26.9"
100
+ },
101
+ "0.10.9": {
102
+ "x86_64": "ba38f5764d5f0510706afe39979eef18bf2b8a72421a3a495810c628db0c962d",
103
+ "aarch64": "b5129b26714c25c0eda83931f3a66961fa9ecd059074c534159db6a68aefd8f7",
104
+ "armv7": "359005fbab7714c29d0d0598f09f3b011aa643be26d0368726a023edbef53b8e",
105
+ "lifecycle": {
106
+ "x86_64": "d65500c4f04713a32b45d360059281391acfa5e00ee24895fdd2de7b82735372",
107
+ "aarch64": "94f6cd119186ff482b8aea56541dd1f9d53c147566bc1efdca6f5a1c86198331",
108
+ "armv7": "cafc97c89f5645c14a8cf31d6d9f258394ed6f2d086478a7aebd04d57c274b4e"
109
+ },
110
+ "goToolchain": "go1.26.9"
89
111
  }
90
112
  }
@@ -192,17 +192,21 @@ ${ns}.callOnce = function (method, params, options, requestTimeout) {
192
192
  };
193
193
 
194
194
  // APP_STOPPED, APP_STARTING and EXECUTOR_STARTING mean the executor op was not
195
- // sent: the package is stopped, or starting. The call repeats on its own, half a
196
- // second, then doubling up to 8 s, for 30 s of waiting in all; each attempt keeps
197
- // its own deadline. Past that it rejects with the last refusal, and leaving the
195
+ // sent. A stopped package waits for the user to start it in Package Center, so
196
+ // APP_STOPPED rejects at once (t-0529). A start ends by itself: a call repeats
197
+ // half a second, then doubling, for 4 s of waiting in all, so a short start
198
+ // shows the page nothing and the SDK's starting copy follows a long one within
199
+ // its own 4 s recheck; executor.control, which the window's approval starts the
200
+ // executor with, repeats up to 8 s apart for 30 s. Each attempt keeps its own
201
+ // deadline; past the wait it rejects with the last refusal, and leaving the
198
202
  // page during a wait rejects request_canceled at once. The SDK's status reads
199
203
  // are not repeated: its panels show the stopped or starting package and check
200
- // again on their own, and a page waiting here shows nothing (t-0503 R1).
201
- ${ns}.retryCodes = ["APP_STOPPED", "APP_STARTING", "EXECUTOR_STARTING"];
204
+ // again on their own (t-0503 R1).
205
+ ${ns}.retryCodes = ["APP_STARTING", "EXECUTOR_STARTING"];
202
206
  ${ns}.statusReads = ["delegate.status", "authorization.status", "executor.status"];
203
207
  ${ns}.call = function (method, params, options, requestTimeout) {
204
208
  var signal = options && options.signal;
205
- var left = ${ns}.statusReads.indexOf(method) < 0 ? 30000 : 0;
209
+ var left = ${ns}.statusReads.indexOf(method) >= 0 ? 0 : method === "executor.control" ? 30000 : 4000;
206
210
  var delay = 500;
207
211
  var attempt = function () {
208
212
  return ${ns}.callOnce(method, params, options, requestTimeout).catch(function (error) {
@@ -291,25 +291,29 @@ export const ROOT_RUNTIME = `function createRootAccess(options) {
291
291
  waited = waited || 0;
292
292
  delay = waited < 4000 ? 500 : Math.min(delay * 2, 2000);
293
293
  step = step === undefined ? stepBudget : step;
294
- return options.call("executor.status", {}).then(function (status) {
294
+ return judged(options.call("executor.status", {})).catch(function (e) {
295
+ var steps = e.code === "executor_starting";
296
+ if ((steps ? step : budget) >= delay && options.wait) return options.wait(delay).then(function () { return steps ? alive(budget, delay, step - delay, waited + delay) : alive(budget - delay, delay, step, waited + delay); });
297
+ throw e;
298
+ });
299
+ }
300
+ // The approved executor's reply to one status request, or why it is not.
301
+ function judged(asked) {
302
+ return asked.then(function (status) {
295
303
  if (starting(status)) throw fail("executor_starting", "the executor's start step has not ended.");
296
304
  var why = mismatch(status);
297
305
  if (why) throw fail("executor_status_mismatch", why);
298
306
  return status;
299
307
  }, function (e) {
300
308
  throw fail(e && e.code, "the executor status request failed.");
301
- }).catch(function (e) {
302
- var steps = e.code === "executor_starting";
303
- if ((steps ? step : budget) >= delay && options.wait) return options.wait(delay).then(function () { return steps ? alive(budget, delay, step - delay, waited + delay) : alive(budget - delay, delay, step, waited + delay); });
304
- throw e;
305
309
  });
306
310
  }
307
311
  // step: how long to wait for a start step (ms). A status read waits none:
308
312
  // executor_starting says the package is starting, which the SDK checks
309
- // again on its own.
310
- function health(verified, step) {
313
+ // again on its own. asked: a status request already made, judged as is.
314
+ function health(verified, step, asked) {
311
315
  if (verified.state !== "ready") return Promise.resolve(verified);
312
- return settle(verified, alive(0, undefined, step)).then(function (result) {
316
+ return settle(verified, asked ? judged(asked) : alive(0, undefined, step)).then(function (result) {
313
317
  if (result.code === "executor_starting") delete result.retry;
314
318
  return result;
315
319
  });
@@ -347,8 +351,23 @@ export const ROOT_RUNTIME = `function createRootAccess(options) {
347
351
  return e && lifecycleCodes.indexOf(e.code) >= 0 ? block({tasks: {}}, fail(e.code, "the executor status request failed.")) : needed;
348
352
  });
349
353
  }
354
+ // An administrator asks the executor first. The pinned, running executor
355
+ // reads both tasks back itself under the same rules (spec/scheduler/v1),
356
+ // at start and every 10 minutes, and its status says whether they were
357
+ // ready; the scheduler takes seconds per read. Anything else (an executor
358
+ // without tasks, a stale or failed readback, other digests) is read back
359
+ // here, and that first status serves the health check. Approval and
360
+ // control read back on their own.
361
+ function checked(status) { return pinned(status) && !!status.tasks && status.tasks.state === "ready"; }
362
+ function adminStatus() {
363
+ var asked = options.call("executor.status", {});
364
+ function verify() { return read().then(function (verified) { return health(verified, 0, asked); }); }
365
+ return asked.then(function (status) {
366
+ return checked(status) ? {state: "ready", tasks: {boot: {state: "ready"}, control: {state: "ready"}}, executor: status} : verify();
367
+ }, verify);
368
+ }
350
369
  return {
351
- status: function () { return (isAdmin() ? read().then(function (verified) { return health(verified, 0); }) : userStatus()).then(publish); },
370
+ status: function () { return (isAdmin() ? adminStatus() : userStatus()).then(publish); },
352
371
  authorize: function (password, selectedScope) {
353
372
  if (!busy) busy = Promise.resolve().then(function () { return approve(password, selectedScope); }).catch(function (e) { var r = block({tasks: {}}, e); r.retry = !!(e && e.passwordConfirm); return r; }).then(function (r) { busy = null; return publish(r); });
354
373
  return busy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/cli",
3
- "version": "0.10.7",
3
+ "version": "0.10.9",
4
4
  "description": "Syno Package Land Developer Kit CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "prepublishOnly": "npm run build"
26
26
  },
27
27
  "dependencies": {
28
- "@synopackageland/templates": "0.10.8",
28
+ "@synopackageland/templates": "0.10.10",
29
29
  "ajv": "^8.17.1",
30
30
  "commander": "^13.1.0",
31
31
  "tar": "^7.4.3",