@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
@@ -0,0 +1,135 @@
1
+ <script setup lang="ts">
2
+ import {computed,inject,onMounted,onBeforeUnmount,ref,watch} from 'vue'
3
+ import {Button,Callout,Checkbox,SettingsSection} from '@synopackageland/ui'
4
+ import {JobsProviderKey,type BackgroundSummary,type JobView} from './provider'
5
+ import {unavailableJobsProvider} from './mock-provider'
6
+ import {jobPage,consentSummary} from './validate'
7
+ import {jobCopy} from './i18n'
8
+ import InteractiveJobForm from './InteractiveJobForm.vue'
9
+ import {useNasRequest} from '../nas/use-request'
10
+ const props=defineProps<{locale:string;section?:'all'|'interactive'|'background'}>(),copy=computed(()=>jobCopy(props.locale))
11
+ // One provider can have both modes; the shell shows them as separate pages
12
+ // while the combined 'all' view stays the default for the standalone preview.
13
+ const mode=computed(()=>props.section??'all')
14
+ const showInteractive=computed(()=>mode.value!=='background'),showBackground=computed(()=>mode.value!=='interactive')
15
+ const visibleJobs=computed(()=>mode.value==='all'?jobs.value:jobs.value.filter(job=>job.mode===(mode.value==='interactive'?'interactive':'background')))
16
+ const provider=inject(JobsProviderKey,unavailableJobsProvider),request=useNasRequest(),{busy,error}=request
17
+ let poll:ReturnType<typeof setTimeout>|undefined
18
+ function clearPoll(){if(poll!==undefined)clearTimeout(poll);poll=undefined}
19
+ function schedulePoll(){if(provider.mode==='connected'&&provider.readiness?.interactive==='ready'&&jobs.value.some(j=>['pending','running','draining','cancel-requested'].includes(j.state)))poll=setTimeout(()=>{poll=undefined;void load()},2500)}
20
+ const invalidated=ref(false)
21
+ const nextCursor=ref<string>()
22
+ const jobs=ref<readonly JobView[]>([]),summary=ref<BackgroundSummary>(),agree=ref(false),uncertain=ref(false)
23
+ watch(error,e=>{if(['denied','session_required','auth_unavailable'].includes((e as {code?:string})?.code??'')){invalidated.value=true;jobs.value=[];summary.value=undefined;agree.value=false}})
24
+ async function load(cursor?:string){if(invalidated.value||busy.value)return;clearPoll();const result=await request.run(async signal=>jobPage(await provider.list(signal,cursor)));if(result){jobs.value=result.items;nextCursor.value=result.nextCursor;schedulePoll()}else if(error.value&&provider.readiness?.interactive!=='revalidating'){jobs.value=[];nextCursor.value=undefined}}
25
+ async function refresh(){await load()}
26
+ async function prepare(){agree.value=false;const result=await request.run(async signal=>consentSummary(await provider.prepare(signal)));if(result)summary.value=result}
27
+ function discard(){request.cancel();summary.value=undefined;agree.value=false}
28
+ async function confirm(){
29
+ const exact=summary.value;if(!exact||!agree.value||uncertain.value)return
30
+ if(Date.now()>=exact.intentExpiresAt){request.error.value={code:'expired'};return}
31
+ // Any missing confirmation reply is uncertain, including AbortSignal/timeout.
32
+ // Keep the original intent and never offer a second submission from this view.
33
+ uncertain.value=true
34
+ const ok=await request.run(async signal=>{await provider.confirm(exact,signal);return true})
35
+ if(ok){summary.value=undefined;uncertain.value=false;await refresh()}
36
+ }
37
+ async function lookup(){const exact=summary.value;if(!exact)return
38
+ const found=await request.run(signal=>provider.lookup(exact.intentId,signal))
39
+ if(found){summary.value=undefined;uncertain.value=false;await refresh()}
40
+ }
41
+ async function stop(job:JobView){
42
+ await request.run(async signal=>{
43
+ if(job.mode==='background'){
44
+ const d=job.delegation;if(!d)throw {code:'unavailable'}
45
+ await provider.revoke(d.id,d.revision,d.storeRevision,signal)
46
+ }else await provider.cancel(job.jobId,job.revision,signal)
47
+ });await refresh()
48
+ }
49
+ async function resubmit(job:JobView){
50
+ await request.run(signal=>provider.resubmit!(job.jobId,signal));await refresh()
51
+ }
52
+ async function lookupResubmission(job:JobView){
53
+ await request.run(signal=>provider.lookupResubmission!(job.jobId,signal));await refresh()
54
+ }
55
+ function fenceCanceled(job:JobView){return job.mode==='interactive'&&job.state==='canceled'&&job.safeReason==='fenced'}
56
+ function label(job:JobView){const c=copy.value
57
+ return ({pending:c.pending,running:c.running,'cancel-requested':c.stopping,draining:c.stopping,succeeded:c.succeeded,failed:c.failed,canceled:c.canceled,interrupted:c.interrupted,'cleanup-required':c.cleanup})[job.state]??c.error
58
+ }
59
+ function time(value:number){try{return new Intl.DateTimeFormat(props.locale,{dateStyle:'medium',timeStyle:'short'}).format(value)}catch{return new Date(value).toISOString()}}
60
+ onMounted(()=>{if(provider.mode!=='unavailable')void refresh()})
61
+ onBeforeUnmount(()=>{clearPoll();request.cancel();provider.disconnect()})
62
+ </script>
63
+ <template>
64
+ <SettingsSection :title="copy.title" :collapsible="false" :aria-busy="busy" class="jobs-panel">
65
+ <Callout v-if="provider.mode==='unavailable'" tone="info" :title="copy.unavailable" />
66
+ <Callout v-else-if="invalidated" tone="danger" :title="copy.accessLost" role="alert" />
67
+ <template v-else>
68
+ <p v-if="provider.mode==='mock'">{{ copy.mock }}</p>
69
+ <template v-if="showInteractive">
70
+ <Callout v-if="provider.readiness?.interactive==='revalidating'" tone="info" :title="copy.revalidating" role="status" aria-live="polite" />
71
+ <Callout v-if="provider.readiness?.interactive==='unavailable'" tone="info" :title="copy.interactiveUnavailable" />
72
+ <p>{{ copy.interactiveHelp }}</p>
73
+ </template>
74
+ <template v-if="showBackground">
75
+ <Callout v-if="provider.readiness?.background==='unavailable'" tone="info" :title="copy.backgroundUnavailable" />
76
+ <p v-else>{{ copy.backgroundHelp }}</p>
77
+ </template>
78
+ <Callout v-if="error && (error as {code?:string}).code!=='revalidating'" tone="danger" :title="copy.error" role="alert" />
79
+ <InteractiveJobForm v-if="showInteractive && provider.interactive" :provider="provider" :locale="locale" @submitted="refresh" />
80
+ <div class="integration-actions">
81
+ <Button v-if="showBackground && provider.readiness?.background!=='unavailable'" :disabled="busy||!!summary" @click="prepare">{{ copy.prepare }}</Button>
82
+ <Button variant="secondary" :disabled="busy" @click="refresh">{{ copy.refresh }}</Button>
83
+ </div>
84
+ <section v-if="showBackground && summary" :aria-label="copy.prepare" class="jobs-review">
85
+ <dl class="nas-summary">
86
+ <dt>{{ copy.app }}</dt><dd>{{ summary.app }}</dd>
87
+ <dt>{{ copy.worker }}</dt><dd>{{ summary.worker }}</dd>
88
+ <dt>{{ copy.scope }}</dt><dd>{{ summary.parent }}</dd>
89
+ <dt>{{ copy.actions }}</dt><dd>{{ summary.actions.join(', ') }}</dd>
90
+ <dt>{{ copy.steps }}</dt><dd>{{ summary.steps }}</dd>
91
+ <dt>{{ copy.starts }}</dt><dd>{{ time(summary.notBefore) }}</dd>
92
+ <dt>{{ copy.expires }}</dt><dd>{{ time(summary.expiresAt) }}</dd>
93
+ </dl>
94
+ <ol><li v-for="(step,index) in summary.inputSummary" :key="index">{{ step }}</li></ol>
95
+ <p>{{ copy.warning }}</p>
96
+ <template v-if="!uncertain">
97
+ <Checkbox v-model="agree" class="jobs-agree" :disabled="busy" :label="copy.agree" />
98
+ <div class="integration-actions"><Button :disabled="busy||!agree" @click="confirm">{{ copy.confirm }}</Button><Button variant="secondary" @click="discard">{{ copy.close }}</Button></div>
99
+ </template>
100
+ <template v-else><p role="status">{{ copy.uncertain }}</p><Button :disabled="busy" @click="lookup">{{ copy.lookup }}</Button></template>
101
+ </section>
102
+ <p v-if="!visibleJobs.length&&!busy&&!error">{{ copy.empty }}</p>
103
+ <ul class="nas-grants">
104
+ <li v-for="job in visibleJobs" :key="job.jobId">
105
+ <p role="status">{{ label(job) }}</p>
106
+ <progress v-if="job.totalUnits!==undefined&&job.totalUnits>0" :value="job.completedUnits" :max="job.totalUnits" :aria-label="label(job)" />
107
+ <p v-else>{{ copy.unknown }}</p>
108
+ <p v-if="job.delegation?.revoked">{{ copy.revoked }}</p><p v-if="job.drained">{{ copy.drained }}</p>
109
+ <p v-if="job.effectsUnknown">{{ copy.effects }}</p>
110
+ <template v-if="fenceCanceled(job)">
111
+ <p>{{ copy.fenceCanceled }}</p>
112
+ <template v-if="provider.resubmissionState?.(job.jobId)==='uncertain'">
113
+ <p role="status">{{ copy.resubmitUncertain }}</p>
114
+ <Button variant="secondary" :disabled="busy||provider.readiness?.interactive!=='ready'" @click="lookupResubmission(job)">{{ copy.resubmitLookup }}</Button>
115
+ </template>
116
+ <p v-else-if="provider.resubmissionState?.(job.jobId)==='submitted'" role="status">{{ copy.resubmitSubmitted }}</p>
117
+ <template v-else>
118
+ <p v-if="!provider.canResubmit?.(job.jobId)">{{ copy.resubmitUnavailable }}</p>
119
+ <Button variant="secondary" :disabled="busy||provider.readiness?.interactive!=='ready'||!provider.canResubmit?.(job.jobId)" @click="resubmit(job)">{{ copy.resubmit }}</Button>
120
+ </template>
121
+ </template>
122
+ <Button v-if="['pending','running','draining','cancel-requested'].includes(job.state)" variant="secondary" :disabled="busy||provider.readiness?.interactive==='revalidating'" @click="stop(job)">{{ job.mode==='background'?copy.revoke:copy.cancel }}</Button>
123
+ </li>
124
+ </ul>
125
+ <Button v-if="nextCursor" :disabled="busy" variant="secondary" @click="load(nextCursor)">{{ copy.next }}</Button>
126
+ </template>
127
+ </SettingsSection>
128
+ </template>
129
+ <style scoped>
130
+ .jobs-panel { max-inline-size: 70ch; overflow-wrap: anywhere; }
131
+ .jobs-review { margin-block: var(--ui-space-4, 1rem); }
132
+ .jobs-agree { margin-block: var(--ui-space-4, 1rem); }
133
+ dd { overflow-wrap: anywhere; }
134
+ progress { max-inline-size: 100%; accent-color: var(--ui-accent); }
135
+ </style>
@@ -0,0 +1,179 @@
1
+ import {reactive,shallowRef} from 'vue'
2
+ import type {Context} from '../context'
3
+ import type {JobsProvider,JobsAdminProvider,JobPage,JobView,BackgroundSummary,InteractivePlan,PreparedInteractive,InteractiveWorker} from './provider'
4
+ import {jobPage,adminPage,jobViews} from './validate'
5
+
6
+ export const ATTACH_RENEW_MS=2000
7
+ export const ATTACH_TTL_MS=6000
8
+ const REQUEST_MS=3000
9
+ const MAX_ATTACH=2
10
+ const ref=(x:unknown):x is string=>typeof x==='string'&&/^[a-f0-9]{64}$/.test(x)
11
+ const positive=(x:unknown):x is number=>Number.isSafeInteger(x)&&Number(x)>0
12
+ const refused=(code='invalid-request'):never=>{throw {code}}
13
+ const safeCodes=new Set(['invalid-request','incompatible','unsupported','replay','stale','expired','denied','unavailable','suspended','revoked','fenced','revalidating','busy','limit-exceeded','canceled','timeout','cleanup-required','session_required','auth_unavailable'])
14
+ function safeError(e:unknown){const code=(e as {code?:string})?.code;return {code:code&&safeCodes.has(code)?code:'unavailable'}}
15
+ export type {PreparedInteractive} from './provider'
16
+ interface Lease {jobId:string;attachId:string;revision:number;deadline:number}
17
+ interface WireJob extends Omit<JobView,'completedUnits'|'totalUnits'|'delegation'> {
18
+ progress:{completedUnits:number;totalUnits?:number}
19
+ delegation?:{id:string;revision:number;storeRevision:number;state:string}
20
+ }
21
+ function view(raw:WireJob):JobView{
22
+ if(!raw||!ref(raw.jobId)||!raw.progress)refused()
23
+ return jobViews([{jobId:raw.jobId,revision:raw.revision,mode:raw.mode,state:raw.state,drained:raw.drained,effectsUnknown:raw.effectsUnknown,completedUnits:raw.progress.completedUnits,...(raw.safeReason?{safeReason:raw.safeReason}:{}),...(raw.progress.totalUnits===undefined?{}:{totalUnits:raw.progress.totalUnits}),...(raw.delegation?{delegation:{id:raw.delegation.id,revision:raw.delegation.revision,storeRevision:raw.delegation.storeRevision,revoked:raw.delegation.state==='revoked'}}:{})}])[0]
24
+ }
25
+ function prepared(raw:PreparedInteractive):PreparedInteractive{
26
+ if(!raw||!ref(raw.intentId)||!ref(raw.jobId)||!ref(raw.summaryDigest)||!positive(raw.expiresAt))refused()
27
+ return {intentId:raw.intentId,jobId:raw.jobId,summaryDigest:raw.summaryDigest,expiresAt:raw.expiresAt}
28
+ }
29
+ function workerViews(raw:unknown):InteractiveWorker[]{
30
+ if(raw===undefined)return [] // Older owners have no submission form.
31
+ if(!Array.isArray(raw)||raw.length>16)return refused()
32
+ const ids=new Set<string>()
33
+ return raw.map(w=>{
34
+ if(!w||typeof w.id!=='string'||! /^[a-z][a-z0-9_]{0,31}$/.test(w.id)||ids.has(w.id)||!positive(w.revision)||!positive(w.maxBytes)||w.maxBytes>524288||!Array.isArray(w.actions)||!w.actions.length||w.actions.length>3||new Set(w.actions).size!==w.actions.length||w.actions.some((a:unknown)=>!['nas.files.list','nas.files.stat','nas.files.read'].includes(a as string)))refused()
35
+ ids.add(w.id);return {id:w.id,revision:w.revision,actions:[...w.actions],maxBytes:w.maxBytes}
36
+ })
37
+ }
38
+ export function createConnectedJobsProvider(ctx:Pick<Context,'call'>){
39
+ let disposed=false,timer:ReturnType<typeof setTimeout>|undefined
40
+ const readiness=reactive<{interactive:'ready'|'revalidating'|'unavailable';background:'unavailable'}>({interactive:'unavailable',background:'unavailable'})
41
+ const workers=shallowRef<readonly InteractiveWorker[]>([])
42
+ // Local plans are display/retry input, never authority or persisted credentials.
43
+ const preparedPlans=new Map<string,InteractivePlan>(),plans=new Map<string,InteractivePlan>()
44
+ const resubmissions=new Map<string,{state:'preparing'|'uncertain'|'submitted';prepared?:PreparedInteractive}>()
45
+ function retain<K,V>(map:Map<K,V>,key:K,value:V){if(map.size>=256&&!map.has(key))map.delete(map.keys().next().value!);map.set(key,value)}
46
+ const life=new AbortController(),leases=new Map<string,Lease>(),known=new Map<string,JobView>()
47
+ async function request<T>(method:string,args:Record<string,unknown>,signal:AbortSignal):Promise<T>{
48
+ if(disposed||signal.aborted)refused('canceled')
49
+ let cleanup=()=>{}
50
+ const abort=new Promise<never>((_,reject)=>{
51
+ const canceled=()=>reject({code:'canceled'})
52
+ const deadline=setTimeout(()=>reject({code:'timeout'}),REQUEST_MS)
53
+ signal.addEventListener('abort',canceled,{once:true});life.signal.addEventListener('abort',canceled,{once:true})
54
+ cleanup=()=>{clearTimeout(deadline);signal.removeEventListener('abort',canceled);life.signal.removeEventListener('abort',canceled)}
55
+ })
56
+ try{
57
+ const value=await Promise.race([ctx.call<T>(method,args),abort])
58
+ if(disposed||signal.aborted)refused('canceled')
59
+ return value
60
+ }catch(e){const error=safeError(e);if(error.code==='revalidating')readiness.interactive='revalidating';else if(readiness.interactive!=='revalidating')readiness.interactive='unavailable';throw error}finally{cleanup()}
61
+ }
62
+ function schedule(){if(!disposed&&leases.size&&timer===undefined)timer=setTimeout(()=>{timer=undefined;void renew()},ATTACH_RENEW_MS)}
63
+ async function renew(){
64
+ for(const lease of [...leases.values()]){
65
+ if(disposed)break
66
+ if(performance.now()>=lease.deadline){leases.delete(lease.jobId);continue}
67
+ try{
68
+ await request('jobs.attach',{jobId:lease.jobId,attachId:lease.attachId},life.signal)
69
+ if(!disposed&&leases.get(lease.jobId)===lease)lease.deadline=performance.now()+ATTACH_TTL_MS
70
+ }catch(e){
71
+ if(['expired','stale','denied','fenced','revalidating','canceled','session_required','auth_unavailable'].includes(safeError(e).code))leases.delete(lease.jobId)
72
+ // Busy/network failure cannot extend the original client deadline. Root
73
+ // monotonic TTL is authoritative even while this tab's timer is suspended.
74
+ }
75
+ }
76
+ schedule()
77
+ }
78
+ function remember(job:JobView){
79
+ if(known.size>=256&&!known.has(job.jobId))known.clear()
80
+ known.set(job.jobId,job)
81
+ const lease=leases.get(job.jobId)
82
+ if(lease){lease.revision=job.revision;if(['succeeded','failed','canceled','interrupted','cleanup-required'].includes(job.state))leases.delete(job.jobId)}
83
+ }
84
+ function disconnect(){
85
+ if(disposed)return
86
+ disposed=true
87
+ readiness.interactive='unavailable'
88
+ if(timer!==undefined)clearTimeout(timer)
89
+ timer=undefined
90
+ window.removeEventListener('pagehide',disconnect)
91
+ life.abort()
92
+ for(const lease of leases.values()){
93
+ // Best effort only. ctx.call preserves native session/CSRF transport. We do
94
+ // not claim delivery or Q and never renew after pagehide/bfcache/unmount.
95
+ void ctx.call('jobs.cancel',{jobId:lease.jobId,revision:lease.revision}).catch(()=>{})
96
+ }
97
+ workers.value=[];leases.clear();known.clear();preparedPlans.clear();plans.clear();resubmissions.clear()
98
+ }
99
+ window.addEventListener('pagehide',disconnect)
100
+ const provider:JobsProvider={
101
+ mode:'connected',readiness,
102
+ async list(signal,cursor){
103
+ const raw=await request<{revision:number;items:WireJob[];nextCursor?:string;availability?:string;workers?:unknown}>('jobs.status',cursor?{cursor}:{},signal)
104
+ if(!raw||!Array.isArray(raw.items)||raw.items.length>10)refused()
105
+ const page=jobPage({revision:raw.revision,items:raw.items.map(view),...(raw.nextCursor?{nextCursor:raw.nextCursor}:{})})
106
+ try{workers.value=raw.availability==='session-required'?workerViews(raw.workers):[]}
107
+ catch(e){workers.value=[];readiness.interactive='unavailable';throw e}
108
+ if(raw.availability==='session-required')readiness.interactive='ready'
109
+ else if(readiness.interactive!=='revalidating')readiness.interactive='unavailable'
110
+ page.items.forEach(remember);return page
111
+ },
112
+ async prepare(){return refused('unavailable')},
113
+ async confirm(_summary:BackgroundSummary){return refused('unavailable')},
114
+ async lookup(intentId,signal){if(!ref(intentId))refused();const job=view(await request<WireJob>('jobs.lookup',{intentId},signal));remember(job);return job},
115
+ async cancel(jobId,revision,signal){if(!ref(jobId)||!positive(revision))refused();await request('jobs.cancel',{jobId,revision},signal);leases.delete(jobId)},
116
+ async revoke(id,revision,storeRevision,signal){
117
+ const job=[...known.values()].find(j=>j.delegation?.id===id)
118
+ if(!job)return refused('stale')
119
+ const raw=await request<{revoked:boolean;drained:boolean}>('jobs.revoke',{jobId:job.jobId,revision:job.revision,delegationRevision:revision,storeRevision},signal)
120
+ if(typeof raw?.revoked!=='boolean'||typeof raw.drained!=='boolean')refused()
121
+ return {revoked:raw.revoked,drained:raw.drained}
122
+ },
123
+ canResubmit(jobId){const job=known.get(jobId);return !!job&&job.mode==='interactive'&&job.state==='canceled'&&job.safeReason==='fenced'&&plans.has(jobId)&&!resubmissions.has(jobId)},
124
+ resubmissionState(jobId){const state=resubmissions.get(jobId)?.state;return state==='preparing'?undefined:state},
125
+ async resubmit(jobId,signal){
126
+ if(!provider.canResubmit?.(jobId)||readiness.interactive!=='ready')return refused('unavailable')
127
+ const plan=plans.get(jobId)!
128
+ // Reserve locally before the first await, preventing simultaneous clicks.
129
+ retain(resubmissions,jobId,{state:'preparing'})
130
+ let value:PreparedInteractive
131
+ try{value=await connected.prepareInteractive(signal,plan.worker,plan.parent,plan.input)}
132
+ catch(e){resubmissions.delete(jobId);throw e}
133
+ plans.delete(jobId) // consume the old plan before the one submit attempt
134
+ resubmissions.set(jobId,{state:'uncertain',prepared:value})
135
+ const result=await connected.submitInteractive(value,signal)
136
+ resubmissions.set(jobId,{state:'submitted',prepared:value})
137
+ return result
138
+ },
139
+ async lookupResubmission(jobId,signal){
140
+ const retry=resubmissions.get(jobId)
141
+ if(!retry||retry.state!=='uncertain'||!retry.prepared)return refused('unavailable')
142
+ const job=await provider.lookup(retry.prepared.intentId,signal)
143
+ if(!job||job.jobId!==retry.prepared.jobId)return refused('unavailable')
144
+ retry.state='submitted';return {jobId:job.jobId}
145
+ },disconnect,
146
+ }
147
+ const connected=Object.assign(provider,{
148
+ readiness,
149
+ async prepareInteractive(signal:AbortSignal,worker:InteractivePlan['worker'],parent:InteractivePlan['parent'],input:InteractivePlan['input']){
150
+ const plan:InteractivePlan={worker:{id:worker.id,revision:worker.revision},parent:{id:parent.id,revision:parent.revision},input:{steps:input.steps.map(s=>({action:s.action,segments:[...s.segments],...(s.limit===undefined?{}:{limit:s.limit}),...(s.maxBytes===undefined?{}:{maxBytes:s.maxBytes})}))}}
151
+ const value=prepared(await request<PreparedInteractive>('jobs.prepare',plan as unknown as Record<string,unknown>,signal))
152
+ retain(preparedPlans,value.intentId,plan);return value
153
+ },
154
+ async submitInteractive(value:PreparedInteractive,signal:AbortSignal){
155
+ const input=prepared(value)
156
+ if(leases.size>=MAX_ATTACH)refused('busy')
157
+ const plan=preparedPlans.get(input.intentId);preparedPlans.delete(input.intentId)
158
+ // Never retry submit automatically, including after a lost response.
159
+ const raw=await request<Lease&{renewAfterMs:number;ttlMs:number}>('jobs.submit',{intentId:input.intentId,summaryDigest:input.summaryDigest},signal)
160
+ if(!raw||raw.jobId!==input.jobId||!ref(raw.attachId)||!positive(raw.revision)||raw.renewAfterMs!==ATTACH_RENEW_MS||raw.ttlMs!==ATTACH_TTL_MS)refused()
161
+ leases.set(raw.jobId,{jobId:raw.jobId,attachId:raw.attachId,revision:raw.revision,deadline:performance.now()+ATTACH_TTL_MS})
162
+ if(plan)retain(plans,raw.jobId,plan)
163
+ schedule()
164
+ return {jobId:raw.jobId}
165
+ },
166
+ })
167
+ return Object.assign(connected,{interactive:{get workers(){return workers.value},prepareInteractive:connected.prepareInteractive,submitInteractive:connected.submitInteractive}})
168
+ }
169
+ export function createConnectedJobsAdminProvider(ctx:Pick<Context,'call'>):JobsAdminProvider{
170
+ return {mode:'connected',async list(signal,cursor){
171
+ if(signal.aborted)refused('canceled')
172
+ const page=adminPage(await ctx.call('jobs.admin.status',cursor?{cursor}:{}))
173
+ if(signal.aborted)refused('canceled');return page
174
+ },async cancel(jobId,revision,signal){
175
+ if(signal.aborted)refused('canceled')
176
+ await ctx.call('jobs.admin.cancel',{jobId,revision})
177
+ if(signal.aborted)refused('canceled')
178
+ }}
179
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "title": "Aufträge",
3
+ "unavailable": "Aufträge sind in diesem Build nicht verfügbar.",
4
+ "mock": "Testvorschau: keine NAS-Aktion",
5
+ "interactiveHelp": "Diese Ansicht erneuert interaktive Aufträge alle 2 Sekunden. Nach 6 Sekunden ohne Erneuerung beginnt der Abbruch; er endet erst nach bestätigter Bereinigung. Schließen fordert den Abbruch an. Verborgene Tabs können zum Ablauf und Abbruch führen.",
6
+ "backgroundHelp": "Bestätigte Hintergrundarbeit kann nach Schließen oder Abmelden bis zum Ablauf oder Neustart weiterlaufen. Kein Fortsetzen nach Neustart.",
7
+ "prepare": "Hintergrundauftrag prüfen",
8
+ "confirm": "Einmal bestätigen",
9
+ "agree": "Ich stimme diesem einmaligen Nur-Lese-Auftrag auch während meiner Abwesenheit zu.",
10
+ "refresh": "Aktualisieren",
11
+ "lookup": "Ursprünglichen Auftrag prüfen",
12
+ "uncertain": "Bestätigungsantwort verloren. Ursprünglichen Auftrag prüfen, nicht erneut senden.",
13
+ "close": "Prüfung verwerfen",
14
+ "cancel": "Auftrag abbrechen",
15
+ "revoke": "Hintergrundzustimmung widerrufen",
16
+ "revoked": "Widerrufen",
17
+ "drained": "Bereinigung bestätigt",
18
+ "cleanup": "Bereinigung erforderlich",
19
+ "unknown": "Gesamtfortschritt unbekannt",
20
+ "error": "Anfrage fehlgeschlagen. Aktuellen Zustand durch Aktualisieren prüfen.",
21
+ "empty": "Keine Aufträge",
22
+ "pending": "Ausstehend",
23
+ "running": "Läuft",
24
+ "stopping": "Wird beendet",
25
+ "succeeded": "Abgeschlossen",
26
+ "failed": "Fehlgeschlagen",
27
+ "canceled": "Abgebrochen",
28
+ "interrupted": "Unterbrochen",
29
+ "app": "App",
30
+ "worker": "Worker",
31
+ "scope": "Bereichsreferenz",
32
+ "actions": "Aktionen",
33
+ "steps": "Schritte",
34
+ "expires": "Ablauf",
35
+ "starts": "Frühester Start",
36
+ "warning": "Bereits erfolgte Aktionen sind nicht rückgängig zu machen. Zustimmung gilt einmal im aktuellen Lauf.",
37
+ "effects": "Auswirkungen möglicherweise unbekannt",
38
+ "next": "Nächste Seite",
39
+ "accessLost": "Zugriff nicht bestätigt. Melden Sie sich erneut an und öffnen Sie diese Ansicht neu.",
40
+ "interactiveUnavailable": "Interaktive Aufträge sind erst nach Anbindung der nativen Sitzungs- und Berechtigungsprüfung verfügbar.",
41
+ "backgroundUnavailable": "Hintergrundaufträge sind nicht verfügbar.",
42
+ "adminTitle": "Auftragsverwaltung",
43
+ "loadManagement": "Aktualisieren, um den Verwaltungsstatus zu laden.",
44
+ "revalidating": "Die Paketprüfungen werden erneut validiert. Neue Aufträge sind pausiert. Aktualisieren Sie zur Prüfung der Wiederherstellung. Abgebrochene Aufträge werden nicht fortgesetzt.",
45
+ "fenceCanceled": "Dieser Auftrag wurde abgebrochen, weil die Paketprüfungen nicht verfügbar waren. Nach der Wiederherstellung erstellt erneutes Senden einen neuen Auftrag mit erneuter Berechtigungsprüfung. Es erfolgt kein automatisches Senden.",
46
+ "resubmit": "Erneut senden",
47
+ "resubmitUnavailable": "Der ursprüngliche Ablauf ist in dieser Ansicht nicht verfügbar. Wählen Sie die Eingaben erneut, um einen neuen Auftrag zu erstellen.",
48
+ "resubmitUncertain": "Die Antwort auf das erneute Senden fehlt. Prüfen Sie den neuen Auftrag und senden Sie nicht erneut.",
49
+ "resubmitLookup": "Neuen Auftrag prüfen",
50
+ "resubmitSubmitted": "Ein neuer Auftrag wurde gesendet. Der abgebrochene Auftrag bleibt gestoppt.",
51
+ "newInteractive": "Neuer interaktiver Auftrag",
52
+ "chooseSource": "Quelldatei oder Ordner wählen",
53
+ "sourceHelp": "Nur lesender Auftrag mit Ihrer aktuellen DSM-Sitzung. Die Dateiauswahl speichert die Zustimmung für den übergeordneten Ordner. Inhalte werden verworfen; nur Zähler werden gemeldet.",
54
+ "operation": "Aktion",
55
+ "statOperation": "Metadaten prüfen",
56
+ "listOperation": "Ordner auflisten",
57
+ "readOperation": "Datei lesen (Bytes zählen)",
58
+ "entryLimit": "Maximale Einträge (1–100)",
59
+ "byteLimit": "Maximale Bytes",
60
+ "submitInteractive": "Auftrag einmal senden",
61
+ "interactiveSubmitted": "Auftrag gesendet. Prüfen Sie unten den Fortschritt."
62
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "title": "Jobs",
3
+ "unavailable": "Jobs are unavailable in this build.",
4
+ "mock": "Mock preview — no NAS operation",
5
+ "interactiveHelp": "This view renews interactive work every 2 seconds. After 6 seconds without renewal, cancellation starts; it completes only after cleanup is confirmed. Closing the view requests cancellation. Hidden tabs may expire and cancel the job.",
6
+ "backgroundHelp": "An explicitly confirmed background job may continue after closing or signing out, until expiry or restart. Restart does not resume it.",
7
+ "prepare": "Review background job",
8
+ "confirm": "Confirm once",
9
+ "agree": "I agree to this one-time read-only job continuing while I am offline.",
10
+ "refresh": "Refresh",
11
+ "lookup": "Check original job",
12
+ "uncertain": "Confirmation reply was lost. Check the original job; do not submit again.",
13
+ "close": "Discard review",
14
+ "cancel": "Cancel job",
15
+ "revoke": "Revoke background consent",
16
+ "revoked": "Revoked",
17
+ "drained": "Cleanup confirmed",
18
+ "cleanup": "Cleanup required",
19
+ "unknown": "Progress total unknown",
20
+ "error": "Request could not be completed. Refresh to check the current state.",
21
+ "empty": "No jobs",
22
+ "pending": "Pending",
23
+ "running": "Running",
24
+ "stopping": "Stopping",
25
+ "succeeded": "Completed",
26
+ "failed": "Failed",
27
+ "canceled": "Canceled",
28
+ "interrupted": "Interrupted",
29
+ "app": "App",
30
+ "worker": "Worker",
31
+ "scope": "Scope reference",
32
+ "actions": "Actions",
33
+ "steps": "Steps",
34
+ "expires": "Expires",
35
+ "starts": "Earliest start",
36
+ "warning": "Effects already completed cannot be undone. Consent is valid for one job before the app restarts.",
37
+ "effects": "Effects may be unknown",
38
+ "next": "Next page",
39
+ "accessLost": "Access could not be verified. Sign in again and reopen this view.",
40
+ "interactiveUnavailable": "Interactive jobs are unavailable until native session and permission checks are connected.",
41
+ "backgroundUnavailable": "Background jobs are unavailable.",
42
+ "adminTitle": "Job management",
43
+ "loadManagement": "Refresh to load management status.",
44
+ "revalidating": "Package checks are being revalidated. New jobs are paused. Refresh to check recovery; canceled jobs will not resume.",
45
+ "fenceCanceled": "This job was canceled because package checks became unavailable. After recovery, resubmit to create a new job and check permissions again. Nothing is resubmitted automatically.",
46
+ "resubmit": "Resubmit",
47
+ "resubmitUnavailable": "The original plan is unavailable in this view. Select the inputs again to create a new job.",
48
+ "resubmitUncertain": "The resubmission reply was lost. Check the new job; do not submit again.",
49
+ "resubmitLookup": "Check new job",
50
+ "resubmitSubmitted": "A new job was submitted. The canceled job remains stopped.",
51
+ "newInteractive": "New interactive job",
52
+ "chooseSource": "Choose source file or folder",
53
+ "sourceHelp": "Read-only job using your current DSM session. Selecting a file saves consent for its containing folder. File contents are discarded; jobs report counters only.",
54
+ "operation": "Operation",
55
+ "statOperation": "Inspect metadata",
56
+ "listOperation": "List folder",
57
+ "readOperation": "Read file (count bytes)",
58
+ "entryLimit": "Maximum entries (1–100)",
59
+ "byteLimit": "Maximum bytes",
60
+ "submitInteractive": "Submit job once",
61
+ "interactiveSubmitted": "Job submitted. Check progress below."
62
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "title": "Trabajos",
3
+ "unavailable": "Los trabajos no están disponibles en esta versión.",
4
+ "mock": "Vista simulada: sin operaciones NAS",
5
+ "interactiveHelp": "Esta vista renueva las tareas interactivas cada 2 segundos. Tras 6 segundos sin renovación, empieza la cancelación; termina cuando se confirma la limpieza. Cerrar la vista solicita la cancelación. Las pestañas ocultas pueden provocar la caducidad y la cancelación.",
6
+ "backgroundHelp": "Un trabajo de fondo confirmado puede continuar tras cerrar o salir hasta caducar o reiniciar. No se reanuda tras reiniciar.",
7
+ "prepare": "Revisar trabajo de fondo",
8
+ "confirm": "Confirmar una vez",
9
+ "agree": "Acepto este trabajo único de solo lectura mientras estoy desconectado.",
10
+ "refresh": "Actualizar",
11
+ "lookup": "Consultar trabajo original",
12
+ "uncertain": "Se perdió la respuesta. Consulte el trabajo original sin enviarlo de nuevo.",
13
+ "close": "Descartar revisión",
14
+ "cancel": "Cancelar trabajo",
15
+ "revoke": "Revocar consentimiento",
16
+ "revoked": "Revocado",
17
+ "drained": "Limpieza confirmada",
18
+ "cleanup": "Limpieza necesaria",
19
+ "unknown": "Total desconocido",
20
+ "error": "No se pudo completar la solicitud. Actualice para comprobar el estado.",
21
+ "empty": "Sin trabajos",
22
+ "pending": "Pendiente",
23
+ "running": "En ejecución",
24
+ "stopping": "Deteniéndose",
25
+ "succeeded": "Completado",
26
+ "failed": "Fallido",
27
+ "canceled": "Cancelado",
28
+ "interrupted": "Interrumpido",
29
+ "app": "Aplicación",
30
+ "worker": "Worker",
31
+ "scope": "Referencia de alcance",
32
+ "actions": "Acciones",
33
+ "steps": "Pasos",
34
+ "expires": "Caducidad",
35
+ "starts": "Inicio más temprano",
36
+ "warning": "Los efectos ya producidos no se pueden deshacer. El consentimiento vale una vez en el período actual.",
37
+ "effects": "Puede haber efectos desconocidos",
38
+ "next": "Página siguiente",
39
+ "accessLost": "No se pudo verificar el acceso. Inicie sesión y abra esta vista de nuevo.",
40
+ "interactiveUnavailable": "Las tareas interactivas no están disponibles hasta conectar las comprobaciones nativas de sesión y permisos.",
41
+ "backgroundUnavailable": "Las tareas en segundo plano no están disponibles.",
42
+ "adminTitle": "Gestión de tareas",
43
+ "loadManagement": "Actualice para cargar el estado de gestión.",
44
+ "revalidating": "Se están revalidando las comprobaciones del paquete. Los trabajos nuevos están en pausa. Actualice para comprobar la recuperación; los trabajos cancelados no se reanudan.",
45
+ "fenceCanceled": "Este trabajo se canceló porque las comprobaciones del paquete no estaban disponibles. Tras la recuperación, reenviarlo crea un trabajo nuevo y vuelve a comprobar los permisos. No hay reenvío automático.",
46
+ "resubmit": "Volver a enviar",
47
+ "resubmitUnavailable": "El plan original no está disponible en esta vista. Seleccione de nuevo las entradas para crear un trabajo nuevo.",
48
+ "resubmitUncertain": "Se perdió la respuesta al reenvío. Compruebe el trabajo nuevo y no vuelva a enviarlo.",
49
+ "resubmitLookup": "Comprobar trabajo nuevo",
50
+ "resubmitSubmitted": "Se envió un trabajo nuevo. El trabajo cancelado sigue detenido.",
51
+ "newInteractive": "Nueva tarea interactiva",
52
+ "chooseSource": "Elegir archivo o carpeta de origen",
53
+ "sourceHelp": "Tarea de solo lectura con su sesión DSM actual. Elegir un archivo guarda el consentimiento para su carpeta. El contenido se descarta; solo se informan contadores.",
54
+ "operation": "Operación",
55
+ "statOperation": "Consultar metadatos",
56
+ "listOperation": "Listar carpeta",
57
+ "readOperation": "Leer archivo (contar bytes)",
58
+ "entryLimit": "Máximo de entradas (1–100)",
59
+ "byteLimit": "Máximo de bytes",
60
+ "submitInteractive": "Enviar tarea una vez",
61
+ "interactiveSubmitted": "Tarea enviada. Consulte el progreso abajo."
62
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "title": "Tâches",
3
+ "unavailable": "Les tâches ne sont pas disponibles dans cette version.",
4
+ "mock": "Aperçu simulé : aucune opération NAS",
5
+ "interactiveHelp": "Cette vue renouvelle les tâches interactives toutes les 2 secondes. Après 6 secondes sans renouvellement, leur annulation commence et se termine après confirmation du nettoyage. Fermer la vue demande une annulation. Un onglet masqué peut entraîner une expiration et une annulation.",
6
+ "backgroundHelp": "Une tâche de fond confirmée peut continuer après fermeture ou déconnexion jusqu’à expiration ou redémarrage. Aucun redémarrage de tâche automatique.",
7
+ "prepare": "Examiner la tâche de fond",
8
+ "confirm": "Confirmer une fois",
9
+ "agree": "J’accepte cette tâche unique en lecture seule pendant mon absence.",
10
+ "refresh": "Actualiser",
11
+ "lookup": "Vérifier la tâche initiale",
12
+ "uncertain": "Réponse perdue. Vérifiez la tâche initiale sans la soumettre à nouveau.",
13
+ "close": "Abandonner l’examen",
14
+ "cancel": "Annuler la tâche",
15
+ "revoke": "Révoquer le consentement",
16
+ "revoked": "Révoqué",
17
+ "drained": "Nettoyage confirmé",
18
+ "cleanup": "Nettoyage nécessaire",
19
+ "unknown": "Total inconnu",
20
+ "error": "Impossible de terminer la demande. Actualisez pour vérifier l’état.",
21
+ "empty": "Aucune tâche",
22
+ "pending": "En attente",
23
+ "running": "En cours",
24
+ "stopping": "Arrêt en cours",
25
+ "succeeded": "Terminé",
26
+ "failed": "Échec",
27
+ "canceled": "Annulé",
28
+ "interrupted": "Interrompu",
29
+ "app": "Application",
30
+ "worker": "Worker",
31
+ "scope": "Référence du périmètre",
32
+ "actions": "Actions",
33
+ "steps": "Étapes",
34
+ "expires": "Expiration",
35
+ "starts": "Début au plus tôt",
36
+ "warning": "Les effets déjà produits ne sont pas annulables. Le consentement ne vaut qu’une fois dans cette session de fonctionnement.",
37
+ "effects": "Effets potentiellement inconnus",
38
+ "next": "Page suivante",
39
+ "accessLost": "Accès non vérifié. Reconnectez-vous et rouvrez cette vue.",
40
+ "interactiveUnavailable": "Les tâches interactives attendent la connexion des contrôles natifs de session et de droits.",
41
+ "backgroundUnavailable": "Les tâches en arrière-plan sont indisponibles.",
42
+ "adminTitle": "Gestion des tâches",
43
+ "loadManagement": "Actualisez pour charger l’état de gestion.",
44
+ "revalidating": "Les vérifications du paquet sont en cours de revalidation. Les nouveaux travaux sont suspendus. Actualisez pour vérifier le rétablissement ; les travaux annulés ne reprennent pas.",
45
+ "fenceCanceled": "Ce travail a été annulé car les vérifications du paquet étaient indisponibles. Après rétablissement, une nouvelle soumission crée un nouveau travail et revérifie les permissions. Aucune soumission automatique.",
46
+ "resubmit": "Soumettre à nouveau",
47
+ "resubmitUnavailable": "Le plan initial est indisponible dans cette vue. Sélectionnez à nouveau les entrées pour créer un nouveau travail.",
48
+ "resubmitUncertain": "La réponse à la nouvelle soumission a été perdue. Vérifiez le nouveau travail sans le soumettre à nouveau.",
49
+ "resubmitLookup": "Vérifier le nouveau travail",
50
+ "resubmitSubmitted": "Un nouveau travail a été soumis. Le travail annulé reste arrêté.",
51
+ "newInteractive": "Nouvelle tâche interactive",
52
+ "chooseSource": "Choisir un fichier ou dossier source",
53
+ "sourceHelp": "Tâche en lecture seule avec votre session DSM actuelle. Choisir un fichier enregistre le consentement pour son dossier parent. Le contenu est supprimé ; seuls les compteurs sont rapportés.",
54
+ "operation": "Opération",
55
+ "statOperation": "Vérifier les métadonnées",
56
+ "listOperation": "Lister le dossier",
57
+ "readOperation": "Lire le fichier (compter les octets)",
58
+ "entryLimit": "Nombre maximal (1–100)",
59
+ "byteLimit": "Octets maximaux",
60
+ "submitInteractive": "Envoyer la tâche une fois",
61
+ "interactiveSubmitted": "Tâche envoyée. Consultez la progression ci-dessous."
62
+ }