@synopackageland/cli 0.17.5 → 0.17.6
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 +4 -0
- package/dist/standalone/inspect-spk.js +35 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.6 (2026-10-20)
|
|
4
|
+
|
|
5
|
+
- Inspect sharedFolder, Portal and install-selected Apps by reconstructing fixed lifecycle scripts from their complete inputs, including native HTTPS ingress and App hooks.
|
|
6
|
+
|
|
3
7
|
## 0.17.5 (2026-10-20)
|
|
4
8
|
|
|
5
9
|
- Run native HTTPS preparation inside the SDK lifecycle steps before App hooks, keeping generated hook wrappers inspectable.
|
|
@@ -28,7 +28,7 @@ import { BACKGROUND_UNIT_DIR, BACKGROUND_WORKER_PAYLOAD, BRIDGE_WORKER_ARGS, bac
|
|
|
28
28
|
import { renderStandaloneResource } from "./resource.js";
|
|
29
29
|
import { recoverSharedFolder, renderSharedFolderUpgradeWizardFiles, sharedFolderInstallSteps, SHARED_FOLDER_MARKER, } from "./shared-folder.js";
|
|
30
30
|
import { renderInstallWizardFiles, renderNativeInstallWizard, } from "../build-spk/install-wizard.js";
|
|
31
|
-
import { renderDelegateScopeSteps,
|
|
31
|
+
import { renderDelegateScopeSteps, } from "../build-spk/delegate-scope.js";
|
|
32
32
|
import { renderUninstallWizardFiles } from "../build-spk/uninstall-wizard.js";
|
|
33
33
|
import { renderNativePrivilege } from "../build-spk/native-lifecycle.js";
|
|
34
34
|
import { renderUiConfig } from "./dsm-window.js";
|
|
@@ -162,7 +162,7 @@ export async function inspectSpk(spkPath, expectedKind) {
|
|
|
162
162
|
: undefined;
|
|
163
163
|
// Resource-worker portals use DSM-owned INFO reload, with no executor requirement.
|
|
164
164
|
const portal = standalone
|
|
165
|
-
? await recoverPortal(dir, info, `SYNO.SDS.${info.package}.Instance`, paths, payload, findings)
|
|
165
|
+
? await recoverPortal(dir, info, `SYNO.SDS.${info.package}.Instance`, paths, payload, findings, nativeGateway)
|
|
166
166
|
: undefined;
|
|
167
167
|
if (portal &&
|
|
168
168
|
info.os_min_ver &&
|
|
@@ -269,7 +269,7 @@ export async function inspectSpk(spkPath, expectedKind) {
|
|
|
269
269
|
? await inspectLoginStyle(dir, info.package, Boolean(portal || executor?.policy.portal), findings)
|
|
270
270
|
: undefined;
|
|
271
271
|
if (standalone)
|
|
272
|
-
checkSharedFolder(dir, findings, info.package, sharedFolder, executor?.policy.scope === "install-selected", portal, hasExecutor);
|
|
272
|
+
checkSharedFolder(dir, findings, info.package, sharedFolder, executor?.policy.scope === "install-selected", portal, hasExecutor, nativeGateway, info.os_min_ver);
|
|
273
273
|
const icon = inspectPackageIcons(dir, findings);
|
|
274
274
|
const cgiEntry = payload.find((entry) => entry.path === CGI_PAYLOAD_PATH);
|
|
275
275
|
if (standalone && !cgiEntry) {
|
|
@@ -1081,7 +1081,7 @@ function checkBackground(dir, info, payload, findings, executor, daemon, bridge
|
|
|
1081
1081
|
* declaration (without one, any present file must be the default native
|
|
1082
1082
|
* install wizard), and no other install/upgrade wizard file may exist.
|
|
1083
1083
|
*/
|
|
1084
|
-
function checkSharedFolder(dir, findings, pkg, folder, selected = false, portal, executor = false) {
|
|
1084
|
+
function checkSharedFolder(dir, findings, pkg, folder, selected = false, portal, executor = false, nativeGateway, osMinVer) {
|
|
1085
1085
|
const wizardDir = join(dir, "WIZARD_UIFILES");
|
|
1086
1086
|
const present = (existsSync(wizardDir) ? readdirSync(wizardDir) : [])
|
|
1087
1087
|
.filter((name) => /^(install|upgrade)_uifile(_|\.|$)/.test(name))
|
|
@@ -1091,6 +1091,22 @@ function checkSharedFolder(dir, findings, pkg, folder, selected = false, portal,
|
|
|
1091
1091
|
findings.push("the install.sharedFolder declaration in scripts/postinst is invalid");
|
|
1092
1092
|
if (!pkg)
|
|
1093
1093
|
return;
|
|
1094
|
+
// App wrappers have already been validated and unwrapped. Reconstruct the
|
|
1095
|
+
// remaining install-hook inputs from INFO, the payload and its build record.
|
|
1096
|
+
const lifecycleManifest = {
|
|
1097
|
+
package: pkg,
|
|
1098
|
+
os_min_ver: osMinVer,
|
|
1099
|
+
sharedFolder: folder,
|
|
1100
|
+
capabilities: selected
|
|
1101
|
+
? { delegate: { scope: "install-selected" } }
|
|
1102
|
+
: executor
|
|
1103
|
+
? { rootOps: true }
|
|
1104
|
+
: {},
|
|
1105
|
+
...(nativeGateway
|
|
1106
|
+
? { identityGateway: nativeGateway }
|
|
1107
|
+
: {}),
|
|
1108
|
+
...portalManifest(portal),
|
|
1109
|
+
};
|
|
1094
1110
|
const wizards = expectedWizardFiles(pkg, folder, selected, portal);
|
|
1095
1111
|
const source = selected
|
|
1096
1112
|
? "the install-selected policy"
|
|
@@ -1110,25 +1126,17 @@ function checkSharedFolder(dir, findings, pkg, folder, selected = false, portal,
|
|
|
1110
1126
|
findings.push(`WIZARD_UIFILES/${name} is not a wizard file produced by ${source}`);
|
|
1111
1127
|
if (selected) {
|
|
1112
1128
|
for (const hook of ["preinst", "postinst"]) {
|
|
1113
|
-
if (
|
|
1114
|
-
|
|
1129
|
+
if (readOptional(join(dir, "scripts", hook)) !==
|
|
1130
|
+
renderStandaloneScript(hook, lifecycleManifest))
|
|
1131
|
+
findings.push(`scripts/${hook} does not match the fixed install-selected draft handling`);
|
|
1115
1132
|
}
|
|
1116
1133
|
}
|
|
1117
|
-
if (!folder)
|
|
1134
|
+
if (!folder && !portal)
|
|
1118
1135
|
return;
|
|
1119
1136
|
for (const hook of ["postinst", "postupgrade"]) {
|
|
1120
1137
|
if (readOptional(join(dir, "scripts", hook)) !==
|
|
1121
|
-
renderStandaloneScript(hook, {
|
|
1122
|
-
|
|
1123
|
-
sharedFolder: folder,
|
|
1124
|
-
...(selected
|
|
1125
|
-
? { capabilities: { delegate: { scope: "install-selected" } } }
|
|
1126
|
-
: executor
|
|
1127
|
-
? { capabilities: { rootOps: true } }
|
|
1128
|
-
: {}),
|
|
1129
|
-
...portalManifest(portal),
|
|
1130
|
-
})) {
|
|
1131
|
-
findings.push(`scripts/${hook} does not match the fixed script declared by install.sharedFolder`);
|
|
1138
|
+
renderStandaloneScript(hook, lifecycleManifest)) {
|
|
1139
|
+
findings.push(`scripts/${hook} does not match the fixed script declared by ${folder ? "install.sharedFolder" : "portal"}`);
|
|
1132
1140
|
}
|
|
1133
1141
|
}
|
|
1134
1142
|
}
|
|
@@ -1160,7 +1168,7 @@ function portalManifest(portal) {
|
|
|
1160
1168
|
* files and alias lifecycle must be exactly what the generator writes for the
|
|
1161
1169
|
* package's own DSM window (native AppInstance or Compose `.url` entry); activation is never part of the package.
|
|
1162
1170
|
*/
|
|
1163
|
-
async function recoverPortal(dir, info, appId, paths, payload, findings) {
|
|
1171
|
+
async function recoverPortal(dir, info, appId, paths, payload, findings, nativeGateway) {
|
|
1164
1172
|
const files = [PORTAL_JSON_RELPATH, PORTAL_MUSTACHE_RELPATH];
|
|
1165
1173
|
if (!files.some((path) => paths.has(path)))
|
|
1166
1174
|
return;
|
|
@@ -1184,7 +1192,14 @@ async function recoverPortal(dir, info, appId, paths, payload, findings) {
|
|
|
1184
1192
|
renderPortalMustache())
|
|
1185
1193
|
throw new Error("content");
|
|
1186
1194
|
for (const hook of ["preinst", "postinst", "postupgrade"]) {
|
|
1187
|
-
|
|
1195
|
+
const prepare = ["postinst", "postupgrade"].includes(hook)
|
|
1196
|
+
? renderNativeGatewayPrepare({
|
|
1197
|
+
package: info.package,
|
|
1198
|
+
os_min_ver: info.os_min_ver,
|
|
1199
|
+
identityGateway: nativeGateway,
|
|
1200
|
+
})
|
|
1201
|
+
: "";
|
|
1202
|
+
if (!readOptional(join(dir, "scripts", hook))?.startsWith(`#!/bin/sh\n${prepare}${renderPortalLifecycle(hook, portal)}`))
|
|
1188
1203
|
throw new Error(hook);
|
|
1189
1204
|
}
|
|
1190
1205
|
return portal;
|