@synopackageland/cli 0.33.1 → 0.33.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.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,6 @@
1
1
  # Changelog
2
2
 
3
- ## 0.33.1 (2026-10-27)
3
+ ## 0.33.2 (2026-10-28)
4
4
 
5
- - Use one NAS connection path for host login, secure session storage, TLS and every DSM request, including package commands, deployment, ctl transfers and e2e login helpers
6
- - Accept self-signed, untrusted CA, hostname-mismatched and expired NAS certificates by default
7
- - Record each leaf SHA-256 for display; warn once and update it when a certificate changes, then continue
8
- - Add opt-in --strict-tls for host profiles and individual commands; --ca also verifies CA trust, hostname, validity and recorded certificates
9
- - Keep passwords on the exact connection whose certificate was inspected, without changing global TLS settings
5
+ - Load the installed app when a DSM window opens after a package upgrade without a page reload; the loader previously reused the app module the previous build left in the page
6
+ - Give DSM windows and full pages `ctx.uiUpdate.check()`, which reports when the installed package has replaced the UI the page loaded, so the SDK's AppShell can offer a reload after an upgrade
package/README.md CHANGED
@@ -282,8 +282,10 @@ for every other frontend. Plain/binary scaffolds explicitly choose new-page; Vue
282
282
  native `ui.launch` resolves to `dsm-window`; the CLI does not guess a frontend's
283
283
  framework from its build command. `new-page` registers DSM `type: "standalone"`,
284
284
  so the main menu and Package Center open a full page on the DSM origin.
285
- `ctx.fullPage`, `ctx.appIcon`, session/SynoToken, launch parameters and entry
286
- permissions use the same wrapper in both modes. The wrapper sets the standalone
285
+ `ctx.fullPage`, `ctx.appIcon`, `ctx.uiUpdate`, session/SynoToken, launch parameters and entry
286
+ permissions use the same wrapper in both modes. `ctx.uiUpdate.check()` reports when
287
+ a package upgrade replaced the UI the page loaded; SDK 0.31.5+ AppShell then shows
288
+ a one-line reload notice. The wrapper sets the standalone
287
289
  page title, favicon and device-width viewport. It retains ExtJS; `pureEnv` is
288
290
  not appropriate, and alternate Portal ports are not needed (`allowAltPort` is omitted).
289
291
 
@@ -49,6 +49,8 @@ export declare function renderUiConfig(manifest: StandaloneManifest, icons?: Pac
49
49
  * (and add a device-width viewport), and `ctx.appIcon` is the package icon a
50
50
  * full-page shell shows beside the name, where a DSM window has a title bar.
51
51
  * A portal App's `ctx.portal` shows `portalText`, the SDK's panel text.
52
+ * `ctx.uiUpdate.check()` answers whether the installed package replaced this
53
+ * window's UI (the SDK's AppShell then offers a reload).
52
54
  * `ctx.launchParams` holds the App's own values from the launch that opened
53
55
  * the window (a `launchParam` desktop URL or `SYNO.SDS.AppLaunch(id, param)`),
54
56
  * and `ctx.onLaunch(fn)` hands fn those of each later launch with values.
@@ -213,6 +213,8 @@ export function renderUiConfig(manifest, icons = packageIcons(manifest.icon), lo
213
213
  * (and add a device-width viewport), and `ctx.appIcon` is the package icon a
214
214
  * full-page shell shows beside the name, where a DSM window has a title bar.
215
215
  * A portal App's `ctx.portal` shows `portalText`, the SDK's panel text.
216
+ * `ctx.uiUpdate.check()` answers whether the installed package replaced this
217
+ * window's UI (the SDK's AppShell then offers a reload).
216
218
  * `ctx.launchParams` holds the App's own values from the launch that opened
217
219
  * the window (a `launchParam` desktop URL or `SYNO.SDS.AppLaunch(id, param)`),
218
220
  * and `ctx.onLaunch(fn)` hands fn those of each later launch with values.
@@ -394,9 +396,14 @@ ${ns}.sessionUser = function () {
394
396
  return { name: typeof session.user === "string" ? session.user : "", isAdmin: session.is_admin === true };
395
397
  };
396
398
 
