@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,64 @@
1
+ # Interactive File Station UI (experimental)
2
+
3
+ This optional entry uses the package CGI's `ctx.call` transport and the current
4
+ user's DSM session. It does not borrow an administrator session, request root
5
+ helper approval, cache DSM credentials or install a mock provider.
6
+
7
+ The existing `main.ts` and SDK worker entry remain the default. To select this
8
+ session-only UI in a generated `native-go --ui vue` project:
9
+
10
+ 1. Enable `integration: {protocol: 2, workers: {}}` in `dsm-package.yaml`.
11
+ 2. Set `SYNOPKGLAND_M2_SIMPLE=1` in `frontend/.env.production.local`.
12
+ 3. Run the existing `synopkgland build-spk` workflow and inspect the final SPK.
13
+
14
+ You can also build the frontend with `SYNOPKGLAND_M2_SIMPLE=1 npm run build`.
15
+ The flag selects `src/m2-main.ts` before the existing SDK-workers entry; it
16
+ selects a session-only surface, without background job or root-maintenance UI.
17
+ It does not change backend permissions. Protocol 1 / no integration lacks the
18
+ required routes and the UI shows that the adapter is unavailable. Without this
19
+ flag, generated artifacts retain their previous bytes.
20
+
21
+ ## SDK display contract
22
+
23
+ `src/nas/m2-contract.ts` exports `M2Provider`, `M2Selection`, `M2Entry`,
24
+ `M2Page`, `M2Session`, safe codes and the 512 KiB / 100-entry bounds.
25
+ `createM2Provider(ctx)` implements status, discovery, confirmation, saved
26
+ selection listing/revocation, relative list/stat/read, mkdir and upload.
27
+ Pass an AbortSignal per operation and call `dispose()` on unmount. Each mount
28
+ owns its provider and clears its UI after account/package change or pagehide.
29
+
30
+ `M2Selection.writable` records consent to attempt writes; it is not a File
31
+ Station permission probe. The backend validates the actual session and current
32
+ File Station permissions on every operation. A selection is an opaque handle
33
+ with a display path, not the native helper's prepare/digest/revision grant.
34
+ User/UID fields in backend records are stripped from the frontend projection.
35
+ Selections use relaxed username/UID identity: recreating both may preserve a
36
+ selection. Paths do not pin inodes or provide symlink/rename confinement.
37
+
38
+ Discovery supports files in returned pages but shows only folders in the
39
+ picker. Pagination advances by the full server page, not the filtered count;
40
+ rendering is bounded to the latest 200 entries. Writes require explicit
41
+ writable consent. Upload creates a new file and does not overwrite. Read and
42
+ upload are limited to 512 KiB; read bytes become a local binary download, never
43
+ HTML or an inline preview.
44
+
45
+ Requests are observed for at most 22 seconds (backend handler: 20 seconds).
46
+ The existing `ctx.call` does not expose transport abort: closing or canceling
47
+ suppresses late display updates but does not establish server rollback or Q.
48
+ No operation is retried automatically. A lost mutation response reports
49
+ `commit-uncertain`; inspect saved selections or the destination before
50
+ resubmitting. Session expiry requires signing into DSM again and refreshing.
51
+ Background/offline work, streaming and atomic publish remain unsupported.
52
+
53
+ ## Local checks
54
+
55
+ Copy `../../_shared/third-party-notices.mjs` into this folder before `npm ci`,
56
+ `npm test`, `npx vue-tsc --noEmit` and `npm run build`. Also build with the M2
57
+ flag. Remove the copied notice tool, `node_modules` and `dist` before root
58
+ repository tests or generating fixtures: the generator copies template files.
59
+
60
+ `test/m2-preview.html` serves synthetic `ctx.call` responses for local browser
61
+ QA. It does not access a NAS and is not the production provider's backend.
62
+ Local unit/jsdom/Chromium tests do not establish DSM compatibility. Actual DSM
63
+ session, File Station ACL, multipart upload and download validation belongs to
64
+ the backend/device-validation thread. No public support claim is made here.
@@ -6,7 +6,8 @@
6
6
  "": {
7
7
  "name": "native-dsm-vue-app",
8
8
  "dependencies": {
9
- "@synopackageland/ui": "0.4.0",
9
+ "@lucide/vue": "1.48.0",
10
+ "@synopackageland/ui": "0.5.7",
10
11
  "vue": "3.5.43"
11
12
  },
12
13
  "devDependencies": {
@@ -1050,9 +1051,9 @@
1050
1051
  }
1051
1052
  },
