@synopackageland/cli 0.3.9 → 0.4.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.
Files changed (286) hide show
  1. package/README.md +20 -9
  2. package/dist/bin.js +1 -2
  3. package/dist/build-spk/generator.d.ts +0 -3
  4. package/dist/build-spk/generator.js +135 -287
  5. package/dist/build-spk/native-lifecycle.js +0 -3
  6. package/dist/build-spk/native-payload.js +0 -1
  7. package/dist/cli.js +171 -151
  8. package/dist/compose/analyze.d.ts +1 -2
  9. package/dist/compose/analyze.js +5 -48
  10. package/dist/contract/unsupported-types.d.ts +10 -0
  11. package/dist/contract/unsupported-types.js +49 -0
  12. package/dist/contract/validate.js +25 -2
  13. package/dist/contract/web-launch.js +0 -2
  14. package/dist/deploy/deploy.d.ts +1 -4
  15. package/dist/deploy/deploy.js +57 -156
  16. package/dist/deploy/homes-values.js +1 -1
  17. package/dist/deploy/plan.d.ts +18 -0
  18. package/dist/deploy/plan.js +54 -0
  19. package/dist/deploy/port-preflight.d.ts +21 -0
  20. package/dist/deploy/port-preflight.js +42 -0
  21. package/dist/deploy/spk-version.d.ts +2 -14
  22. package/dist/deploy/spk-version.js +25 -111
  23. package/dist/dev.d.ts +1 -3
  24. package/dist/dev.js +14 -28
  25. package/dist/error-registry.js +810 -857
  26. package/dist/host/dsm-client.js +23 -263
  27. package/dist/host/dsm-port-profile.d.ts +47 -0
  28. package/dist/host/dsm-port-profile.js +206 -0
  29. package/dist/host/port-info-lookup.d.ts +9 -0
  30. package/dist/host/port-info-lookup.js +87 -0
  31. package/dist/host/port-info.d.ts +33 -0
  32. package/dist/host/port-info.js +66 -0
  33. package/dist/host/types.d.ts +6 -78
  34. package/dist/index.d.ts +0 -9
  35. package/dist/index.js +0 -6
  36. package/dist/info.d.ts +0 -1
  37. package/dist/info.js +3 -10
  38. package/dist/init.d.ts +11 -1
  39. package/dist/init.js +112 -4
  40. package/dist/log.js +2 -3
  41. package/dist/native/validate.js +0 -1
  42. package/dist/standalone/binary.d.ts +9 -0
  43. package/dist/standalone/binary.js +67 -0
  44. package/dist/standalone/build.d.ts +25 -0
  45. package/dist/standalone/build.js +108 -0
  46. package/dist/standalone/dsm-window.d.ts +26 -0
  47. package/dist/standalone/dsm-window.js +251 -0
  48. package/dist/standalone/helper.d.ts +31 -0
  49. package/dist/standalone/helper.js +104 -0
  50. package/dist/standalone/i18n.d.ts +28 -0
  51. package/dist/standalone/i18n.js +161 -0
  52. package/dist/standalone/inspect-spk.d.ts +21 -0
  53. package/dist/standalone/inspect-spk.js +160 -0
  54. package/dist/standalone/manifest.d.ts +71 -0
  55. package/dist/standalone/manifest.js +276 -0
  56. package/dist/standalone/root-messages.d.ts +7 -0
  57. package/dist/standalone/root-messages.js +250 -0
  58. package/dist/standalone/root-ops.d.ts +42 -0
  59. package/dist/standalone/root-ops.js +101 -0
  60. package/dist/standalone/root-window.d.ts +35 -0
  61. package/dist/standalone/root-window.js +290 -0
  62. package/dist/standalone/spk.d.ts +22 -0
  63. package/dist/standalone/spk.js +205 -0
  64. package/dist/templates/binary/synology-app.yaml +7 -0
  65. package/dist/templates/hello-files/compose.yaml +0 -1
  66. package/dist/templates/hello-web/compose.yaml +13 -10
  67. package/dist/templates/hello-web/html/app.js +1 -23
  68. package/dist/templates/hello-web/html/index.html +1 -3
  69. package/dist/templates/hello-web-page/compose.yaml +13 -10
  70. package/dist/templates/hello-web-page/html/app.js +1 -23
  71. package/dist/templates/hello-web-page/html/index.html +1 -3
  72. package/dist/templates/native-go/README.md +268 -0
  73. package/dist/templates/native-go/backend/cmd/app/main.go +49 -0
  74. package/dist/templates/native-go/backend/cmd/helper/main.go +38 -0
  75. package/dist/templates/native-go/backend/go.mod +3 -0
  76. package/dist/templates/native-go/backend/internal/api/errors.go +33 -0
  77. package/dist/templates/native-go/backend/internal/api/registry.go +94 -0
  78. package/dist/templates/native-go/backend/internal/api/registry_test.go +329 -0
  79. package/dist/templates/native-go/backend/internal/api/server.go +155 -0
  80. package/dist/templates/native-go/backend/internal/app/root_none.go +9 -0
  81. package/dist/templates/native-go/backend/internal/app/routes.go +127 -0
  82. package/dist/templates/native-go/backend/internal/app/routes_test.go +167 -0
  83. package/dist/templates/native-go/backend/internal/dsm/auth.go +118 -0
  84. package/dist/templates/native-go/backend/internal/dsm/auth_test.go +139 -0
  85. package/dist/templates/native-go/backend/internal/helper/control.go +219 -0
  86. package/dist/templates/native-go/backend/internal/helper/control_test.go +242 -0
  87. package/dist/templates/native-go/backend/internal/helper/peer_linux.go +44 -0
  88. package/dist/templates/native-go/backend/internal/helper/peer_other.go +7 -0
  89. package/dist/templates/native-go/backend/internal/helper/process_linux.go +167 -0
  90. package/dist/templates/native-go/backend/internal/helper/process_other.go +5 -0
  91. package/dist/templates/native-go/backend/internal/helper/server_linux.go +83 -0
  92. package/dist/templates/native-go/backend/internal/helper/status.go +271 -0
  93. package/dist/templates/native-go/backend/internal/helper/status_test.go +205 -0
  94. package/dist/templates/native-go/backend/internal/helper/supervision.go +84 -0
  95. package/dist/templates/native-go/backend/internal/helper/supervision_test.go +124 -0
  96. package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +192 -0
  97. package/dist/templates/native-go/backend/internal/helper/supervisor_linux_test.go +302 -0
  98. package/dist/templates/native-go/dsm-package.yaml +58 -0
  99. package/dist/templates/native-go/gitignore +1 -0
  100. package/dist/templates/native-go/i18n/glossary.json +662 -0
  101. package/dist/templates/native-go/i18n/messages/de.json +28 -0
  102. package/dist/templates/native-go/i18n/messages/en.json +28 -0
  103. package/dist/templates/native-go/i18n/messages/es.json +28 -0
  104. package/dist/templates/native-go/i18n/messages/fr.json +28 -0
  105. package/dist/templates/native-go/i18n/messages/it.json +28 -0
  106. package/dist/templates/native-go/i18n/messages/ja.json +28 -0
  107. package/dist/templates/native-go/i18n/messages/ko.json +28 -0
  108. package/dist/templates/native-go/i18n/messages/zh-CN.json +28 -0
  109. package/dist/templates/native-go/i18n/messages/zh-TW.json +28 -0
  110. package/dist/templates/native-go/ui/app.css +35 -0
  111. package/dist/templates/native-go/ui/app.js +94 -0
  112. package/dist/templates/native-go-better-auth/backend/internal/app/identity.go +208 -0
  113. package/dist/templates/native-go-better-auth/backend/internal/app/identity_test.go +113 -0
  114. package/dist/templates/native-go-better-auth/node/app.mjs +72 -0
  115. package/dist/templates/native-go-better-auth/node/build.mjs +2 -0
  116. package/dist/templates/native-go-better-auth/node/package-lock.json +862 -0
  117. package/dist/templates/native-go-better-auth/node/package.json +1 -0
  118. package/dist/templates/native-go-better-auth/node/test/auth.test.mjs +31 -0
  119. package/dist/templates/native-go-integration/backend/internal/app/identity_none.go +6 -0
  120. package/dist/templates/native-go-integration/backend/internal/app/personal.go +203 -0
  121. package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +119 -0
  122. package/dist/templates/native-go-root/backend/internal/app/root.go +107 -0
  123. package/dist/templates/native-go-root/backend/internal/app/root_test.go +124 -0
  124. package/dist/templates/native-go-root/root/whoami.sh +6 -0
  125. package/dist/templates/native-go-vue/README.md +110 -0
  126. package/dist/templates/native-go-vue/frontend/DESIGN.md +78 -0
  127. package/dist/templates/native-go-vue/frontend/package-lock.json +2507 -0
  128. package/dist/templates/native-go-vue/frontend/package.json +6 -0
  129. package/dist/templates/native-go-vue/frontend/src/App.vue +132 -0
  130. package/dist/templates/native-go-vue/frontend/src/context.ts +17 -0
  131. package/dist/templates/native-go-vue/frontend/src/main.ts +26 -0
  132. package/dist/templates/native-go-vue/frontend/src/style.css +14 -0
  133. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +148 -0
  134. package/dist/templates/native-go-vue/frontend/tsconfig.json +1 -0
  135. package/dist/templates/native-go-vue/frontend/vite.config.ts +8 -0
  136. package/dist/templates/native-go-vue/gitignore +2 -0
  137. package/dist/types.d.ts +1 -1
  138. package/dist/validate.js +11 -7
  139. package/package.json +3 -7
  140. package/schema/synology-app.schema.json +36 -37
  141. package/skills/SKILL.md +4 -48
  142. package/skills/reference/create.md +11 -83
  143. package/skills/reference/deploy.md +7 -78
  144. package/skills/reference/diagnose.md +4 -101
  145. package/skills/reference/files.md +5 -41
  146. package/skills/reference/identity.md +3 -29
  147. package/skills/reference/wrap.md +0 -2
  148. package/templates/binary/synology-app.yaml +7 -0
  149. package/templates/hello-files/compose.yaml +0 -1
  150. package/templates/hello-web/compose.yaml +13 -10
  151. package/templates/hello-web/html/app.js +1 -23
  152. package/templates/hello-web/html/index.html +1 -3
  153. package/templates/hello-web-page/compose.yaml +13 -10
  154. package/templates/hello-web-page/html/app.js +1 -23
  155. package/templates/hello-web-page/html/index.html +1 -3
  156. package/templates/native-go/README.md +268 -0
  157. package/templates/native-go/backend/cmd/app/main.go +49 -0
  158. package/templates/native-go/backend/cmd/helper/main.go +38 -0
  159. package/templates/native-go/backend/go.mod +3 -0
  160. package/templates/native-go/backend/internal/api/errors.go +33 -0
  161. package/templates/native-go/backend/internal/api/registry.go +94 -0
  162. package/templates/native-go/backend/internal/api/registry_test.go +329 -0
  163. package/templates/native-go/backend/internal/api/server.go +155 -0
  164. package/templates/native-go/backend/internal/app/root_none.go +9 -0
  165. package/templates/native-go/backend/internal/app/routes.go +127 -0
  166. package/templates/native-go/backend/internal/app/routes_test.go +167 -0
  167. package/templates/native-go/backend/internal/dsm/auth.go +118 -0
  168. package/templates/native-go/backend/internal/dsm/auth_test.go +139 -0
  169. package/templates/native-go/backend/internal/helper/control.go +219 -0
  170. package/templates/native-go/backend/internal/helper/control_test.go +242 -0
  171. package/templates/native-go/backend/internal/helper/peer_linux.go +44 -0
  172. package/templates/native-go/backend/internal/helper/peer_other.go +7 -0
  173. package/templates/native-go/backend/internal/helper/process_linux.go +167 -0
  174. package/templates/native-go/backend/internal/helper/process_other.go +5 -0
  175. package/templates/native-go/backend/internal/helper/server_linux.go +83 -0
  176. package/templates/native-go/backend/internal/helper/status.go +271 -0
  177. package/templates/native-go/backend/internal/helper/status_test.go +205 -0
  178. package/templates/native-go/backend/internal/helper/supervision.go +84 -0
  179. package/templates/native-go/backend/internal/helper/supervision_test.go +124 -0
  180. package/templates/native-go/backend/internal/helper/supervisor_linux.go +192 -0
  181. package/templates/native-go/backend/internal/helper/supervisor_linux_test.go +302 -0
  182. package/templates/native-go/dsm-package.yaml +58 -0
  183. package/templates/native-go/gitignore +1 -0
  184. package/templates/native-go/i18n/glossary.json +662 -0
  185. package/templates/native-go/i18n/messages/de.json +28 -0
  186. package/templates/native-go/i18n/messages/en.json +28 -0
  187. package/templates/native-go/i18n/messages/es.json +28 -0
  188. package/templates/native-go/i18n/messages/fr.json +28 -0
  189. package/templates/native-go/i18n/messages/it.json +28 -0
  190. package/templates/native-go/i18n/messages/ja.json +28 -0
  191. package/templates/native-go/i18n/messages/ko.json +28 -0
  192. package/templates/native-go/i18n/messages/zh-CN.json +28 -0
  193. package/templates/native-go/i18n/messages/zh-TW.json +28 -0
  194. package/templates/native-go/ui/app.css +35 -0
  195. package/templates/native-go/ui/app.js +94 -0
  196. package/templates/native-go-better-auth/backend/internal/app/identity.go +208 -0
  197. package/templates/native-go-better-auth/backend/internal/app/identity_test.go +113 -0
  198. package/templates/native-go-better-auth/node/app.mjs +72 -0
  199. package/templates/native-go-better-auth/node/build.mjs +2 -0
  200. package/templates/native-go-better-auth/node/package-lock.json +862 -0
  201. package/templates/native-go-better-auth/node/package.json +1 -0
  202. package/templates/native-go-better-auth/node/test/auth.test.mjs +31 -0
  203. package/templates/native-go-integration/backend/internal/app/identity_none.go +6 -0
  204. package/templates/native-go-integration/backend/internal/app/personal.go +203 -0
  205. package/templates/native-go-integration/backend/internal/app/personal_test.go +119 -0
  206. package/templates/native-go-root/backend/internal/app/root.go +107 -0
  207. package/templates/native-go-root/backend/internal/app/root_test.go +124 -0
  208. package/templates/native-go-root/root/whoami.sh +6 -0
  209. package/templates/native-go-vue/README.md +110 -0
  210. package/templates/native-go-vue/frontend/DESIGN.md +78 -0
  211. package/templates/native-go-vue/frontend/package-lock.json +2507 -0
  212. package/templates/native-go-vue/frontend/package.json +6 -0
  213. package/templates/native-go-vue/frontend/src/App.vue +132 -0
  214. package/templates/native-go-vue/frontend/src/context.ts +17 -0
  215. package/templates/native-go-vue/frontend/src/main.ts +26 -0
  216. package/templates/native-go-vue/frontend/src/style.css +14 -0
  217. package/templates/native-go-vue/frontend/test/apps.test.ts +148 -0
  218. package/templates/native-go-vue/frontend/tsconfig.json +1 -0
  219. package/templates/native-go-vue/frontend/vite.config.ts +8 -0
  220. package/templates/native-go-vue/gitignore +2 -0
  221. package/dist/attestation/app-package.d.ts +0 -86
  222. package/dist/attestation/app-package.js +0 -206
  223. package/dist/attestation/install-on-host.d.ts +0 -14
  224. package/dist/attestation/install-on-host.js +0 -52
  225. package/dist/attestation/keyring.d.ts +0 -21
  226. package/dist/attestation/keyring.js +0 -168
  227. package/dist/attestation/platform-service.d.ts +0 -70
  228. package/dist/attestation/platform-service.js +0 -250
  229. package/dist/build-spk/broker-glue.d.ts +0 -16
  230. package/dist/build-spk/broker-glue.js +0 -40
  231. package/dist/deploy/catalog-publish.d.ts +0 -3
  232. package/dist/deploy/catalog-publish.js +0 -7
  233. package/dist/doctor.d.ts +0 -22
  234. package/dist/doctor.js +0 -721
  235. package/dist/error-collector.d.ts +0 -2
  236. package/dist/error-collector.js +0 -46
  237. package/dist/host/broker-paths.d.ts +0 -1
  238. package/dist/host/broker-paths.js +0 -1
  239. package/dist/host/broker-upgrade-preflight.d.ts +0 -61
  240. package/dist/host/broker-upgrade-preflight.js +0 -156
  241. package/dist/host/digests.d.ts +0 -5
  242. package/dist/host/digests.js +0 -63
  243. package/dist/host/fake-nas.d.ts +0 -41
  244. package/dist/host/fake-nas.js +0 -174
  245. package/dist/mock-broker/bootstrap.d.ts +0 -2
  246. package/dist/mock-broker/bootstrap.js +0 -8
  247. package/dist/mock-broker/files.d.ts +0 -60
  248. package/dist/mock-broker/files.js +0 -408
  249. package/dist/mock-broker/oidc.d.ts +0 -31
  250. package/dist/mock-broker/oidc.js +0 -161
  251. package/dist/mock-broker/path.d.ts +0 -9
  252. package/dist/mock-broker/path.js +0 -50
  253. package/dist/mock-broker/server.d.ts +0 -19
  254. package/dist/mock-broker/server.js +0 -350
  255. package/dist/publish/build-ledger.d.ts +0 -22
  256. package/dist/publish/build-ledger.js +0 -26
  257. package/dist/publish/community-path.d.ts +0 -6
  258. package/dist/publish/community-path.js +0 -41
  259. package/dist/publish/curated-release.d.ts +0 -78
  260. package/dist/publish/curated-release.js +0 -883
  261. package/dist/publish/file-build-ledger.d.ts +0 -18
  262. package/dist/publish/file-build-ledger.js +0 -268
  263. package/dist/publish/github-pr.d.ts +0 -25
  264. package/dist/publish/github-pr.js +0 -85
  265. package/dist/publish/github-repo.d.ts +0 -8
  266. package/dist/publish/github-repo.js +0 -21
  267. package/dist/publish/platform-service-release.d.ts +0 -60
  268. package/dist/publish/platform-service-release.js +0 -333
  269. package/dist/publish/preflight.d.ts +0 -24
  270. package/dist/publish/preflight.js +0 -138
  271. package/dist/publish/publish.d.ts +0 -27
  272. package/dist/publish/publish.js +0 -136
  273. package/dist/publish/sync-definition.d.ts +0 -4
  274. package/dist/publish/sync-definition.js +0 -48
  275. package/dist/release-bin.d.ts +0 -2
  276. package/dist/release-bin.js +0 -23
  277. package/dist/templates/hello-web/html/sdk.js +0 -68
  278. package/dist/templates/hello-web-page/html/sdk.js +0 -68
  279. package/dist/templates/native/synology-app.yaml +0 -7
  280. package/dist/test-host.d.ts +0 -15
  281. package/dist/test-host.js +0 -37
  282. package/templates/hello-web/html/sdk.js +0 -68
  283. package/templates/hello-web-page/html/sdk.js +0 -68
  284. package/templates/native/synology-app.yaml +0 -7
  285. /package/dist/templates/{native → binary}/native.yaml +0 -0
  286. /package/templates/{native → binary}/native.yaml +0 -0
