@synopackageland/cli 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/README.md +7 -3
  2. package/dist/build-spk/delete-app-data.d.ts +27 -7
  3. package/dist/build-spk/delete-app-data.js +35 -34
  4. package/dist/build-spk/dsm-arch.d.ts +6 -1
  5. package/dist/build-spk/dsm-arch.js +25 -1
  6. package/dist/build-spk/dsm-version.d.ts +14 -0
  7. package/dist/build-spk/dsm-version.js +47 -0
  8. package/dist/build-spk/gateway.d.ts +31 -0
  9. package/dist/build-spk/gateway.js +55 -0
  10. package/dist/build-spk/generator.d.ts +5 -0
  11. package/dist/build-spk/generator.js +103 -107
  12. package/dist/build-spk/install-wizard.d.ts +20 -0
  13. package/dist/build-spk/install-wizard.js +76 -0
  14. package/dist/build-spk/native-lifecycle.d.ts +5 -0
  15. package/dist/build-spk/native-lifecycle.js +12 -2
  16. package/dist/build-spk/resource-worker.d.ts +9 -4
  17. package/dist/build-spk/resource-worker.js +15 -6
  18. package/dist/build-spk/share-combobox.d.ts +3 -0
  19. package/dist/build-spk/share-combobox.js +27 -0
  20. package/dist/build-spk/uninstall-wizard.d.ts +14 -0
  21. package/dist/build-spk/uninstall-wizard.js +33 -0
  22. package/dist/build-spk/wizard-i18n.d.ts +18 -0
  23. package/dist/build-spk/wizard-i18n.js +38 -0
  24. package/dist/build-spk/wizard-messages.d.ts +388 -0
  25. package/dist/build-spk/wizard-messages.js +387 -0
  26. package/dist/cli.js +130 -30
  27. package/dist/compose/analyze.d.ts +20 -0
  28. package/dist/compose/analyze.js +75 -11
  29. package/dist/contract/validate.js +33 -1
  30. package/dist/contract/web-launch.d.ts +22 -0
  31. package/dist/contract/web-launch.js +37 -0
  32. package/dist/deploy/deploy.d.ts +3 -0
  33. package/dist/deploy/deploy.js +11 -2
  34. package/dist/error-registry.js +60 -1
  35. package/dist/host/open-url.d.ts +2 -0
  36. package/dist/host/open-url.js +4 -1
  37. package/dist/images/pin.d.ts +52 -0
  38. package/dist/images/pin.js +249 -0
  39. package/dist/init.d.ts +27 -3
  40. package/dist/init.js +104 -15
  41. package/dist/inspect.d.ts +3 -0
  42. package/dist/inspect.js +15 -3
  43. package/dist/standalone/background.d.ts +21 -0
  44. package/dist/standalone/background.js +52 -0
  45. package/dist/standalone/binary.d.ts +1 -0
  46. package/dist/standalone/binary.js +1 -1
  47. package/dist/standalone/build.d.ts +2 -0
  48. package/dist/standalone/build.js +38 -6
  49. package/dist/standalone/dsm-window.js +2 -2
  50. package/dist/standalone/helper-inventory.d.ts +15 -0
  51. package/dist/standalone/helper-inventory.js +9 -0
  52. package/dist/standalone/helper.d.ts +1 -0
  53. package/dist/standalone/helper.js +28 -10
  54. package/dist/standalone/host-adapter.d.ts +1 -1
  55. package/dist/standalone/host-adapter.js +33 -15
  56. package/dist/standalone/host-file-navigation.d.ts +7 -0
  57. package/dist/standalone/host-file-navigation.js +172 -0
  58. package/dist/standalone/inspect-helper.js +9 -4
  59. package/dist/standalone/inspect-spk.d.ts +1 -1
  60. package/dist/standalone/inspect-spk.js +200 -7
  61. package/dist/standalone/job-diagnostics.d.ts +1 -0
  62. package/dist/standalone/job-diagnostics.js +49 -0
  63. package/dist/standalone/lifecycle.js +12 -2
  64. package/dist/standalone/manifest.d.ts +15 -2
  65. package/dist/standalone/manifest.js +37 -6
  66. package/dist/standalone/native-layout.d.ts +74 -0
  67. package/dist/standalone/native-layout.js +318 -0
  68. package/dist/standalone/resource.d.ts +11 -0
  69. package/dist/standalone/resource.js +13 -0
  70. package/dist/standalone/root-window.d.ts +3 -1
  71. package/dist/standalone/root-window.js +156 -38
  72. package/dist/standalone/shared-folder.d.ts +39 -0
  73. package/dist/standalone/shared-folder.js +141 -0
  74. package/dist/standalone/spk.d.ts +2 -0
  75. package/dist/standalone/spk.js +33 -3
  76. package/dist/standalone/worker-contract-json.d.ts +8 -0
  77. package/dist/standalone/worker-contract-json.js +141 -0
  78. package/dist/standalone/worker-contract.d.ts +189 -0
  79. package/dist/standalone/worker-contract.js +175 -0
  80. package/dist/standalone/worker-registry.d.ts +40 -0
  81. package/dist/standalone/worker-registry.js +167 -0
  82. package/dist/templates/_daemon/go.mod +2 -0
  83. package/dist/templates/_gateway/auth.go +101 -0
  84. package/dist/templates/_gateway/auth_test.go +216 -0
  85. package/dist/templates/_gateway/cgi.go +133 -0
  86. package/dist/templates/_gateway/cgi_test.go +156 -0
  87. package/dist/templates/_gateway/csrf.go +73 -0
  88. package/dist/templates/_gateway/csrf_test.go +155 -0
  89. package/dist/templates/_gateway/directory.go +108 -0
  90. package/dist/templates/_gateway/directory_test.go +202 -0
  91. package/dist/templates/_gateway/gateway.go +412 -0
  92. package/dist/templates/_gateway/gateway_test.go +676 -0
  93. package/dist/templates/_gateway/go.mod +3 -0
  94. package/dist/templates/_gateway/groups.go +66 -0
  95. package/dist/templates/_gateway/main.go +45 -0
  96. package/dist/templates/binary/synology-app.yaml +1 -1
  97. package/dist/templates/compose-import/compose.yaml +1 -1
  98. package/dist/templates/compose-import/synology-app.yaml +1 -1
  99. package/dist/templates/hello-files/compose.yaml +1 -1
  100. package/dist/templates/hello-files/synology-app.yaml +1 -1
  101. package/dist/templates/hello-web/compose.yaml +5 -2
  102. package/dist/templates/hello-web/synology-app.yaml +4 -1
  103. package/dist/templates/hello-web-page/compose.yaml +5 -2
  104. package/dist/templates/hello-web-page/synology-app.yaml +4 -1
  105. package/dist/templates/native-go/README.md +93 -4
  106. package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  107. package/dist/templates/native-go/backend/cmd/app/main.go +17 -0
  108. package/dist/templates/native-go/backend/cmd/app/sdk_main.go +60 -0
  109. package/dist/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  110. package/dist/templates/native-go/backend/cmd/helper/main.go +10 -1
  111. package/dist/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  112. package/dist/templates/native-go/backend/go.mod +5 -3
  113. package/dist/templates/native-go/backend/go.sum +4 -4
  114. package/dist/templates/native-go/backend/internal/api/registry.go +17 -6
  115. package/dist/templates/native-go/backend/internal/api/server.go +7 -1
  116. package/dist/templates/native-go/backend/internal/app/background.go +270 -0
  117. package/dist/templates/native-go/backend/internal/app/background_none.go +8 -0
  118. package/dist/templates/native-go/backend/internal/app/background_owner.go +59 -0
  119. package/dist/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  120. package/dist/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  121. package/dist/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  122. package/dist/templates/native-go/backend/internal/app/background_test.go +346 -0
  123. package/dist/templates/native-go/backend/internal/app/integration_state.go +16 -0
  124. package/dist/templates/native-go/backend/internal/app/migrations.go +41 -0
  125. package/dist/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  126. package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  127. package/dist/templates/native-go/backend/internal/app/routes.go +17 -3
  128. package/dist/templates/native-go/backend/internal/app/routes_test.go +20 -3
  129. package/dist/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  130. package/dist/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  131. package/dist/templates/native-go/backend/internal/app/sdk_routes.go +174 -0
  132. package/dist/templates/native-go/backend/internal/app/session_files.go +15 -0
  133. package/dist/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  134. package/dist/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  135. package/dist/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  136. package/dist/templates/native-go/backend/internal/background/access.go +57 -0
  137. package/dist/templates/native-go/backend/internal/background/owner_test.go +126 -0
  138. package/dist/templates/native-go/backend/internal/background/runner.go +185 -0
  139. package/dist/templates/native-go/backend/internal/background/runner_test.go +209 -0
  140. package/dist/templates/native-go/backend/internal/background/schedule.go +300 -0
  141. package/dist/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  142. package/dist/templates/native-go/backend/internal/background/store.go +807 -0
  143. package/dist/templates/native-go/backend/internal/background/store_test.go +407 -0
  144. package/dist/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  145. package/dist/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  146. package/dist/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  147. package/dist/templates/native-go/backend/internal/filestation/client.go +251 -0
  148. package/dist/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  149. package/dist/templates/native-go/backend/internal/filestation/doc.go +4 -0
  150. package/dist/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  151. package/dist/templates/native-go/backend/internal/filestation/repository.go +207 -0
  152. package/dist/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  153. package/dist/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  154. package/dist/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  155. package/dist/templates/native-go/backend/internal/filestation/service.go +254 -0
  156. package/dist/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  157. package/dist/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  158. package/dist/templates/native-go/backend/internal/filestation/write.go +72 -0
  159. package/dist/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  160. package/dist/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  161. package/dist/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  162. package/dist/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  163. package/dist/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  164. package/dist/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  165. package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  166. package/dist/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  167. package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  168. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  169. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  170. package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  171. package/dist/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  172. package/dist/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  173. package/dist/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  174. package/dist/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  175. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  176. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  177. package/dist/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  178. package/dist/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  179. package/dist/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  180. package/dist/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  181. package/dist/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  182. package/dist/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  183. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  184. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  185. package/dist/templates/native-go/backend/internal/helper/management.go +79 -0
  186. package/dist/templates/native-go/backend/internal/helper/observation.go +42 -2
  187. package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  188. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  189. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  190. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  191. package/dist/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  192. package/dist/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  193. package/dist/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  194. package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  195. package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  196. package/dist/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  197. package/dist/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  198. package/dist/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  199. package/dist/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  200. package/dist/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  201. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  202. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  203. package/dist/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  204. package/dist/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  205. package/dist/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  206. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  207. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  208. package/dist/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  209. package/dist/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  210. package/dist/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  211. package/dist/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  212. package/dist/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  213. package/dist/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  214. package/dist/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  215. package/dist/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  216. package/dist/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  217. package/dist/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  218. package/dist/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  219. package/dist/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  220. package/dist/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  221. package/dist/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  222. package/dist/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  223. package/dist/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  224. package/dist/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  225. package/dist/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  226. package/dist/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  227. package/dist/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  228. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  229. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  230. package/dist/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  231. package/dist/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  232. package/dist/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  233. package/dist/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  234. package/dist/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  235. package/dist/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  236. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  237. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  238. package/dist/templates/native-go/backend/internal/helper/sdk_server_linux.go +152 -0
  239. package/dist/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  240. package/dist/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  241. package/dist/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  242. package/dist/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  243. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  244. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  245. package/dist/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  246. package/dist/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  247. package/dist/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  248. package/dist/templates/native-go/backend/internal/helper/server_linux.go +3 -0
  249. package/dist/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  250. package/dist/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  251. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  252. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  253. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  254. package/dist/templates/native-go/backend/internal/helper/status.go +22 -13
  255. package/dist/templates/native-go/backend/internal/helper/status_test.go +45 -0
  256. package/dist/templates/native-go/backend/internal/helper/supervision.go +1 -1
  257. package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  258. package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  259. package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  260. package/dist/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  261. package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  262. package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  263. package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  264. package/dist/templates/native-go/dsm-package.yaml +1 -1
  265. package/dist/templates/native-go-background/BACKGROUND.md +111 -0
  266. package/dist/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  267. package/dist/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  268. package/dist/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  269. package/dist/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  270. package/dist/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  271. package/dist/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  272. package/dist/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  273. package/dist/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  274. package/dist/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  275. package/dist/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  276. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  277. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  278. package/dist/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  279. package/dist/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  280. package/dist/templates/native-go-background/frontend/test/background.test.ts +179 -0
  281. package/dist/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  282. package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  283. package/dist/templates/native-go-vue/README.md +38 -7
  284. package/dist/templates/native-go-vue/frontend/DESIGN.md +15 -3
  285. package/dist/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  286. package/dist/templates/native-go-vue/frontend/README-M2.md +64 -0
  287. package/dist/templates/native-go-vue/frontend/package-lock.json +5 -4
  288. package/dist/templates/native-go-vue/frontend/package.json +1 -1
  289. package/dist/templates/native-go-vue/frontend/src/App.vue +39 -11
  290. package/dist/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  291. package/dist/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  292. package/dist/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  293. package/dist/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  294. package/dist/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  295. package/dist/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  296. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  297. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  298. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  299. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  300. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  301. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  302. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  303. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  304. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  305. package/dist/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  306. package/dist/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  307. package/dist/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  308. package/dist/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  309. package/dist/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  310. package/dist/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  311. package/dist/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  312. package/dist/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  313. package/dist/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  314. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  315. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  316. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  317. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  318. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  319. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  320. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  321. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  322. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  323. package/dist/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  324. package/dist/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  325. package/dist/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  326. package/dist/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  327. package/dist/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  328. package/dist/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  329. package/dist/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  330. package/dist/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  331. package/dist/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  332. package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  333. package/dist/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  334. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  335. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  336. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  337. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  338. package/dist/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  339. package/dist/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  340. package/dist/templates/native-go-vue/frontend/src/style.css +2 -6
  341. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  342. package/dist/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  343. package/dist/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  344. package/dist/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  345. package/dist/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  346. package/dist/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  347. package/dist/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  348. package/dist/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  349. package/dist/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  350. package/dist/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  351. package/dist/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  352. package/dist/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  353. package/dist/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  354. package/dist/templates/native-go-vue/frontend/vite.config.ts +2 -2
  355. package/dist/validate.js +6 -3
  356. package/package.json +1 -1
  357. package/schema/synology-app.schema.json +19 -0
  358. package/skills/reference/create.md +4 -0
  359. package/templates/_daemon/go.mod +2 -0
  360. package/templates/_gateway/auth.go +101 -0
  361. package/templates/_gateway/auth_test.go +216 -0
  362. package/templates/_gateway/cgi.go +133 -0
  363. package/templates/_gateway/cgi_test.go +156 -0
  364. package/templates/_gateway/csrf.go +73 -0
  365. package/templates/_gateway/csrf_test.go +155 -0
  366. package/templates/_gateway/directory.go +108 -0
  367. package/templates/_gateway/directory_test.go +202 -0
  368. package/templates/_gateway/gateway.go +412 -0
  369. package/templates/_gateway/gateway_test.go +676 -0
  370. package/templates/_gateway/go.mod +3 -0
  371. package/templates/_gateway/groups.go +66 -0
  372. package/templates/_gateway/main.go +45 -0
  373. package/templates/binary/synology-app.yaml +1 -1
  374. package/templates/compose-import/compose.yaml +1 -1
  375. package/templates/compose-import/synology-app.yaml +1 -1
  376. package/templates/hello-files/compose.yaml +1 -1
  377. package/templates/hello-files/synology-app.yaml +1 -1
  378. package/templates/hello-web/compose.yaml +5 -2
  379. package/templates/hello-web/synology-app.yaml +4 -1
  380. package/templates/hello-web-page/compose.yaml +5 -2
  381. package/templates/hello-web-page/synology-app.yaml +4 -1
  382. package/templates/native-go/README.md +93 -4
  383. package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  384. package/templates/native-go/backend/cmd/app/main.go +17 -0
  385. package/templates/native-go/backend/cmd/app/sdk_main.go +60 -0
  386. package/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  387. package/templates/native-go/backend/cmd/helper/main.go +10 -1
  388. package/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  389. package/templates/native-go/backend/go.mod +5 -3
  390. package/templates/native-go/backend/go.sum +4 -4
  391. package/templates/native-go/backend/internal/api/registry.go +17 -6
  392. package/templates/native-go/backend/internal/api/server.go +7 -1
  393. package/templates/native-go/backend/internal/app/background.go +270 -0
  394. package/templates/native-go/backend/internal/app/background_none.go +8 -0
  395. package/templates/native-go/backend/internal/app/background_owner.go +59 -0
  396. package/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  397. package/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  398. package/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  399. package/templates/native-go/backend/internal/app/background_test.go +346 -0
  400. package/templates/native-go/backend/internal/app/integration_state.go +16 -0
  401. package/templates/native-go/backend/internal/app/migrations.go +41 -0
  402. package/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  403. package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  404. package/templates/native-go/backend/internal/app/routes.go +17 -3
  405. package/templates/native-go/backend/internal/app/routes_test.go +20 -3
  406. package/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  407. package/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  408. package/templates/native-go/backend/internal/app/sdk_routes.go +174 -0
  409. package/templates/native-go/backend/internal/app/session_files.go +15 -0
  410. package/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  411. package/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  412. package/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  413. package/templates/native-go/backend/internal/background/access.go +57 -0
  414. package/templates/native-go/backend/internal/background/owner_test.go +126 -0
  415. package/templates/native-go/backend/internal/background/runner.go +185 -0
  416. package/templates/native-go/backend/internal/background/runner_test.go +209 -0
  417. package/templates/native-go/backend/internal/background/schedule.go +300 -0
  418. package/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  419. package/templates/native-go/backend/internal/background/store.go +807 -0
  420. package/templates/native-go/backend/internal/background/store_test.go +407 -0
  421. package/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  422. package/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  423. package/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  424. package/templates/native-go/backend/internal/filestation/client.go +251 -0
  425. package/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  426. package/templates/native-go/backend/internal/filestation/doc.go +4 -0
  427. package/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  428. package/templates/native-go/backend/internal/filestation/repository.go +207 -0
  429. package/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  430. package/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  431. package/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  432. package/templates/native-go/backend/internal/filestation/service.go +254 -0
  433. package/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  434. package/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  435. package/templates/native-go/backend/internal/filestation/write.go +72 -0
  436. package/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  437. package/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  438. package/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  439. package/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  440. package/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  441. package/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  442. package/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  443. package/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  444. package/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  445. package/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  446. package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  447. package/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  448. package/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  449. package/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  450. package/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  451. package/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  452. package/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  453. package/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  454. package/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  455. package/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  456. package/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  457. package/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  458. package/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  459. package/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  460. package/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  461. package/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  462. package/templates/native-go/backend/internal/helper/management.go +79 -0
  463. package/templates/native-go/backend/internal/helper/observation.go +42 -2
  464. package/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  465. package/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  466. package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  467. package/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  468. package/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  469. package/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  470. package/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  471. package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  472. package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  473. package/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  474. package/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  475. package/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  476. package/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  477. package/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  478. package/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  479. package/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  480. package/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  481. package/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  482. package/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  483. package/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  484. package/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  485. package/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  486. package/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  487. package/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  488. package/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  489. package/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  490. package/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  491. package/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  492. package/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  493. package/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  494. package/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  495. package/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  496. package/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  497. package/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  498. package/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  499. package/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  500. package/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  501. package/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  502. package/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  503. package/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  504. package/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  505. package/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  506. package/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  507. package/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  508. package/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  509. package/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  510. package/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  511. package/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  512. package/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  513. package/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  514. package/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  515. package/templates/native-go/backend/internal/helper/sdk_server_linux.go +152 -0
  516. package/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  517. package/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  518. package/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  519. package/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  520. package/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  521. package/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  522. package/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  523. package/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  524. package/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  525. package/templates/native-go/backend/internal/helper/server_linux.go +3 -0
  526. package/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  527. package/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  528. package/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  529. package/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  530. package/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  531. package/templates/native-go/backend/internal/helper/status.go +22 -13
  532. package/templates/native-go/backend/internal/helper/status_test.go +45 -0
  533. package/templates/native-go/backend/internal/helper/supervision.go +1 -1
  534. package/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  535. package/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  536. package/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  537. package/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  538. package/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  539. package/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  540. package/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  541. package/templates/native-go/dsm-package.yaml +1 -1
  542. package/templates/native-go-background/BACKGROUND.md +111 -0
  543. package/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  544. package/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  545. package/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  546. package/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  547. package/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  548. package/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  549. package/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  550. package/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  551. package/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  552. package/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  553. package/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  554. package/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  555. package/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  556. package/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  557. package/templates/native-go-background/frontend/test/background.test.ts +179 -0
  558. package/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  559. package/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  560. package/templates/native-go-vue/README.md +38 -7
  561. package/templates/native-go-vue/frontend/DESIGN.md +15 -3
  562. package/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  563. package/templates/native-go-vue/frontend/README-M2.md +64 -0
  564. package/templates/native-go-vue/frontend/package-lock.json +5 -4
  565. package/templates/native-go-vue/frontend/package.json +1 -1
  566. package/templates/native-go-vue/frontend/src/App.vue +39 -11
  567. package/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  568. package/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  569. package/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  570. package/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  571. package/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  572. package/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  573. package/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  574. package/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  575. package/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  576. package/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  577. package/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  578. package/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  579. package/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  580. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  581. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  582. package/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  583. package/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  584. package/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  585. package/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  586. package/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  587. package/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  588. package/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  589. package/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  590. package/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  591. package/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  592. package/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  593. package/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  594. package/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  595. package/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  596. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  597. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  598. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  599. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  600. package/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  601. package/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  602. package/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  603. package/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  604. package/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  605. package/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  606. package/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  607. package/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  608. package/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  609. package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  610. package/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  611. package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  612. package/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  613. package/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  614. package/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  615. package/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  616. package/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  617. package/templates/native-go-vue/frontend/src/style.css +2 -6
  618. package/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  619. package/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  620. package/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  621. package/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  622. package/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  623. package/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  624. package/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  625. package/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  626. package/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  627. package/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  628. package/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  629. package/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  630. package/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  631. package/templates/native-go-vue/frontend/vite.config.ts +2 -2
