@synopackageland/cli 0.4.1 → 0.5.3

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 (699) hide show
  1. package/README.md +7 -3
  2. package/dist/authorization-sdk.d.ts +5 -0
  3. package/dist/authorization-sdk.js +5 -0
  4. package/dist/build-spk/delete-app-data.d.ts +27 -7
  5. package/dist/build-spk/delete-app-data.js +35 -34
  6. package/dist/build-spk/dsm-arch.d.ts +6 -1
  7. package/dist/build-spk/dsm-arch.js +25 -1
  8. package/dist/build-spk/dsm-version.d.ts +14 -0
  9. package/dist/build-spk/dsm-version.js +47 -0
  10. package/dist/build-spk/gateway.d.ts +31 -0
  11. package/dist/build-spk/gateway.js +55 -0
  12. package/dist/build-spk/generator.d.ts +5 -0
  13. package/dist/build-spk/generator.js +103 -107
  14. package/dist/build-spk/install-wizard.d.ts +20 -0
  15. package/dist/build-spk/install-wizard.js +76 -0
  16. package/dist/build-spk/native-lifecycle.d.ts +5 -0
  17. package/dist/build-spk/native-lifecycle.js +12 -2
  18. package/dist/build-spk/resource-worker.d.ts +9 -4
  19. package/dist/build-spk/resource-worker.js +15 -6
  20. package/dist/build-spk/share-combobox.d.ts +3 -0
  21. package/dist/build-spk/share-combobox.js +27 -0
  22. package/dist/build-spk/uninstall-wizard.d.ts +14 -0
  23. package/dist/build-spk/uninstall-wizard.js +33 -0
  24. package/dist/build-spk/wizard-i18n.d.ts +18 -0
  25. package/dist/build-spk/wizard-i18n.js +38 -0
  26. package/dist/build-spk/wizard-messages.d.ts +388 -0
  27. package/dist/build-spk/wizard-messages.js +387 -0
  28. package/dist/cli.js +132 -32
  29. package/dist/compose/analyze.d.ts +20 -0
  30. package/dist/compose/analyze.js +75 -11
  31. package/dist/contract/validate.js +33 -1
  32. package/dist/contract/web-launch.d.ts +22 -0
  33. package/dist/contract/web-launch.js +37 -0
  34. package/dist/deploy/deploy.d.ts +3 -0
  35. package/dist/deploy/deploy.js +11 -2
  36. package/dist/error-registry.js +62 -3
  37. package/dist/host/dsm-port-profile.d.ts +1 -1
  38. package/dist/host/dsm-port-profile.js +1 -1
  39. package/dist/host/open-url.d.ts +2 -0
  40. package/dist/host/open-url.js +4 -1
  41. package/dist/images/pin.d.ts +52 -0
  42. package/dist/images/pin.js +249 -0
  43. package/dist/init.d.ts +27 -3
  44. package/dist/init.js +126 -16
  45. package/dist/inspect.d.ts +3 -0
  46. package/dist/inspect.js +15 -3
  47. package/dist/standalone/authorization-window.d.ts +2 -0
  48. package/dist/standalone/authorization-window.js +28 -0
  49. package/dist/standalone/authorization.d.ts +48 -0
  50. package/dist/standalone/authorization.js +116 -0
  51. package/dist/standalone/background.d.ts +21 -0
  52. package/dist/standalone/background.js +52 -0
  53. package/dist/standalone/binary.d.ts +1 -0
  54. package/dist/standalone/binary.js +1 -1
  55. package/dist/standalone/build.d.ts +2 -0
  56. package/dist/standalone/build.js +54 -10
  57. package/dist/standalone/dsm-window.js +10 -3
  58. package/dist/standalone/helper-inventory.d.ts +15 -0
  59. package/dist/standalone/helper-inventory.js +9 -0
  60. package/dist/standalone/helper.d.ts +1 -0
  61. package/dist/standalone/helper.js +29 -11
  62. package/dist/standalone/host-adapter.d.ts +1 -1
  63. package/dist/standalone/host-adapter.js +33 -15
  64. package/dist/standalone/host-file-navigation.d.ts +7 -0
  65. package/dist/standalone/host-file-navigation.js +172 -0
  66. package/dist/standalone/inspect-helper.js +21 -6
  67. package/dist/standalone/inspect-spk.d.ts +1 -1
  68. package/dist/standalone/inspect-spk.js +211 -7
  69. package/dist/standalone/job-diagnostics.d.ts +1 -0
  70. package/dist/standalone/job-diagnostics.js +49 -0
  71. package/dist/standalone/lifecycle-helper.d.ts +1 -1
  72. package/dist/standalone/lifecycle-helper.js +2 -2
  73. package/dist/standalone/lifecycle.d.ts +1 -1
  74. package/dist/standalone/lifecycle.js +14 -4
  75. package/dist/standalone/manifest.d.ts +15 -2
  76. package/dist/standalone/manifest.js +37 -6
  77. package/dist/standalone/native-layout.d.ts +74 -0
  78. package/dist/standalone/native-layout.js +318 -0
  79. package/dist/standalone/resource.d.ts +11 -0
  80. package/dist/standalone/resource.js +13 -0
  81. package/dist/standalone/root-ops.d.ts +2 -0
  82. package/dist/standalone/root-ops.js +10 -0
  83. package/dist/standalone/root-window.d.ts +3 -1
  84. package/dist/standalone/root-window.js +156 -38
  85. package/dist/standalone/shared-folder.d.ts +39 -0
  86. package/dist/standalone/shared-folder.js +141 -0
  87. package/dist/standalone/spk.d.ts +4 -0
  88. package/dist/standalone/spk.js +47 -3
  89. package/dist/standalone/worker-contract-json.d.ts +8 -0
  90. package/dist/standalone/worker-contract-json.js +141 -0
  91. package/dist/standalone/worker-contract.d.ts +189 -0
  92. package/dist/standalone/worker-contract.js +175 -0
  93. package/dist/standalone/worker-registry.d.ts +40 -0
  94. package/dist/standalone/worker-registry.js +167 -0
  95. package/dist/templates/_authorization/main.go +104 -0
  96. package/dist/templates/_authorization/main_test.go +35 -0
  97. package/dist/templates/_daemon/go.mod +2 -0
  98. package/dist/templates/_gateway/auth.go +101 -0
  99. package/dist/templates/_gateway/auth_test.go +216 -0
  100. package/dist/templates/_gateway/cgi.go +133 -0
  101. package/dist/templates/_gateway/cgi_test.go +156 -0
  102. package/dist/templates/_gateway/csrf.go +73 -0
  103. package/dist/templates/_gateway/csrf_test.go +155 -0
  104. package/dist/templates/_gateway/directory.go +108 -0
  105. package/dist/templates/_gateway/directory_test.go +202 -0
  106. package/dist/templates/_gateway/gateway.go +412 -0
  107. package/dist/templates/_gateway/gateway_test.go +676 -0
  108. package/dist/templates/_gateway/go.mod +3 -0
  109. package/dist/templates/_gateway/groups.go +66 -0
  110. package/dist/templates/_gateway/main.go +45 -0
  111. package/dist/templates/binary/synology-app.yaml +1 -1
  112. package/dist/templates/compose-import/compose.yaml +1 -1
  113. package/dist/templates/compose-import/synology-app.yaml +1 -1
  114. package/dist/templates/hello-files/compose.yaml +1 -1
  115. package/dist/templates/hello-files/synology-app.yaml +1 -1
  116. package/dist/templates/native-go/README.md +118 -5
  117. package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  118. package/dist/templates/native-go/backend/cmd/app/main.go +25 -6
  119. package/dist/templates/native-go/backend/cmd/app/sdk_main.go +62 -0
  120. package/dist/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  121. package/dist/templates/native-go/backend/cmd/helper/main.go +27 -1
  122. package/dist/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  123. package/dist/templates/native-go/backend/go.mod +5 -3
  124. package/dist/templates/native-go/backend/go.sum +4 -4
  125. package/dist/templates/native-go/backend/internal/api/registry.go +17 -6
  126. package/dist/templates/native-go/backend/internal/api/server.go +7 -1
  127. package/dist/templates/native-go/backend/internal/app/authorization_none.go +5 -0
  128. package/dist/templates/native-go/backend/internal/app/background.go +270 -0
  129. package/dist/templates/native-go/backend/internal/app/background_none.go +8 -0
  130. package/dist/templates/native-go/backend/internal/app/background_owner.go +59 -0
  131. package/dist/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  132. package/dist/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  133. package/dist/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  134. package/dist/templates/native-go/backend/internal/app/background_test.go +346 -0
  135. package/dist/templates/native-go/backend/internal/app/integration_state.go +16 -0
  136. package/dist/templates/native-go/backend/internal/app/migrations.go +41 -0
  137. package/dist/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  138. package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  139. package/dist/templates/native-go/backend/internal/app/routes.go +22 -5
  140. package/dist/templates/native-go/backend/internal/app/routes_test.go +20 -3
  141. package/dist/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  142. package/dist/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  143. package/dist/templates/native-go/backend/internal/app/sdk_routes.go +177 -0
  144. package/dist/templates/native-go/backend/internal/app/session_files.go +15 -0
  145. package/dist/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  146. package/dist/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  147. package/dist/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  148. package/dist/templates/native-go/backend/internal/background/access.go +57 -0
  149. package/dist/templates/native-go/backend/internal/background/owner_test.go +126 -0
  150. package/dist/templates/native-go/backend/internal/background/runner.go +185 -0
  151. package/dist/templates/native-go/backend/internal/background/runner_test.go +209 -0
  152. package/dist/templates/native-go/backend/internal/background/schedule.go +300 -0
  153. package/dist/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  154. package/dist/templates/native-go/backend/internal/background/store.go +807 -0
  155. package/dist/templates/native-go/backend/internal/background/store_test.go +407 -0
  156. package/dist/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  157. package/dist/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  158. package/dist/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  159. package/dist/templates/native-go/backend/internal/filestation/client.go +251 -0
  160. package/dist/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  161. package/dist/templates/native-go/backend/internal/filestation/doc.go +4 -0
  162. package/dist/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  163. package/dist/templates/native-go/backend/internal/filestation/repository.go +207 -0
  164. package/dist/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  165. package/dist/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  166. package/dist/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  167. package/dist/templates/native-go/backend/internal/filestation/service.go +254 -0
  168. package/dist/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  169. package/dist/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  170. package/dist/templates/native-go/backend/internal/filestation/write.go +72 -0
  171. package/dist/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  172. package/dist/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  173. package/dist/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  174. package/dist/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  175. package/dist/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  176. package/dist/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  177. package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  178. package/dist/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  179. package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  180. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  181. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  182. package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  183. package/dist/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  184. package/dist/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  185. package/dist/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  186. package/dist/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  187. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  188. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  189. package/dist/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  190. package/dist/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  191. package/dist/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  192. package/dist/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  193. package/dist/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  194. package/dist/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  195. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  196. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  197. package/dist/templates/native-go/backend/internal/helper/management.go +86 -0
  198. package/dist/templates/native-go/backend/internal/helper/observation.go +42 -2
  199. package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  200. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  201. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  202. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  203. package/dist/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  204. package/dist/templates/native-go/backend/internal/helper/purge.go +115 -0
  205. package/dist/templates/native-go/backend/internal/helper/purge_test.go +59 -0
  206. package/dist/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  207. package/dist/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  208. package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  209. package/dist/templates/native-go/backend/internal/helper/revoke.go +109 -0
  210. package/dist/templates/native-go/backend/internal/helper/revoke_test.go +121 -0
  211. package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  212. package/dist/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  213. package/dist/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  214. package/dist/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  215. package/dist/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  216. package/dist/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  217. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  218. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  219. package/dist/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  220. package/dist/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  221. package/dist/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  222. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  223. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  224. package/dist/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  225. package/dist/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  226. package/dist/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  227. package/dist/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  228. package/dist/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  229. package/dist/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  230. package/dist/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  231. package/dist/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  232. package/dist/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  233. package/dist/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  234. package/dist/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  235. package/dist/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  236. package/dist/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  237. package/dist/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  238. package/dist/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  239. package/dist/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  240. package/dist/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  241. package/dist/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  242. package/dist/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  243. package/dist/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  244. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  245. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  246. package/dist/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  247. package/dist/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  248. package/dist/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  249. package/dist/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  250. package/dist/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  251. package/dist/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  252. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  253. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  254. package/dist/templates/native-go/backend/internal/helper/sdk_server_linux.go +161 -0
  255. package/dist/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  256. package/dist/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  257. package/dist/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  258. package/dist/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  259. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  260. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  261. package/dist/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  262. package/dist/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  263. package/dist/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  264. package/dist/templates/native-go/backend/internal/helper/server_linux.go +14 -2
  265. package/dist/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  266. package/dist/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  267. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  268. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  269. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  270. package/dist/templates/native-go/backend/internal/helper/status.go +22 -13
  271. package/dist/templates/native-go/backend/internal/helper/status_test.go +45 -0
  272. package/dist/templates/native-go/backend/internal/helper/supervision.go +1 -1
  273. package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  274. package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  275. package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  276. package/dist/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  277. package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  278. package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  279. package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  280. package/dist/templates/native-go/dsm-package.yaml +2 -2
  281. package/dist/templates/native-go-authorization/backend/internal/app/authorization.go +298 -0
  282. package/dist/templates/native-go-authorization/backend/internal/app/authorization_test.go +96 -0
  283. package/dist/templates/native-go-authorization/frontend/src/authorization/AuthorizationGate.vue +89 -0
  284. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/de.json +36 -0
  285. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/en.json +36 -0
  286. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/es.json +36 -0
  287. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/fr.json +36 -0
  288. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/index.ts +15 -0
  289. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/it.json +36 -0
  290. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/ja.json +36 -0
  291. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/ko.json +36 -0
  292. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/zh-CN.json +36 -0
  293. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/zh-TW.json +36 -0
  294. package/dist/templates/native-go-authorization/frontend/test/authorization-preview.html +14 -0
  295. package/dist/templates/native-go-authorization/frontend/test/authorization.test.ts +59 -0
  296. package/dist/templates/native-go-background/BACKGROUND.md +111 -0
  297. package/dist/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  298. package/dist/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  299. package/dist/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  300. package/dist/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  301. package/dist/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  302. package/dist/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  303. package/dist/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  304. package/dist/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  305. package/dist/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  306. package/dist/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  307. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  308. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  309. package/dist/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  310. package/dist/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  311. package/dist/templates/native-go-background/frontend/test/background.test.ts +179 -0
  312. package/dist/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  313. package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  314. package/dist/templates/native-go-vue/README.md +38 -7
  315. package/dist/templates/native-go-vue/frontend/DESIGN.md +15 -3
  316. package/dist/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  317. package/dist/templates/native-go-vue/frontend/README-M2.md +64 -0
  318. package/dist/templates/native-go-vue/frontend/package-lock.json +5 -4
  319. package/dist/templates/native-go-vue/frontend/package.json +1 -1
  320. package/dist/templates/native-go-vue/frontend/src/App.vue +39 -11
  321. package/dist/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  322. package/dist/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  323. package/dist/templates/native-go-vue/frontend/src/context.ts +3 -0
  324. package/dist/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  325. package/dist/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  326. package/dist/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  327. package/dist/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  328. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  329. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  330. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  331. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  332. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  333. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  334. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  335. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  336. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  337. package/dist/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  338. package/dist/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  339. package/dist/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  340. package/dist/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  341. package/dist/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  342. package/dist/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  343. package/dist/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  344. package/dist/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  345. package/dist/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  346. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  347. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  348. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  349. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  350. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  351. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  352. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  353. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  354. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  355. package/dist/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  356. package/dist/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  357. package/dist/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  358. package/dist/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  359. package/dist/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  360. package/dist/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  361. package/dist/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  362. package/dist/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  363. package/dist/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  364. package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  365. package/dist/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  366. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  367. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  368. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  369. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  370. package/dist/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  371. package/dist/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  372. package/dist/templates/native-go-vue/frontend/src/style.css +2 -6
  373. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  374. package/dist/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  375. package/dist/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  376. package/dist/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  377. package/dist/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  378. package/dist/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  379. package/dist/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  380. package/dist/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  381. package/dist/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  382. package/dist/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  383. package/dist/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  384. package/dist/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  385. package/dist/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  386. package/dist/templates/native-go-vue/frontend/vite.config.ts +2 -2
  387. package/dist/types.d.ts +1 -1
  388. package/dist/validate.js +6 -3
  389. package/package.json +5 -2
  390. package/schema/synology-app.schema.json +19 -0
  391. package/skills/reference/create.md +6 -2
  392. package/templates/_authorization/main.go +104 -0
  393. package/templates/_authorization/main_test.go +35 -0
  394. package/templates/_daemon/go.mod +2 -0
  395. package/templates/_gateway/auth.go +101 -0
  396. package/templates/_gateway/auth_test.go +216 -0
  397. package/templates/_gateway/cgi.go +133 -0
  398. package/templates/_gateway/cgi_test.go +156 -0
  399. package/templates/_gateway/csrf.go +73 -0
  400. package/templates/_gateway/csrf_test.go +155 -0
  401. package/templates/_gateway/directory.go +108 -0
  402. package/templates/_gateway/directory_test.go +202 -0
  403. package/templates/_gateway/gateway.go +412 -0
  404. package/templates/_gateway/gateway_test.go +676 -0
  405. package/templates/_gateway/go.mod +3 -0
  406. package/templates/_gateway/groups.go +66 -0
  407. package/templates/_gateway/main.go +45 -0
  408. package/templates/binary/synology-app.yaml +1 -1
  409. package/templates/compose-import/compose.yaml +1 -1
  410. package/templates/compose-import/synology-app.yaml +1 -1
  411. package/templates/hello-files/compose.yaml +1 -1
  412. package/templates/hello-files/synology-app.yaml +1 -1
  413. package/templates/native-go/README.md +118 -5
  414. package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  415. package/templates/native-go/backend/cmd/app/main.go +25 -6
  416. package/templates/native-go/backend/cmd/app/sdk_main.go +62 -0
  417. package/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  418. package/templates/native-go/backend/cmd/helper/main.go +27 -1
  419. package/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  420. package/templates/native-go/backend/go.mod +5 -3
  421. package/templates/native-go/backend/go.sum +4 -4
  422. package/templates/native-go/backend/internal/api/registry.go +17 -6
  423. package/templates/native-go/backend/internal/api/server.go +7 -1
  424. package/templates/native-go/backend/internal/app/authorization_none.go +5 -0
  425. package/templates/native-go/backend/internal/app/background.go +270 -0
  426. package/templates/native-go/backend/internal/app/background_none.go +8 -0
  427. package/templates/native-go/backend/internal/app/background_owner.go +59 -0
  428. package/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  429. package/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  430. package/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  431. package/templates/native-go/backend/internal/app/background_test.go +346 -0
  432. package/templates/native-go/backend/internal/app/integration_state.go +16 -0
  433. package/templates/native-go/backend/internal/app/migrations.go +41 -0
  434. package/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  435. package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  436. package/templates/native-go/backend/internal/app/routes.go +22 -5
  437. package/templates/native-go/backend/internal/app/routes_test.go +20 -3
  438. package/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  439. package/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  440. package/templates/native-go/backend/internal/app/sdk_routes.go +177 -0
  441. package/templates/native-go/backend/internal/app/session_files.go +15 -0
  442. package/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  443. package/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  444. package/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  445. package/templates/native-go/backend/internal/background/access.go +57 -0
  446. package/templates/native-go/backend/internal/background/owner_test.go +126 -0
  447. package/templates/native-go/backend/internal/background/runner.go +185 -0
  448. package/templates/native-go/backend/internal/background/runner_test.go +209 -0
  449. package/templates/native-go/backend/internal/background/schedule.go +300 -0
  450. package/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  451. package/templates/native-go/backend/internal/background/store.go +807 -0
  452. package/templates/native-go/backend/internal/background/store_test.go +407 -0
  453. package/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  454. package/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  455. package/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  456. package/templates/native-go/backend/internal/filestation/client.go +251 -0
  457. package/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  458. package/templates/native-go/backend/internal/filestation/doc.go +4 -0
  459. package/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  460. package/templates/native-go/backend/internal/filestation/repository.go +207 -0
  461. package/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  462. package/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  463. package/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  464. package/templates/native-go/backend/internal/filestation/service.go +254 -0
  465. package/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  466. package/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  467. package/templates/native-go/backend/internal/filestation/write.go +72 -0
  468. package/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  469. package/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  470. package/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  471. package/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  472. package/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  473. package/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  474. package/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  475. package/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  476. package/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  477. package/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  478. package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  479. package/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  480. package/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  481. package/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  482. package/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  483. package/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  484. package/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  485. package/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  486. package/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  487. package/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  488. package/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  489. package/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  490. package/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  491. package/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  492. package/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  493. package/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  494. package/templates/native-go/backend/internal/helper/management.go +86 -0
  495. package/templates/native-go/backend/internal/helper/observation.go +42 -2
  496. package/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  497. package/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  498. package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  499. package/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  500. package/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  501. package/templates/native-go/backend/internal/helper/purge.go +115 -0
  502. package/templates/native-go/backend/internal/helper/purge_test.go +59 -0
  503. package/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  504. package/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  505. package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  506. package/templates/native-go/backend/internal/helper/revoke.go +109 -0
  507. package/templates/native-go/backend/internal/helper/revoke_test.go +121 -0
  508. package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  509. package/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  510. package/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  511. package/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  512. package/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  513. package/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  514. package/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  515. package/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  516. package/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  517. package/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  518. package/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  519. package/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  520. package/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  521. package/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  522. package/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  523. package/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  524. package/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  525. package/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  526. package/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  527. package/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  528. package/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  529. package/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  530. package/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  531. package/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  532. package/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  533. package/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  534. package/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  535. package/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  536. package/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  537. package/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  538. package/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  539. package/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  540. package/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  541. package/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  542. package/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  543. package/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  544. package/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  545. package/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  546. package/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  547. package/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  548. package/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  549. package/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  550. package/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  551. package/templates/native-go/backend/internal/helper/sdk_server_linux.go +161 -0
  552. package/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  553. package/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  554. package/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  555. package/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  556. package/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  557. package/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  558. package/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  559. package/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  560. package/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  561. package/templates/native-go/backend/internal/helper/server_linux.go +14 -2
  562. package/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  563. package/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  564. package/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  565. package/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  566. package/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  567. package/templates/native-go/backend/internal/helper/status.go +22 -13
  568. package/templates/native-go/backend/internal/helper/status_test.go +45 -0
  569. package/templates/native-go/backend/internal/helper/supervision.go +1 -1
  570. package/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  571. package/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  572. package/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  573. package/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  574. package/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  575. package/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  576. package/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  577. package/templates/native-go/dsm-package.yaml +2 -2
  578. package/templates/native-go-authorization/backend/internal/app/authorization.go +298 -0
  579. package/templates/native-go-authorization/backend/internal/app/authorization_test.go +96 -0
  580. package/templates/native-go-authorization/frontend/src/authorization/AuthorizationGate.vue +89 -0
  581. package/templates/native-go-authorization/frontend/src/authorization/i18n/de.json +36 -0
  582. package/templates/native-go-authorization/frontend/src/authorization/i18n/en.json +36 -0
  583. package/templates/native-go-authorization/frontend/src/authorization/i18n/es.json +36 -0
  584. package/templates/native-go-authorization/frontend/src/authorization/i18n/fr.json +36 -0
  585. package/templates/native-go-authorization/frontend/src/authorization/i18n/index.ts +15 -0
  586. package/templates/native-go-authorization/frontend/src/authorization/i18n/it.json +36 -0
  587. package/templates/native-go-authorization/frontend/src/authorization/i18n/ja.json +36 -0
  588. package/templates/native-go-authorization/frontend/src/authorization/i18n/ko.json +36 -0
  589. package/templates/native-go-authorization/frontend/src/authorization/i18n/zh-CN.json +36 -0
  590. package/templates/native-go-authorization/frontend/src/authorization/i18n/zh-TW.json +36 -0
  591. package/templates/native-go-authorization/frontend/test/authorization-preview.html +14 -0
  592. package/templates/native-go-authorization/frontend/test/authorization.test.ts +59 -0
  593. package/templates/native-go-background/BACKGROUND.md +111 -0
  594. package/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  595. package/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  596. package/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  597. package/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  598. package/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  599. package/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  600. package/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  601. package/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  602. package/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  603. package/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  604. package/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  605. package/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  606. package/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  607. package/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  608. package/templates/native-go-background/frontend/test/background.test.ts +179 -0
  609. package/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  610. package/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  611. package/templates/native-go-vue/README.md +38 -7
  612. package/templates/native-go-vue/frontend/DESIGN.md +15 -3
  613. package/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  614. package/templates/native-go-vue/frontend/README-M2.md +64 -0
  615. package/templates/native-go-vue/frontend/package-lock.json +5 -4
  616. package/templates/native-go-vue/frontend/package.json +1 -1
  617. package/templates/native-go-vue/frontend/src/App.vue +39 -11
  618. package/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  619. package/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  620. package/templates/native-go-vue/frontend/src/context.ts +3 -0
  621. package/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  622. package/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  623. package/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  624. package/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  625. package/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  626. package/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  627. package/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  628. package/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  629. package/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  630. package/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  631. package/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  632. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  633. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  634. package/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  635. package/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  636. package/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  637. package/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  638. package/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  639. package/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  640. package/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  641. package/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  642. package/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  643. package/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  644. package/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  645. package/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  646. package/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  647. package/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  648. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  649. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  650. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  651. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  652. package/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  653. package/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  654. package/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  655. package/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  656. package/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  657. package/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  658. package/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  659. package/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  660. package/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  661. package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  662. package/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  663. package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  664. package/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  665. package/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  666. package/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  667. package/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  668. package/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  669. package/templates/native-go-vue/frontend/src/style.css +2 -6
  670. package/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  671. package/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  672. package/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  673. package/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  674. package/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  675. package/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  676. package/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  677. package/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  678. package/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  679. package/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  680. package/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  681. package/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  682. package/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  683. package/templates/native-go-vue/frontend/vite.config.ts +2 -2
  684. package/dist/templates/hello-web/compose.yaml +0 -21
  685. package/dist/templates/hello-web/html/app.js +0 -1
  686. package/dist/templates/hello-web/html/index.html +0 -13
  687. package/dist/templates/hello-web/synology-app.yaml +0 -13
  688. package/dist/templates/hello-web-page/compose.yaml +0 -21
  689. package/dist/templates/hello-web-page/html/app.js +0 -1
  690. package/dist/templates/hello-web-page/html/index.html +0 -13
  691. package/dist/templates/hello-web-page/synology-app.yaml +0 -13
  692. package/templates/hello-web/compose.yaml +0 -21
  693. package/templates/hello-web/html/app.js +0 -1
  694. package/templates/hello-web/html/index.html +0 -13
  695. package/templates/hello-web/synology-app.yaml +0 -13
  696. package/templates/hello-web-page/compose.yaml +0 -21
  697. package/templates/hello-web-page/html/app.js +0 -1
  698. package/templates/hello-web-page/html/index.html +0 -13
  699. package/templates/hello-web-page/synology-app.yaml +0 -13