1052
1053
  "node_modules/@synopackageland/ui": {
1053
- "version": "0.4.0",
1054
- "resolved": "https://registry.npmjs.org/@synopackageland/ui/-/ui-0.4.0.tgz",
1055
- "integrity": "sha512-is5/UdiaDbqvqy53IaecTwoGtFBiX0tcaypBhma6dEnlefHaQrb8UszwPWdY0YrMhgLmt8Z2EIhnesfxnrRVFA==",
1054
+ "version": "0.5.7",
1055
+ "resolved": "https://registry.npmjs.org/@synopackageland/ui/-/ui-0.5.7.tgz",
1056
+ "integrity": "sha512-egHKoU4Jk33MhZULykelsq5+JB+l8DuRTCD/hOo3ZZa+p2aXoZSl6M0Gwpd+FGLvvARTsrtT8A5lk/PXTMqUmA==",
1056
1057
  "license": "MIT",
1057
1058
  "dependencies": {
1058
1059
  "@internationalized/date": "3.12.4",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-dsm-vue-app", "private": true, "type": "module",
3
3
  "scripts": {"build": "vue-tsc --noEmit && vite build", "test": "vitest run"},
4
- "dependencies": {"@synopackageland/ui": "0.4.0", "vue": "3.5.43"},
4
+ "dependencies": {"@lucide/vue": "1.48.0", "@synopackageland/ui": "0.5.7", "vue": "3.5.43"},
5
5
  "devDependencies": {"@vitejs/plugin-vue": "6.0.9", "vite": "7.3.6", "typescript": "5.9.3", "vue-tsc": "3.3.11", "vitest": "4.1.11", "jsdom": "26.1.0"}
6
6
  }
@@ -1,11 +1,14 @@
1
1
  <script setup lang="ts">
2
- import {computed, inject, onMounted, onUnmounted, ref} from 'vue'
3
- import {AppRoot, Button, Callout, Dialog, SettingsSection, Textarea} from '@synopackageland/ui'
2
+ import {computed, inject, onMounted, onUnmounted, ref, watch} from 'vue'
3
+ import {AppRoot, ConfigProvider, Button, Callout, Dialog, Form, FormActions, FormItem, SettingsSection, Textarea} from '@synopackageland/ui'
4
+ import {uiLocale} from './nas/m2-i18n'
4
5
  import {stateCopy, type AppStatus, type Context, type Status} from './context'
5
6
  import {NasProviderKey} from './nas/provider'
6
7
  import {errorCopy, nasCopy} from './nas/i18n'
7
8
  import NasGrantSettings from './nas/NasGrantSettings.vue'
8
9
  import NasUnavailable from './nas/NasUnavailable.vue'
10
+ import AppShell from './shell/AppShell.vue'
11
+ import {activePage, shellPages, type ShellPage} from './shell/pages'
9
12
  const nasProvider = inject(NasProviderKey, null)
10
13
  // A mount owns one provider binding. A native subject/package switch must
11
14
  // discard its UI and pending work; the host supplies a new provider on remount.
@@ -22,9 +25,20 @@ const text = ref('')
22
25
  const identity = ref('')
23
26
  let disposed = false
24
27
  const refreshing = ref(false)
28
+ const hasIdentity = ref(false)
25
29
  let appCookie = ''
30
+ // The CLI rewrites this to "true" only for a project whose manifest declares
31
+ // the sha256-v1 background worker (--background).
32
+ const backgroundEnabled = (('__BACKGROUND_ENABLED__') as string) === 'true'
33
+ const page = ref<ShellPage>('status')
34
+ const pages = computed(() => shellPages({sample:status.value?.state === 'ready',nas:true,background:backgroundEnabled,identity:hasIdentity.value}))
35
+ watch(pages,list => {page.value = activePage(page.value,list)})
36
+ const subtitle = computed(() => app.value ? `${app.value.package} · ${app.value.user} · ${app.value.version}` : undefined)
26
37
  const configured = computed(() => status.value?.reason !== "not-requested")
38
+ // An integration built without a privileged helper has nothing to approve.
39
+ const packageOnly = computed(() => status.value?.reason === 'package-only')
27
40
  const details = computed(() => {
41
+ if(packageOnly.value) return {label:'Ready',description:'This package runs as its own DSM package account. No privileged helper is installed.'}
28
42
  if(status.value?.state === 'pending') {
29
43
  const copy = nasCopy(props.ctx.locale)
30
44
  return {label:copy.healthPending,description:copy.healthPendingHelp}
@@ -97,7 +111,6 @@ async function checkIdentity() {
97
111
  try {const result=await props.ctx.call<{user:string}>('identity.current',{cookie:appCookie});if(!disposed) identity.value=`App session for ${result.user}`}
98
112
  catch(e) {if(!disposed) {appCookie='';identity.value='';error.value=message(e)}} finally {if(!disposed) busy.value=false}
99
113
  }
100
- const hasIdentity = ref(false)
101
114
  onMounted(async()=>{
102
115
  props.ctx.reopen(()=>{if(!disposed) void refresh()})
103
116
  await refresh()
@@ -109,20 +122,22 @@ onUnmounted(()=>{disposed=true;appCookie='';text.value='';id.value=''})
109
122
 
110
123
  <template>
111
124
  <AppRoot modal-scope="app" style="height: 100%">
112
- <main class="integration-app" :aria-busy="busy || refreshing" aria-label="Package settings">
113
- <header class="integration-heading">
114
- <div><h1>{{ app?.package || 'Package settings' }}</h1><p v-if="app">{{ app.user }} · {{ app.version }}</p></div>
125
+ <ConfigProvider :locale="uiLocale(ctx.locale)">
126
+ <AppShell v-model="page" :locale="ctx.locale" :pages="pages" :description="subtitle">
127
+ <template #actions>
115
128
  <Button variant="secondary" :disabled="busy || refreshing" @click="error=''; refresh()">Refresh</Button>
116
- </header>
129
+ </template>
130
+ <div class="integration-app" :aria-busy="busy || refreshing" aria-label="Package settings">
117
131
  <p v-if="refreshing" role="status">Refreshing status…</p>
118
132
  <p v-else-if="busy" role="status">Completing operation…</p>
119
133
  <Callout v-if="error" tone="danger" title="Action required"><span role="alert">{{ error }}</span></Callout>
120
134
  <p v-if="notice" class="integration-notice" role="status">{{ notice }}</p>
135
+ <div data-page="status" v-show="page==='status'">
121
136
  <SettingsSection title="DSM integration" :collapsible="false">
122
137
  <div v-if="status && details" :data-integration-state="status.state" class="integration-status" role="status">
123
138
  <h2>{{ details.label }}</h2><p>{{ details.description }}</p>
124
139
  <p v-if="status.cleanup === 'required'">Cleanup is required. Ask an administrator to run teardown or disable. If the helper supervisor was lost, use Repair cleanup and follow the package recovery instructions.</p>
125
- <dl><dt>Package running</dt><dd>{{ status.packageRunning }}</dd><dt>Scheduler</dt><dd>{{ status.scheduler }}</dd></dl>
140
+ <dl><dt>Package running</dt><dd>{{ status.packageRunning }}</dd><template v-if="!packageOnly"><dt>Scheduler</dt><dd>{{ status.scheduler }}</dd></template></dl>
126
141
  </div>
127
142
  <p v-else-if="error" role="status">Status could not be loaded. Refresh to try again.</p>
128
143
  <p v-else role="status">Loading integration status…</p>
@@ -136,24 +151,37 @@ onUnmounted(()=>{disposed=true;appCookie='';text.value='';id.value=''})
136
151
  <p v-if="app?.admin && ctx.root && configured" class="integration-help">Repair cleanup clears verified leftover helper state. It does not restart integration.</p>
137
152
  <Callout v-if="app && !app.admin && status?.state !== 'ready' && status?.state !== 'pending'" title="Administrator action needed">Ask a DSM administrator to open this package's settings. Your login cannot approve root operations.</Callout>
138
153
  </SettingsSection>
154
+ </div>
155
+ <div data-page="sample" v-show="page==='sample'">
139
156
  <SettingsSection v-if="status?.state === 'ready'" title="My sample data" :collapsible="false">
140
157
  <p class="integration-help">This synthetic note belongs to your DSM account and is stored in package data.</p>
141
158
  <p v-if="refreshing" role="status">Loading your sample data…</p>
142
159
  <Callout v-else-if="!id" title="No sample data">Refresh to request your sample data again.</Callout>
143
- <label v-if="id" class="integration-field"><span>My sample note</span><Textarea v-model="text" aria-label="My sample note" :disabled="busy || refreshing" /></label>
144
- <Button v-if="id" variant="primary" :disabled="busy || refreshing" @click="save">Save my note</Button>
160
+ <Form v-if="id" @submit.prevent><FormItem label="My sample note"><Textarea v-model="text" :disabled="busy || refreshing" /></FormItem>
161
+ <FormActions><Button variant="primary" :disabled="busy || refreshing" @click="save">Save my note</Button></FormActions>
162
+ </Form>
145
163
  </SettingsSection>
164
+ </div>
165
+ <div data-page="nas" v-show="page==='nas'">
146
166
  <NasGrantSettings v-if="nasProvider && app && status && !nasInvalidated" :locale="ctx.locale" />
147
167
  <NasUnavailable v-else :locale="ctx.locale" />
168
+ </div>
169
+ <div data-page="background" v-show="page==='background'">
170
+ <!-- BACKGROUND_PANEL -->
171
+ </div>
172
+ <div data-page="identity" v-show="page==='identity'">
148
173
  <SettingsSection v-if="hasIdentity" title="Optional app identity" :collapsible="false">
149
174
  <p class="integration-help">Your DSM login is checked again for every app session request.</p>
150
175
  <div class="integration-actions"><Button variant="primary" :disabled="busy || refreshing" @click="login">Create app session</Button><Button variant="secondary" :disabled="busy || refreshing || !identity" @click="checkIdentity">Check app session</Button></div>
151
176
  <p v-if="identity" role="status">{{ identity }}</p>
152
177
  </SettingsSection>
178
+ </div>
179
+ </div>
153
180
  <Dialog v-model:open="disableOpen" title="Disable integration?" description="New integration requests will be refused before helper cleanup begins.">
154
181
  <p>Your sample data and historical root output are retained. A failed cleanup remains visible.</p>
155
182
  <template #footer><Button variant="secondary" @click="disableOpen=false">Cancel</Button><Button variant="danger" :disabled="busy || refreshing" @click="disableOpen=false; action('helper_disable')">Confirm disable</Button></template>
156
183
  </Dialog>
157
- </main>
184
+ </AppShell>
185
+ </ConfigProvider>
158
186
  </AppRoot>
159
187
  </template>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import {computed,inject,onMounted,onUnmounted,ref} from 'vue'
3
+ import {AppRoot,ConfigProvider,Button,Callout,SettingsSection} from '@synopackageland/ui'
4
+ import type {AppStatus,Context} from './context'
5
+ import {M2ProviderKey} from './nas/m2-contract'
6
+ import {m2Copy,m2ErrorCopy,uiLocale} from './nas/m2-i18n'
7
+ import {useM2Request} from './nas/use-m2-request'
8
+ import M2Settings from './nas/M2Settings.vue'
9
+ import AppShell from './shell/AppShell.vue'
10
+ import {shellPages,type ShellPage} from './shell/pages'
11
+ const props=defineProps<{ctx:Context}>(),copy=computed(()=>m2Copy(props.ctx.locale)),provider=inject(M2ProviderKey)!
12
+ const request=useM2Request(),{busy,error}=request
13
+ const app=ref<AppStatus>(),invalid=ref(false),view=ref(0),nestedBusy=ref(false)
14
+ const page=ref<ShellPage>('status')
15
+ // The simple session build only has the File Station folder screen.
16
+ const pages=computed(()=>shellPages({folders:true}))
17
+ const subtitle=computed(()=>app.value?`${app.value.package} · ${app.value.version} · ${app.value.user}`:undefined)
18
+ let bound:{user:string;package:string}|undefined
19
+ let removeReopen:()=>void=()=>{}
20
+ async function refresh(){
21
+ if(invalid.value)return
22
+ const value=await request.run(()=>props.ctx.call<AppStatus>('app.status'))
23
+ if(value){
24
+ if(typeof value.user!=='string'||!value.user||typeof value.package!=='string'||!value.package){error.value={code:'unavailable'};return}
25
+ if(bound&&(bound.user!==value.user||bound.package!==value.package)){invalidate();return}
26
+ bound??={user:value.user,package:value.package};app.value=value;view.value++
27
+ }else{app.value=undefined}
28
+ }
29
+ function invalidate(){invalid.value=true;app.value=undefined;request.cancel();provider.dispose()}
30
+ onMounted(()=>{removeReopen=props.ctx.reopen(()=>void refresh());window.addEventListener('pagehide',invalidate);void refresh()})
31
+ onUnmounted(()=>{removeReopen?.();window.removeEventListener('pagehide',invalidate);app.value=undefined})
32
+ </script>
33
+ <template>
34
+ <AppRoot theme="dsm7" modal-scope="app" style="height: 100%">
35
+ <ConfigProvider :locale="uiLocale(ctx.locale)">
36
+ <AppShell v-model="page" :locale="ctx.locale" :pages="pages" :description="subtitle">
37
+ <template #actions>
38
+ <Button v-if="!invalid" variant="secondary" :disabled="busy||nestedBusy" @click="refresh">{{ copy.refresh }}</Button>
39
+ </template>
40
+ <div class="integration-app m2-app" :aria-busy="busy||nestedBusy">
41
+ <Callout v-if="invalid" tone="warning" role="alert">{{ copy.accountChanged }}</Callout>
42
+ <Callout v-else-if="error" tone="danger" role="alert">{{ m2ErrorCopy(error,copy) }}</Callout>
43
+ <p v-if="busy" role="status">{{ copy.loading }}</p>
44
+ <div data-page="status" v-show="page==='status'">
45
+ <SettingsSection title="Package" :collapsible="false">
46
+ <p v-if="app" role="status">{{ app.package }} · {{ app.version }} · {{ app.user }}</p>
47
+ <p v-else role="status">{{ copy.loading }}</p>
48
+ </SettingsSection>
49
+ </div>
50
+ <div data-page="folders" v-show="page==='folders'">
51
+ <M2Settings v-if="app&&!invalid" :key="view" :locale="ctx.locale" @busy="value=>nestedBusy=value" />
52
+ </div>
53
+ </div>
54
+ </AppShell>
55
+ </ConfigProvider>
56
+ </AppRoot>
57
+ </template>
@@ -0,0 +1,203 @@
1
+ <script setup lang="ts">
2
+ import {computed, inject, onMounted, onUnmounted, ref, watch} from 'vue'
3
+ import {AppRoot, ConfigProvider, Button, Callout, Dialog, Form, FormActions, FormItem, SettingsSection, Textarea} from '@synopackageland/ui'
4
+ import {uiLocale} from './nas/m2-i18n'
5
+ import {stateCopy, type AppStatus, type Context, type Status} from './context'
6
+ import {NasProviderKey} from './nas/provider'
7
+ import {errorCopy, nasCopy} from './nas/i18n'
8
+ import NasGrantSettings from './nas/NasGrantSettings.vue'
9
+ import NasUnavailable from './nas/NasUnavailable.vue'
10
+ import JobsPanel from './jobs/JobsPanel.vue'
11
+ import {JobsProviderKey} from './jobs/provider'
12
+ const jobsProvider=inject(JobsProviderKey,null)
13
+ import JobsAdminPanel from './jobs/JobsAdminPanel.vue'
14
+ import AppShell from './shell/AppShell.vue'
15
+ import {activePage,shellPages,type ShellPage} from './shell/pages'
16
+ const nasProvider = inject(NasProviderKey, null)
17
+ // A mount owns one provider binding. A native subject/package switch must
18
+ // discard its UI and pending work; the host supplies a new provider on remount.
19
+ const nasInvalidated = ref(false)
20
+ const props = defineProps<{ctx: Context}>()
21
+ const app = ref<AppStatus>()
22
+ const status = ref<Status>()
23
+ const busy = ref(false)
24
+ const error = ref('')
25
+ const notice = ref('')
26
+ const disableOpen = ref(false)
27
+ const id = ref('')
28
+ const text = ref('')
29
+ const identity = ref('')
30
+ let disposed = false
31
+ const refreshing = ref(false)
32
+ const hasIdentity = ref(false)
33
+ let appCookie = ''
34
+ const page = ref<ShellPage>('status')
35
+ const pages = computed(() => shellPages({
36
+ // The session-SDK build submits interactive work instead of sample notes.
37
+ sample: status.value?.state === 'ready' && !jobsProvider?.interactive,
38
+ // Connected workers carry their own consent per job; the grant screen only
39
+ // exists while no interactive worker is advertised.
40
+ nas: !!nasProvider || !jobsProvider?.interactive?.workers.length,
41
+ interactive: !!jobsProvider?.interactive,
42
+ background: jobsProvider?.readiness?.background !== 'unavailable',
43
+ admin: !!app.value?.admin,
44
+ identity: hasIdentity.value,
45
+ }))
46
+ watch(pages,list => {page.value = activePage(page.value,list)})
47
+ const subtitle = computed(() => app.value ? `${app.value.package} · ${app.value.user} · ${app.value.version}` : undefined)
48
+ const configured = computed(() => status.value?.reason !== "not-requested")
49
+ const details = computed(() => {
50
+ if(status.value?.state === 'pending') {
51
+ const copy = nasCopy(props.ctx.locale)
52
+ return {label:copy.healthPending,description:copy.healthPendingHelp}
53
+ }
54
+ return status.value ? stateCopy[status.value.state] : undefined
55
+ })
56
+ function message(e: unknown) {
57
+ const code = (e as {code?: string})?.code || 'request_failed'
58
+ if(['denied','unknown_method','unavailable','unsupported','session_required','auth_unavailable'].includes(code)) return errorCopy(e,nasCopy(props.ctx.locale))
59
+ return ({session_required:'Your DSM session expired. Sign in again.',access_denied:'This sample belongs to another account.',integration_unavailable:'Integration is unavailable. Ask an administrator to activate or recover it.',personal_unavailable:'Sample storage is unavailable. Ask an administrator to check package data.',root_conflict:'A conflicting scheduler task exists. Ask an administrator to review it.',root_verify_failed:'Scheduler verification failed. Refresh and review the task.',root_run_failed:'The approved operation failed. Review integration status and cleanup.'} as Record<string,string>)[code] || `Request failed (${code}). Refresh and try again.`
60
+ }
61
+ async function refresh() {
62
+ if(disposed || refreshing.value) return
63
+ refreshing.value = true; error.value = ''
64
+ try {
65
+ const [a,s] = await Promise.all([props.ctx.call<AppStatus>('app.status'),props.ctx.call<Status>('integration.status')])
66
+ if(disposed) return
67
+ if(app.value && (app.value.user!==a.user || app.value.package!==a.package)) nasInvalidated.value=true
68
+ app.value = a; status.value = s
69
+ if(s.state !== 'ready') {id.value='';text.value='';return}
70
+ // The session SDK build exposes File Station jobs, not native sample notes.
71
+ if(jobsProvider?.interactive) {id.value='';text.value='';return}
72
+ // Plain --ui vue has no personal routes; not-enabled status hides this.
73
+ const list = await props.ctx.call<{items:Array<{id:string;name:string}>}>('personal.list')
74
+ if(disposed) return
75
+ id.value = list.items[0]?.id || ''
76
+ if(id.value) {
77
+ const note = await props.ctx.call<{text:string}>('personal.read',{id:id.value})
78
+ if(!disposed) text.value = note.text
79
+ }
80
+ } catch(e) {if(!disposed) {error.value = message(e);status.value=undefined;id.value='';text.value=''}} finally {refreshing.value=false}
81
+ }
82
+ async function action(op: string) {
83
+ if(busy.value || refreshing.value || disposed) return
84
+ busy.value=true;error.value='';notice.value=''
85
+ try {
86
+ if(!props.ctx.root) throw {code:'unsupported'}
87
+ const approved = await props.ctx.root.authorize(op)
88
+ if(disposed) return
89
+ if(approved !== 'ready') {notice.value='Approval cancelled. No operation was run.';return}
90
+ await props.ctx.root.run(op)
91
+ if(disposed) return
92
+ notice.value=op==='helper_repair' ? 'Cleanup repaired. Use Recover or Approve and activate when ready.' : 'Operation completed. Integration status was checked again.'
93
+ await refresh()
94
+ } catch(e) {if(!disposed) {
95
+ await refresh()
96
+ if(!disposed) {
97
+ const code=(e as {code?:string})?.code
98
+ if(code==='root_cancelled') notice.value='Repair confirmation cancelled. No operation was run.'
99
+ else error.value=op==='helper_repair' && (code==='root_run_failed' || code==='root_task_failed') ? 'Repair could not verify safe cleanup. Review the package recovery instructions before trying again.' : message(e)
100
+ }
101
+ }}
102
+ finally {if(!disposed) busy.value=false}
103
+ }
104
+ async function save() {
105
+ if(busy.value || refreshing.value || !id.value || disposed) return
106
+ busy.value=true;error.value='';notice.value=''
107
+ try {await props.ctx.call('personal.write',{id:id.value,text:text.value});if(!disposed) notice.value='Your sample note was saved.'}
108
+ catch(e) {if(!disposed) error.value=message(e)} finally {if(!disposed) busy.value=false}
109
+ }
110
+ async function login() {
111
+ if(busy.value || refreshing.value || disposed) return
112
+ busy.value=true;error.value=''
113
+ try {
114
+ const result=await props.ctx.call<{cookie:string;user:string}>('identity.login')
115
+ if(!disposed){appCookie=result.cookie;identity.value=`App session for ${result.user}`}
116
+ } catch(e) {if(!disposed) error.value=message(e)} finally {if(!disposed) busy.value=false}
117
+ }
118
+ async function checkIdentity() {
119
+ if(busy.value || refreshing.value || disposed) return
120
+ busy.value=true;error.value=''
121
+ try {const result=await props.ctx.call<{user:string}>('identity.current',{cookie:appCookie});if(!disposed) identity.value=`App session for ${result.user}`}
122
+ catch(e) {if(!disposed) {appCookie='';identity.value='';error.value=message(e)}} finally {if(!disposed) busy.value=false}
123
+ }
124
+ onMounted(async()=>{
125
+ props.ctx.reopen(()=>{if(!disposed) void refresh()})
126
+ await refresh()
127
+ if(disposed || !app.value) return
128
+ try {const result = await props.ctx.call<{mode:string}>('identity.status');if(!disposed) hasIdentity.value = result.mode==='better-auth'} catch { /* Optional route absent in Go-only. */ }
129
+ })
130
+ onUnmounted(()=>{disposed=true;appCookie='';text.value='';id.value=''})
131
+ </script>
132
+
133
+ <template>
134
+ <AppRoot modal-scope="app" style="height: 100%">
135
+ <ConfigProvider :locale="uiLocale(ctx.locale)">
136
+ <AppShell v-model="page" :locale="ctx.locale" :pages="pages" :description="subtitle">
137
+ <template #actions>
138
+ <Button variant="secondary" :disabled="busy || refreshing" @click="error=''; refresh()">Refresh</Button>
139
+ </template>
140
+ <div class="integration-app" :aria-busy="busy || refreshing" aria-label="Package settings">
141
+ <p v-if="refreshing" role="status">Refreshing status…</p>
142
+ <p v-else-if="busy" role="status">Completing operation…</p>
143
+ <Callout v-if="error" tone="danger" title="Action required"><span role="alert">{{ error }}</span></Callout>
144
+ <p v-if="notice" class="integration-notice" role="status">{{ notice }}</p>
145
+ <div data-page="status" v-show="page==='status'">
146
+ <SettingsSection title="DSM integration" :collapsible="false">
147
+ <div v-if="status && details" :data-integration-state="status.state" class="integration-status" role="status">
148
+ <h2>{{ details.label }}</h2><p>{{ details.description }}</p>
149
+ <p v-if="status.cleanup === 'required'">Cleanup is required. Ask an administrator to run teardown or disable. If the helper supervisor was lost, use Repair cleanup and follow the package recovery instructions.</p>
150
+ <dl><dt>Package running</dt><dd>{{ status.packageRunning }}</dd><dt>Scheduler</dt><dd>{{ status.scheduler }}</dd></dl>
151
+ </div>
152
+ <p v-else-if="error" role="status">Status could not be loaded. Refresh to try again.</p>
153
+ <p v-else role="status">Loading integration status…</p>
154
+ <div v-if="app?.admin && ctx.root && configured" class="integration-actions">
155
+ <Button variant="primary" :disabled="busy || refreshing" @click="action('helper_enable')">Approve and activate</Button>
156
+ <Button variant="secondary" :disabled="busy || refreshing" @click="action('helper_recover')">Recover</Button>
157
+ <Button variant="secondary" :disabled="busy || refreshing" @click="action('helper_teardown')">Teardown</Button>
158
+ <Button variant="secondary" :disabled="busy || refreshing" @click="disableOpen=true">Disable</Button>
159
+ <Button variant="secondary" :disabled="busy || refreshing" @click="action('helper_repair')">Repair cleanup</Button>
160
+ </div>
161
+ <p v-if="app?.admin && ctx.root && configured" class="integration-help">Repair cleanup clears verified leftover helper state. It does not restart integration.</p>
162
+ <Callout v-if="app && !app.admin && status?.state !== 'ready' && status?.state !== 'pending'" title="Administrator action needed">Ask a DSM administrator to open this package's settings. Your login cannot approve root operations.</Callout>
163
+ </SettingsSection>
164
+ </div>
165
+ <div data-page="sample" v-show="page==='sample'">
166
+ <SettingsSection v-if="status?.state === 'ready' && !jobsProvider?.interactive" title="My sample data" :collapsible="false">
167
+ <p class="integration-help">This synthetic note belongs to your DSM account and is stored in package data.</p>
168
+ <p v-if="refreshing" role="status">Loading your sample data…</p>
169
+ <Callout v-else-if="!id" title="No sample data">Refresh to request your sample data again.</Callout>
170
+ <Form v-if="id" @submit.prevent><FormItem label="My sample note"><Textarea v-model="text" :disabled="busy || refreshing" /></FormItem>
171
+ <FormActions><Button variant="primary" :disabled="busy || refreshing" @click="save">Save my note</Button></FormActions>
172
+ </Form>
173
+ </SettingsSection>
174
+ </div>
175
+ <div data-page="nas" v-show="page==='nas'">
176
+ <NasGrantSettings v-if="nasProvider && app && status && !nasInvalidated" :locale="ctx.locale" />
177
+ <NasUnavailable v-else-if="!jobsProvider?.interactive?.workers.length" :locale="ctx.locale" />
178
+ </div>
179
+ <div data-page="interactive" v-show="page==='interactive'">
180
+ <JobsPanel v-if="app && !nasInvalidated" section="interactive" :locale="ctx.locale" />
181
+ </div>
182
+ <div data-page="background" v-show="page==='background'">
183
+ <JobsPanel v-if="app && !nasInvalidated" section="background" :locale="ctx.locale" />
184
+ </div>
185
+ <div data-page="admin" v-show="page==='admin'">
186
+ <JobsAdminPanel v-if="app?.admin && !nasInvalidated" :locale="ctx.locale" />
187
+ </div>
188
+ <div data-page="identity" v-show="page==='identity'">
189
+ <SettingsSection v-if="hasIdentity" title="Optional app identity" :collapsible="false">
190
+ <p class="integration-help">Your DSM login is checked again for every app session request.</p>
191
+ <div class="integration-actions"><Button variant="primary" :disabled="busy || refreshing" @click="login">Create app session</Button><Button variant="secondary" :disabled="busy || refreshing || !identity" @click="checkIdentity">Check app session</Button></div>
192
+ <p v-if="identity" role="status">{{ identity }}</p>
193
+ </SettingsSection>
194
+ </div>
195
+ </div>
196
+ <Dialog v-model:open="disableOpen" title="Disable integration?" description="New integration requests will be refused before helper cleanup begins.">
197
+ <p>Your sample data and historical root output are retained. A failed cleanup remains visible.</p>
198
+ <template #footer><Button variant="secondary" @click="disableOpen=false">Cancel</Button><Button variant="danger" :disabled="busy || refreshing" @click="disableOpen=false; action('helper_disable')">Confirm disable</Button></template>
199
+ </Dialog>
200
+ </AppShell>
201
+ </ConfigProvider>
202
+ </AppRoot>
203
+ </template>
@@ -0,0 +1,70 @@
1
+ <script setup lang="ts">
2
+ import {computed,ref,watch} from 'vue'
3
+ import {Button,Callout,Form,FormActions,FormItem,Input,Select} from '@synopackageland/ui'
4
+ import type {JobsProvider,PreparedInteractive} from './provider'
5
+ import type {M2JobSource} from '../nas/m2-contract'
6
+ import M2PathPicker from '../nas/M2PathPicker.vue'
7
+ import {m2Copy,m2ErrorCopy} from '../nas/m2-i18n'
8
+ import {jobCopy} from './i18n'
9
+ import {useNasRequest} from '../nas/use-request'
10
+ const props=defineProps<{locale:string;provider:JobsProvider}>(),emit=defineEmits<{submitted:[]}>()
11
+ const copy=computed(()=>jobCopy(props.locale)),request=useNasRequest(),{busy,error}=request
12
+ const open=ref(false),pickerBusy=ref(false),source=ref<M2JobSource>(),workerId=ref(''),action=ref('nas.files.stat'),bound=ref(100),uncertain=ref<PreparedInteractive>(),notice=ref(false),invalid=ref(false)
13
+ const worker=computed(()=>props.provider.interactive?.workers.find(w=>w.id===workerId.value))
14
+ const actions=computed(()=>worker.value?.actions.filter(a=>source.value?.entry.isDir?a!=='nas.files.read':a!=='nas.files.list')??[])
15
+ const workerOptions=computed(()=>props.provider.interactive?.workers.map(w=>({value:w.id,label:`${w.id} · ${w.revision}`}))??[])
16
+ const operationLabel=(a:string)=>a==='nas.files.list'?copy.value.listOperation:a==='nas.files.read'?copy.value.readOperation:copy.value.statOperation
17
+ const actionOptions=computed(()=>actions.value.map(a=>({value:a,label:operationLabel(a)})))
18
+ const ready=computed(()=>props.provider.readiness?.interactive==='ready'&&!invalid.value)
19
+ const locked=computed(()=>busy.value||pickerBusy.value||!!uncertain.value||!ready.value)
20
+ watch(()=>props.provider.interactive?.workers,workers=>{if(!workers?.some(w=>w.id===workerId.value))workerId.value=workers?.[0]?.id??''},{immediate:true})
21
+ watch(actions,values=>{if(!values.includes(action.value as never))action.value=values[0]??''})
22
+ watch(action,value=>{bound.value=value==='nas.files.read'?worker.value?.maxBytes??1:100})
23
+ watch(error,e=>{if(['session_required','auth_unavailable','denied'].includes((e as {code?:string})?.code??'')){invalid.value=true;source.value=undefined;open.value=false}})
24
+ function select(value:M2JobSource){source.value=value;notice.value=false}
25
+ async function submit(){
26
+ if(locked.value||!source.value||!worker.value)return
27
+ const chosen=source.value,w=worker.value,a=action.value
28
+ if(!actions.value.includes(a as never)||((a==='nas.files.list'||a==='nas.files.read')&&(!Number.isSafeInteger(bound.value)||bound.value<1||bound.value>(a==='nas.files.list'?100:w.maxBytes)))){error.value={code:'invalid-request'};return}
29
+ await request.run(async signal=>{
30
+ const prepared=await props.provider.interactive!.prepareInteractive(signal,{id:w.id,revision:w.revision},{id:chosen.selection.grantId,revision:1},{steps:[{action:a,segments:[...chosen.segments],...(a==='nas.files.list'?{limit:bound.value}:a==='nas.files.read'?{maxBytes:bound.value}:{})}]})
31
+ if(Date.now()>=prepared.expiresAt)throw {code:'expired'}
32
+ // Preserve the original intent before the single submit attempt. A missing
33
+ // reply cannot establish rollback; lookup never creates or attaches a job.
34
+ uncertain.value=prepared
35
+ await props.provider.interactive!.submitInteractive(prepared,signal)
36
+ uncertain.value=undefined;source.value=undefined;notice.value=true;emit('submitted')
37
+ })
38
+ }
39
+ async function lookup(){
40
+ const original=uncertain.value;if(!original||busy.value)return
41
+ const found=await request.run(signal=>props.provider.lookup(original.intentId,signal))
42
+ if(found?.jobId===original.jobId){uncertain.value=undefined;source.value=undefined;notice.value=true;emit('submitted')}
43
+ }
44
+ const errorText=computed(()=>{
45
+ const code=(error.value as {code?:string})?.code
46
+ if(code==='revalidating')return copy.value.revalidating
47
+ if(code==='session_required'||code==='auth_unavailable')return copy.value.accessLost
48
+ if(['denied','invalid-request','limit-exceeded'].includes(code??''))return m2ErrorCopy(error.value,m2Copy(props.locale))
49
+ return copy.value.error
50
+ })
51
+ </script>
52
+ <template>
53
+ <Form class="jobs-input" :aria-label="copy.newInteractive" :aria-busy="busy||pickerBusy" @submit.prevent="submit">
54
+ <h3>{{ copy.newInteractive }}</h3>
55
+ <p>{{ copy.sourceHelp }}</p>
56
+ <Callout v-if="error" tone="danger" role="alert">{{ errorText }}</Callout>
57
+ <p v-if="notice" role="status">{{ copy.interactiveSubmitted }}</p>
58
+ <Button variant="secondary" :disabled="locked" @click="open=true">{{ copy.chooseSource }}</Button>
59
+ <p v-if="source" role="status">{{ source.entry.path }}</p>
60
+ <FormItem :label="copy.worker"><Select v-model="workerId" :options="workerOptions" :disabled="locked" /></FormItem>
61
+ <FormItem :label="copy.operation"><Select v-model="action" data-job-action :options="actionOptions" :disabled="locked||!source" /></FormItem>
62
+ <FormItem v-if="action==='nas.files.list'||action==='nas.files.read'" :label="action==='nas.files.list'?copy.entryLimit:copy.byteLimit"><Input v-model.number="bound" data-job-bound type="number" min="1" :max="action==='nas.files.list'?100:worker?.maxBytes" step="1" :disabled="locked" /></FormItem>
63
+ <FormActions><Button type="submit" variant="primary" :disabled="locked||!source||!worker||!actions.length">{{ copy.submitInteractive }}</Button></FormActions>
64
+ <template v-if="uncertain"><p role="status">{{ copy.uncertain }}</p><Button variant="secondary" :disabled="busy||invalid" @click="lookup">{{ copy.lookup }}</Button></template>
65
+ <M2PathPicker v-model:open="open" :locale="locale" :title="copy.chooseSource" select-files read-only @source="select" @busy="value=>pickerBusy=value" />
66
+ </Form>
67
+ </template>
68
+ <style scoped>
69
+ .jobs-input { margin-block: var(--ui-space-4, 16px); }
70
+ </style>
@@ -0,0 +1,33 @@
1
+ <script setup lang="ts">
2
+ import {computed,inject,onMounted,ref,watch} from 'vue'
3
+ import {Button,Callout,SettingsSection} from '@synopackageland/ui'
4
+ import {JobsAdminProviderKey,type AdminJobView} from './provider'
5
+ import {jobCopy} from './i18n'
6
+ import {adminPage} from './validate'
7
+ import {useNasRequest} from '../nas/use-request'
8
+ const props=defineProps<{locale:string}>(),copy=computed(()=>jobCopy(props.locale))
9
+ const provider=inject(JobsAdminProviderKey,null),request=useNasRequest(),{busy,error}=request,items=ref<readonly AdminJobView[]>([]),nextCursor=ref<string>()
10
+ const invalidated=ref(false),loaded=ref(false)
11
+ watch(error,e=>{if(['denied','session_required','auth_unavailable'].includes((e as {code?:string})?.code??'')){invalidated.value=true;items.value=[]}})
12
+ async function load(cursor?:string){if(!provider||invalidated.value)return;const result=await request.run(async signal=>adminPage(await provider.list(signal,cursor)));if(result){loaded.value=true;items.value=result.items;nextCursor.value=result.nextCursor}else if(error.value){items.value=[];nextCursor.value=undefined}}
13
+ async function refresh(){await load()}
14
+ async function cancel(item:AdminJobView){if(!provider)return;await request.run(signal=>provider.cancel(item.jobId,item.revision,signal));await refresh()}
15
+ function state(item:AdminJobView){return ({pending:copy.value.pending,running:copy.value.running,'cancel-requested':copy.value.stopping,draining:copy.value.stopping,succeeded:copy.value.succeeded,failed:copy.value.failed,canceled:copy.value.canceled,interrupted:copy.value.interrupted,'cleanup-required':copy.value.cleanup})[item.state]}
16
+ onMounted(()=>{if(provider?.mode==='mock')void refresh()})
17
+ </script>
18
+ <template>
19
+ <SettingsSection :title="copy.adminTitle" :collapsible="false" :aria-busy="busy">
20
+ <Callout v-if="!provider||provider.mode==='unavailable'" tone="info" :title="copy.unavailable" />
21
+ <Callout v-else-if="invalidated" tone="danger" :title="copy.accessLost" role="alert" />
22
+ <template v-else>
23
+ <p v-if="provider.mode==='mock'">{{ copy.mock }}</p><p v-else-if="!loaded&&!error">{{ copy.loadManagement }}</p><Callout v-if="error" tone="danger" :title="copy.error" role="alert" />
24
+ <Button :disabled="busy" variant="secondary" @click="refresh">{{ copy.refresh }}</Button>
25
+ <p v-if="loaded&&!items.length&&!error">{{ copy.empty }}</p>
26
+ <ul class="nas-grants"><li v-for="item in items" :key="item.jobId">
27
+ <p role="status">{{ state(item) }}</p><p v-if="item.drained">{{ copy.drained }}</p><p v-if="item.effectsUnknown">{{ copy.effects }}</p>
28
+ <Button v-if="['pending','running','cancel-requested','draining'].includes(item.state)" :disabled="busy" variant="secondary" @click="cancel(item)">{{ copy.cancel }}</Button>
29
+ </li></ul>
30
+ <Button v-if="nextCursor" :disabled="busy" variant="secondary" @click="load(nextCursor)">{{ copy.next }}</Button>
31
+ </template>
32
+ </SettingsSection>
33
+ </template>