package/dist/init.js CHANGED
@@ -1,6 +1,8 @@
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
7
  "hello-web",
6
8
  "hello-web-page",
@@ -9,6 +11,17 @@ const TEMPLATE_NAMES = [
9
11
  "binary",
10
12
  "native-go",
11
13
  ];
14
+ /** Templates whose App runs through the DSM docker-project resource worker. */
15
+ const CONTAINER_TEMPLATES = [
16
+ "hello-web",
17
+ "hello-web-page",
18
+ "hello-files",
19
+ "compose-import",
20
+ ];
21
+ /** The container templates need DSM 7.2.1 or later; native-go and binary need 7.1. */
22
+ export function isContainerTemplate(template) {
23
+ return CONTAINER_TEMPLATES.includes(template);
24
+ }
12
25
  export function isTemplateName(value) {
13
26
  return TEMPLATE_NAMES.includes(value);
14
27
  }
@@ -17,10 +30,14 @@ export function listTemplates() {
17
30
  }
18
31
  /**
19
32
  * native-go --privilege root: files laid over the native-go template, and the
20
- * files they replace.
33
+ * files they replace. An integration's helper brings its own root tasks, so
34
+ * the whoami example is not added to it.
21
35
  */
22
36
  const ROOT_OVERLAY = "native-go-root";