package/dist/init.js CHANGED
@@ -1,14 +1,23 @@
1
1
  import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
2
2
  import { basename, join, relative } from "node:path";
3
3
  import { templatesRoot } from "./template-paths.js";
4
+ import { resolveMinDsm, assertContainerMinDsm, DEFAULT_MIN_DSM, isDsmAtLeast } from "./build-spk/dsm-version.js";
5
+ import { readSharedFolder } from "./standalone/shared-folder.js";
4
6
  const TEMPLATE_NAMES = [
5
- "hello-web",
6
- "hello-web-page",
7
7
  "hello-files",
8
8
  "compose-import",
9
9
  "binary",
10
10
  "native-go",
11
11
  ];
12
+ /** Templates whose App runs through the DSM docker-project resource worker. */
13
+ const CONTAINER_TEMPLATES = [
14
+ "hello-files",
15
+ "compose-import",
16
+ ];
17
+ /** The container templates need DSM 7.2.1 or later; native-go and binary need 7.1. */
18
+ export function isContainerTemplate(template) {
19
+ return CONTAINER_TEMPLATES.includes(template);
20
+ }
12
21
  export function isTemplateName(value) {
13
22
  return TEMPLATE_NAMES.includes(value);
14
23
  }
@@ -17,10 +26,14 @@ export function listTemplates() {
17
26
  }