397
- ${root ? root.definitions : ""}${manifest.portal ? renderPortalDefinition(ns, portalText) : ""}${ns}.loadApp = function (done) {
399
+ ${root ? root.definitions : ""}${manifest.portal ? renderPortalDefinition(ns, portalText) : ""}// DSM loads the installed build's window script when a window opens after a
400
+ // package upgrade, but keeps the page and the app module the previous build
401
+ // registered. Reuse it only when this build loaded it; an older loader records
402
+ // no build, so its app is replaced as well.
403
+ ${ns}.loadApp = function (done) {
398
404
  var apps = window.DsmPackageApps || {};
399
- if (apps[${p}]) {
405
+ var versions = window.DsmPackageAppVersions = window.DsmPackageAppVersions || {};
406
+ if (apps[${p}] && versions[${p}] === "${assetVersion}") {
400
407
  done(apps[${p}]);
401
408
  return;
402
409
  }
@@ -408,10 +415,29 @@ ${root ? root.definitions : ""}${manifest.portal ? renderPortalDefinition(ns, po
408
415
  var js = document.createElement("script");
409
416
  js.src = base + "app.js?v=${assetVersion}";
410
417
  js.dataset.package = ${p};
411
- js.onload = function () { done((window.DsmPackageApps || {})[${p}]); };
418
+ js.onload = function () { versions[${p}] = "${assetVersion}"; done((window.DsmPackageApps || {})[${p}]); };
412
419
  document.head.appendChild(js);
413
420
  };
414
421
 
422
+ // DSM keeps a loaded window script after a package upgrade until the page
423
+ // reloads, so a window opened again runs the old UI. ui/config names the
424
+ // installed build's window file: once it no longer names this one, the
425
+ // installed UI replaced this page's. no-store, not no-cache: DSM tags
426
+ // ui/config by size alone, so a revalidation can keep an older build's copy.
427
+ // An uninstalled package or a failed read answers false.
428
+ ${ns}.uiUpdate = {
429
+ check: function (signal) {
430
+ if (typeof fetch !== "function") return Promise.resolve(false);
431
+ return fetch("webman/3rdparty/${pkg}/config", { cache: "no-store", credentials: "same-origin", signal: signal })
432
+ .then(function (response) { return response.ok ? response.json() : null; })
433
+ .then(function (config) {
434
+ return !!config && typeof config === "object" && !Array.isArray(config) &&
435
+ !Object.prototype.hasOwnProperty.call(config, ${JSON.stringify(windowScriptName(manifest))});
436
+ })
437
+ .catch(function () { return false; });
438
+ }
439
+ };
440
+
415
441
  // A Portal/standalone launch is the whole page, on a phone as well: no desktop
416
442
  // minimum width, and the app lays itself out full-page.
417
443
  ${ns}.fullPage = function () {
@@ -501,6 +527,7 @@ ${root ? root.mount : ""} ${ns}.loadApp(function (app) {
501
527
  appWindow: me,
502
528
  fullPage: ${ns}.fullPage(),
503
529
  appIcon: ${ns}.appIcon,
530
+ uiUpdate: ${ns}.uiUpdate,
504
531
  lang: lang,
505
532
  locale: i18n.locale,
506
533
  t: i18n.t${root ? `,\n executor: access` : ""}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@synopackageland/cli",
3
- "version": "0.33.1",
3
+ "version": "0.33.2",
4
4
  "description": "Syno Package Land Developer Kit CLI",
5
5
  "type": "module",
6
6
  "bin": {
7
- "synopkgland": "dist/bin.js"
7
+ "synopkgland": "./dist/bin.js"
8
8
  },
9
9
  "engines": {
10
10
  "node": ">=22.12"
package/skills/SKILL.md CHANGED
@@ -184,7 +184,7 @@ Scaffold 明確寫入此選擇,plain/binary 使用 `new-page`,Vue UI SDK
184
184
  預設的 `dsm-window`(省略 `ui.launch`)。原生 manifest 省略 `ui.launch` 時解析為 `dsm-window`,CLI 不猜測前端依賴。
185
185
 
186
186
  `new-page` 產生 DSM `type: "standalone"` launcher,主選單及套件中心皆在 DSM
187
- 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、SynoToken/session、
187
+ 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、`ctx.uiUpdate`、SynoToken/session、
188
188
  `ctx.launchParams`/`onLaunch`、`entry` 權限沿用共用 wrapper;全頁的標題、
189
189
  favicon 與手機 viewport 由 wrapper 設定。不需要 `pureEnv` 或 `allowAltPort`。
190
190
 
@@ -231,7 +231,7 @@ Scaffold 明確寫入此選擇,plain/binary 使用 `new-page`,Vue UI SDK
231
231
  預設的 `dsm-window`(省略 `ui.launch`)。原生 manifest 省略 `ui.launch` 時解析為 `dsm-window`,CLI 不猜測前端依賴。
232
232
 
233
233
  `new-page` 產生 DSM `type: "standalone"` launcher,主選單及套件中心皆在 DSM
234
- 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、SynoToken/session、
234
+ 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、`ctx.uiUpdate`、SynoToken/session、
235
235
  `ctx.launchParams`/`onLaunch`、`entry` 權限沿用共用 wrapper;全頁的標題、
236
236
  favicon 與手機 viewport 由 wrapper 設定。不需要 `pureEnv` 或 `allowAltPort`。
237
237
 
@@ -49,7 +49,7 @@ Scaffold 明確寫入此選擇,plain/binary 使用 `new-page`,Vue UI SDK
49
49
  預設的 `dsm-window`(省略 `ui.launch`)。原生 manifest 省略 `ui.launch` 時解析為 `dsm-window`,CLI 不猜測前端依賴。
50
50
 
51
51
  `new-page` 產生 DSM `type: "standalone"` launcher,主選單及套件中心皆在 DSM
52
- 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、SynoToken/session、
52
+ 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、`ctx.uiUpdate`、SynoToken/session、
53
53
  `ctx.launchParams`/`onLaunch`、`entry` 權限沿用共用 wrapper;全頁的標題、
54
54
  favicon 與手機 viewport 由 wrapper 設定。不需要 `pureEnv` 或 `allowAltPort`。
55
55
 
@@ -173,7 +173,7 @@ Scaffold 明確寫入此選擇,plain/binary 使用 `new-page`,Vue UI SDK
173
173
  預設的 `dsm-window`(省略 `ui.launch`)。原生 manifest 省略 `ui.launch` 時解析為 `dsm-window`,CLI 不猜測前端依賴。
174
174
 
175
175
  `new-page` 產生 DSM `type: "standalone"` launcher,主選單及套件中心皆在 DSM
176
- 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、SynoToken/session、
176
+ 本身的 origin 開啟全頁。`ctx.fullPage`、`ctx.appIcon`、`ctx.uiUpdate`、SynoToken/session、
177
177
  `ctx.launchParams`/`onLaunch`、`entry` 權限沿用共用 wrapper;全頁的標題、
178
178
  favicon 與手機 viewport 由 wrapper 設定。不需要 `pureEnv` 或 `allowAltPort`。
179
179