23
37
  const ROOT_REPLACED = ["backend/internal/app/root_none.go"];
38
+ /** native-go --background: overlay with the routes, the UI panel and the docs. */
39
+ const BACKGROUND_OVERLAY = "native-go-background";
40
+ const BACKGROUND_REPLACED = ["backend/internal/app/background_none.go"];
24
41
  /** Templates whose identity is filled in at init (placeholders in these files). */
25
42
  const SUBSTITUTED = {
26
43
  "native-go": ["dsm-package.yaml", "README.md"],
@@ -42,22 +59,51 @@ function defaultDisplayName(dir) {
42
59
  function templateFiles(root, dir = root) {
43
60
  return readdirSync(dir).flatMap((name) => {
44
61
  const path = join(dir, name);
45
- return statSync(path).isDirectory() ? templateFiles(root, path) : [relative(root, path)];
62
+ if (statSync(path).isDirectory()) {
63
+ return isTemplateBuildArtifact(path) ? [] : templateFiles(root, path);
64
+ }
65
+ return [relative(root, path)];
46
66
  });
47
67
  }
48
68
  function targetName(file) {
49
69
  return RENAMED[file] ?? file;
50
70
  }
71
+ /** native-go defaults to the Vue shell; the CLI and the library entry point agree. */
72
+ function resolvedUi(template, options) {
73
+ return template === "native-go" ? options.ui ?? "vue" : options.ui;
74
+ }
75
+ /**
76
+ * Copy one template tree into a project. A template directory may carry a local
77
+ * `node_modules`/`dist` from developing the template itself; those never belong
78
+ * to a generated project (and would otherwise shadow the project's own install).
79
+ */
80
+ export function copyTemplateTree(source, target) {
81
+ cpSync(source, target, { recursive: true, filter: (path) => !isTemplateBuildArtifact(path) });
82
+ }
83
+ function isTemplateBuildArtifact(path) {
84
+ const name = basename(path);
85
+ return name === "node_modules" || name === "dist";
86
+ }
51
87
  export function initFromTemplate(template, targetDir, options = {}) {
52
88
  const source = join(templatesRoot(), template);
53
89
  if (!existsSync(source)) {
54
90
  throw new Error(`找不到模板:${template}`);
55
91
  }
92
+ const minDsm = options.minDsm === undefined ? undefined : resolveMinDsm(options.minDsm);
93
+ if (minDsm !== undefined && isContainerTemplate(template)) {
94
+ assertContainerMinDsm(minDsm);
95
+ }
56
96
  const substitutions = substitutionsFor(template, targetDir, options);
57
- const privilege = options.privilege ?? (options.integration ? "root" : "none");
97
+ const ui = resolvedUi(template, options);
98
+ const privilege = options.privilege ?? "none";
99
+ if (privilege === "root" && minDsm !== undefined && !isDsmAtLeast(minDsm, DEFAULT_MIN_DSM)) {
100
+ throw new Error(`[MIN_DSM_INVALID] root templates require DSM ${DEFAULT_MIN_DSM} or later.`);
101
+ }
102
+ const rootExample = privilege === "root" && !options.integration;
58
103
  const overlays = [
59
- ...(privilege === "root" ? [ROOT_OVERLAY] : []),
60
- ...(options.ui === "vue" ? ["native-go-vue"] : []),
104
+ ...(rootExample ? [ROOT_OVERLAY] : []),
105
+ ...(ui === "vue" ? ["native-go-vue"] : []),
106
+ ...(options.background ? [BACKGROUND_OVERLAY] : []),
61
107
  ...(options.integration ? ["native-go-integration"] : []),
62
108
  ...(options.integration === "better-auth" ? ["native-go-better-auth"] : []),
63
109
  ].map(name => join(templatesRoot(), name));
@@ -65,25 +111,27 @@ export function initFromTemplate(template, targetDir, options = {}) {
65
111
  // terms are an unconditional part of a generated project.
66
112
  const shared = join(templatesRoot(), "_shared");
67
113
  const files = [...templateFiles(source), "LICENSES/TEMPLATE.txt", ...overlays.flatMap(root => templateFiles(root)),
68
- ...(options.ui === "vue" ? ["frontend/third-party-notices.mjs"] : []),
114
+ ...(ui === "vue" ? ["frontend/third-party-notices.mjs"] : []),
69
115
  ...(options.integration === "better-auth" ? ["node/third-party-notices.mjs", ...templateFiles(join(shared, 'notice-overrides')).map(file => `node/notice-overrides/${file}`)] : [])];
70
116
  const collisions = files.map(targetName).filter((file) => existsSync(join(targetDir, file)));
71
117
  if (collisions.length > 0) {
72
118
  throw new Error(`[INIT_TARGET_NOT_EMPTY] ${targetDir} 已有 ${collisions.join(", ")};init 不會覆蓋既有檔案。請改用空目錄。`);
73
119
  }
74
120
  mkdirSync(targetDir, { recursive: true });
75
- cpSync(source, targetDir, { recursive: true });
121
+ copyTemplateTree(source, targetDir);
76
122
  mkdirSync(join(targetDir, "LICENSES"), { recursive: true });
77
123
  cpSync(join(shared, "LICENSES/TEMPLATE.txt"), join(targetDir, "LICENSES/TEMPLATE.txt"));
78
124
  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"] : [])]) {
125
+ copyTemplateTree(overlay, targetDir);
126
+ for (const dir of [...(ui === "vue" ? ["frontend"] : []), ...(options.integration === "better-auth" ? ["node"] : [])]) {
81
127
  cpSync(join(shared, "third-party-notices.mjs"), join(targetDir, dir, "third-party-notices.mjs"));
82
128
  }
83
129
  if (options.integration === "better-auth")
84
130
  cpSync(join(shared, 'notice-overrides'), join(targetDir, 'node/notice-overrides'), { recursive: true });
85
- if (privilege === "root")
131
+ if (rootExample)
86
132
  ROOT_REPLACED.forEach(file => rmSync(join(targetDir, file)));
133
+ if (options.background)
134
+ BACKGROUND_REPLACED.forEach(file => rmSync(join(targetDir, file)));
87
135
  for (const [from, to] of Object.entries(RENAMED)) {
88
136
  if (files.includes(from)) {
89
137
  renameSync(join(targetDir, from), join(targetDir, to));
@@ -97,11 +145,31 @@ export function initFromTemplate(template, targetDir, options = {}) {
97
145
  }
98
146
  writeFileSync(path, text);
99
147
  }
100
- if (options.ui === "vue") {
148
+ if (minDsm) {
149
+ const manifest = join(targetDir, template === "native-go" ? "dsm-package.yaml" : "synology-app.yaml");
150
+ writeFileSync(manifest, readFileSync(manifest, "utf8").replace(/^os_min_ver:.*$/m, `os_min_ver: "${minDsm}"`));
151
+ }
152
+ if (ui === "vue") {
101
153
  const manifest = join(targetDir, "dsm-package.yaml");
102
154
  writeFileSync(manifest, readFileSync(manifest, "utf8").replace(" dir: ui", " dir: frontend/dist\n build: {cwd: frontend, command: [npm, run, build]}"));
103
155
  rmSync(join(targetDir, "ui"), { recursive: true });
104
156
  }
157
+ if (options.background) {
158
+ const manifest = join(targetDir, "dsm-package.yaml");
159
+ writeFileSync(manifest, readFileSync(manifest, "utf8") + "\nbackground:\n worker: sha256-v1\n");
160
+ const app = join(targetDir, "frontend/src/App.vue");
161
+ writeFileSync(app, readFileSync(app, "utf8")
162
+ .replace("import NasUnavailable from './nas/NasUnavailable.vue'\n", "import NasUnavailable from './nas/NasUnavailable.vue'\nimport BackgroundPanel from './background/BackgroundPanel.vue'\n")
163
+ .replace(" <!-- BACKGROUND_PANEL -->", " <BackgroundPanel v-if=\"app\" :key=\"app.user\" :ctx=\"ctx\" />"));
164
+ }
165
+ if (options.fileStation) {
166
+ const manifest = join(targetDir, "dsm-package.yaml");
167
+ writeFileSync(manifest, readFileSync(manifest, "utf8") + "\nfileStation: session\n");
168
+ }
169
+ if (options.sharedFolder) {
170
+ const manifest = join(targetDir, "dsm-package.yaml");
171
+ writeFileSync(manifest, readFileSync(manifest, "utf8") + sharedFolderYaml(options.sharedFolder));
172
+ }
105
173
  if (options.integration === "better-auth")
106
174
  rmSync(join(targetDir, "backend/internal/app/identity_none.go"));
107
175
  if (options.integration) {
@@ -113,12 +181,31 @@ export function initFromTemplate(template, targetDir, options = {}) {
113
181
  writeFileSync(routes, readFileSync(routes, "utf8").replace("return append(routes, cfg.rootRoutes()...)", "routes = append(routes, cfg.integrationRoutes()...)\n\treturn append(routes, cfg.rootRoutes()...)"));
114
182
  }
115
183
  }
184
+ /** The `install.sharedFolder` block, validated by the same reader build-spk uses. */
185
+ function sharedFolderYaml(options) {
186
+ const folder = { mode: options.mode, key: options.key ?? "shared", ...(options.name === undefined ? {} : { name: options.name }), permission: options.permission ?? "rw" };
187
+ const errors = [];
188
+ if (!readSharedFolder({ sharedFolder: folder }, e => errors.push(e.message))) {
189
+ throw new Error(`[INIT_SHARED_FOLDER_INVALID] ${errors.join(" ")}`);
190
+ }
191
+ return `\ninstall:\n sharedFolder:\n${Object.entries(folder).map(([k, v]) => ` ${k}: ${v}\n`).join("")}`;
192
+ }
116
193
  function substitutionsFor(template, targetDir, options) {
194
+ const ui = resolvedUi(template, options);
117
195
  if (options.privilege !== undefined && template !== "native-go") {
118
196
  throw new Error("[INIT_PRIVILEGE_UNSUPPORTED] --privilege 只適用於 -t native-go。");
119
197
  }
120
198
  if ((options.ui !== undefined || options.integration !== undefined) && template !== "native-go")
121
199
  throw new Error("[INIT_OPTIONS_UNSUPPORTED] --ui/--integration 只適用於 native-go。");
200
+ if (options.background && (template !== "native-go" || ui !== "vue" || options.privilege === "root" || options.integration === "better-auth"))
201
+ 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 併用。");
202
+ if (options.fileStation && (template !== "native-go" || (options.integration !== undefined && options.privilege === "root")))
203
+ throw new Error("[INIT_FILESTATION_OPTIONS] --file-station 只適用於 -t native-go,且不能與 --privilege root 的 --integration 並用(helper 有自己的 File Station gate)。");
204
+ if (options.sharedFolder) {
205
+ if (template !== "native-go")
206
+ throw new Error("[INIT_SHARED_FOLDER_INVALID] --shared-folder 只適用於 -t native-go。");
207
+ sharedFolderYaml(options.sharedFolder);
208
+ }
122
209
  if (options.ui !== undefined && !["plain", "vue"].includes(options.ui))
123
210
  throw new Error("[INIT_UI_INVALID] --ui 只接受 plain 或 vue。");
124
211
  if (options.integration !== undefined && !["go", "better-auth"].includes(options.integration))
@@ -127,9 +214,11 @@ function substitutionsFor(template, targetDir, options) {
127
214
  throw new Error("[INIT_DATA_ACCESS_INVALID] --data-access 只接受 unavailable 或 relaxed,且需要 --integration 與 --integration-protocol 2;缺少已認證 adapter 仍拒絕 NAS 操作。");
128
215
  if (options.integrationProtocol !== undefined && (!options.integration || ![1, 2].includes(options.integrationProtocol)))
129
216
  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");
217
+ if (options.integration && ui !== "vue")
218
+ throw new Error("[INIT_INTEGRATION_OPTIONS] integration 需要 Vue UI(--ui vue,預設);--ui plain 不適用。");
219
+ if (options.integration && options.privilege !== "root" && (options.integrationProtocol !== undefined || options.dataAccess !== undefined))
220
+ throw new Error("[INIT_INTEGRATION_HELPER_OPTIONS] --integration-protocol 與 --data-access 屬於 root helper,需要 --privilege root;沒有它時 integration 只以套件帳號執行,不含 helper。");
221
+ const privilege = options.privilege ?? "none";
133
222
  if (privilege !== "none" && privilege !== "root") {
134
223
  throw new Error(`[INIT_PRIVILEGE_INVALID] --privilege 只接受 none 或 root,收到「${String(privilege)}」。`);
135
224
  }
@@ -144,5 +233,5 @@ function substitutionsFor(template, targetDir, options) {
144
233
  if (displayName.trim() === "" || /[\r\n"\\]/.test(displayName)) {
145
234
  throw new Error("[INIT_DISPLAY_NAME_INVALID] 顯示名稱必須是單行,且不含 \" 或 \\。");
146
235
  }
147
- return { __PACKAGE__: packageId, __DISPLAY_NAME__: displayName, __PRIVILEGE__: privilege };
236
+ return { __PACKAGE__: packageId, __DISPLAY_NAME__: displayName, __PRIVILEGE__: privilege, __BACKGROUND_ENABLED__: options.background ? "true" : "false" };
148
237
  }
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,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. */
@@ -1,12 +1,14 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import { mkdtempSync, rmSync } from "node:fs";
2
+ import { existsSync, mkdtempSync, rmSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import { resolveMinDsm, DEFAULT_MIN_DSM, isDsmAtLeast } from "../build-spk/dsm-version.js";
5
6
  import { checkCgiBinary } from "./binary.js";
6
7
  import { loadStandaloneManifest } from "./manifest.js";
7
8
  import { assembleStandaloneSpk, StandaloneBuildError } from "./spk.js";
8
9
  import { buildHelper } from "./helper.js";
9
10
  import { buildDaemonControl } from "./daemon.js";
11
+ import { BACKGROUND_WORKER_MAIN } from "./background.js";
10
12
  const GOARCH = { x86_64: "amd64", aarch64: "arm64" };
11
13
  /** Argv only, never a shell; output streams to the terminal except stderr, which is also kept. */
12
14
  export const runCommand = (command, args, options) => {
@@ -29,7 +31,12 @@ export async function buildStandalone(options) {
29
31
  const [first] = loaded.errors;
30
32
  throw new StandaloneBuildError(first.code, loaded.errors.map((e) => `[${e.code}] ${e.message}`).join("\n"));
31
33
  }
32
- const manifest = loaded.manifest;
34
+ const manifest = options.minDsm === undefined
35
+ ? loaded.manifest
36
+ : { ...loaded.manifest, os_min_ver: resolveMinDsm(options.minDsm) };
37
+ if (manifest.privilege === "root" && !isDsmAtLeast(manifest.os_min_ver, DEFAULT_MIN_DSM)) {
38
+ throw new StandaloneBuildError("STANDALONE_OS_MIN_VER_INVALID", `root templates require DSM ${DEFAULT_MIN_DSM} or later.`);
39
+ }
33
40
  const run = options.run ?? runCommand;
34
41
  const arches = options.arches ?? manifest.arches;
35
42
  for (const arch of arches) {
@@ -62,7 +69,8 @@ export async function buildStandalone(options) {
62
69
  const outputPath = join(outDir, `${manifest.package}-${manifest.spkVersion}-${arch}.spk`);
63
70
  const daemonControl = buildDaemonControl(manifest, arch, work, run);
64
71
  const builtManifest = helper ? { ...manifest, rootOps: [...(manifest.rootOps ?? []), ...helper.ops] } : manifest;
65
- await assembleStandaloneSpk({ manifest: builtManifest, arch, cgiPath, outputPath, helper, daemonControl });
72
+ const backgroundWorker = buildBackgroundWorker(manifest, arch, work, run);
73
+ await assembleStandaloneSpk({ manifest: builtManifest, arch, cgiPath, outputPath, helper, daemonControl, backgroundWorker });
66
74
  outputs.push(outputPath);
67
75
  }
68
76
  return { outputs };
@@ -77,9 +85,12 @@ function buildUi(manifest, run) {
77
85
  return;
78
86
  }
79
87
  const [command, ...args] = build.command;
80
- const result = run(command, args, { cwd: build.cwd, env: { ...process.env } });
88
+ const result = run(command, args, { cwd: build.cwd, env: { ...process.env, SYNOPKGLAND_SDK_WORKERS: manifest.integration?.sdkWorkers ? "1" : "0" } });
81
89
  if (result.missing || result.status !== 0) {
82
- throw new StandaloneBuildError("STANDALONE_UI_BUILD_FAILED", `UI build(${build.command.join(" ")})失敗。\n${result.stderr}`);
90
+ const installHint = command === "npm" && existsSync(join(build.cwd, "package.json")) && !existsSync(join(build.cwd, "node_modules"))
91
+ ? `\nUI 依賴尚未安裝。請在 ${build.cwd} 執行 npm ${existsSync(join(build.cwd, "package-lock.json")) ? "ci" : "install"},然後重新執行 build-spk。`
92
+ : "";
93
+ throw new StandaloneBuildError("STANDALONE_UI_BUILD_FAILED", `UI build(${build.command.join(" ")})失敗。${installHint}\n${result.stderr}`);
83
94
  }
84
95
  }
85
96
  function backendFor(manifest, arch, work, run, helper) {
@@ -95,8 +106,11 @@ function backendFor(manifest, arch, work, run, helper) {
95
106
  `-X main.packageID=${manifest.package}`,
96
107
  `-X main.version=${manifest.spkVersion}`,
97
108
  ...(helper ? [`-X 'main.helperInventory=${JSON.stringify(helper.inventory)}'`] : []),
109
+ // Integration without a helper: the CGI serves its package-account features itself.
110
+ ...(manifest.integration && !helper ? ["-X main.integrationMode=package"] : []),
111
+ ...(manifest.fileStation ? [`-X main.fileStation=${manifest.fileStation}`] : []),
98
112
  ].join(" ");
99
- const result = run("go", ["build", "-trimpath", "-buildvcs=false", "-ldflags", ldflags, "-o", out, backend.main], {
113
+ const result = run("go", ["build", ...(manifest.integration?.sdkWorkers ? ["-tags=synopkgland_sdk_workers"] : []), "-trimpath", "-buildvcs=false", "-ldflags", ldflags, "-o", out, backend.main], {
100
114
  cwd: backend.dir,
101
115
  env: { ...process.env, CGO_ENABLED: "0", GOOS: "linux", GOARCH: GOARCH[arch] },
102
116
  });
@@ -108,3 +122,21 @@ function backendFor(manifest, arch, work, run, helper) {
108
122
  }
109
123
  return out;
110
124
  }
125
+ /** The fixed worker is a second binary of the project's own Go module. */
126
+ function buildBackgroundWorker(manifest, arch, work, run) {
127
+ if (!manifest.background || manifest.backend.kind !== "go")
128
+ return undefined;
129
+ const out = join(work, `background-worker-${arch}`);
130
+ const ldflags = ["-s", "-w", "-buildid=", `-X main.packageID=${manifest.package}`].join(" ");
131
+ const result = run("go", ["build", "-trimpath", "-buildvcs=false", "-ldflags", ldflags, "-o", out, BACKGROUND_WORKER_MAIN], {
132
+ cwd: manifest.backend.dir,
133
+ env: { ...process.env, CGO_ENABLED: "0", GOOS: "linux", GOARCH: GOARCH[arch] },
134
+ });
135
+ if (result.missing || result.status !== 0) {
136
+ throw new StandaloneBuildError("STANDALONE_BACKGROUND_BUILD_FAILED", `background worker(${BACKGROUND_WORKER_MAIN})build 失敗;這個專案的 backend 需要含該 package。\n${result.stderr}`);
137
+ }
138
+ const problem = checkCgiBinary(work, out, arch);
139
+ if (problem)
140
+ throw new StandaloneBuildError(problem.code, problem.message);
141
+ return out;
142
+ }
@@ -273,8 +273,8 @@ ${ROOT_PANEL}
273
273
  confirmPassword: function () {
274
274
  return new Promise(function (resolve) {
275
275
  SYNO.SDS.Utils.PasswordConfirmDialog.openDialog(me, function (confirmation) {
276
- resolve((confirmation && confirmation.SynoConfirmPWToken) || null);
277
- }, [], function () { resolve(null); });
276
+ resolve({ confirmed: true, token: (confirmation && confirmation.SynoConfirmPWToken) || null });
277
+ }, [], function () { resolve({ confirmed: false, token: null }); });
278
278
  });
279
279
  },
280
280
  call: ${ns}.call,
@@ -1,9 +1,11 @@
1
+ import type { SDKWorkerConfig } from "./worker-registry.js";
1
2
  export type DataAccessMode = "unavailable" | "relaxed";
2
3
  export interface Integration {
3
4
  protocol: 1 | 2;
4
5
  workers: Record<string, string>;
5
6
  identity?: "better-auth";
6
7
  dataAccess?: DataAccessMode;
8
+ sdkWorkers?: Record<string, SDKWorkerConfig>;
7
9
  }
8
10
  export interface HelperInventory {
9
11
  package: string;
@@ -13,4 +15,17 @@ export interface HelperInventory {
13
15
  registryDigest: string;
14
16
  dataAccess?: DataAccessMode;
15
17
  }
18
+ /**
19
+ * The privileged helper exists only for an integration that also declares
20
+ * privilege: root. Without it, integration is package-account only.
21
+ */
22
+ export declare const hasHelper: (m: {
23
+ integration?: unknown;
24
+ privilege?: "none" | "root";
25
+ }) => boolean;
16
26
  export declare const sha256: (b: string | Buffer) => string;
27
+ /** Preserve the original inert inventory byte format, including property order. */
28
+ export declare function inertWorkerRegistry(workers: readonly {
29
+ id: string;
30
+ digest: string;
31
+ }[]): string;
@@ -1,2 +1,11 @@
1
1
  import { createHash } from "node:crypto";
2
+ /**
3
+ * The privileged helper exists only for an integration that also declares
4
+ * privilege: root. Without it, integration is package-account only.
5
+ */
6
+ export const hasHelper = (m) => m.integration !== undefined && m.privilege === "root";
2
7
  export const sha256 = (b) => createHash("sha256").update(b).digest("hex");
8
+ /** Preserve the original inert inventory byte format, including property order. */
9
+ export function inertWorkerRegistry(workers) {
10
+ return JSON.stringify(workers.map(({ id, digest }) => ({ id, digest })));
11
+ }
@@ -13,6 +13,7 @@ export interface HelperArtifact {
13
13
  binary: string;
14
14
  inventory: HelperInventory;
15
15
  workers: WorkerPayload[];
16
+ registry?: string;
16
17
  ops: RootOp[];
17
18
  }
18
19
  export declare function readIntegration(raw: unknown, root: string, fail: (e: StandaloneError) => void): Integration | undefined;
@@ -2,13 +2,14 @@ import { lstatSync, readFileSync, realpathSync } from "node:fs";
2
2
  import { isAbsolute, join, relative, resolve } from "node:path";
3
3
  import { renderRootTaskScript } from "./root-ops.js";
4
4
  import { StandaloneBuildError } from "./spk.js";
5
- import { sha256 } from "./helper-inventory.js";
5
+ import { hasHelper, sha256 } from "./helper-inventory.js";
6
+ import { buildWorkerRegistry, parseSDKWorkers } from "./worker-registry.js";
6
7
  const record = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
7
8
  export function readIntegration(raw, root, fail) {
8
9
  if (raw === undefined)
9
10
  return undefined;
10
- const invalid = () => { fail({ code: "STANDALONE_INTEGRATION_INVALID", message: "integration 需要 protocol: 1 或 2 與 workers: {固定 ID: 專案內檔案};最多 16 個,僅作 inventory,不執行 worker。" }); return undefined; };
11
- if (!record(raw) || Object.keys(raw).some(k => !["protocol", "workers", "identity", "dataAccess"].includes(k)) || ![1, 2].includes(raw.protocol) || !record(raw.workers) || Object.keys(raw.workers).length > 16)
11
+ const invalid = () => { fail({ code: "STANDALONE_INTEGRATION_INVALID", message: "integration 需要 protocol: 1 或 2 與 inert workers;sdkWorkers 僅接受 protocol 2/relaxed 的固定 SDK kind、action/mode 與較低 limits。總數最多 16,production unavailable。" }); return undefined; };
12
+ if (!record(raw) || Object.keys(raw).some(k => !["protocol", "workers", "identity", "dataAccess", "sdkWorkers"].includes(k)) || ![1, 2].includes(raw.protocol) || !record(raw.workers) || Object.keys(raw.workers).length > 16)
12
13
  return invalid();
13
14
  if (raw.identity !== undefined && raw.identity !== "better-auth")
14
15
  return invalid();
@@ -23,7 +24,18 @@ export function readIntegration(raw, root, fail) {
23
24
  return invalid();
24
25
  workers[id] = path;
25
26
  }
26
- return { protocol: raw.protocol, workers, ...(raw.identity === "better-auth" ? { identity: "better-auth" } : {}), ...(raw.dataAccess !== undefined ? { dataAccess: raw.dataAccess } : {}) };
27
+ let sdkWorkers;
28
+ if (Object.hasOwn(raw, "sdkWorkers")) {
29
+ if (raw.protocol !== 2 || raw.dataAccess !== "relaxed")
30
+ return invalid();
31
+ try {
32
+ sdkWorkers = parseSDKWorkers(raw.sdkWorkers, Object.keys(workers));
33
+ }
34
+ catch {
35
+ return invalid();
36
+ }
37
+ }
38
+ return { protocol: raw.protocol, workers, ...(raw.identity === "better-auth" ? { identity: "better-auth" } : {}), ...(raw.dataAccess !== undefined ? { dataAccess: raw.dataAccess } : {}), ...(sdkWorkers ? { sdkWorkers } : {}) };
27
39
  }
28
40
  function snapshotWorkers(m) {
29
41
  let total = 0;
@@ -87,19 +99,25 @@ exec "$exe" ${action}
87
99
  });
88
100
  }
89
101
  export function buildHelper(m, arch, work, run) {
90
- if (!m.integration)
102
+ if (!m.integration || !hasHelper(m))
91
103
  return undefined;
92
104
  if (m.backend.kind !== "go")
93
105
  throw new StandaloneBuildError("HELPER_GO_REQUIRED", "M1a integration 僅支援 native-go。");
94
106
  const workers = snapshotWorkers(m);
95
- const registry = workers.map(({ id, digest }) => ({ id, digest }));
96
- const base = { package: m.package, version: m.spkVersion, protocol: m.integration.protocol, payloadDigest: "", registryDigest: sha256(JSON.stringify(registry)), ...(m.integration.dataAccess ? { dataAccess: m.integration.dataAccess } : {}) };
107
+ const registry = buildWorkerRegistry(workers, m.integration.sdkWorkers, m.backend.dir);
108
+ const base = { package: m.package, version: m.spkVersion, protocol: m.integration.protocol, payloadDigest: "", registryDigest: sha256(registry), ...(m.integration.dataAccess ? { dataAccess: m.integration.dataAccess } : {}) };
97
109
  const binary = join(work, `helper-${arch}`);
98
- const result = run("go", ["build", "-trimpath", "-buildvcs=false", "-ldflags", `-s -w -buildid= -X 'main.helperInventory=${JSON.stringify(base)}'`, "-o", binary, "./cmd/helper"], {
110
+ const sdkFlags = m.integration.sdkWorkers ? ["-tags=synopkgland_sdk_workers"] : [];
111
+ const sdkBinding = m.integration.sdkWorkers ? ` -X 'main.sdkWorkerRegistry=${registry}'` : "";
112
+ const result = run("go", ["build", ...sdkFlags, "-trimpath", "-buildvcs=false", "-ldflags", `-s -w -buildid= -X 'main.helperInventory=${JSON.stringify(base)}'${sdkBinding}`, "-o", binary, "./cmd/helper"], {
99
113
  cwd: m.backend.dir, env: { ...process.env, CGO_ENABLED: "0", GOOS: "linux", GOARCH: arch === "x86_64" ? "amd64" : "arm64" },
100
114
  });
101
115
  if (result.missing || result.status !== 0)
102
116
  throw new StandaloneBuildError("HELPER_BUILD_FAILED", `Go helper build 失敗:${result.stderr}`);
103
- const inventory = { ...base, payloadDigest: sha256(readFileSync(binary)) };
104
- return { binary, inventory, workers, ops: helperOps(m, inventory) };
117
+ const payload = readFileSync(binary);
118
+ if (m.integration.sdkWorkers && (!payload.includes(Buffer.from(registry)) || buildWorkerRegistry(workers, m.integration.sdkWorkers, m.backend.dir) !== registry)) {
119
+ throw new StandaloneBuildError("HELPER_BUILD_FAILED", "compiled SDK registry 缺失或 source 在建置期間變動;請用完整 SDK 模板重新建置。");
120
+ }
121
+ const inventory = { ...base, payloadDigest: sha256(payload) };
122
+ return { binary, inventory, workers, ...(m.integration.sdkWorkers ? { registry } : {}), ops: helperOps(m, inventory) };
105
123
  }