18
27
  /**
19
28
  * native-go --privilege root: files laid over the native-go template, and the
20
- * files they replace.
29
+ * files they replace. An integration's helper brings its own root tasks, so
30
+ * the whoami example is not added to it.
21
31
  */
22
32
  const ROOT_OVERLAY = "native-go-root";
23
33
  const ROOT_REPLACED = ["backend/internal/app/root_none.go"];
34
+ /** native-go --background: overlay with the routes, the UI panel and the docs. */
35
+ const BACKGROUND_OVERLAY = "native-go-background";
36
+ const BACKGROUND_REPLACED = ["backend/internal/app/background_none.go"];
24
37
  /** Templates whose identity is filled in at init (placeholders in these files). */
25
38
  const SUBSTITUTED = {
26
39
  "native-go": ["dsm-package.yaml", "README.md"],
@@ -42,22 +55,52 @@ function defaultDisplayName(dir) {
42
55
  function templateFiles(root, dir = root) {
43
56
  return readdirSync(dir).flatMap((name) => {
44
57
  const path = join(dir, name);
45
- return statSync(path).isDirectory() ? templateFiles(root, path) : [relative(root, path)];
58
+ if (statSync(path).isDirectory()) {
59
+ return isTemplateBuildArtifact(path) ? [] : templateFiles(root, path);
60
+ }
61
+ return [relative(root, path)];
46
62
  });
47
63
  }
48
64
  function targetName(file) {
49
65
  return RENAMED[file] ?? file;
50
66
  }
67
+ /** native-go defaults to the Vue shell; the CLI and the library entry point agree. */
68
+ function resolvedUi(template, options) {
69
+ return template === "native-go" ? options.ui ?? "vue" : options.ui;
70
+ }
71
+ /**
72
+ * Copy one template tree into a project. A template directory may carry a local
73
+ * `node_modules`/`dist` from developing the template itself; those never belong
74
+ * to a generated project (and would otherwise shadow the project's own install).
75
+ */
76
+ export function copyTemplateTree(source, target) {
77
+ cpSync(source, target, { recursive: true, filter: (path) => !isTemplateBuildArtifact(path) });
78
+ }
79
+ function isTemplateBuildArtifact(path) {
80
+ const name = basename(path);
81
+ return name === "node_modules" || name === "dist";
82
+ }
51
83
  export function initFromTemplate(template, targetDir, options = {}) {
52
84
  const source = join(templatesRoot(), template);
53
85
  if (!existsSync(source)) {
54
86
  throw new Error(`找不到模板:${template}`);
55
87
  }
88
+ const minDsm = options.minDsm === undefined ? undefined : resolveMinDsm(options.minDsm);
89
+ if (minDsm !== undefined && isContainerTemplate(template)) {
90
+ assertContainerMinDsm(minDsm);
91
+ }
56
92
  const substitutions = substitutionsFor(template, targetDir, options);
57
- const privilege = options.privilege ?? (options.integration ? "root" : "none");
93
+ const ui = resolvedUi(template, options);
94
+ const privilege = options.privilege ?? "none";
95
+ if (privilege === "root" && minDsm !== undefined && !isDsmAtLeast(minDsm, DEFAULT_MIN_DSM)) {
96
+ throw new Error(`[MIN_DSM_INVALID] root templates require DSM ${DEFAULT_MIN_DSM} or later.`);
97
+ }
98
+ const rootExample = privilege === "root" && !options.integration;
58
99
  const overlays = [
59
- ...(privilege === "root" ? [ROOT_OVERLAY] : []),
60
- ...(options.ui === "vue" ? ["native-go-vue"] : []),
100
+ ...(rootExample ? [ROOT_OVERLAY] : []),
101
+ ...(ui === "vue" ? ["native-go-vue"] : []),
102
+ ...(privilege === "root" ? ["native-go-authorization"] : []),
103
+ ...(options.background ? [BACKGROUND_OVERLAY] : []),
61
104
  ...(options.integration ? ["native-go-integration"] : []),
62
105
  ...(options.integration === "better-auth" ? ["native-go-better-auth"] : []),
63
106
  ].map(name => join(templatesRoot(), name));
@@ -65,25 +108,29 @@ export function initFromTemplate(template, targetDir, options = {}) {
65
108
  // terms are an unconditional part of a generated project.
66
109
  const shared = join(templatesRoot(), "_shared");
67
110
  const files = [...templateFiles(source), "LICENSES/TEMPLATE.txt", ...overlays.flatMap(root => templateFiles(root)),
68
- ...(options.ui === "vue" ? ["frontend/third-party-notices.mjs"] : []),
111
+ ...(ui === "vue" ? ["frontend/third-party-notices.mjs"] : []),
69
112
  ...(options.integration === "better-auth" ? ["node/third-party-notices.mjs", ...templateFiles(join(shared, 'notice-overrides')).map(file => `node/notice-overrides/${file}`)] : [])];
70
113
  const collisions = files.map(targetName).filter((file) => existsSync(join(targetDir, file)));
71
114
  if (collisions.length > 0) {
72
115
  throw new Error(`[INIT_TARGET_NOT_EMPTY] ${targetDir} 已有 ${collisions.join(", ")};init 不會覆蓋既有檔案。請改用空目錄。`);
73
116
  }
74
117
  mkdirSync(targetDir, { recursive: true });
75
- cpSync(source, targetDir, { recursive: true });
118
+ copyTemplateTree(source, targetDir);
76
119
  mkdirSync(join(targetDir, "LICENSES"), { recursive: true });
77
120
  cpSync(join(shared, "LICENSES/TEMPLATE.txt"), join(targetDir, "LICENSES/TEMPLATE.txt"));
78
121
  for (const overlay of overlays)
79
- cpSync(overlay, targetDir, { recursive: true });
80
- for (const dir of [...(options.ui === "vue" ? ["frontend"] : []), ...(options.integration === "better-auth" ? ["node"] : [])]) {
122
+ copyTemplateTree(overlay, targetDir);
123
+ for (const dir of [...(ui === "vue" ? ["frontend"] : []), ...(options.integration === "better-auth" ? ["node"] : [])]) {
81
124
  cpSync(join(shared, "third-party-notices.mjs"), join(targetDir, dir, "third-party-notices.mjs"));
82
125
  }
83
126
  if (options.integration === "better-auth")
84
127
  cpSync(join(shared, 'notice-overrides'), join(targetDir, 'node/notice-overrides'), { recursive: true });
85
128
  if (privilege === "root")
129
+ rmSync(join(targetDir, "backend/internal/app/authorization_none.go"));
130
+ if (rootExample)
86
131
  ROOT_REPLACED.forEach(file => rmSync(join(targetDir, file)));
132
+ if (options.background)
133
+ BACKGROUND_REPLACED.forEach(file => rmSync(join(targetDir, file)));
87
134
  for (const [from, to] of Object.entries(RENAMED)) {
88
135
  if (files.includes(from)) {
89
136
  renameSync(join(targetDir, from), join(targetDir, to));
@@ -97,11 +144,53 @@ export function initFromTemplate(template, targetDir, options = {}) {
97
144
  }
98
145
  writeFileSync(path, text);
99
146
  }
100
- if (options.ui === "vue") {
147
+ if (minDsm) {
148
+ const manifest = join(targetDir, template === "native-go" ? "dsm-package.yaml" : "synology-app.yaml");
149
+ writeFileSync(manifest, readFileSync(manifest, "utf8").replace(/^os_min_ver:.*$/m, `os_min_ver: "${minDsm}"`));
150
+ }
151
+ if (ui === "vue") {
101
152
  const manifest = join(targetDir, "dsm-package.yaml");
102
153
  writeFileSync(manifest, readFileSync(manifest, "utf8").replace(" dir: ui", " dir: frontend/dist\n build: {cwd: frontend, command: [npm, run, build]}"));
103
154
  rmSync(join(targetDir, "ui"), { recursive: true });
104
155
  }
156
+ if (privilege === "root" && ui === "vue") {
157
+ for (const entry of ["App.vue", "SDKApp.vue"]) {
158
+ const app = join(targetDir, "frontend/src", entry);
159
+ writeFileSync(app, readFileSync(app, "utf8")
160
+ .replace("import AppShell from './shell/AppShell.vue'", "import AuthorizationGate from './authorization/AuthorizationGate.vue'\nimport AppShell from './shell/AppShell.vue'")
161
+ .replace('<AppShell v-model="page"', '<AuthorizationGate :ctx="ctx" @ready="authorizationReady"><AppShell v-model="page"')
162
+ .replace('onMounted(async()=>{\n props.ctx.reopen(()=>{if(!disposed) void refresh()})\n await refresh()', 'async function authorizationReady(){\n await refresh()')
163
+ .replace('})\nonUnmounted', '}\nonMounted(()=>{if(!props.ctx.authorization){props.ctx.reopen(()=>{if(!disposed) void refresh()});void authorizationReady()}})\nonUnmounted')
164
+ .replace('</AppShell>', '</AppShell></AuthorizationGate>'));
165
+ }
166
+ for (const entry of ["main.ts", "sdk-main.ts"]) {
167
+ const main = join(targetDir, "frontend/src", entry);
168
+ writeFileSync(main, readFileSync(main, "utf8").replace('{mount: typeof mount}', '{mount: typeof mount; authorizationUI?: boolean}').replace('{mount}', '{mount, authorizationUI: true}'));
169
+ }
170
+ for (const file of ["apps.test.ts", "nas-ui.test.ts", "shell-ui.test.ts", "shell-sdk.test.ts", "picker-wire.test.ts"]) {
171
+ const test = join(targetDir, "frontend/test", file);
172
+ const source = readFileSync(test, "utf8");
173
+ writeFileSync(test, source + "\n// Test the application surface independently; authorization has its own contract suite.\nvi.mock('../src/authorization/AuthorizationGate.vue',()=>({default:{template:'<slot />'}}))\n");
174
+ }
175
+ }
176
+ if (ui !== "vue")
177
+ rmSync(join(targetDir, "frontend"), { recursive: true, force: true });
178
+ if (options.background) {
179
+ const manifest = join(targetDir, "dsm-package.yaml");
180
+ writeFileSync(manifest, readFileSync(manifest, "utf8") + "\nbackground:\n worker: sha256-v1\n");
181
+ const app = join(targetDir, "frontend/src/App.vue");
182
+ writeFileSync(app, readFileSync(app, "utf8")
183
+ .replace("import NasUnavailable from './nas/NasUnavailable.vue'\n", "import NasUnavailable from './nas/NasUnavailable.vue'\nimport BackgroundPanel from './background/BackgroundPanel.vue'\n")
184
+ .replace(" <!-- BACKGROUND_PANEL -->", " <BackgroundPanel v-if=\"app\" :key=\"app.user\" :ctx=\"ctx\" />"));
185
+ }
186
+ if (options.fileStation) {
187
+ const manifest = join(targetDir, "dsm-package.yaml");
188
+ writeFileSync(manifest, readFileSync(manifest, "utf8") + "\nfileStation: session\n");
189
+ }
190
+ if (options.sharedFolder) {
191
+ const manifest = join(targetDir, "dsm-package.yaml");
192
+ writeFileSync(manifest, readFileSync(manifest, "utf8") + sharedFolderYaml(options.sharedFolder));
193
+ }
105
194
  if (options.integration === "better-auth")
106
195
  rmSync(join(targetDir, "backend/internal/app/identity_none.go"));
107
196
  if (options.integration) {
@@ -113,12 +202,31 @@ export function initFromTemplate(template, targetDir, options = {}) {
113
202
  writeFileSync(routes, readFileSync(routes, "utf8").replace("return append(routes, cfg.rootRoutes()...)", "routes = append(routes, cfg.integrationRoutes()...)\n\treturn append(routes, cfg.rootRoutes()...)"));
114
203
  }
115
204
  }
205
+ /** The `install.sharedFolder` block, validated by the same reader build-spk uses. */
206
+ function sharedFolderYaml(options) {
207
+ const folder = { mode: options.mode, key: options.key ?? "shared", ...(options.name === undefined ? {} : { name: options.name }), permission: options.permission ?? "rw" };
208
+ const errors = [];
209
+ if (!readSharedFolder({ sharedFolder: folder }, e => errors.push(e.message))) {
210
+ throw new Error(`[INIT_SHARED_FOLDER_INVALID] ${errors.join(" ")}`);
211
+ }
212
+ return `\ninstall:\n sharedFolder:\n${Object.entries(folder).map(([k, v]) => ` ${k}: ${v}\n`).join("")}`;
213
+ }
116
214
  function substitutionsFor(template, targetDir, options) {
215
+ const ui = resolvedUi(template, options);
117
216
  if (options.privilege !== undefined && template !== "native-go") {
118
217
  throw new Error("[INIT_PRIVILEGE_UNSUPPORTED] --privilege 只適用於 -t native-go。");
119
218
  }
120
219
  if ((options.ui !== undefined || options.integration !== undefined) && template !== "native-go")
121
220
  throw new Error("[INIT_OPTIONS_UNSUPPORTED] --ui/--integration 只適用於 native-go。");
221
+ if (options.background && (template !== "native-go" || ui !== "vue" || options.privilege === "root" || options.integration === "better-auth"))
222
+ throw new Error("[INIT_BACKGROUND_OPTIONS] --background 只適用於 -t native-go 的 Vue UI(--ui vue,預設;--ui plain 不適用),且不能與 --privilege root 或 --integration better-auth 併用(背景 worker 只以套件帳號執行);可與 --integration go、--file-station 併用。");
223
+ if (options.fileStation && (template !== "native-go" || (options.integration !== undefined && options.privilege === "root")))
224
+ throw new Error("[INIT_FILESTATION_OPTIONS] --file-station 只適用於 -t native-go,且不能與 --privilege root 的 --integration 並用(helper 有自己的 File Station gate)。");
225
+ if (options.sharedFolder) {
226
+ if (template !== "native-go")
227
+ throw new Error("[INIT_SHARED_FOLDER_INVALID] --shared-folder 只適用於 -t native-go。");
228
+ sharedFolderYaml(options.sharedFolder);
229
+ }
122
230
  if (options.ui !== undefined && !["plain", "vue"].includes(options.ui))
123
231
  throw new Error("[INIT_UI_INVALID] --ui 只接受 plain 或 vue。");
124
232
  if (options.integration !== undefined && !["go", "better-auth"].includes(options.integration))
@@ -127,9 +235,11 @@ function substitutionsFor(template, targetDir, options) {
127
235
  throw new Error("[INIT_DATA_ACCESS_INVALID] --data-access 只接受 unavailable 或 relaxed,且需要 --integration 與 --integration-protocol 2;缺少已認證 adapter 仍拒絕 NAS 操作。");
128
236
  if (options.integrationProtocol !== undefined && (!options.integration || ![1, 2].includes(options.integrationProtocol)))
129
237
  throw new Error("[INIT_INTEGRATION_PROTOCOL_INVALID] --integration-protocol 只接受 1 或 2,且需要 --integration;protocol 2 不啟用 NAS data path。");
130
- if (options.integration && (options.ui !== "vue" || options.privilege === "none"))
131
- throw new Error("[INIT_INTEGRATION_OPTIONS] integration 需要 --ui vue 與 root privilege(自動選用)。");
132
- const privilege = options.privilege ?? (options.integration ? "root" : "none");
238
+ if (options.integration && ui !== "vue")
239
+ throw new Error("[INIT_INTEGRATION_OPTIONS] integration 需要 Vue UI(--ui vue,預設);--ui plain 不適用。");
240
+ if (options.integration && options.privilege !== "root" && (options.integrationProtocol !== undefined || options.dataAccess !== undefined))
241
+ throw new Error("[INIT_INTEGRATION_HELPER_OPTIONS] --integration-protocol 與 --data-access 屬於 root helper,需要 --privilege root;沒有它時 integration 只以套件帳號執行,不含 helper。");
242
+ const privilege = options.privilege ?? "none";
133
243
  if (privilege !== "none" && privilege !== "root") {
134
244
  throw new Error(`[INIT_PRIVILEGE_INVALID] --privilege 只接受 none 或 root,收到「${String(privilege)}」。`);
135
245
  }
@@ -144,5 +254,5 @@ function substitutionsFor(template, targetDir, options) {
144
254
  if (displayName.trim() === "" || /[\r\n"\\]/.test(displayName)) {
145
255
  throw new Error("[INIT_DISPLAY_NAME_INVALID] 顯示名稱必須是單行,且不含 \" 或 \\。");
146
256
  }
147
- return { __PACKAGE__: packageId, __DISPLAY_NAME__: displayName, __PRIVILEGE__: privilege };
257
+ return { __PACKAGE__: packageId, __DISPLAY_NAME__: displayName, __PRIVILEGE__: privilege, __BACKGROUND_ENABLED__: options.background ? "true" : "false" };
148
258
  }
package/dist/inspect.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type PortExposure } from "./compose/analyze.js";
1
2
  import { type ProjectRoot } from "./discovery.js";
2
3
  export interface InspectReport {
3
4
  services: string[];
@@ -8,6 +9,8 @@ export interface InspectReport {
8
9
  dataMounts: string[];
9
10
  risks: string[];
10
11
  webHints: string[];
12
+ /** Ports reachable from outside the NAS without DSM authentication. */
13
+ exposedPorts: PortExposure[];
11
14
  }
12
15
  export declare function inspectProject(project: ProjectRoot): InspectReport;
13
16
  export declare function formatInspectReport(report: InspectReport): string;
package/dist/inspect.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
- import { collectPublishedTcpPorts, listServiceNames, loadCompose, } from "./compose/analyze.js";
2
+ import { collectPublishedTcpPorts, collectUnpinnedImages, listPortExposures, listServiceNames, loadCompose, } from "./compose/analyze.js";
3
3
  export function inspectProject(project) {
4
4
  const services = [];
5
5
  const publishedPorts = [];
@@ -13,11 +13,12 @@ export function inspectProject(project) {
13
13
  dataMounts,
14
14
  risks: ["缺少 compose.yaml"],
15
15
  webHints,
16
+ exposedPorts: [],
16
17
  };
17
18
  }
18
19
  const parsed = loadCompose(project.composePath);
19
20
  if (!parsed) {
20
- return { services, publishedPorts, dataMounts, risks, webHints };
21
+ return { services, publishedPorts, dataMounts, risks, webHints, exposedPorts: [] };
21
22
  }
22
23
  const compose = parsed.compose;
23
24
  services.push(...listServiceNames(compose));
@@ -32,7 +33,8 @@ export function inspectProject(project) {
32
33
  webHints.push("Web App 通常還需要 adminprotocol 與 adminurl。");
33
34
  webHints.push("Launch Mode:integration.web.launch 為 dsm-window(預設,DSM 視窗)或 new-page(新分頁)。");
34
35
  }
35
- return { services, publishedPorts, dataMounts, risks, webHints };
36
+ const exposedPorts = listPortExposures(compose).filter((exposure) => !exposure.loopbackOnly);
37
+ return { services, publishedPorts, dataMounts, risks, webHints, exposedPorts };
36
38
  }
37
39
  function collectDataMounts(compose, out) {
38
40
  if (!compose.services) {
@@ -51,6 +53,9 @@ function collectRisks(compose, out) {
51
53
  if (!compose.services) {
52
54
  return;
53
55
  }
56
+ for (const { service, image } of collectUnpinnedImages(compose)) {
57
+ out.push(`${service}: image ${image} is not pinned by digest (run \`synopkgland images pin\`; build-spk sets force_pull: true, so installs re-resolve the tag)`);
58
+ }
54
59
  for (const [serviceName, service] of Object.entries(compose.services)) {
55
60
  if (service.privileged) {
56
61
  out.push(`${serviceName}: privileged`);
@@ -96,6 +101,13 @@ export function formatInspectReport(report) {
96
101
  lines.push("Risk intents:");
97
102
  lines.push(report.risks.length > 0 ? report.risks.join("\n") : "(none)");
98
103
  lines.push("");
104
+ lines.push("Port exposure:");
105
+ lines.push(report.exposedPorts.length > 0
106
+ ? report.exposedPorts
107
+ .map((e) => `CONTAINER_PORT_EXPOSED ${e.service}: ${e.entry} 綁在所有網路介面,可不經 DSM 驗證直接連線;請改綁 127.0.0.1。`)
108
+ .join("\n")
109
+ : "(none)");
110
+ lines.push("");
99
111
  lines.push("Web entry hints:");
100
112
  lines.push(report.webHints.length > 0 ? report.webHints.join("\n") : "(none)");
101
113
  return lines.join("\n");
@@ -0,0 +1,2 @@
1
+ /** Shared host flow. CGI plans are never accepted as completed authorization. */
2
+ export declare const AUTHORIZATION_RUNTIME = "function createAuthorizationAccess(options) {\n var busy = null;\n function fail(code) { var error = new Error(code); error.code = code; return error; }\n function status() { return options.call(\"authorization.status\").then(function (d) {\n if (!d || d.command !== \"authorization\" || d.schema_version !== 1 || [\"ready\",\"authorization_required\",\"not_admin\",\"session_expired\",\"unavailable\"].indexOf(d.state) < 0) throw fail(\"authorization_bad_response\");\n return d;\n }); }\n function plan(method) { return options.call(method).then(function (p) {\n if (!p || p.command !== \"authorization\" || p.schema_version !== 1 || p.phase !== \"plan\" || !Array.isArray(p.operations) || p.operations.length === 0 || p.operations.length > options.tasks.length) throw fail(\"authorization_bad_response\");\n var seen = {};\n p.operations.forEach(function (op) { if (seen[op] || !options.tasks.some(function (t) { return t.op === op; })) throw fail(\"authorization_bad_response\"); seen[op] = true; });\n return p;\n }); }\n function exclusive(fn) { if (busy) return busy; busy = Promise.resolve().then(fn).then(function (s) { busy = null; return s; },function (e) { busy = null; throw e; });return busy; }\n function authorize(ops,run) { return ops.reduce(function (previous,op) { return previous.then(function () {\n return options.root.authorize(op).then(function (state) { if (state !== \"ready\") throw fail(\"root_cancelled\"); return run ? options.root.run(op) : null; });\n }); },Promise.resolve()); }\n return {canManage:function () {return !!options.user && options.user().admin === true;},status:status,request:function () { return exclusive(function () {\n return plan(\"authorization.request\").then(function (p) { return authorize(p.operations,p.run === true); }).then(status,function (e) { if (e.code === \"root_cancelled\") return status();throw e; });\n }); },revoke:function () { return exclusive(function () {\n return plan(\"authorization.revoke\").then(function (p) {\n if (p.withdraw === true && typeof options.withdraw !== \"function\") throw fail(\"authorization_bad_response\");\n var disabled = p.withdraw === true ? options.withdraw() : p.disable === true ? authorize([\"helper_disable\"],true) : Promise.resolve();\n return disabled.then(function () { return p.purge === true ? authorize([\"helper_purge\"],true) : null; }).then(function () { return p.operations.reduce(function (previous,op) {return previous.then(function () {return options.root.remove(op);});},Promise.resolve()); });\n }).then(status,function (e) { if (e.code === \"root_cancelled\") return status();throw e; });\n }); }};\n}";
@@ -0,0 +1,28 @@
1
+ /** Shared host flow. CGI plans are never accepted as completed authorization. */
2
+ export const AUTHORIZATION_RUNTIME = `function createAuthorizationAccess(options) {
3
+ var busy = null;
4
+ function fail(code) { var error = new Error(code); error.code = code; return error; }
5
+ function status() { return options.call("authorization.status").then(function (d) {
6
+ if (!d || d.command !== "authorization" || d.schema_version !== 1 || ["ready","authorization_required","not_admin","session_expired","unavailable"].indexOf(d.state) < 0) throw fail("authorization_bad_response");
7
+ return d;
8
+ }); }
9
+ function plan(method) { return options.call(method).then(function (p) {
10
+ if (!p || p.command !== "authorization" || p.schema_version !== 1 || p.phase !== "plan" || !Array.isArray(p.operations) || p.operations.length === 0 || p.operations.length > options.tasks.length) throw fail("authorization_bad_response");
11
+ var seen = {};
12
+ p.operations.forEach(function (op) { if (seen[op] || !options.tasks.some(function (t) { return t.op === op; })) throw fail("authorization_bad_response"); seen[op] = true; });
13
+ return p;
14
+ }); }
15
+ function exclusive(fn) { if (busy) return busy; busy = Promise.resolve().then(fn).then(function (s) { busy = null; return s; },function (e) { busy = null; throw e; });return busy; }
16
+ function authorize(ops,run) { return ops.reduce(function (previous,op) { return previous.then(function () {
17
+ return options.root.authorize(op).then(function (state) { if (state !== "ready") throw fail("root_cancelled"); return run ? options.root.run(op) : null; });
18
+ }); },Promise.resolve()); }
19
+ return {canManage:function () {return !!options.user && options.user().admin === true;},status:status,request:function () { return exclusive(function () {
20
+ return plan("authorization.request").then(function (p) { return authorize(p.operations,p.run === true); }).then(status,function (e) { if (e.code === "root_cancelled") return status();throw e; });
21
+ }); },revoke:function () { return exclusive(function () {
22
+ return plan("authorization.revoke").then(function (p) {
23
+ if (p.withdraw === true && typeof options.withdraw !== "function") throw fail("authorization_bad_response");
24
+ var disabled = p.withdraw === true ? options.withdraw() : p.disable === true ? authorize(["helper_disable"],true) : Promise.resolve();
25
+ return disabled.then(function () { return p.purge === true ? authorize(["helper_purge"],true) : null; }).then(function () { return p.operations.reduce(function (previous,op) {return previous.then(function () {return options.root.remove(op);});},Promise.resolve()); });
26
+ }).then(status,function (e) { if (e.code === "root_cancelled") return status();throw e; });
27
+ }); }};
28
+ }`;
@@ -0,0 +1,48 @@
1
+ import type { NativeArchFamily } from '../build-spk/dsm-arch.js';
2
+ import type { CommandRunner } from './build.js';
3
+ import { type RootOp } from './root-ops.js';
4
+ import type { StandaloneManifest } from './manifest.js';
5
+ export interface PinnedFile {
6
+ path: string;
7
+ size: number;
8
+ sha256: string;
9
+ }
10
+ export interface AuthorizationInventory {
11
+ schema: 2;
12
+ package: string;
13
+ version: string;
14
+ arch: string;
15
+ operations: RootOp[];
16
+ files: PinnedFile[];
17
+ digest: string;
18
+ }
19
+ export interface AuthorizationArtifact {
20
+ binary: string;
21
+ inventory: AuthorizationInventory;
22
+ bootstrapSha256: string;
23
+ ops: RootOp[];
24
+ }
25
+ export declare function authorizationInventory(m: {
26
+ package: string;
27
+ spkVersion: string;
28
+ rootOps?: RootOp[];
29
+ }, arch: string, files: PinnedFile[]): AuthorizationInventory;
30
+ export declare function bootstrapOps(m: {
31
+ package: string;
32
+ spkVersion: string;
33
+ rootOps?: RootOp[];
34
+ }, pin: string): RootOp[];
35
+ export declare function authorizationPlan(a: AuthorizationArtifact, m: {
36
+ package: string;
37
+ spkVersion: string;
38
+ }): {
39
+ schema: number;
40
+ package: string;
41
+ version: string;
42
+ bootstrapSha256: string;
43
+ inventory: AuthorizationInventory;
44
+ tasks: import("./root-window.js").RootTask[];
45
+ };
46
+ export declare function buildAuthorization(m: StandaloneManifest, arch: NativeArchFamily, work: string, run: CommandRunner): AuthorizationArtifact | undefined;
47
+ /** Archive consistency, not publisher authenticity or device runtime certification. */
48
+ export declare function inspectAuthorization(dir: string, pkg: string, version: string): string[];
@@ -0,0 +1,116 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { existsSync, lstatSync, readFileSync, readdirSync, mkdirSync, writeFileSync } from 'node:fs';
3
+ import { join, relative } from 'node:path';
4
+ import { renderRootTaskScript } from './root-ops.js';
5
+ import { rootTasks } from './root-window.js';
6
+ import { StandaloneBuildError } from './spk.js';
7
+ import { assertHelperTaskBudget } from './helper.js';
8
+ const hash = (bytes) => createHash('sha256').update(bytes).digest('hex');
9
+ export function authorizationInventory(m, arch, files) {
10
+ const base = { schema: 2, package: m.package, version: m.spkVersion, arch, operations: m.rootOps ?? [], files: [...files].sort((a, b) => a.path.localeCompare(b.path, 'en')) };
11
+ return { ...base, digest: hash(JSON.stringify(base)) };
12
+ }
13
+ export function bootstrapOps(m, pin) {
14
+ if (!/^[a-f0-9]{64}$/.test(pin))
15
+ throw new StandaloneBuildError('AUTHORIZATION_PIN_REQUIRED', 'bootstrap SHA-256 pin required');
16
+ return (m.rootOps ?? []).map(op => ({ name: op.name, protectedOutput: true, exposeOutput: op.protectedOutput !== true, body: `#!/bin/sh
17
+ set -eu
18
+ umask 077
19
+ [ "$(id -u)" = 0 ]
20
+ info=/var/packages/${m.package}/INFO
21
+ [ ! -L "$info" ] && [ "$(stat -c %u "$info")" = 0 ]
22
+ grep -Fqx 'version="${m.spkVersion}"' "$info"
23
+ for p in /var /var/lib; do
24
+ [ ! -L "$p" ] && [ -d "$p" ] && [ "$(stat -c %u "$p")" = 0 ]
25
+ mode=$(stat -c %a "$p"); [ "$((0$mode & 0022))" = 0 ]
26
+ done
27
+ s=/var/lib/synopkgland-auth-${m.package}
28
+ [ ! -L "$s" ]
29
+ if [ ! -e "$s" ]; then mkdir -m 0700 "$s"; fi
30
+ [ -d "$s" ] && [ "$(stat -c %u:%a "$s")" = 0:700 ]
31
+ tmp=$(mktemp "$s/.bootstrap.XXXXXX")
32
+ trap 'rm -f "$tmp"; rmdir "$s" 2>/dev/null || :' EXIT HUP INT TERM
33
+ dd if=/var/packages/${m.package}/target/authorization/bootstrap of="$tmp" bs=65536 count=1025 2>/dev/null
34
+ [ "$(stat -c %s "$tmp")" -le 67108864 ]
35
+ chmod 0700 "$tmp"
36
+ [ "$(sha256sum "$tmp" | cut -d ' ' -f 1)" = '${pin}' ]
37
+ "$tmp" '${op.name}'
38
+ ` }));
39
+ }
40
+ export function authorizationPlan(a, m) {
41
+ return { schema: 2, package: m.package, version: m.spkVersion, bootstrapSha256: a.bootstrapSha256, inventory: a.inventory, tasks: rootTasks({ ...m, rootOps: a.ops }) };
42
+ }
43
+ export function buildAuthorization(m, arch, work, run) {
44
+ if (m.privilege !== 'root')
45
+ return undefined;
46
+ if (m.backend.kind !== 'go')
47
+ throw new StandaloneBuildError('AUTHORIZATION_GO_REQUIRED', 'root authorization requires the native-Go CGI template');
48
+ const files = [];
49
+ const add = (path, source) => { const bytes = readFileSync(source); files.push({ path, size: bytes.length, sha256: hash(bytes) }); };
50
+ const walk = (dir) => { for (const name of readdirSync(dir).sort()) {
51
+ const p = join(dir, name), st = lstatSync(p);
52
+ if (st.isDirectory())
53
+ walk(p);
54
+ else if (st.isFile())
55
+ add('ui/app/' + relative(m.ui.dir, p).split('\\').join('/'), p);
56
+ else
57
+ throw new StandaloneBuildError('AUTHORIZATION_PAYLOAD_UNSAFE', 'UI inventory requires regular files');
58
+ } };
59
+ walk(m.ui.dir);
60
+ // Helper bodies already contain the exact helper digest; worker payloads are
61
+ // bound by its compiled registry. UI bytes are additionally checked at launch.
62
+ const inventory = authorizationInventory(m, arch, files);
63
+ const dir = join(work, 'authorization-' + arch);
64
+ mkdirSync(dir);
65
+ const source = readFileSync(new URL('../../templates/_authorization/main.go', import.meta.url), 'utf8');
66
+ writeFileSync(join(dir, 'main.go'), source);
67
+ const binary = join(work, 'bootstrap-' + arch);
68
+ const compiled = JSON.stringify({ ...inventory, operations: inventory.operations.map(op => ({ ...op, body: op.body })) });
69
+ const result = run('go', ['build', '-trimpath', '-buildvcs=false', '-ldflags', `-s -w -buildid= -X 'main.inventoryBase64=${Buffer.from(compiled).toString('base64')}'`, '-o', binary, 'main.go'], { cwd: dir, env: { ...process.env, CGO_ENABLED: '0', GOOS: 'linux', GOARCH: arch === 'x86_64' ? 'amd64' : 'arm64' } });
70
+ if (result.missing || result.status !== 0)
71
+ throw new StandaloneBuildError('AUTHORIZATION_BUILD_FAILED', result.stderr);
72
+ const bootstrapSha256 = hash(readFileSync(binary));
73
+ const ops = bootstrapOps(m, bootstrapSha256);
74
+ ops.forEach(op => assertHelperTaskBudget(renderRootTaskScript(m, op)));
75
+ return { binary, inventory, bootstrapSha256, ops };
76
+ }
77
+ /** Archive consistency, not publisher authenticity or device runtime certification. */
78
+ export function inspectAuthorization(dir, pkg, version) {
79
+ if (!existsSync(join(dir, 'authorization/manifest.json')))
80
+ return ['root authorization manifest missing'];
81
+ try {
82
+ const plan = JSON.parse(readFileSync(join(dir, 'authorization/manifest.json'), 'utf8'));
83
+ if (plan.schema !== 2 || plan.package !== pkg || plan.version !== version || !/^[a-f0-9]{64}$/.test(plan.bootstrapSha256))
84
+ throw Error();
85
+ const bytes = readFileSync(join(dir, 'authorization/bootstrap'));
86
+ if (hash(bytes) !== plan.bootstrapSha256 || !bytes.includes(Buffer.from(Buffer.from(JSON.stringify(plan.inventory)).toString('base64'))))
87
+ throw Error();
88
+ const inventory = authorizationInventory({ package: pkg, spkVersion: version, rootOps: plan.inventory.operations }, plan.inventory.arch, plan.inventory.files);
89
+ if (JSON.stringify(inventory) !== JSON.stringify(plan.inventory))
90
+ throw Error();
91
+ if (JSON.stringify(plan.tasks) !== JSON.stringify(rootTasks({ package: pkg, spkVersion: version, rootOps: bootstrapOps({ package: pkg, spkVersion: version, rootOps: inventory.operations }, plan.bootstrapSha256) })))
92
+ throw Error();
93
+ const seen = new Set();
94
+ for (const f of inventory.files) {
95
+ if (!/^ui\/app\/(?!.*(?:^|\/)\.\.(?:\/|$))[^\x00\\]+$/.test(f.path) || seen.has(f.path))
96
+ throw Error();
97
+ seen.add(f.path);
98
+ const b = readFileSync(join(dir, f.path));
99
+ if (b.length !== f.size || hash(b) !== f.sha256)
100
+ throw Error();
101
+ }
102
+ const cgi = readFileSync(join(dir, 'ui/cgi/api.cgi'));
103
+ if (!cgi.includes(Buffer.from(Buffer.from(JSON.stringify(plan)).toString('base64'))))
104
+ throw Error();
105
+ const windows = readdirSync(join(dir, 'ui')).filter(f => /^window-\d+\.js$/.test(f));
106
+ if (windows.length !== 1)
107
+ throw Error();
108
+ const window = readFileSync(join(dir, 'ui', windows[0]), 'utf8');
109
+ if (!window.includes(JSON.stringify(plan.tasks)))
110
+ throw Error();
111
+ return [];
112
+ }
113
+ catch {
114
+ return ['root authorization bootstrap pin, inventory, CGI or task binding invalid'];
115
+ }
116
+ }
@@ -0,0 +1,21 @@
1
+ import type { StandaloneError } from "./manifest.js";
2
+ /**
3
+ * Opt-in package-private background jobs: DSM's official `systemd-user-unit`
4
+ * resource runs one fixed worker as the package account. There is no root,
5
+ * no root boot task and no process started from the CGI.
6
+ */
7
+ export interface Background {
8
+ worker: "sha256-v1";
9
+ }
10
+ /** Payload path of the worker executable, relative to the package target. */
11
+ export declare const BACKGROUND_WORKER_PAYLOAD = "background/worker";
12
+ /** Go main package of the fixed worker inside the project's backend module. */
13
+ export declare const BACKGROUND_WORKER_MAIN = "./cmd/background-worker";
14
+ export declare const BACKGROUND_UNIT_DIR = "conf/systemd";
15
+ export declare function backgroundUnitName(pkg: string): string;
16
+ export declare function readBackground(value: unknown, fail: (error: StandaloneError) => void): Background | undefined;
17
+ /** `conf/resource`: only the official user-unit resource. */
18
+ export declare function renderBackgroundResource(): string;
19
+ export declare function renderBackgroundUnit(pkg: string): string;
20
+ /** Package Center's start/stop/status map straight onto the user unit. */
21
+ export declare function renderBackgroundControl(pkg: string): string;
@@ -0,0 +1,52 @@
1
+ /** Payload path of the worker executable, relative to the package target. */
2
+ export const BACKGROUND_WORKER_PAYLOAD = "background/worker";
3
+ /** Go main package of the fixed worker inside the project's backend module. */
4
+ export const BACKGROUND_WORKER_MAIN = "./cmd/background-worker";
5
+ export const BACKGROUND_UNIT_DIR = "conf/systemd";
6
+ const SYNOSYSTEMCTL = "/usr/syno/bin/synosystemctl";
7
+ export function backgroundUnitName(pkg) {
8
+ return `pkguser-${pkg}-background.service`;
9
+ }
10
+ export function readBackground(value, fail) {
11
+ if (value === undefined)
12
+ return undefined;
13
+ const ok = typeof value === "object" && value !== null && !Array.isArray(value)
14
+ && Object.keys(value).length === 1 && value.worker === "sha256-v1";
15
+ if (!ok) {
16
+ fail({ code: "STANDALONE_BACKGROUND_INVALID", message: "background 只接受 { worker: sha256-v1 };背景程序固定以套件帳號執行,不能指定使用者、指令或權限。" });
17
+ return undefined;
18
+ }
19
+ return { worker: "sha256-v1" };
20
+ }
21
+ /** `conf/resource`: only the official user-unit resource. */
22
+ export function renderBackgroundResource() {
23
+ return JSON.stringify({ "systemd-user-unit": {} });
24
+ }
25
+ export function renderBackgroundUnit(pkg) {
26
+ return `[Unit]
27
+ Description=${pkg} background worker
28
+
29
+ [Service]
30
+ Type=simple
31
+ ExecStart=/var/packages/${pkg}/target/${BACKGROUND_WORKER_PAYLOAD}
32
+ UMask=0077
33
+ KillMode=control-group
34
+ TimeoutStopSec=10
35
+ Restart=no
36
+ `;
37
+ }
38
+ /** Package Center's start/stop/status map straight onto the user unit. */
39
+ export function renderBackgroundControl(pkg) {
40
+ const unit = backgroundUnitName(pkg);
41
+ return `#!/bin/sh
42
+ case "$1" in
43
+ start) exec ${SYNOSYSTEMCTL} start ${unit} ;;
44
+ stop) exec ${SYNOSYSTEMCTL} stop ${unit} ;;
45
+ status)
46
+ [ "$(${SYNOSYSTEMCTL} get-active-status ${unit})" = active ] && exit 0
47
+ exit 3
48
+ ;;
49
+ *) exit 1 ;;
50
+ esac
51
+ `;
52
+ }
@@ -1,5 +1,6 @@
1
1
  import type { NativeArchFamily } from "../build-spk/dsm-arch.js";
2
2
  import type { StandaloneError } from "./manifest.js";
3
+ export declare const ELF_MACHINE: Record<NativeArchFamily, number>;
3
4
  /**
4
5
  * Checks a prebuilt CGI before it is packaged: a regular file inside the
5
6
  * project, a 64-bit little-endian ELF for `arch`, and statically linked
@@ -1,6 +1,6 @@
1
1
  import { closeSync, lstatSync, openSync, readSync, realpathSync } from "node:fs";
2
2
  import { relative } from "node:path";
3
- const ELF_MACHINE = { x86_64: 62, aarch64: 183 };
3
+ export const ELF_MACHINE = { x86_64: 62, aarch64: 183 };
4
4
  const PT_INTERP = 3;
5
5
  const MAX_BINARY_BYTES = 256 * 1024 * 1024;
6
6
  const HEADER_BYTES = 64 * 1024;
@@ -15,6 +15,8 @@ export interface StandaloneBuildOptions {
15
15
  arches?: NativeArchFamily[];
16
16
  /** Defaults to `<root>/dist`. */
17
17
  outDir?: string;
18
+ /** INFO os_min_ver for every SPK (a release such as 7.1, or a full 7.x-build); defaults to the manifest's. */
19
+ minDsm?: string;
18
20
  run?: CommandRunner;
19
21
  }
20
22
  /** Argv only, never a shell; output streams to the terminal except stderr, which is also kept. */