@@ -1,2 +0,0 @@
1
- export declare function extractReferencedErrorCodes(srcDirectory: string): Set<string>;
2
- export declare function extractAllStringLiterals(srcDirectory: string): Set<string>;
@@ -1,46 +0,0 @@
1
- import { readFileSync, readdirSync, statSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { ERROR_REGISTRY } from "../src/error-registry.js";
4
- function getAllTsFiles(dir, excludeDirs = []) {
5
- const files = [];
6
- for (const entry of readdirSync(dir)) {
7
- const fullPath = join(dir, entry);
8
- if (statSync(fullPath).isDirectory()) {
9
- if (!excludeDirs.includes(entry)) {
10
- files.push(...getAllTsFiles(fullPath, excludeDirs));
11
- }
12
- }
13
- else if (fullPath.endsWith(".ts")) {
14
- files.push(fullPath);
15
- }
16
- }
17
- return files;
18
- }
19
- export function extractReferencedErrorCodes(srcDirectory) {
20
- const tsFiles = getAllTsFiles(srcDirectory, ["mock-broker"]).filter((f) => !f.endsWith("error-registry.ts"));
21
- const referenced = new Set();
22
- for (const file of tsFiles) {
23
- const content = readFileSync(file, "utf8");
24
- for (const code of Object.keys(ERROR_REGISTRY)) {
25
- // Check if `code` appears as a string literal or identifier in the file
26
- if (content.includes(`"${code}"`) || content.includes(`'${code}'`) || content.includes(`\`${code}\``)) {
27
- referenced.add(code);
28
- }
29
- }
30
- }
31
- return referenced;
32
- }
33
- export function extractAllStringLiterals(srcDirectory) {
34
- const tsFiles = getAllTsFiles(srcDirectory, ["mock-broker"]).filter((f) => !f.endsWith("error-registry.ts"));
35
- const literals = new Set();
36
- const codeRegex = /["']([A-Z][A-Z0-9_]{2,})["']/g;
37
- for (const file of tsFiles) {
38
- const content = readFileSync(file, "utf8");
39
- codeRegex.lastIndex = 0;
40
- let match;
41
- while ((match = codeRegex.exec(content)) !== null) {
42
- literals.add(match[1]);
43
- }
44
- }
45
- return literals;
46
- }
@@ -1 +0,0 @@
1
- export declare const IDENTITY_CGI_PATH = "/webman/3rdparty/SynoPkgLandService/index.cgi";
@@ -1 +0,0 @@
1
- export const IDENTITY_CGI_PATH = "/webman/3rdparty/SynoPkgLandService/index.cgi";
@@ -1,61 +0,0 @@
1
- export declare const BROKER_UPGRADE_TARGET_HOST = "10.17.83.200";
2
- export type DsmUpgradeResponseKind = "error-4552" | "success" | "consent" | "unknown";
3
- export interface ConsentDialogEvidence {
4
- consentDialog: {
5
- dependers: string[];
6
- };
7
- }
8
- export interface BrokerUpgradeDependerBaseline {
9
- packageIdentity: string;
10
- version: string;
11
- status: string;
12
- running: boolean;
13
- }
14
- export interface BrokerUpgradeDepender extends BrokerUpgradeDependerBaseline {
15
- healthCheckOk: boolean;
16
- a23Classified: boolean;
17
- dataSnapshotOk: boolean;
18
- }
19
- export interface BrokerUpgradePreflightInput {
20
- targetHost: string;
21
- broker: {
22
- version: string;
23
- status: string;
24
- running: boolean;
25
- };
26
- dependers: BrokerUpgradeDepender[];
27
- previousSpk: {
28
- available: boolean;
29
- sha256?: string;
30
- };
31
- canonicalizeGateSatisfied: boolean;
32
- catalogEntry: {
33
- version: string;
34
- };
35
- }
36
- export type PreflightDecision = {
37
- ok: true;
38
- } | {
39
- ok: false;
40
- codes: string[];
41
- };
42
- export interface Evaluate4552BranchInput {
43
- response: unknown;
44
- dependers: BrokerUpgradeDependerBaseline[];
45
- }
46
- /**
47
- * Classify only already-parsed DSM evidence. Strings are deliberately never
48
- * parsed or searched: a textual mention of 4552 is not a DSM error response.
49
- */
50
- export declare function classifyDsmUpgradeResponse(raw: unknown): DsmUpgradeResponseKind;
51
- /**
52
- * Evaluate every local prerequisite without performing an upgrade or
53
- * proposing a stop/start action. A missing or malformed prerequisite is a
54
- * failure, even when another part of the input looks healthy.
55
- */
56
- export declare function evaluateBrokerUpgradePreflight(input: BrokerUpgradePreflightInput): PreflightDecision;
57
- /**
58
- * The 4552 path is entered only for a numeric DSM error and a non-empty,
59
- * fully identified running baseline inventory.
60
- */
61
- export declare function evaluate4552Branch(input: Evaluate4552BranchInput): PreflightDecision;
@@ -1,156 +0,0 @@
1
- import { comparePackageVersions } from "@synopackageland/package-source/index-manifest";
2
- export const BROKER_UPGRADE_TARGET_HOST = "10.17.83.200";
3
- /**
4
- * Classify only already-parsed DSM evidence. Strings are deliberately never
5
- * parsed or searched: a textual mention of 4552 is not a DSM error response.
6
- */
7
- export function classifyDsmUpgradeResponse(raw) {
8
- if (!isRecord(raw)) {
9
- return "unknown";
10
- }
11
- if (isRecord(raw.error) && raw.error.code === 4552) {
12
- return "error-4552";
13
- }
14
- const hasError = Object.prototype.hasOwnProperty.call(raw, "error") &&
15
- raw.error !== null &&
16
- raw.error !== undefined;
17
- if (raw.success === true && !hasError) {
18
- return "success";
19
- }
20
- if (isConsentDialogEvidence(raw)) {
21
- return "consent";
22
- }
23
- return "unknown";
24
- }
25
- /**
26
- * Evaluate every local prerequisite without performing an upgrade or
27
- * proposing a stop/start action. A missing or malformed prerequisite is a
28
- * failure, even when another part of the input looks healthy.
29
- */
30
- export function evaluateBrokerUpgradePreflight(input) {
31
- const candidate = isRecord(input) ? input : {};
32
- const codes = [];
33
- const addCode = (code) => {
34
- if (!codes.includes(code)) {
35
- codes.push(code);
36
- }
37
- };
38
- if (candidate.targetHost !== BROKER_UPGRADE_TARGET_HOST) {
39
- addCode("PREFLIGHT_WRONG_TARGET");
40
- }
41
- const broker = candidate.broker;
42
- if (!isRecord(broker)) {
43
- addCode("PREFLIGHT_BROKER_NOT_RUNNING");
44
- addCode("PREFLIGHT_BROKER_VERSION_INVALID");
45
- }
46
- else {
47
- if (broker.running !== true || broker.status !== "running") {
48
- addCode("PREFLIGHT_BROKER_NOT_RUNNING");
49
- }
50
- if (!isNonEmptyString(broker.version)) {
51
- addCode("PREFLIGHT_BROKER_VERSION_INVALID");
52
- }
53
- }
54
- const dependers = candidate.dependers;
55
- if (!Array.isArray(dependers)) {
56
- addCode("PREFLIGHT_DEPENDER_INVENTORY_INVALID");
57
- }
58
- else {
59
- for (const depender of dependers) {
60
- if (!isRecord(depender)) {
61
- addCode("PREFLIGHT_DEPENDER_INVENTORY_INVALID");
62
- continue;
63
- }
64
- if (!isNonEmptyString(depender.packageIdentity) || !isNonEmptyString(depender.version)) {
65
- addCode("PREFLIGHT_DEPENDER_INVENTORY_INVALID");
66
- }
67
- if (depender.running !== true) {
68
- addCode("PREFLIGHT_DEPENDER_NOT_RUNNING");
69
- }
70
- if (depender.status !== "running") {
71
- addCode("PREFLIGHT_DEPENDER_UNSAFE_STATUS");
72
- }
73
- if (depender.healthCheckOk !== true) {
74
- addCode("PREFLIGHT_DEPENDER_HEALTHCHECK_FAILED");
75
- }
76
- if (depender.a23Classified !== true) {
77
- addCode("PREFLIGHT_DEPENDER_A23_UNCLASSIFIED");
78
- }
79
- if (depender.dataSnapshotOk !== true) {
80
- addCode("PREFLIGHT_DEPENDER_DATA_SNAPSHOT_MISSING");
81
- }
82
- }
83
- }
84
- const previousSpk = candidate.previousSpk;
85
- if (!isRecord(previousSpk) || previousSpk.available !== true) {
86
- addCode("PREFLIGHT_PREVIOUS_SPK_UNAVAILABLE");
87
- }
88
- else if (!isSha256(previousSpk.sha256)) {
89
- addCode("PREFLIGHT_PREVIOUS_SPK_DIGEST_INVALID");
90
- }
91
- if (candidate.canonicalizeGateSatisfied !== true) {
92
- addCode("PREFLIGHT_CANONICALIZE_GATE_UNSATISFIED");
93
- }
94
- const catalogEntry = candidate.catalogEntry;
95
- if (!isRecord(catalogEntry) || !isNonEmptyString(catalogEntry.version)) {
96
- addCode("PREFLIGHT_CATALOG_VERSION_INVALID");
97
- }
98
- else if (!isRecord(broker) || !isNonEmptyString(broker.version)) {
99
- // The broker version gate is already reported above; without both version
100
- // strings there is no safe comparison to perform.
101
- addCode("PREFLIGHT_VERSION_COMPARISON_INVALID");
102
- }
103
- else {
104
- const comparison = comparePackageVersions(catalogEntry.version, broker.version);
105
- if (!Number.isFinite(comparison)) {
106
- addCode("PREFLIGHT_VERSION_COMPARISON_INVALID");
107
- }
108
- else if (comparison <= 0) {
109
- addCode("PREFLIGHT_CATALOG_VERSION_NOT_NEWER");
110
- }
111
- }
112
- return decisionFromCodes(codes);
113
- }
114
- /**
115
- * The 4552 path is entered only for a numeric DSM error and a non-empty,
116
- * fully identified running baseline inventory.
117
- */
118
- export function evaluate4552Branch(input) {
119
- const candidate = isRecord(input) ? input : {};
120
- const codes = [];
121
- if (classifyDsmUpgradeResponse(candidate.response) !== "error-4552") {
122
- codes.push("PREFLIGHT_RESPONSE_NOT_4552");
123
- }
124
- const dependers = candidate.dependers;
125
- if (!Array.isArray(dependers) ||
126
- dependers.length === 0 ||
127
- dependers.some((depender) => !isRunningBaseline(depender))) {
128
- codes.push("PREFLIGHT_DEPENDER_INVENTORY_INCOMPLETE");
129
- }
130
- return decisionFromCodes(codes);
131
- }
132
- function decisionFromCodes(codes) {
133
- return codes.length === 0 ? { ok: true } : { ok: false, codes };
134
- }
135
- function isRunningBaseline(value) {
136
- return (isRecord(value) &&
137
- isNonEmptyString(value.packageIdentity) &&
138
- isNonEmptyString(value.version) &&
139
- value.status === "running" &&
140
- value.running === true);
141
- }
142
- function isConsentDialogEvidence(value) {
143
- const dialog = value.consentDialog;
144
- return (isRecord(dialog) &&
145
- Array.isArray(dialog.dependers) &&
146
- dialog.dependers.every((depender) => typeof depender === "string"));
147
- }
148
- function isRecord(value) {
149
- return value !== null && typeof value === "object" && !Array.isArray(value);
150
- }
151
- function isNonEmptyString(value) {
152
- return typeof value === "string" && value.length > 0;
153
- }
154
- function isSha256(value) {
155
- return typeof value === "string" && /^[0-9a-fA-F]{64}$/.test(value);
156
- }
@@ -1,5 +0,0 @@
1
- import type { ProjectRoot } from "../discovery.js";
2
- export declare function digestString(value: string): string;
3
- export declare function digestDirectory(root: string): string;
4
- export declare function digestProjectContract(project: ProjectRoot): string;
5
- export declare function digestProjectBundle(project: ProjectRoot): string;
@@ -1,63 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- export function digestString(value) {
6
- return createHash("sha256").update(value).digest("hex");
7
- }
8
- export function digestDirectory(root) {
9
- const hash = createHash("sha256");
10
- for (const relative of walkFiles(root)) {
11
- hash.update(relative);
12
- hash.update("\0");
13
- hash.update(readFileSync(join(root, relative)));
14
- hash.update("\0");
15
- }
16
- return hash.digest("hex");
17
- }
18
- export function digestProjectContract(project) {
19
- return digestString(readFileSync(project.contractPath, "utf8"));
20
- }
21
- export function digestProjectBundle(project) {
22
- const staging = mkdtempSync(join(tmpdir(), "syno-bundle-digest-"));
23
- try {
24
- const packageDir = join(staging, "package");
25
- mkdirSync(packageDir, { recursive: true });
26
- // Runtime members are whichever of the two exist; validate already refuses
27
- // a project that has both or neither. The Broker computes the same set
28
- // (packages/broker/src/digest.ts), so the two digests have to agree.
29
- if (existsSync(project.composePath)) {
30
- cpSync(project.composePath, join(packageDir, "compose.yaml"));
31
- }
32
- if (project.nativePath && existsSync(project.nativePath)) {
33
- cpSync(project.nativePath, join(packageDir, "native.yaml"));
34
- }
35
- cpSync(project.contractPath, join(packageDir, "synology-app.yaml"));
36
- const htmlDir = join(project.root, "html");
37
- if (existsSync(htmlDir)) {
38
- cpSync(htmlDir, join(packageDir, "html"), { recursive: true });
39
- }
40
- return digestDirectory(packageDir);
41
- }
42
- finally {
43
- rmSync(staging, { recursive: true, force: true });
44
- }
45
- }
46
- function walkFiles(root, prefix = "") {
47
- const files = [];
48
- for (const entry of readdirSync(root).sort(comparePosixPaths)) {
49
- const relative = prefix ? `${prefix}/${entry}` : entry;
50
- const absolute = join(root, entry);
51
- const stat = statSync(absolute);
52
- if (stat.isDirectory()) {
53
- files.push(...walkFiles(absolute, relative));
54
- }
55
- else if (stat.isFile()) {
56
- files.push(relative);
57
- }
58
- }
59
- return files;
60
- }
61
- function comparePosixPaths(left, right) {
62
- return left < right ? -1 : left > right ? 1 : 0;
63
- }
@@ -1,41 +0,0 @@
1
- import type { SharePermissionRow } from "./share-permission.js";
2
- import type { AttestationKind, HostInstallRecord, HostOidcCompatSettings, NasHost, PackageRoute } from "./types.js";
3
- export type SharePermissionRowInput = {
4
- name: string;
5
- } & Partial<Omit<SharePermissionRow, "name">>;
6
- export interface FakeNasHostOptions {
7
- curated?: string[];
8
- dsmOrigin?: string;
9
- homesPath?: string;
10
- installationId?: string;
11
- shareNames?: string[];
12
- shares?: Record<string, string>;
13
- /**
14
- * SYNO.Core.Share.Permission rows per Share, as partials -- every flag
15
- * defaults to false, matching a row DSM grants nothing on. Omit the whole
16
- * option to model a host that cannot answer the permission question.
17
- */
18
- sharePermissions?: Record<string, {
19
- users: SharePermissionRowInput[];
20
- groups: SharePermissionRowInput[];
21
- }>;
22
- /** Group membership per DSM user, for share-permission resolution. */
23
- userGroups?: Record<string, string[]>;
24
- installedEnv?: Record<string, Record<string, string>>;
25
- diagnostics?: {
26
- dsmResidue?: import("./types.js").DsmResidueInventory;
27
- packageRoute?: PackageRoute;
28
- isPackageOnly?: boolean;
29
- [key: string]: unknown;
30
- };
31
- /** Omit to model an older Broker without the OIDC settings endpoint. */
32
- oidcCompat?: HostOidcCompatSettings;
33
- }
34
- export declare function createFakeNasHost(options?: FakeNasHostOptions): NasHost & {
35
- installs: HostInstallRecord[];
36
- attestations: Set<string>;
37
- attestationInfo(packageIdentity: string): {
38
- attestationKind: AttestationKind;
39
- } | undefined;
40
- seedInstalled(packageIdentity: string): void;
41
- };
@@ -1,174 +0,0 @@
1
- import { webStationAlias } from "../contract/web-launch.js";
2
- function sharePermissionRow(input) {
3
- return {
4
- is_admin: false,
5
- is_writable: false,
6
- is_readonly: false,
7
- is_deny: false,
8
- is_custom: false,
9
- ...input,
10
- };
11
- }
12
- export function createFakeNasHost(options = {}) {
13
- const dsmOrigin = options.dsmOrigin ?? "http://nas.example:5000";
14
- const installationId = options.installationId ?? "fake-installation";
15
- const curated = new Set(options.curated ?? []);
16
- const installs = [];
17
- const localAttestations = new Map();
18
- const installed = new Set();
19
- const openUrls = new Map();
20
- const shares = { ...(options.shares ?? {}) };
21
- const shareNames = options.shareNames
22
- ? [...options.shareNames]
23
- : Object.keys(shares).length > 0
24
- ? Object.keys(shares)
25
- : ["docker", "home", "photo"];
26
- const installedEnv = Object.fromEntries(Object.entries(options.installedEnv ?? {}).map(([packageId, env]) => [packageId, { ...env }]));
27
- const host = {
28
- dsmOrigin,
29
- installationId,
30
- installs,
31
- attestations: new Set(),
32
- markCurated(packageIdentity) {
33
- curated.add(packageIdentity);
34
- localAttestations.set(packageIdentity, "app-package");
35
- },
36
- seedInstalled(packageIdentity) {
37
- installed.add(packageIdentity);
38
- },
39
- async resolveSharePath(logicalName) {
40
- return shares[logicalName];
41
- },
42
- async listShareNames() {
43
- return [...shareNames];
44
- },
45
- ...(options.sharePermissions
46
- ? {
47
- async listSharePermissions(logicalName) {
48
- const listing = options.sharePermissions?.[logicalName];
49
- if (!listing) {
50
- return undefined;
51
- }
52
- return {
53
- users: listing.users.map(sharePermissionRow),
54
- groups: listing.groups.map(sharePermissionRow),
55
- };
56
- },
57
- }
58
- : {}),
59
- ...(options.userGroups
60
- ? {
61
- async listUserGroups(userName) {
62
- return options.userGroups?.[userName];
63
- },
64
- }
65
- : {}),
66
- async resolveHomesPath() {
67
- return options.homesPath;
68
- },
69
- async getInstalledProjectEnv(packageIdentity) {
70
- const env = installedEnv[packageIdentity];
71
- return env ? { ...env } : undefined;
72
- },
73
- attestationInfo(packageIdentity) {
74
- const kind = localAttestations.get(packageIdentity) ?? (installed.has(packageIdentity) ? "local" : "none");
75
- return kind === "none" ? undefined : { attestationKind: kind };
76
- },
77
- async requestAttestation(input) {
78
- if (curated.has(input.packageIdentity) && !input.allowCuratedDowngrade) {
79
- const error = new Error("Curated deploy refused");
80
- error.code = "CURATED_DEPLOY_REFUSED";
81
- throw error;
82
- }
83
- if (curated.has(input.packageIdentity) && input.allowCuratedDowngrade) {
84
- localAttestations.set(input.packageIdentity, "local");
85
- }
86
- else {
87
- localAttestations.set(input.packageIdentity, "local");
88
- }
89
- const digest = `${input.packageIdentity}:${input.bundleDigest}:${input.contractDigest}`;
90
- host.attestations.add(input.packageIdentity);
91
- return {
92
- kind: "local",
93
- attestationDigest: digest,
94
- token: `fake-local-attestation.${input.packageIdentity}`,
95
- };
96
- },
97
- async ensurePackageSource() { },
98
- async installFromCatalog(input) {
99
- installs.push({
100
- packageId: input.packageId,
101
- version: input.version,
102
- source: "package-center",
103
- extraValues: { ...(input.extraValues ?? {}) },
104
- });
105
- installed.add(input.packageId);
106
- installedEnv[input.packageId] = {
107
- ...(installedEnv[input.packageId] ?? {}),
108
- ...(input.extraValues ?? {}),
109
- };
110
- openUrls.set(input.packageId, `${new URL(dsmOrigin).protocol}//${new URL(dsmOrigin).hostname}/${webStationAlias(input.packageId)}/`);
111
- if (!localAttestations.has(input.packageId)) {
112
- localAttestations.set(input.packageId, "local");
113
- }
114
- },
115
- async installFromLocalSpk(input) {
116
- installs.push({
117
- packageId: input.packageId,
118
- version: input.version,
119
- source: "local-spk",
120
- extraValues: { ...(input.extraValues ?? {}) },
121
- });
122
- installed.add(input.packageId);
123
- installedEnv[input.packageId] = {
124
- ...(installedEnv[input.packageId] ?? {}),
125
- ...(input.extraValues ?? {}),
126
- };
127
- openUrls.set(input.packageId, `${new URL(dsmOrigin).protocol}//${new URL(dsmOrigin).hostname}/${webStationAlias(input.packageId)}/`);
128
- if (!localAttestations.has(input.packageId)) {
129
- localAttestations.set(input.packageId, "local");
130
- }
131
- },
132
- async getInstalledPackageVersion(packageIdentity) {
133
- const latest = [...installs].reverse().find((entry) => entry.packageId === packageIdentity);
134
- return latest?.version;
135
- },
136
- async getAttestationInfo(packageIdentity) {
137
- return {
138
- packageIdentity,
139
- attestationKind: localAttestations.get(packageIdentity) ?? (installed.has(packageIdentity) ? "local" : "none"),
140
- developmentInstance: packageIdentity.endsWith(".dev"),
141
- openUrl: openUrls.get(packageIdentity),
142
- readiness: installed.has(packageIdentity) ? "RUNNING" : "NOT_INSTALLED",
143
- };
144
- },
145
- async isPackageInstalled(packageIdentity) {
146
- return installed.has(packageIdentity);
147
- },
148
- async fetchContainerLogs(packageIdentity) {
149
- if (!installed.has(packageIdentity)) {
150
- return [];
151
- }
152
- return [`[${packageIdentity}] container ready`];
153
- },
154
- async getDsmDiagnostics() {
155
- return options.diagnostics;
156
- },
157
- async getOidcCompatSettings() {
158
- if (!options.oidcCompat) {
159
- return undefined;
160
- }
161
- return {
162
- enabled: options.oidcCompat.enabled,
163
- origin: { ...options.oidcCompat.origin },
164
- };
165
- },
166
- async smokeRequireLogin() {
167
- return { ok: true, username: "admin" };
168
- },
169
- };
170
- for (const packageId of curated) {
171
- localAttestations.set(packageId, "app-package");
172
- }
173
- return host;
174
- }
@@ -1,2 +0,0 @@
1
- import type { BrokerBootstrap } from "@synopackageland/dev-sdk/node";
2
- export declare function writeMockBrokerBootstrap(projectRoot: string, bootstrap: BrokerBootstrap): string;
@@ -1,8 +0,0 @@
1
- import { mkdirSync, writeFileSync } from "node:fs";
2
- import { dirname, resolve } from "node:path";
3
- export function writeMockBrokerBootstrap(projectRoot, bootstrap) {
4
- const path = resolve(projectRoot, ".synopkgland", "mock-broker.json");
5
- mkdirSync(dirname(path), { recursive: true });
6
- writeFileSync(path, `${JSON.stringify(bootstrap, null, 2)}\n`, "utf8");
7
- return path;
8
- }
@@ -1,60 +0,0 @@
1
- import { createReadStream } from "node:fs";
2
- export interface FileItem {
3
- name: string;
4
- type: "file" | "directory";
5
- path: string;
6
- size?: number;
7
- }
8
- export declare class FileStoreError extends Error {
9
- readonly code: string;
10
- readonly status: number;
11
- constructor(code: string, status: number, message: string);
12
- }
13
- export interface MockFileStoreOptions {
14
- filesRoot?: string;
15
- recycleBinDisabled?: boolean;
16
- }
17
- export interface DownloadResult {
18
- buffer?: Buffer;
19
- stream?: ReturnType<typeof createReadStream>;
20
- size: number;
21
- totalSize: number;
22
- }
23
- export declare class MockFileStore {
24
- private readonly filesRoot?;
25
- private readonly recycleBinDisabled;
26
- private readonly treeRoot;
27
- constructor(options?: MockFileStoreOptions);
28
- list(rawPath: string): FileItem[];
29
- stat(rawPath: string): FileItem;
30
- download(rawPath: string, range?: {
31
- start: number;
32
- end?: number;
33
- }): DownloadResult;
34
- upload(rawPath: string, body: Buffer, overwrite?: boolean): void;
35
- mkdir(rawPath: string): void;
36
- rename(rawPath: string, rawTo: string, overwrite?: boolean): void;
37
- move(rawPath: string, rawTo: string, overwrite?: boolean): void;
38
- copy(rawPath: string, rawTo: string, overwrite?: boolean): void;
39
- trash(rawPath: string): void;
40
- private resolveListPath;
41
- private resolveOperationPath;
42
- private listMemory;
43
- private statMemory;
44
- private downloadMemory;
45
- private uploadMemory;
46
- private mkdirMemory;
47
- private moveMemory;
48
- private copyMemory;
49
- private trashMemory;
50
- private listMapped;
51
- private statMapped;
52
- private downloadMapped;
53
- private uploadMapped;
54
- private mkdirMapped;
55
- private moveMapped;
56
- private copyMapped;
57
- private trashMapped;
58
- }
59
- /** @deprecated Use MockFileStore.list instead */
60
- export declare function listFakeFiles(path: string, filesRoot?: string): FileItem[];