@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,18 +0,0 @@
1
- import type { BuildLedger, BuildLedgerSnapshot } from "./build-ledger.js";
2
- export declare const BUILD_LEDGER_FILENAME = "package-build-ledger.jsonl";
3
- export declare const BUILD_LEDGER_PATH_ENV = "SYNOPKGLAND_BUILD_LEDGER_PATH";
4
- export interface ResolveBuildLedgerPathOptions {
5
- env?: NodeJS.Dict<string>;
6
- cwd?: string;
7
- communityAppsRoot?: string;
8
- }
9
- export declare function defaultBuildLedgerPath(communityAppsRoot: string): string;
10
- export declare function resolveBuildLedgerPath(options?: ResolveBuildLedgerPathOptions): string;
11
- export declare class FileBuildLedger implements BuildLedger {
12
- readonly ledgerPath: string;
13
- constructor(ledgerPath: string);
14
- allocate(packageIdentity: string): number;
15
- markPublishFailed(packageIdentity: string, build: number): void;
16
- snapshot(packageIdentity: string): BuildLedgerSnapshot;
17
- }
18
- export declare function runFileBuildLedgerCli(argv: string[], env?: NodeJS.Dict<string>): void;
@@ -1,268 +0,0 @@
1
- /**
2
- * Durable append-only Package Build ledger for protected-main merge CI.
3
- *
4
- * Default path: synopkgland-community-apps/ci/package-build-ledger.jsonl
5
- * (override with SYNOPKGLAND_BUILD_LEDGER_PATH). Concurrent allocate() is
6
- * serialized with an exclusive lockfile next to the ledger. Do not commit live
7
- * numbers; Git history / release artifacts remain disaster recovery.
8
- *
9
- * This module does not sign, upload artifacts, or mutate Package Source index.
10
- */
11
- import { randomUUID } from "node:crypto";
12
- import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeSync, } from "node:fs";
13
- import { dirname, join, resolve } from "node:path";
14
- import { fileURLToPath, pathToFileURL } from "node:url";
15
- import { resolveCommunityAppsRoot } from "./community-path.js";
16
- export const BUILD_LEDGER_FILENAME = "package-build-ledger.jsonl";
17
- export const BUILD_LEDGER_PATH_ENV = "SYNOPKGLAND_BUILD_LEDGER_PATH";
18
- const LOCK_RETRY_MS = 15;
19
- const LOCK_TIMEOUT_MS = 30_000;
20
- const LOCK_FRESH_MS = 2_000;
21
- export function defaultBuildLedgerPath(communityAppsRoot) {
22
- return join(communityAppsRoot, "ci", BUILD_LEDGER_FILENAME);
23
- }
24
- export function resolveBuildLedgerPath(options = {}) {
25
- const env = options.env ?? process.env;
26
- const fromEnv = env[BUILD_LEDGER_PATH_ENV]?.trim();
27
- if (fromEnv) {
28
- return resolve(fromEnv);
29
- }
30
- const cwd = options.cwd ?? process.cwd();
31
- const communityRoot = options.communityAppsRoot ?? resolveCommunityAppsRoot(cwd);
32
- if (communityRoot) {
33
- return defaultBuildLedgerPath(communityRoot);
34
- }
35
- return resolve(cwd, "synopkgland-community-apps", "ci", BUILD_LEDGER_FILENAME);
36
- }
37
- export class FileBuildLedger {
38
- ledgerPath;
39
- constructor(ledgerPath) {
40
- this.ledgerPath = ledgerPath;
41
- }
42
- allocate(packageIdentity) {
43
- requirePackageIdentity(packageIdentity);
44
- return withLedgerLock(this.ledgerPath, () => {
45
- const records = readRecords(this.ledgerPath);
46
- const build = lastAllocated(records, packageIdentity) + 1;
47
- appendRecord(this.ledgerPath, {
48
- packageIdentity,
49
- build,
50
- event: "allocated",
51
- at: new Date().toISOString(),
52
- });
53
- return build;
54
- });
55
- }
56
- markPublishFailed(packageIdentity, build) {
57
- requirePackageIdentity(packageIdentity);
58
- withLedgerLock(this.ledgerPath, () => {
59
- appendRecord(this.ledgerPath, {
60
- packageIdentity,
61
- build,
62
- event: "publish-failed",
63
- at: new Date().toISOString(),
64
- });
65
- });
66
- }
67
- snapshot(packageIdentity) {
68
- requirePackageIdentity(packageIdentity);
69
- return withLedgerLock(this.ledgerPath, () => snapshotFromRecords(readRecords(this.ledgerPath), packageIdentity));
70
- }
71
- }
72
- export function runFileBuildLedgerCli(argv, env = process.env) {
73
- const command = argv[2];
74
- const ledger = new FileBuildLedger(resolveBuildLedgerPath({ env }));
75
- if (command === "allocate") {
76
- const packageIdentity = requirePackageIdentity(argv[3]);
77
- const build = ledger.allocate(packageIdentity);
78
- process.stdout.write(`${JSON.stringify({ packageIdentity, build })}\n`);
79
- return;
80
- }
81
- if (command === "mark-failed") {
82
- const packageIdentity = requirePackageIdentity(argv[3]);
83
- const build = Number(argv[4]);
84
- if (!Number.isInteger(build) || build < 1) {
85
- throw new Error("usage: file-build-ledger mark-failed <packageIdentity> <build>");
86
- }
87
- ledger.markPublishFailed(packageIdentity, build);
88
- process.stdout.write(`${JSON.stringify({ packageIdentity, build, event: "publish-failed" })}\n`);
89
- return;
90
- }
91
- if (command === "snapshot") {
92
- const packageIdentity = requirePackageIdentity(argv[3]);
93
- process.stdout.write(`${JSON.stringify({ packageIdentity, ...ledger.snapshot(packageIdentity) })}\n`);
94
- return;
95
- }
96
- throw new Error("usage: file-build-ledger <allocate|mark-failed|snapshot> <packageIdentity> [build]");
97
- }
98
- function requirePackageIdentity(packageIdentity) {
99
- if (typeof packageIdentity !== "string" || packageIdentity.trim().length === 0) {
100
- throw new Error("package identity is required");
101
- }
102
- return packageIdentity;
103
- }
104
- function snapshotFromRecords(records, packageIdentity) {
105
- const consumed = records
106
- .filter((record) => record.packageIdentity === packageIdentity && record.event === "allocated")
107
- .map((record) => record.build);
108
- return {
109
- nextBuild: lastAllocated(records, packageIdentity),
110
- consumed,
111
- };
112
- }
113
- function lastAllocated(records, packageIdentity) {
114
- let max = 0;
115
- for (const record of records) {
116
- if (record.packageIdentity === packageIdentity && record.event === "allocated" && record.build > max) {
117
- max = record.build;
118
- }
119
- }
120
- return max;
121
- }
122
- function readRecords(ledgerPath) {
123
- if (!existsSync(ledgerPath)) {
124
- return [];
125
- }
126
- const text = readFileSync(ledgerPath, "utf8");
127
- const records = [];
128
- for (const [index, line] of text.split("\n").entries()) {
129
- if (line.trim().length === 0) {
130
- continue;
131
- }
132
- try {
133
- records.push(JSON.parse(line));
134
- }
135
- catch (error) {
136
- throw new Error(`invalid ledger record at ${ledgerPath}:${index + 1}: ${String(error)}`);
137
- }
138
- }
139
- return records;
140
- }
141
- function appendRecord(ledgerPath, record) {
142
- mkdirSync(dirname(ledgerPath), { recursive: true });
143
- const fd = openSync(ledgerPath, "a");
144
- try {
145
- writeSync(fd, `${JSON.stringify(record)}\n`);
146
- fsyncSync(fd);
147
- }
148
- finally {
149
- closeSync(fd);
150
- }
151
- }
152
- function withLedgerLock(ledgerPath, fn) {
153
- const lockPath = `${ledgerPath}.lock`;
154
- mkdirSync(dirname(ledgerPath), { recursive: true });
155
- const held = acquireExclusiveLock(lockPath);
156
- try {
157
- return fn();
158
- }
159
- finally {
160
- releaseLock(held.fd, lockPath, held.token);
161
- }
162
- }
163
- function acquireExclusiveLock(lockPath) {
164
- const started = Date.now();
165
- for (;;) {
166
- const token = randomUUID();
167
- try {
168
- const fd = openSync(lockPath, "wx");
169
- writeSync(fd, `${process.pid} ${token}\n`);
170
- fsyncSync(fd);
171
- return { fd, token };
172
- }
173
- catch (error) {
174
- if (!isAlreadyExists(error)) {
175
- throw error;
176
- }
177
- if (Date.now() - started > LOCK_TIMEOUT_MS) {
178
- throw new Error(`timed out acquiring ledger lock: ${lockPath}`);
179
- }
180
- stealIfStale(lockPath);
181
- sleepSync(LOCK_RETRY_MS);
182
- }
183
- }
184
- }
185
- function stealIfStale(lockPath) {
186
- try {
187
- const ageMs = Date.now() - statSync(lockPath).mtimeMs;
188
- if (ageMs < LOCK_FRESH_MS) {
189
- return;
190
- }
191
- const parsed = parseLockOwner(readFileSync(lockPath, "utf8"));
192
- if (parsed && pidIsAlive(parsed.pid) && ageMs < LOCK_TIMEOUT_MS) {
193
- return;
194
- }
195
- unlinkSync(lockPath);
196
- }
197
- catch (error) {
198
- if (!isNotFound(error)) {
199
- return;
200
- }
201
- }
202
- }
203
- function parseLockOwner(raw) {
204
- const match = raw.trim().match(/^(\d+)\s+(\S+)$/);
205
- if (!match) {
206
- return null;
207
- }
208
- const pid = Number(match[1]);
209
- if (!Number.isInteger(pid) || pid <= 0) {
210
- return null;
211
- }
212
- return { pid, token: match[2] };
213
- }
214
- function releaseLock(fd, lockPath, token) {
215
- try {
216
- closeSync(fd);
217
- }
218
- finally {
219
- try {
220
- const parsed = parseLockOwner(readFileSync(lockPath, "utf8"));
221
- if (parsed?.token === token) {
222
- unlinkSync(lockPath);
223
- }
224
- }
225
- catch {
226
- // Best effort; a leftover lock is stolen if the holder is gone.
227
- }
228
- }
229
- }
230
- function pidIsAlive(pid) {
231
- try {
232
- process.kill(pid, 0);
233
- return true;
234
- }
235
- catch {
236
- return false;
237
- }
238
- }
239
- function sleepSync(ms) {
240
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
241
- }
242
- function isAlreadyExists(error) {
243
- return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
244
- }
245
- function isNotFound(error) {
246
- return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
247
- }
248
- function invokedAsCli() {
249
- const entry = process.argv[1];
250
- if (!entry) {
251
- return false;
252
- }
253
- try {
254
- return resolve(fileURLToPath(import.meta.url)) === resolve(entry);
255
- }
256
- catch {
257
- return pathToFileURL(resolve(entry)).href === import.meta.url;
258
- }
259
- }
260
- if (invokedAsCli()) {
261
- try {
262
- runFileBuildLedgerCli(process.argv);
263
- }
264
- catch (error) {
265
- process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
266
- process.exit(1);
267
- }
268
- }
@@ -1,25 +0,0 @@
1
- export interface CreatePullRequestOptions {
2
- title: string;
3
- body: string;
4
- base: string;
5
- head: string;
6
- draft?: boolean;
7
- }
8
- export interface PullRequestRef {
9
- url: string;
10
- number: number;
11
- }
12
- export interface GitHubCli {
13
- createPullRequest(options: CreatePullRequestOptions): Promise<PullRequestRef>;
14
- }
15
- export interface GitOps {
16
- currentBranch(): string;
17
- checkoutNewBranch(branchName: string): void;
18
- checkoutExisting(branchName: string): void;
19
- add(paths: string[]): void;
20
- commit(message: string, paths: string[]): void;
21
- push(branchName: string, setUpstream: boolean): void;
22
- hasChanges(paths: string[]): boolean;
23
- }
24
- export declare function createExecGitOps(cwd: string): GitOps;
25
- export declare function createExecGitHubCli(cwd: string, repo?: string): GitHubCli;
@@ -1,85 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { communityAppsGitHubRepo, githubToken } from "./github-repo.js";
3
- export function createExecGitOps(cwd) {
4
- const run = (args) => execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
5
- return {
6
- currentBranch() {
7
- return run(["rev-parse", "--abbrev-ref", "HEAD"]);
8
- },
9
- checkoutNewBranch(branchName) {
10
- run(["checkout", "-b", branchName]);
11
- },
12
- checkoutExisting(branchName) {
13
- run(["checkout", branchName]);
14
- },
15
- add(paths) {
16
- if (paths.length === 0) {
17
- return;
18
- }
19
- run(["add", "--", ...paths]);
20
- },
21
- commit(message, paths) {
22
- if (paths.length === 0) {
23
- throw new Error("git commit requires a pathspec");
24
- }
25
- run(["commit", "-m", message, "--", ...paths]);
26
- },
27
- push(branchName, setUpstream) {
28
- const args = ["push"];
29
- if (setUpstream) {
30
- args.push("-u", "origin", branchName);
31
- }
32
- else {
33
- args.push("origin", branchName);
34
- }
35
- run(args);
36
- },
37
- hasChanges(paths) {
38
- if (paths.length === 0) {
39
- return false;
40
- }
41
- const status = run(["status", "--porcelain", "--", ...paths]);
42
- return status.length > 0;
43
- },
44
- };
45
- }
46
- export function createExecGitHubCli(cwd, repo) {
47
- const targetRepo = repo ?? communityAppsGitHubRepo();
48
- return {
49
- async createPullRequest(options) {
50
- const token = githubToken();
51
- const args = [
52
- "pr",
53
- "create",
54
- "--repo",
55
- targetRepo,
56
- "--title",
57
- options.title,
58
- "--body",
59
- options.body,
60
- "--base",
61
- options.base,
62
- "--head",
63
- options.head,
64
- ];
65
- if (options.draft) {
66
- args.push("--draft");
67
- }
68
- const stdout = execFileSync("gh", args, {
69
- cwd,
70
- encoding: "utf8",
71
- stdio: ["ignore", "pipe", "pipe"],
72
- env: {
73
- ...process.env,
74
- ...(token ? { GH_TOKEN: token, GITHUB_TOKEN: token } : {}),
75
- },
76
- }).trim();
77
- const url = stdout.split(/\s+/).pop() ?? stdout;
78
- const match = url.match(/\/pull\/(\d+)\/?$/);
79
- return {
80
- url,
81
- number: match ? Number(match[1]) : 0,
82
- };
83
- },
84
- };
85
- }
@@ -1,8 +0,0 @@
1
- export declare const DEFAULT_GITHUB_OWNER = "synopackageland";
2
- export declare const COMMUNITY_APPS_GITHUB_REPO = "synopkgland-community-apps";
3
- export declare const PLATFORM_GITHUB_REPO = "syno-package-land";
4
- export declare function githubOwner(env?: NodeJS.ProcessEnv): string;
5
- export declare function communityAppsGitHubRepo(env?: NodeJS.ProcessEnv): string;
6
- export declare function communityAppsGitHubUrl(env?: NodeJS.ProcessEnv): string;
7
- export declare function platformGitHubUrl(env?: NodeJS.ProcessEnv): string;
8
- export declare function githubToken(env?: NodeJS.ProcessEnv): string | undefined;
@@ -1,21 +0,0 @@
1
- export const DEFAULT_GITHUB_OWNER = "synopackageland";
2
- export const COMMUNITY_APPS_GITHUB_REPO = "synopkgland-community-apps";
3
- export const PLATFORM_GITHUB_REPO = "syno-package-land";
4
- export function githubOwner(env = process.env) {
5
- const fromEnv = env.GITHUB_OWNER?.trim();
6
- return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_GITHUB_OWNER;
7
- }
8
- export function communityAppsGitHubRepo(env = process.env) {
9
- const repo = env.GITHUB_COMMUNITY_APPS_REPO?.trim() || COMMUNITY_APPS_GITHUB_REPO;
10
- return `${githubOwner(env)}/${repo}`;
11
- }
12
- export function communityAppsGitHubUrl(env = process.env) {
13
- return `https://github.com/${communityAppsGitHubRepo(env)}`;
14
- }
15
- export function platformGitHubUrl(env = process.env) {
16
- return `https://github.com/${githubOwner(env)}/${PLATFORM_GITHUB_REPO}`;
17
- }
18
- export function githubToken(env = process.env) {
19
- const token = env.GH_TOKEN?.trim() || env.GITHUB_TOKEN?.trim();
20
- return token && token.length > 0 ? token : undefined;
21
- }
@@ -1,60 +0,0 @@
1
- import { type CuratedReleasePublisher } from "@synopackageland/package-source/publish-spk";
2
- import { type PlatformServiceReleaseErrorCode, type PlatformAttestationSigner } from "../attestation/platform-service.js";
3
- export declare const SYNOPKGLAND_SOURCE_REVISION_ENV = "SYNOPKGLAND_SOURCE_REVISION";
4
- export declare const PLATFORM_SERVICE_OS_MIN_VER = "7.2-69057";
5
- export type PlatformReleaseErrorCode = "PLATFORM_RELEASE_USAGE" | "PLATFORM_BROKER_DIR_INVALID" | "PLATFORM_APP_PROJECT_FORBIDDEN" | "PLATFORM_ARTIFACT_INPUT_FORBIDDEN" | "PLATFORM_BUILD_INVALID" | "PLATFORM_SOURCE_REVISION_MISSING" | "PLATFORM_BUILDER_UNAVAILABLE" | "PLATFORM_BUILD_FAILED" | "PLATFORM_RELEASE_FAILED" | PlatformServiceReleaseErrorCode;
6
- /** Errors owned by the platform release entry point, separate from signer errors. */
7
- export declare class PlatformReleaseError extends Error {
8
- readonly code: PlatformReleaseErrorCode;
9
- constructor(code: PlatformReleaseErrorCode, detail?: string);
10
- }
11
- export interface PlatformServiceReleaseBaseline {
12
- sourceVersion: string;
13
- baselineBuild: number;
14
- }
15
- export interface PlatformServiceBuildOptions {
16
- outputPath: string;
17
- releaseVersion: string;
18
- }
19
- /** The broker-side module contract used by production and by release tests. */
20
- export interface PlatformServiceBuilder {
21
- buildBrokerSpk(options: PlatformServiceBuildOptions): unknown | Promise<unknown>;
22
- brokerReleaseBaseline(): PlatformServiceReleaseBaseline;
23
- }
24
- export interface PlatformServiceReleaseOptions {
25
- brokerDir: string;
26
- build: number;
27
- sourceRevision: string;
28
- signer: PlatformAttestationSigner;
29
- publisher: CuratedReleasePublisher;
30
- /** Tests may inject a builder; production loads the broker-side module. */
31
- builder?: PlatformServiceBuilder;
32
- }
33
- export interface PlatformServiceReleaseResult {
34
- packageIdentity: string;
35
- packageBuild: number;
36
- version: string;
37
- artifactKey: string;
38
- artifactDigest: string;
39
- attestationKey: string;
40
- attestationDigest: string;
41
- }
42
- export interface PlatformServiceReleaseCliDependencies {
43
- /** Test seams; production creates these from the environment and R2 target. */
44
- signer?: PlatformAttestationSigner;
45
- publisher?: CuratedReleasePublisher;
46
- builder?: PlatformServiceBuilder;
47
- /** Optional output seams keep CLI tests independent of process-global streams. */
48
- writeStdout?: (line: string) => void;
49
- writeStderr?: (line: string) => void;
50
- }
51
- /**
52
- * Build, attest and publish one immutable Broker SPK release.
53
- *
54
- * All cheap input gates run before the broker builder is loaded or invoked.
55
- * Publication is delegated to the package-source three-phase boundary, which
56
- * enforces artifact -> attestation -> index ordering.
57
- */
58
- export declare function releasePlatformService(options: PlatformServiceReleaseOptions): Promise<PlatformServiceReleaseResult>;
59
- /** Run the trusted platform release verb and emit exactly one line. */
60
- export declare function runPlatformServiceReleaseCli(argv?: string[], env?: NodeJS.Dict<string>, dependencies?: PlatformServiceReleaseCliDependencies): Promise<number>;