@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.
- package/README.md +7 -3
- package/dist/build-spk/delete-app-data.d.ts +27 -7
- package/dist/build-spk/delete-app-data.js +35 -34
- package/dist/build-spk/dsm-arch.d.ts +6 -1
- package/dist/build-spk/dsm-arch.js +25 -1
- package/dist/build-spk/dsm-version.d.ts +14 -0
- package/dist/build-spk/dsm-version.js +47 -0
- package/dist/build-spk/gateway.d.ts +31 -0
- package/dist/build-spk/gateway.js +55 -0
- package/dist/build-spk/generator.d.ts +5 -0
- package/dist/build-spk/generator.js +103 -107
- package/dist/build-spk/install-wizard.d.ts +20 -0
- package/dist/build-spk/install-wizard.js +76 -0
- package/dist/build-spk/native-lifecycle.d.ts +5 -0
- package/dist/build-spk/native-lifecycle.js +12 -2
- package/dist/build-spk/resource-worker.d.ts +9 -4
- package/dist/build-spk/resource-worker.js +15 -6
- package/dist/build-spk/share-combobox.d.ts +3 -0
- package/dist/build-spk/share-combobox.js +27 -0
- package/dist/build-spk/uninstall-wizard.d.ts +14 -0
- package/dist/build-spk/uninstall-wizard.js +33 -0
- package/dist/build-spk/wizard-i18n.d.ts +18 -0
- package/dist/build-spk/wizard-i18n.js +38 -0
- package/dist/build-spk/wizard-messages.d.ts +388 -0
- package/dist/build-spk/wizard-messages.js +387 -0
- package/dist/cli.js +130 -30
- package/dist/compose/analyze.d.ts +20 -0
- package/dist/compose/analyze.js +75 -11
- package/dist/contract/validate.js +33 -1
- package/dist/contract/web-launch.d.ts +22 -0
- package/dist/contract/web-launch.js +37 -0
- package/dist/deploy/deploy.d.ts +3 -0
- package/dist/deploy/deploy.js +11 -2
- package/dist/error-registry.js +60 -1
- package/dist/host/open-url.d.ts +2 -0
- package/dist/host/open-url.js +4 -1
- package/dist/images/pin.d.ts +52 -0
- package/dist/images/pin.js +249 -0
- package/dist/init.d.ts +27 -3
- package/dist/init.js +104 -15
- package/dist/inspect.d.ts +3 -0
- package/dist/inspect.js +15 -3
- package/dist/standalone/background.d.ts +21 -0
- package/dist/standalone/background.js +52 -0
- package/dist/standalone/binary.d.ts +1 -0
- package/dist/standalone/binary.js +1 -1
- package/dist/standalone/build.d.ts +2 -0
- package/dist/standalone/build.js +38 -6
- package/dist/standalone/dsm-window.js +2 -2
- package/dist/standalone/helper-inventory.d.ts +15 -0
- package/dist/standalone/helper-inventory.js +9 -0
- package/dist/standalone/helper.d.ts +1 -0
- package/dist/standalone/helper.js +28 -10
- package/dist/standalone/host-adapter.d.ts +1 -1
- package/dist/standalone/host-adapter.js +33 -15
- package/dist/standalone/host-file-navigation.d.ts +7 -0
- package/dist/standalone/host-file-navigation.js +172 -0
- package/dist/standalone/inspect-helper.js +9 -4
- package/dist/standalone/inspect-spk.d.ts +1 -1
- package/dist/standalone/inspect-spk.js +200 -7
- package/dist/standalone/job-diagnostics.d.ts +1 -0
- package/dist/standalone/job-diagnostics.js +49 -0
- package/dist/standalone/lifecycle.js +12 -2
- package/dist/standalone/manifest.d.ts +15 -2
- package/dist/standalone/manifest.js +37 -6
- package/dist/standalone/native-layout.d.ts +74 -0
- package/dist/standalone/native-layout.js +318 -0
- package/dist/standalone/resource.d.ts +11 -0
- package/dist/standalone/resource.js +13 -0
- package/dist/standalone/root-window.d.ts +3 -1
- package/dist/standalone/root-window.js +156 -38
- package/dist/standalone/shared-folder.d.ts +39 -0
- package/dist/standalone/shared-folder.js +141 -0
- package/dist/standalone/spk.d.ts +2 -0
- package/dist/standalone/spk.js +33 -3
- package/dist/standalone/worker-contract-json.d.ts +8 -0
- package/dist/standalone/worker-contract-json.js +141 -0
- package/dist/standalone/worker-contract.d.ts +189 -0
- package/dist/standalone/worker-contract.js +175 -0
- package/dist/standalone/worker-registry.d.ts +40 -0
- package/dist/standalone/worker-registry.js +167 -0
- package/dist/templates/_daemon/go.mod +2 -0
- package/dist/templates/_gateway/auth.go +101 -0
- package/dist/templates/_gateway/auth_test.go +216 -0
- package/dist/templates/_gateway/cgi.go +133 -0
- package/dist/templates/_gateway/cgi_test.go +156 -0
- package/dist/templates/_gateway/csrf.go +73 -0
- package/dist/templates/_gateway/csrf_test.go +155 -0
- package/dist/templates/_gateway/directory.go +108 -0
- package/dist/templates/_gateway/directory_test.go +202 -0
- package/dist/templates/_gateway/gateway.go +412 -0
- package/dist/templates/_gateway/gateway_test.go +676 -0
- package/dist/templates/_gateway/go.mod +3 -0
- package/dist/templates/_gateway/groups.go +66 -0
- package/dist/templates/_gateway/main.go +45 -0
- package/dist/templates/binary/synology-app.yaml +1 -1
- package/dist/templates/compose-import/compose.yaml +1 -1
- package/dist/templates/compose-import/synology-app.yaml +1 -1
- package/dist/templates/hello-files/compose.yaml +1 -1
- package/dist/templates/hello-files/synology-app.yaml +1 -1
- package/dist/templates/hello-web/compose.yaml +5 -2
- package/dist/templates/hello-web/synology-app.yaml +4 -1
- package/dist/templates/hello-web-page/compose.yaml +5 -2
- package/dist/templates/hello-web-page/synology-app.yaml +4 -1
- package/dist/templates/native-go/README.md +93 -4
- package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
- package/dist/templates/native-go/backend/cmd/app/main.go +17 -0
- package/dist/templates/native-go/backend/cmd/app/sdk_main.go +60 -0
- package/dist/templates/native-go/backend/cmd/background-worker/main.go +38 -0
- package/dist/templates/native-go/backend/cmd/helper/main.go +10 -1
- package/dist/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
- package/dist/templates/native-go/backend/go.mod +5 -3
- package/dist/templates/native-go/backend/go.sum +4 -4
- package/dist/templates/native-go/backend/internal/api/registry.go +17 -6
- package/dist/templates/native-go/backend/internal/api/server.go +7 -1
- package/dist/templates/native-go/backend/internal/app/background.go +270 -0
- package/dist/templates/native-go/backend/internal/app/background_none.go +8 -0
- package/dist/templates/native-go/backend/internal/app/background_owner.go +59 -0
- package/dist/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
- package/dist/templates/native-go/backend/internal/app/background_schedule.go +74 -0
- package/dist/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
- package/dist/templates/native-go/backend/internal/app/background_test.go +346 -0
- package/dist/templates/native-go/backend/internal/app/integration_state.go +16 -0
- package/dist/templates/native-go/backend/internal/app/migrations.go +41 -0
- package/dist/templates/native-go/backend/internal/app/migrations_test.go +41 -0
- package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +17 -3
- package/dist/templates/native-go/backend/internal/app/routes_test.go +20 -3
- package/dist/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
- package/dist/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
- package/dist/templates/native-go/backend/internal/app/sdk_routes.go +174 -0
- package/dist/templates/native-go/backend/internal/app/session_files.go +15 -0
- package/dist/templates/native-go/backend/internal/app/session_files_test.go +26 -0
- package/dist/templates/native-go/backend/internal/app/shared_folder.go +144 -0
- package/dist/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
- package/dist/templates/native-go/backend/internal/background/access.go +57 -0
- package/dist/templates/native-go/backend/internal/background/owner_test.go +126 -0
- package/dist/templates/native-go/backend/internal/background/runner.go +185 -0
- package/dist/templates/native-go/backend/internal/background/runner_test.go +209 -0
- package/dist/templates/native-go/backend/internal/background/schedule.go +300 -0
- package/dist/templates/native-go/backend/internal/background/schedule_test.go +335 -0
- package/dist/templates/native-go/backend/internal/background/store.go +807 -0
- package/dist/templates/native-go/backend/internal/background/store_test.go +407 -0
- package/dist/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
- package/dist/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
- package/dist/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
- package/dist/templates/native-go/backend/internal/filestation/client.go +251 -0
- package/dist/templates/native-go/backend/internal/filestation/client_test.go +155 -0
- package/dist/templates/native-go/backend/internal/filestation/doc.go +4 -0
- package/dist/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
- package/dist/templates/native-go/backend/internal/filestation/repository.go +207 -0
- package/dist/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
- package/dist/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
- package/dist/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
- package/dist/templates/native-go/backend/internal/filestation/service.go +254 -0
- package/dist/templates/native-go/backend/internal/filestation/service_test.go +94 -0
- package/dist/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
- package/dist/templates/native-go/backend/internal/filestation/write.go +72 -0
- package/dist/templates/native-go/backend/internal/filestation/write_test.go +123 -0
- package/dist/templates/native-go/backend/internal/helper/background_proof.go +163 -0
- package/dist/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
- package/dist/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
- package/dist/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
- package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
- package/dist/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
- package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
- package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
- package/dist/templates/native-go/backend/internal/helper/management.go +79 -0
- package/dist/templates/native-go/backend/internal/helper/observation.go +42 -2
- package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/process_linux.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
- package/dist/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
- package/dist/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_server_linux.go +152 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
- package/dist/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
- package/dist/templates/native-go/backend/internal/helper/server_linux.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
- package/dist/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
- package/dist/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
- package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
- package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
- package/dist/templates/native-go/backend/internal/helper/status.go +22 -13
- package/dist/templates/native-go/backend/internal/helper/status_test.go +45 -0
- package/dist/templates/native-go/backend/internal/helper/supervision.go +1 -1
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
- package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
- package/dist/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
- package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
- package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
- package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
- package/dist/templates/native-go/dsm-package.yaml +1 -1
- package/dist/templates/native-go-background/BACKGROUND.md +111 -0
- package/dist/templates/native-go-background/backend/internal/app/background_on.go +7 -0
- package/dist/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
- package/dist/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
- package/dist/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
- package/dist/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
- package/dist/templates/native-go-background/frontend/test/background.test.ts +179 -0
- package/dist/templates/native-go-integration/backend/internal/app/personal.go +2 -2
- package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
- package/dist/templates/native-go-vue/README.md +38 -7
- package/dist/templates/native-go-vue/frontend/DESIGN.md +15 -3
- package/dist/templates/native-go-vue/frontend/README-JOBS.md +75 -0
- package/dist/templates/native-go-vue/frontend/README-M2.md +64 -0
- package/dist/templates/native-go-vue/frontend/package-lock.json +5 -4
- package/dist/templates/native-go-vue/frontend/package.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/App.vue +39 -11
- package/dist/templates/native-go-vue/frontend/src/M2App.vue +57 -0
- package/dist/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
- package/dist/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
- package/dist/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
- package/dist/templates/native-go-vue/frontend/src/m2-style.css +7 -0
- package/dist/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
- package/dist/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
- package/dist/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
- package/dist/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
- package/dist/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
- package/dist/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
- package/dist/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
- package/dist/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
- package/dist/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
- package/dist/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
- package/dist/templates/native-go-vue/frontend/src/style.css +2 -6
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
- package/dist/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
- package/dist/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
- package/dist/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
- package/dist/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
- package/dist/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
- package/dist/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
- package/dist/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
- package/dist/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
- package/dist/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
- package/dist/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
- package/dist/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
- package/dist/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
- package/dist/templates/native-go-vue/frontend/vite.config.ts +2 -2
- package/dist/validate.js +6 -3
- package/package.json +1 -1
- package/schema/synology-app.schema.json +19 -0
- package/skills/reference/create.md +4 -0
- package/templates/_daemon/go.mod +2 -0
- package/templates/_gateway/auth.go +101 -0
- package/templates/_gateway/auth_test.go +216 -0
- package/templates/_gateway/cgi.go +133 -0
- package/templates/_gateway/cgi_test.go +156 -0
- package/templates/_gateway/csrf.go +73 -0
- package/templates/_gateway/csrf_test.go +155 -0
- package/templates/_gateway/directory.go +108 -0
- package/templates/_gateway/directory_test.go +202 -0
- package/templates/_gateway/gateway.go +412 -0
- package/templates/_gateway/gateway_test.go +676 -0
- package/templates/_gateway/go.mod +3 -0
- package/templates/_gateway/groups.go +66 -0
- package/templates/_gateway/main.go +45 -0
- package/templates/binary/synology-app.yaml +1 -1
- package/templates/compose-import/compose.yaml +1 -1
- package/templates/compose-import/synology-app.yaml +1 -1
- package/templates/hello-files/compose.yaml +1 -1
- package/templates/hello-files/synology-app.yaml +1 -1
- package/templates/hello-web/compose.yaml +5 -2
- package/templates/hello-web/synology-app.yaml +4 -1
- package/templates/hello-web-page/compose.yaml +5 -2
- package/templates/hello-web-page/synology-app.yaml +4 -1
- package/templates/native-go/README.md +93 -4
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
- package/templates/native-go/backend/cmd/app/main.go +17 -0
- package/templates/native-go/backend/cmd/app/sdk_main.go +60 -0
- package/templates/native-go/backend/cmd/background-worker/main.go +38 -0
- package/templates/native-go/backend/cmd/helper/main.go +10 -1
- package/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
- package/templates/native-go/backend/go.mod +5 -3
- package/templates/native-go/backend/go.sum +4 -4
- package/templates/native-go/backend/internal/api/registry.go +17 -6
- package/templates/native-go/backend/internal/api/server.go +7 -1
- package/templates/native-go/backend/internal/app/background.go +270 -0
- package/templates/native-go/backend/internal/app/background_none.go +8 -0
- package/templates/native-go/backend/internal/app/background_owner.go +59 -0
- package/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
- package/templates/native-go/backend/internal/app/background_schedule.go +74 -0
- package/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
- package/templates/native-go/backend/internal/app/background_test.go +346 -0
- package/templates/native-go/backend/internal/app/integration_state.go +16 -0
- package/templates/native-go/backend/internal/app/migrations.go +41 -0
- package/templates/native-go/backend/internal/app/migrations_test.go +41 -0
- package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
- package/templates/native-go/backend/internal/app/routes.go +17 -3
- package/templates/native-go/backend/internal/app/routes_test.go +20 -3
- package/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
- package/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
- package/templates/native-go/backend/internal/app/sdk_routes.go +174 -0
- package/templates/native-go/backend/internal/app/session_files.go +15 -0
- package/templates/native-go/backend/internal/app/session_files_test.go +26 -0
- package/templates/native-go/backend/internal/app/shared_folder.go +144 -0
- package/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
- package/templates/native-go/backend/internal/background/access.go +57 -0
- package/templates/native-go/backend/internal/background/owner_test.go +126 -0
- package/templates/native-go/backend/internal/background/runner.go +185 -0
- package/templates/native-go/backend/internal/background/runner_test.go +209 -0
- package/templates/native-go/backend/internal/background/schedule.go +300 -0
- package/templates/native-go/backend/internal/background/schedule_test.go +335 -0
- package/templates/native-go/backend/internal/background/store.go +807 -0
- package/templates/native-go/backend/internal/background/store_test.go +407 -0
- package/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
- package/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
- package/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
- package/templates/native-go/backend/internal/filestation/client.go +251 -0
- package/templates/native-go/backend/internal/filestation/client_test.go +155 -0
- package/templates/native-go/backend/internal/filestation/doc.go +4 -0
- package/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
- package/templates/native-go/backend/internal/filestation/repository.go +207 -0
- package/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
- package/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
- package/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
- package/templates/native-go/backend/internal/filestation/service.go +254 -0
- package/templates/native-go/backend/internal/filestation/service_test.go +94 -0
- package/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
- package/templates/native-go/backend/internal/filestation/write.go +72 -0
- package/templates/native-go/backend/internal/filestation/write_test.go +123 -0
- package/templates/native-go/backend/internal/helper/background_proof.go +163 -0
- package/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
- package/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
- package/templates/native-go/backend/internal/helper/data_contract.go +3 -0
- package/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
- package/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
- package/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
- package/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
- package/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
- package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
- package/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
- package/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
- package/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
- package/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
- package/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
- package/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
- package/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
- package/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
- package/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
- package/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
- package/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
- package/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
- package/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
- package/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
- package/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
- package/templates/native-go/backend/internal/helper/management.go +79 -0
- package/templates/native-go/backend/internal/helper/observation.go +42 -2
- package/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
- package/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
- package/templates/native-go/backend/internal/helper/process_linux.go +3 -0
- package/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
- package/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
- package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
- package/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
- package/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
- package/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
- package/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
- package/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
- package/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
- package/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
- package/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
- package/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
- package/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
- package/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
- package/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
- package/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
- package/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
- package/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
- package/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
- package/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
- package/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
- package/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
- package/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
- package/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
- package/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
- package/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
- package/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
- package/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
- package/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
- package/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
- package/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
- package/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
- package/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
- package/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
- package/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
- package/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
- package/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
- package/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
- package/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
- package/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
- package/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
- package/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
- package/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
- package/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
- package/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
- package/templates/native-go/backend/internal/helper/sdk_server_linux.go +152 -0
- package/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
- package/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
- package/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
- package/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
- package/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
- package/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
- package/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
- package/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
- package/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
- package/templates/native-go/backend/internal/helper/server_linux.go +3 -0
- package/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
- package/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
- package/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
- package/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
- package/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
- package/templates/native-go/backend/internal/helper/status.go +22 -13
- package/templates/native-go/backend/internal/helper/status_test.go +45 -0
- package/templates/native-go/backend/internal/helper/supervision.go +1 -1
- package/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
- package/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
- package/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
- package/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
- package/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
- package/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
- package/templates/native-go/dsm-package.yaml +1 -1
- package/templates/native-go-background/BACKGROUND.md +111 -0
- package/templates/native-go-background/backend/internal/app/background_on.go +7 -0
- package/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
- package/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
- package/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
- package/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
- package/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
- package/templates/native-go-background/frontend/test/background.test.ts +179 -0
- package/templates/native-go-integration/backend/internal/app/personal.go +2 -2
- package/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
- package/templates/native-go-vue/README.md +38 -7
- package/templates/native-go-vue/frontend/DESIGN.md +15 -3
- package/templates/native-go-vue/frontend/README-JOBS.md +75 -0
- package/templates/native-go-vue/frontend/README-M2.md +64 -0
- package/templates/native-go-vue/frontend/package-lock.json +5 -4
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-go-vue/frontend/src/App.vue +39 -11
- package/templates/native-go-vue/frontend/src/M2App.vue +57 -0
- package/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
- package/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
- package/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
- package/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
- package/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
- package/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
- package/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
- package/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
- package/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
- package/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
- package/templates/native-go-vue/frontend/src/m2-style.css +7 -0
- package/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
- package/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
- package/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
- package/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
- package/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
- package/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
- package/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
- package/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
- package/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
- package/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
- package/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
- package/templates/native-go-vue/frontend/src/style.css +2 -6
- package/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
- package/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
- package/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
- package/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
- package/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
- package/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
- package/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
- package/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
- package/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
- package/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
- package/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
- package/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
- package/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
- package/templates/native-go-vue/frontend/vite.config.ts +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isNativeLayout, loadNativeLayout, buildNativeLayout } from "./standalone/native-layout.js";
|
|
1
2
|
import { planDeployment, deployStandalone } from "./deploy/plan.js";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import { readFileSync, renameSync } from "node:fs";
|
|
@@ -6,12 +7,14 @@ import { findProjectRoot } from "./discovery.js";
|
|
|
6
7
|
import { loadContract } from "./contract/load.js";
|
|
7
8
|
import { formatErrors } from "./errors.js";
|
|
8
9
|
import { formatInspectReport, inspectProject } from "./inspect.js";
|
|
10
|
+
import { formatPinReport, pinProjectImages } from "./images/pin.js";
|
|
9
11
|
import { initFromTemplate, isTemplateName, listTemplates } from "./init.js";
|
|
10
12
|
import { validateProject } from "./validate.js";
|
|
11
13
|
import { runDev } from "./dev.js";
|
|
12
14
|
import { testProject } from "./test-command.js";
|
|
13
15
|
import { buildSpk } from "./build-spk/generator.js";
|
|
14
|
-
import { isNativeArchFamily } from "./build-spk/dsm-arch.js";
|
|
16
|
+
import { isNativeArchFamily, NATIVE_ARCH_FAMILIES, parseArchList } from "./build-spk/dsm-arch.js";
|
|
17
|
+
import { DEFAULT_MIN_DSM, CONTAINER_MIN_DSM } from "./build-spk/dsm-version.js";
|
|
15
18
|
import { deployProject } from "./deploy/deploy.js";
|
|
16
19
|
import { createNasHost } from "./host/dsm-client.js";
|
|
17
20
|
import { projectInfo, formatProjectInfo } from "./info.js";
|
|
@@ -75,8 +78,8 @@ function requireProject(cwd, project) {
|
|
|
75
78
|
}
|
|
76
79
|
return found;
|
|
77
80
|
}
|
|
78
|
-
async function buildStandaloneCommand(root,
|
|
79
|
-
if (options.output &&
|
|
81
|
+
async function buildStandaloneCommand(root, arches, options) {
|
|
82
|
+
if (options.output && arches?.length !== 1) {
|
|
80
83
|
console.error("-o 只能搭配 --arch 建置單一架構;多架構請用 --out-dir。");
|
|
81
84
|
process.exit(1);
|
|
82
85
|
}
|
|
@@ -84,7 +87,7 @@ async function buildStandaloneCommand(root, arch, options) {
|
|
|
84
87
|
? dirname(resolve(process.cwd(), options.output))
|
|
85
88
|
: options.outDir ? resolve(process.cwd(), options.outDir) : undefined;
|
|
86
89
|
try {
|
|
87
|
-
const { outputs } = await buildStandalone({ root, arches
|
|
90
|
+
const { outputs } = await buildStandalone({ root, arches, outDir, minDsm: options.minDsm });
|
|
88
91
|
for (let output of outputs) {
|
|
89
92
|
if (options.output) {
|
|
90
93
|
const target = resolve(process.cwd(), options.output);
|
|
@@ -99,6 +102,46 @@ async function buildStandaloneCommand(root, arch, options) {
|
|
|
99
102
|
process.exit(1);
|
|
100
103
|
}
|
|
101
104
|
}
|
|
105
|
+
const MIN_DSM_HELP = `最低 DSM 版本(INFO os_min_ver):7.0、7.1、7.2、7.2.1 或完整的 7.x-build(例如 7.2.1-69057);省略時用專案宣告的值(native-go/binary 預設 DSM ${DEFAULT_MIN_DSM},容器模板 ${CONTAINER_MIN_DSM})`;
|
|
106
|
+
const ARCH_REQUIRED = ["NATIVE_ARCH_FAMILY_REQUIRED", "GATEWAY_ARCH_FAMILY_REQUIRED"];
|
|
107
|
+
/**
|
|
108
|
+
* Container / binary App: an architecture-neutral App builds one SPK. One that
|
|
109
|
+
* needs an architecture (binary, DSM gateway) builds one SPK per --arch family,
|
|
110
|
+
* all of them when --arch is omitted.
|
|
111
|
+
*/
|
|
112
|
+
async function buildContainerCommand(project, arches, options) {
|
|
113
|
+
const outputPath = options.output ? resolve(process.cwd(), options.output) : undefined;
|
|
114
|
+
const build = (archFamily, output = outputPath) => buildSpk({ project, outputPath: output, archFamily, minDsm: options.minDsm });
|
|
115
|
+
const fail = (errors) => {
|
|
116
|
+
console.error(`建置失敗:${errors.join(", ")}`);
|
|
117
|
+
return process.exit(1);
|
|
118
|
+
};
|
|
119
|
+
let results = [];
|
|
120
|
+
if (arches?.length === 1) {
|
|
121
|
+
results = [await build(arches[0])];
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const first = await build();
|
|
125
|
+
if (first.ok || !first.errors.every((code) => ARCH_REQUIRED.includes(code))) {
|
|
126
|
+
results = [first];
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
if (outputPath) {
|
|
130
|
+
console.error("-o 只能搭配 --arch 建置單一架構;多架構請不要加 -o。");
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
const packageId = String(loadContract(project.contractPath).contract.package);
|
|
134
|
+
for (const arch of arches ?? NATIVE_ARCH_FAMILIES) {
|
|
135
|
+
results.push(await build(arch, join(project.root, `${packageId}-${arch}.spk`)));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
for (const result of results) {
|
|
140
|
+
if (!result.ok)
|
|
141
|
+
fail(result.errors);
|
|
142
|
+
console.log(`已產生 ${result.outputPath}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
102
145
|
export async function runCli(argv) {
|
|
103
146
|
const program = new Command();
|
|
104
147
|
program
|
|
@@ -112,7 +155,7 @@ export async function runCli(argv) {
|
|
|
112
155
|
const global = command.parent?.opts() ?? {};
|
|
113
156
|
const standalone = standaloneRoot(process.cwd(), global.project);
|
|
114
157
|
if (standalone) {
|
|
115
|
-
const loaded = loadStandaloneManifest(standalone);
|
|
158
|
+
const loaded = isNativeLayout(standalone) ? loadNativeLayout(standalone) : loadStandaloneManifest(standalone);
|
|
116
159
|
if (!loaded.ok) {
|
|
117
160
|
console.error(loaded.errors.map((e) => `[${e.code}] ${e.message}`).join("\n"));
|
|
118
161
|
process.exit(1);
|
|
@@ -158,6 +201,29 @@ export async function runCli(argv) {
|
|
|
158
201
|
const report = inspectProject(project);
|
|
159
202
|
console.log(formatInspectReport(report));
|
|
160
203
|
});
|
|
204
|
+
const images = program
|
|
205
|
+
.command("images")
|
|
206
|
+
.description("Container image 工具");
|
|
207
|
+
images
|
|
208
|
+
.command("pin")
|
|
209
|
+
.description("讀取 compose.yaml 的 image,向 registry 取得 manifest digest,改寫為 tag@sha256:...")
|
|
210
|
+
.option("--check", "只報告未 pin 或已過期的 image,不寫入;有問題時 exit 1")
|
|
211
|
+
.action(async (options, command) => {
|
|
212
|
+
const global = command.parent?.parent?.opts() ?? {};
|
|
213
|
+
const project = requireProject(process.cwd(), global.project);
|
|
214
|
+
const check = options.check === true;
|
|
215
|
+
try {
|
|
216
|
+
const result = await pinProjectImages({ project, check });
|
|
217
|
+
console.log(formatPinReport(result, { check }));
|
|
218
|
+
if (check && result.findings.length > 0) {
|
|
219
|
+
process.exit(1);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
161
227
|
program
|
|
162
228
|
.command("init")
|
|
163
229
|
.description("從模板建立 App 專案(不覆蓋既有檔案)")
|
|
@@ -165,11 +231,18 @@ export async function runCli(argv) {
|
|
|
165
231
|
.option("--binary", "建立 Binary App:以套件自己的帳號執行預先建置的 binary(等同 -t binary)")
|
|
166
232
|
.option("--package <id>", "native-go:INFO.package(預設由目錄名產生,例如 photo-tagger → PhotoTagger)")
|
|
167
233
|
.option("--name <display>", "native-go:顯示名稱(預設由目錄名產生)")
|
|
168
|
-
.option("--privilege <none|root>", "native-go:root 另加由 DSM 管理員在套件視窗核准的 root
|
|
169
|
-
.option("--ui <plain|vue>", `native-go
|
|
170
|
-
.option("--
|
|
171
|
-
.option("--
|
|
172
|
-
.option("--
|
|
234
|
+
.option("--privilege <none|root>", "native-go:root 另加由 DSM 管理員在套件視窗核准的 root 操作;與 --integration 並用時才加入特權 helper(預設 none)")
|
|
235
|
+
.option("--ui <plain|vue>", `native-go:UI 實作;預設 vue(沿用 UI ${JSON.parse(readFileSync(join(templatesRoot(), "native-go-vue/frontend/package.json"), "utf8")).dependencies["@synopackageland/ui"]} 的 DSM 左右分欄版面);plain 為舊的純 JS UI`)
|
|
236
|
+
.option("--background", "native-go(預設 --ui vue):以套件帳號執行的背景工作(systemd user unit + 固定 sha256-v1 worker;僅管理員;可併用 --integration go、--file-station,不可併用 --privilege root)")
|
|
237
|
+
.option("--file-station", "native-go:以使用者自己的 DSM session 提供互動 File Station 路由,由套件帳號執行、不需 root(不保存 session,不支援離線 job)")
|
|
238
|
+
.option("--shared-folder <select|create>", "native-go:安裝精靈選擇既有共用資料夾(select),或由 DSM data-share 建立專屬共用資料夾(create,需 --shared-folder-name);解除安裝不會刪除共用資料夾")
|
|
239
|
+
.option("--shared-folder-name <name>", "--shared-folder create:要建立的共用資料夾名稱")
|
|
240
|
+
.option("--shared-folder-key <key>", "--shared-folder:精靈變數與 var/config.json 的鍵(預設 shared)")
|
|
241
|
+
.option("--shared-folder-permission <ro|rw>", "--shared-folder:套件帳號需要的權限(預設 rw)")
|
|
242
|
+
.option("--integration <go|better-auth>", "native-go(預設 --ui vue):以套件帳號執行的私有範例,不含 helper(加 --privilege root 才有每包 helper);better-auth 才加入 Node")
|
|
243
|
+
.option("--integration-protocol <1|2>", "helper inventory protocol(需要 --privilege root;預設 1);2 可選 NAS data policy,缺已認證 adapters 仍拒絕")
|
|
244
|
+
.option("--data-access <unavailable|relaxed>", "protocol 2 build-time 身分模式(需要 --privilege root;預設 unavailable);relaxed 不繞過 DSM/App/lifecycle gates")
|
|
245
|
+
.option("--min-dsm <version>", `新專案的最低 DSM 版本(os_min_ver):7.0、7.1、7.2、7.2.1 或完整的 7.x-build(native-go/binary 預設 ${DEFAULT_MIN_DSM},容器模板 ${CONTAINER_MIN_DSM})`)
|
|
173
246
|
.argument("[dir]", "目標目錄", ".")
|
|
174
247
|
.addHelpText("after", `
|
|
175
248
|
模板分兩類:
|
|
@@ -183,9 +256,11 @@ export async function runCli(argv) {
|
|
|
183
256
|
|
|
184
257
|
快速開始(native-go,需要 Go 1.24+):
|
|
185
258
|
synopkgland init -t native-go my-app
|
|
186
|
-
cd my-app && $EDITOR backend/internal/app/routes.go
|
|
259
|
+
cd my-app && $EDITOR backend/internal/app/routes.go frontend/src/App.vue
|
|
187
260
|
synopkgland build-spk # → dist/<Package>-<version>-<arch>.spk
|
|
188
|
-
synopkgland inspect --spk dist/<file>.spk
|
|
261
|
+
synopkgland inspect --spk dist/<file>.spk
|
|
262
|
+
|
|
263
|
+
UI 預設為 --ui vue(DSM 左右分欄);--ui plain 使用舊的 ui/app.js。`)
|
|
189
264
|
.action(async (dir, options, command) => {
|
|
190
265
|
const global = command.parent?.opts() ?? {};
|
|
191
266
|
if (global.project) {
|
|
@@ -210,9 +285,13 @@ export async function runCli(argv) {
|
|
|
210
285
|
initFromTemplate(template, targetDir, {
|
|
211
286
|
packageId: options.package,
|
|
212
287
|
displayName: options.name,
|
|
288
|
+
minDsm: options.minDsm,
|
|
213
289
|
privilege: options.privilege,
|
|
214
290
|
ui: options.ui,
|
|
215
291
|
integration: options.integration,
|
|
292
|
+
background: options.background === true,
|
|
293
|
+
fileStation: options.fileStation === true,
|
|
294
|
+
sharedFolder: options.sharedFolder === undefined ? undefined : { mode: options.sharedFolder, name: options.sharedFolderName, key: options.sharedFolderKey, permission: options.sharedFolderPermission },
|
|
216
295
|
integrationProtocol: options.integrationProtocol === undefined ? undefined : (["1", "2"].includes(options.integrationProtocol) ? Number(options.integrationProtocol) : NaN),
|
|
217
296
|
dataAccess: options.dataAccess,
|
|
218
297
|
});
|
|
@@ -282,7 +361,7 @@ export async function runCli(argv) {
|
|
|
282
361
|
.command("deploy")
|
|
283
362
|
.description("建置獨立 SPK 並直接安裝到 DSM")
|
|
284
363
|
.option("--host <name>", "synoagentcli profile 或 NAS 名稱")
|
|
285
|
-
.option("--arch <family>",
|
|
364
|
+
.option("--arch <family>", `native App 的目標架構:${NATIVE_ARCH_FAMILIES.join(" 或 ")}(省略時由 NAS 判定)`)
|
|
286
365
|
.option("--dev", "部署到 Development Package Identity({package}.dev)")
|
|
287
366
|
.option("--share <slot=name>", "此 NAS 上的 Shared Folder 邏輯名(契約 shared_folder 槽,可重複)", collectShareOption)
|
|
288
367
|
.option("--run-as <slot=name>", "此 NAS 上的 DSM 使用者邏輯名(契約 dsm_user 槽)", collectRunAsOption)
|
|
@@ -291,7 +370,7 @@ export async function runCli(argv) {
|
|
|
291
370
|
.action(async (options, command) => {
|
|
292
371
|
const global = command.parent?.opts() ?? {};
|
|
293
372
|
if (options.arch !== undefined && !isNativeArchFamily(String(options.arch))) {
|
|
294
|
-
throw new Error(
|
|
373
|
+
throw new Error(`--arch accepts ${NATIVE_ARCH_FAMILIES.join(" or ")}`);
|
|
295
374
|
}
|
|
296
375
|
const plan = planDeployment(resolve(process.cwd(), global.project ?? '.'), {
|
|
297
376
|
arch: options.arch, dev: options.dev,
|
|
@@ -330,7 +409,7 @@ export async function runCli(argv) {
|
|
|
330
409
|
}
|
|
331
410
|
try {
|
|
332
411
|
if (options.arch !== undefined && !isNativeArchFamily(String(options.arch))) {
|
|
333
|
-
console.error(`--arch 只接受
|
|
412
|
+
console.error(`--arch 只接受 ${NATIVE_ARCH_FAMILIES.join("、")},收到 ${String(options.arch)}。`);
|
|
334
413
|
process.exit(1);
|
|
335
414
|
}
|
|
336
415
|
const result = await deployProject({
|
|
@@ -444,30 +523,51 @@ export async function runCli(argv) {
|
|
|
444
523
|
.description("產生本機未簽署 SPK:容器 App(synology-app.yaml)或 Standalone Package(dsm-package.yaml,會先編譯 UI 與 Go)")
|
|
445
524
|
.option("-o, --output <path>", "輸出 .spk 路徑(Standalone Package 只在建置單一架構時可用)")
|
|
446
525
|
.option("--out-dir <dir>", "Standalone Package:輸出目錄(預設 dist/)")
|
|
447
|
-
.option("--arch <
|
|
526
|
+
.option("--arch <families>", `目標架構,可用逗號列出多個,例如 x86_64,aarch64(可填:${NATIVE_ARCH_FAMILIES.join("、")};省略時兩者都建,每個架構各產一個 SPK)`)
|
|
527
|
+
.option("--min-dsm <version>", MIN_DSM_HELP)
|
|
528
|
+
.option("--build <number>", "Native layout: override DSM build number")
|
|
448
529
|
.action(async (options, command) => {
|
|
449
530
|
const global = command.parent?.opts() ?? {};
|
|
450
|
-
|
|
451
|
-
|
|
531
|
+
const layoutRoot = standaloneRoot(process.cwd(), global.project);
|
|
532
|
+
if (layoutRoot && isNativeLayout(layoutRoot)) {
|
|
533
|
+
try {
|
|
534
|
+
if (options.minDsm)
|
|
535
|
+
throw new Error("Native layout: set os_min_ver in dsm-package.yaml");
|
|
536
|
+
const arches = options.arch === undefined ? undefined : String(options.arch).split(",");
|
|
537
|
+
if (options.output && arches?.length !== 1)
|
|
538
|
+
throw new Error("-o requires exactly one --arch");
|
|
539
|
+
const result = await buildNativeLayout({ root: layoutRoot, arches, build: options.build === undefined ? undefined : Number(options.build), outDir: options.outDir ? resolve(options.outDir) : undefined });
|
|
540
|
+
for (const output of result.outputs) {
|
|
541
|
+
if (options.output)
|
|
542
|
+
renameSync(output, resolve(options.output));
|
|
543
|
+
console.log(`已產生 ${options.output ?? output}`);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
catch (e) {
|
|
547
|
+
console.error(String(e));
|
|
548
|
+
process.exit(1);
|
|
549
|
+
}
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
if (options.build !== undefined) {
|
|
553
|
+
console.error("--build requires native layout");
|
|
554
|
+
process.exit(1);
|
|
555
|
+
}
|
|
556
|
+
let arches;
|
|
557
|
+
try {
|
|
558
|
+
arches = options.arch === undefined ? undefined : parseArchList(String(options.arch));
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
452
562
|
process.exit(1);
|
|
453
563
|
}
|
|
454
|
-
const archFamily = options.arch ? String(options.arch) : undefined;
|
|
455
564
|
const standalone = standaloneRoot(process.cwd(), global.project);
|
|
456
565
|
if (standalone) {
|
|
457
|
-
await buildStandaloneCommand(standalone,
|
|
566
|
+
await buildStandaloneCommand(standalone, arches, options);
|
|
458
567
|
return;
|
|
459
568
|
}
|
|
460
569
|
const project = requireProject(process.cwd(), global.project);
|
|
461
|
-
|
|
462
|
-
project,
|
|
463
|
-
outputPath: options.output ? resolve(process.cwd(), options.output) : undefined,
|
|
464
|
-
archFamily,
|
|
465
|
-
});
|
|
466
|
-
if (!result.ok) {
|
|
467
|
-
console.error(`建置失敗:${result.errors.join(", ")}`);
|
|
468
|
-
process.exit(1);
|
|
469
|
-
}
|
|
470
|
-
console.log(`已產生 ${result.outputPath}`);
|
|
570
|
+
await buildContainerCommand(project, arches, options);
|
|
471
571
|
});
|
|
472
572
|
await program.parseAsync(argv);
|
|
473
573
|
}
|
|
@@ -9,6 +9,18 @@ export interface ParsedCompose {
|
|
|
9
9
|
export declare function loadCompose(composePath: string): ParsedCompose | null;
|
|
10
10
|
export declare function listServiceNames(compose: ComposeDocument): string[];
|
|
11
11
|
export declare function extractPublishedTcpPorts(service: ComposeService): number[];
|
|
12
|
+
export interface PortExposure {
|
|
13
|
+
service: string;
|
|
14
|
+
/** The Compose entry, as written (long form entries as JSON). */
|
|
15
|
+
entry: string;
|
|
16
|
+
/** Published host port when it is a single number. */
|
|
17
|
+
hostPort?: number;
|
|
18
|
+
containerPort?: string;
|
|
19
|
+
/** Reachable only from the NAS itself (127.0.0.0/8 or ::1). */
|
|
20
|
+
loopbackOnly: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Every way a Compose service is reachable from outside its container network. */
|
|
23
|
+
export declare function listPortExposures(compose: ComposeDocument): PortExposure[];
|
|
12
24
|
export declare function collectPublishedTcpPorts(compose: ComposeDocument): Map<number, string[]>;
|
|
13
25
|
export type ResourceWorkerIneligibleReason = "HAS_INSTALL_PARAMETERS" | "HAS_COMPOSE_INTERPOLATION" | "HAS_COMPOSE_SECRETS_OR_CONFIGS" | "HAS_BUILD_STANZA" | "HAS_PRIVILEGED_CAPABILITY" | "WEB_APP_MISSING_OR_AMBIGUOUS_ADMINPORT";
|
|
14
26
|
export interface ResourceWorkerEligibility {
|
|
@@ -28,6 +40,12 @@ export interface ResourceWorkerEligibility {
|
|
|
28
40
|
* - any non-headless App without a unique literal published adminport status probe
|
|
29
41
|
*/
|
|
30
42
|
export declare function resourceWorkerEligibility(contract: AppContract, compose: ComposeDocument): ResourceWorkerEligibility;
|
|
43
|
+
export interface UnpinnedImage {
|
|
44
|
+
service: string;
|
|
45
|
+
image: string;
|
|
46
|
+
}
|
|
47
|
+
/** Service images a registry can move: anything without a trailing `@sha256:<64 hex>` digest. */
|
|
48
|
+
export declare function collectUnpinnedImages(compose: ComposeDocument): UnpinnedImage[];
|
|
31
49
|
export type ComposeRoute = "static-zero-config" | "dynamic" | "reject";
|
|
32
50
|
export interface ComposeRouteClassification {
|
|
33
51
|
route: ComposeRoute;
|
|
@@ -65,4 +83,6 @@ export declare function validateComposeRunAs(compose: ComposeDocument, composeFi
|
|
|
65
83
|
hasSharedFolder: boolean;
|
|
66
84
|
hasDsmUser?: boolean;
|
|
67
85
|
}): ValidationError[];
|
|
86
|
+
/** The gateway is the only door: the container's web port must not be reachable except through it. */
|
|
87
|
+
export declare function validateGatewayPortLoopback(adminport: number, compose: ComposeDocument, composeFile: string): ValidationError[];
|
|
68
88
|
export declare function validateAdminPortMapping(adminport: number, compose: ComposeDocument, composeFile: string): ValidationError[];
|
package/dist/compose/analyze.js
CHANGED
|
@@ -66,30 +66,76 @@ export function extractPublishedTcpPorts(service) {
|
|
|
66
66
|
}
|
|
67
67
|
return published;
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
/** Splits `[ip:]host:container[/proto]`, `[ip:]container` and the long form. */
|
|
70
|
+
function splitPortEntry(entry) {
|
|
70
71
|
if (typeof entry === "number") {
|
|
71
|
-
return entry;
|
|
72
|
+
return { hostPort: String(entry) };
|
|
72
73
|
}
|
|
73
74
|
if (typeof entry === "string") {
|
|
74
75
|
const trimmed = entry.trim();
|
|
75
76
|
if (!trimmed || trimmed.startsWith("/")) {
|
|
76
77
|
return null;
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
let rest = trimmed;
|
|
80
|
+
let hostIp;
|
|
81
|
+
if (rest.startsWith("[")) {
|
|
82
|
+
const close = rest.indexOf("]");
|
|
83
|
+
if (close < 0) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
hostIp = rest.slice(1, close);
|
|
87
|
+
rest = rest.slice(close + 1).replace(/^:/, "");
|
|
88
|
+
}
|
|
89
|
+
const parts = rest.split("/")[0].split(":");
|
|
90
|
+
if (hostIp === undefined && parts.length === 3) {
|
|
91
|
+
hostIp = parts.shift();
|
|
92
|
+
}
|
|
93
|
+
return { ...(hostIp ? { hostIp } : {}), hostPort: parts[0], containerPort: parts[parts.length - 1] };
|
|
81
94
|
}
|
|
82
95
|
if (entry && typeof entry === "object") {
|
|
83
96
|
const record = entry;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
const hostIp = typeof record.host_ip === "string" && record.host_ip ? record.host_ip : undefined;
|
|
98
|
+
const published = record.published ?? record.target;
|
|
99
|
+
return {
|
|
100
|
+
...(hostIp ? { hostIp } : {}),
|
|
101
|
+
...(typeof published === "number" || typeof published === "string" ? { hostPort: String(published) } : {}),
|
|
102
|
+
...(typeof record.target === "number" ? { containerPort: String(record.target) } : {}),
|
|
103
|
+
};
|
|
90
104
|
}
|
|
91
105
|
return null;
|
|
92
106
|
}
|
|
107
|
+
function parsePortEntry(entry) {
|
|
108
|
+
if (entry && typeof entry === "object" && typeof entry.published === "string") {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const hostPort = Number(splitPortEntry(entry)?.hostPort);
|
|
112
|
+
return Number.isInteger(hostPort) ? hostPort : null;
|
|
113
|
+
}
|
|
114
|
+
function isLoopbackAddress(address) {
|
|
115
|
+
return address !== undefined && (address === "::1" || /^127(\.\d{1,3}){3}$/.test(address));
|
|
116
|
+
}
|
|
117
|
+
/** Every way a Compose service is reachable from outside its container network. */
|
|
118
|
+
export function listPortExposures(compose) {
|
|
119
|
+
const exposures = [];
|
|
120
|
+
for (const [service, definition] of Object.entries(compose.services ?? {})) {
|
|
121
|
+
if (definition.network_mode === "host") {
|
|
122
|
+
exposures.push({ service, entry: "network_mode: host", loopbackOnly: false });
|
|
123
|
+
}
|
|
124
|
+
const ports = definition.ports;
|
|
125
|
+
for (const entry of ports ? (Array.isArray(ports) ? ports : [ports]) : []) {
|
|
126
|
+
const parsed = splitPortEntry(entry);
|
|
127
|
+
const hostPort = parsePortEntry(entry);
|
|
128
|
+
exposures.push({
|
|
129
|
+
service,
|
|
130
|
+
entry: typeof entry === "string" ? entry : JSON.stringify(entry),
|
|
131
|
+
...(hostPort === null ? {} : { hostPort }),
|
|
132
|
+
...(parsed?.containerPort ? { containerPort: parsed.containerPort } : {}),
|
|
133
|
+
loopbackOnly: isLoopbackAddress(parsed?.hostIp),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return exposures;
|
|
138
|
+
}
|
|
93
139
|
export function collectPublishedTcpPorts(compose) {
|
|
94
140
|
const result = new Map();
|
|
95
141
|
if (!compose.services) {
|
|
@@ -180,6 +226,18 @@ function hasBuildStanza(compose) {
|
|
|
180
226
|
}
|
|
181
227
|
return Object.values(compose.services).some((service) => "build" in service && service.build !== undefined);
|
|
182
228
|
}
|
|
229
|
+
const DIGEST_PINNED_IMAGE = /@sha256:[0-9a-f]{64}$/i;
|
|
230
|
+
/** Service images a registry can move: anything without a trailing `@sha256:<64 hex>` digest. */
|
|
231
|
+
export function collectUnpinnedImages(compose) {
|
|
232
|
+
const unpinned = [];
|
|
233
|
+
for (const [service, definition] of Object.entries(compose.services ?? {})) {
|
|
234
|
+
const image = definition.image;
|
|
235
|
+
if (typeof image === "string" && !DIGEST_PINNED_IMAGE.test(image)) {
|
|
236
|
+
unpinned.push({ service, image });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return unpinned;
|
|
240
|
+
}
|
|
183
241
|
const HEADLESS_UNSUPPORTED_REASONS = new Set([
|
|
184
242
|
"HAS_COMPOSE_SECRETS_OR_CONFIGS",
|
|
185
243
|
"HAS_BUILD_STANZA",
|
|
@@ -811,6 +869,12 @@ export function validateComposeRunAs(compose, composeFile, context) {
|
|
|
811
869
|
}
|
|
812
870
|
return errors;
|
|
813
871
|
}
|
|
872
|
+
/** The gateway is the only door: the container's web port must not be reachable except through it. */
|
|
873
|
+
export function validateGatewayPortLoopback(adminport, compose, composeFile) {
|
|
874
|
+
return listPortExposures(compose)
|
|
875
|
+
.filter((exposure) => exposure.hostPort === adminport && !exposure.loopbackOnly)
|
|
876
|
+
.map((exposure) => makeError("COMPOSE_GATEWAY_PORT_EXPOSED", composeSpanForPath(compose, composeFile, `services.${exposure.service}.ports`), `${exposure.service} 的 port ${exposure.entry} 綁在所有網路介面上,不經 DSM 驗證就能直接連到容器。`, `請改成只綁 loopback:\"127.0.0.1:${adminport}:${exposure.containerPort ?? adminport}\",或在 synology-app.yaml 的 integration.web.access 明確選 public。`));
|
|
877
|
+
}
|
|
814
878
|
export function validateAdminPortMapping(adminport, compose, composeFile) {
|
|
815
879
|
const published = collectPublishedTcpPorts(compose);
|
|
816
880
|
const services = published.get(adminport) ?? [];
|
|
@@ -3,7 +3,7 @@ import { dirname, join } from "node:path";
|
|
|
3
3
|
import { contractSpan, makeError } from "../errors.js";
|
|
4
4
|
import { collectInstallParameters, getValuePosition, stringViolations, } from "./load.js";
|
|
5
5
|
import { validateContractSchema } from "./schema-validate.js";
|
|
6
|
-
import { isWebLaunchMode, readWebIntegration } from "./web-launch.js";
|
|
6
|
+
import { DSM_GROUP_NAME, isWebAccessMode, isWebLaunchMode, readWebIntegration } from "./web-launch.js";
|
|
7
7
|
import { loadCompose } from "../compose/analyze.js";
|
|
8
8
|
import { collectPosixAllSharesParameters, isPosixAllSharesType, validatePosixAllSharesSources, } from "./posix-all-shares.js";
|
|
9
9
|
import { getErrorCode } from "../error-registry.js";
|
|
@@ -52,6 +52,7 @@ export function validateContract(parsed, contractFile) {
|
|
|
52
52
|
errors.push(...validateInstallParameters(parsed, contractFile));
|
|
53
53
|
errors.push(...validatePosixAllShares(parsed, contractFile));
|
|
54
54
|
errors.push(...validateWebLaunch(parsed, contractFile));
|
|
55
|
+
errors.push(...validateWebAccess(parsed, contractFile));
|
|
55
56
|
return errors;
|
|
56
57
|
}
|
|
57
58
|
function validatePosixAllShares(parsed, contractFile) {
|
|
@@ -87,6 +88,37 @@ function validateWebLaunch(parsed, contractFile) {
|
|
|
87
88
|
}
|
|
88
89
|
return errors;
|
|
89
90
|
}
|
|
91
|
+
function validateWebAccess(parsed, contractFile) {
|
|
92
|
+
const { contract, doc } = parsed;
|
|
93
|
+
const web = readWebIntegration(contract);
|
|
94
|
+
if (!web || (web.access === undefined && web.groups === undefined)) {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
const at = (key) => {
|
|
98
|
+
const pos = getValuePosition(doc, ["integration", "web", key]) ?? { line: 1, column: 1 };
|
|
99
|
+
return contractSpan(contractFile, pos.line, pos.column, `integration.web.${key}`);
|
|
100
|
+
};
|
|
101
|
+
if (contract.adminport === undefined) {
|
|
102
|
+
return [
|
|
103
|
+
makeError("CONTRACT_ACCESS_REQUIRES_WEB", at(web.access !== undefined ? "access" : "groups"), "Headless App 沒有網頁入口,不需要 access 或 groups。", "請省略 integration.web.access/groups,或補上對應 Compose published port 的 adminport。"),
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
if (web.access !== undefined && !isWebAccessMode(web.access)) {
|
|
107
|
+
return [
|
|
108
|
+
makeError("CONTRACT_ACCESS_INVALID", at("access"), "integration.web.access 只能是 dsm-users、dsm-admins、dsm-groups 或 public。", "請改為 dsm-users(已登入的 DSM 使用者,預設)、dsm-admins、dsm-groups(需搭配 groups),或明確選 public 以保留匿名 Web Station 入口。"),
|
|
109
|
+
];
|
|
110
|
+
}
|
|
111
|
+
const groups = web.groups;
|
|
112
|
+
const groupsValid = Array.isArray(groups) &&
|
|
113
|
+
groups.length > 0 &&
|
|
114
|
+
groups.every((g) => typeof g === "string" && DSM_GROUP_NAME.test(g));
|
|
115
|
+
if (web.access === "dsm-groups" ? !groupsValid : groups !== undefined) {
|
|
116
|
+
return [
|
|
117
|
+
makeError("CONTRACT_ACCESS_GROUPS_INVALID", at("groups"), "integration.web.groups 必須搭配 access: dsm-groups,且是 DSM 本機群組或完整 DOMAIN\\group/group@domain 名稱(網域最長 64、群組最長 128 字元)的非空清單。", "請改用 access: dsm-groups 並列出群組名稱,或移除 groups。"),
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
90
122
|
function validateDeveloperString(value, contractFile, path, pos) {
|
|
91
123
|
const errors = [];
|
|
92
124
|
const violations = stringViolations(value);
|
|
@@ -7,11 +7,33 @@ export declare const DEFAULT_WEB_LAUNCH_MODE: WebLaunchMode;
|
|
|
7
7
|
export interface WebIntegration {
|
|
8
8
|
launch?: unknown;
|
|
9
9
|
cookies?: unknown;
|
|
10
|
+
access?: unknown;
|
|
11
|
+
groups?: unknown;
|
|
10
12
|
}
|
|
11
13
|
export declare function readWebIntegration(contract: AppContract): WebIntegration | undefined;
|
|
12
14
|
export declare function isWebLaunchMode(value: unknown): value is WebLaunchMode;
|
|
13
15
|
export declare function resolvedWebLaunch(contract: AppContract): WebLaunchMode | undefined;
|
|
16
|
+
export declare const WEB_ACCESS_MODES: readonly ["dsm-users", "dsm-admins", "dsm-groups", "public"];
|
|
17
|
+
export type WebAccessMode = (typeof WEB_ACCESS_MODES)[number];
|
|
18
|
+
export declare const DEFAULT_WEB_ACCESS_MODE: WebAccessMode;
|
|
19
|
+
/** Local or qualified directory group names (exact case and domain); also what the gateway accepts at startup. */
|
|
20
|
+
export declare const DSM_GROUP_NAME: RegExp;
|
|
21
|
+
export declare function isWebAccessMode(value: unknown): value is WebAccessMode;
|
|
22
|
+
export interface WebAccess {
|
|
23
|
+
mode: WebAccessMode;
|
|
24
|
+
groups: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Who may open a web App. Defaults to every signed-in DSM user; `public` is the
|
|
28
|
+
* explicit opt-out that keeps the anonymous Web Station portal. Undefined for a
|
|
29
|
+
* headless App or an access rule validation already rejects.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolvedWebAccess(contract: AppContract): WebAccess | undefined;
|
|
32
|
+
/** True when the App's container is reached only through the DSM-authenticated gateway CGI. */
|
|
33
|
+
export declare function usesAuthGateway(contract: AppContract): boolean;
|
|
14
34
|
export declare function webStationAlias(packageId: string): string;
|
|
35
|
+
/** DSM serves a package's `ui` directory under this root; the gateway CGI lives in it. */
|
|
36
|
+
export declare function gatewayEntryPath(packageId: string, adminurl: unknown): string;
|
|
15
37
|
export declare function trustedAppEntryPath(contract: AppContract): string;
|
|
16
38
|
export declare const DSM_RESERVED_COOKIES: readonly ["id", "did"];
|
|
17
39
|
export declare function extractContractCookieNames(contract: AppContract): string[];
|
|
@@ -27,6 +27,35 @@ export function resolvedWebLaunch(contract) {
|
|
|
27
27
|
}
|
|
28
28
|
return isWebLaunchMode(launch) ? launch : undefined;
|
|
29
29
|
}
|
|
30
|
+
export const WEB_ACCESS_MODES = ["dsm-users", "dsm-admins", "dsm-groups", "public"];
|
|
31
|
+
export const DEFAULT_WEB_ACCESS_MODE = "dsm-users";
|
|
32
|
+
/** Local or qualified directory group names (exact case and domain); also what the gateway accepts at startup. */
|
|
33
|
+
export const DSM_GROUP_NAME = /^(?:[A-Za-z0-9._-]{1,64}|[A-Za-z0-9._-]{1,64}\\[A-Za-z0-9._-](?:[A-Za-z0-9._ -]{0,126}[A-Za-z0-9._-])?|[A-Za-z0-9._-](?:[A-Za-z0-9._ -]{0,126}[A-Za-z0-9._-])?@[A-Za-z0-9._-]{1,64})$(?![\s\S])/;
|
|
34
|
+
export function isWebAccessMode(value) {
|
|
35
|
+
return WEB_ACCESS_MODES.includes(value);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Who may open a web App. Defaults to every signed-in DSM user; `public` is the
|
|
39
|
+
* explicit opt-out that keeps the anonymous Web Station portal. Undefined for a
|
|
40
|
+
* headless App or an access rule validation already rejects.
|
|
41
|
+
*/
|
|
42
|
+
export function resolvedWebAccess(contract) {
|
|
43
|
+
if (contract.adminport === undefined) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const web = readWebIntegration(contract);
|
|
47
|
+
const mode = web?.access ?? DEFAULT_WEB_ACCESS_MODE;
|
|
48
|
+
if (!isWebAccessMode(mode)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const groups = Array.isArray(web?.groups) ? web.groups.filter((g) => typeof g === "string") : [];
|
|
52
|
+
return { mode, groups };
|
|
53
|
+
}
|
|
54
|
+
/** True when the App's container is reached only through the DSM-authenticated gateway CGI. */
|
|
55
|
+
export function usesAuthGateway(contract) {
|
|
56
|
+
const access = resolvedWebAccess(contract);
|
|
57
|
+
return access !== undefined && access.mode !== "public";
|
|
58
|
+
}
|
|
30
59
|
export function webStationAlias(packageId) {
|
|
31
60
|
const slug = packageId
|
|
32
61
|
.toLowerCase()
|
|
@@ -37,7 +66,15 @@ export function webStationAlias(packageId) {
|
|
|
37
66
|
}
|
|
38
67
|
return `p${createHash("sha256").update(packageId).digest("hex").slice(0, 16)}`;
|
|
39
68
|
}
|
|
69
|
+
/** DSM serves a package's `ui` directory under this root; the gateway CGI lives in it. */
|
|
70
|
+
export function gatewayEntryPath(packageId, adminurl) {
|
|
71
|
+
const path = typeof adminurl === "string" ? adminurl.trim().replace(/^\/+/, "") : "";
|
|
72
|
+
return `/webman/3rdparty/${packageId}/cgi/gateway.cgi/${path}`;
|
|
73
|
+
}
|
|
40
74
|
export function trustedAppEntryPath(contract) {
|
|
75
|
+
if (usesAuthGateway(contract)) {
|
|
76
|
+
return gatewayEntryPath(String(contract.package ?? ""), contract.adminurl);
|
|
77
|
+
}
|
|
41
78
|
const alias = webStationAlias(String(contract.package ?? ""));
|
|
42
79
|
const adminurl = String(contract.adminurl ?? "/").trim() || "/";
|
|
43
80
|
const extra = adminurl.startsWith("/") ? adminurl : `/${adminurl}`;
|
package/dist/deploy/deploy.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CommandRunner } from "../standalone/build.js";
|
|
1
2
|
import type { NativeArchFamily } from "../build-spk/dsm-arch.js";
|
|
2
3
|
import type { ProjectRoot } from "../discovery.js";
|
|
3
4
|
import type { NasHost } from "../host/types.js";
|
|
@@ -12,6 +13,8 @@ export interface DeployProjectOptions {
|
|
|
12
13
|
shareValues?: Record<string, string>;
|
|
13
14
|
runAsValues?: Record<string, string>;
|
|
14
15
|
paramValues?: Record<string, string>;
|
|
16
|
+
/** Command runner for the DSM gateway's `go build` (tests inject a fake). */
|
|
17
|
+
gatewayRun?: CommandRunner;
|
|
15
18
|
}
|
|
16
19
|
export interface DeployProjectResult {
|
|
17
20
|
ok: boolean;
|
package/dist/deploy/deploy.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { buildSpk } from "../build-spk/generator.js";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { loadContract } from "../contract/load.js";
|
|
4
|
+
import { usesAuthGateway } from "../contract/web-launch.js";
|
|
4
5
|
import { findUnsupportedInstallTypes } from "../contract/unsupported-types.js";
|
|
5
6
|
import { appOriginFromContract } from "../host/open-url.js";
|
|
6
7
|
import { validateProject } from "../validate.js";
|
|
@@ -133,7 +134,7 @@ export async function deployProject(options) {
|
|
|
133
134
|
...shareResolved.extraValues,
|
|
134
135
|
...runAsResolved.extraValues,
|
|
135
136
|
};
|
|
136
|
-
// The upgrade wizard deliberately ignores auto-filled Share controls unless
|
|
137
|
+
// The upgrade wizard deliberately ignores auto-filled Share and Run-as controls unless
|
|
137
138
|
// the administrator opted into a change. Keep the CLI's explicit upgrade
|
|
138
139
|
// flags equivalent to checking those controls.
|
|
139
140
|
if (packageInstalled) {
|
|
@@ -142,6 +143,11 @@ export async function deployProject(options) {
|
|
|
142
143
|
extraValues[`CHANGE_${name}`] = "true";
|
|
143
144
|
}
|
|
144
145
|
}
|
|
146
|
+
for (const name of dsmUserParameterNames(contract)) {
|
|
147
|
+
if ((options.runAsValues?.[name] ?? "").trim() !== "") {
|
|
148
|
+
extraValues[`CHANGE_${name}`] = "true";
|
|
149
|
+
}
|
|
150
|
+
}
|
|
145
151
|
for (const name of posixAllSharesNames) {
|
|
146
152
|
if (explicitParamNames.has(name) && (paramValues[name] ?? "").trim() !== "") {
|
|
147
153
|
extraValues[`CHANGE_${name}`] = "true";
|
|
@@ -158,7 +164,9 @@ export async function deployProject(options) {
|
|
|
158
164
|
message: error instanceof Error ? error.message : String(error) };
|
|
159
165
|
}
|
|
160
166
|
let archFamily = options.archFamily;
|
|
161
|
-
|
|
167
|
+
const isNative = options.project.nativePath !== undefined && existsSync(options.project.nativePath);
|
|
168
|
+
// A DSM-authenticated web App ships a native gateway CGI, so it is built per architecture too.
|
|
169
|
+
if (archFamily === undefined && (isNative || usesAuthGateway(contract))) {
|
|
162
170
|
archFamily = await options.host.getArchFamily?.();
|
|
163
171
|
if (archFamily === undefined) {
|
|
164
172
|
return {
|
|
@@ -174,6 +182,7 @@ export async function deployProject(options) {
|
|
|
174
182
|
displayname: identity.displayname,
|
|
175
183
|
spkVersion,
|
|
176
184
|
archFamily,
|
|
185
|
+
gatewayRun: options.gatewayRun,
|
|
177
186
|
});
|
|
178
187
|
if (!build.ok || !build.outputPath) {
|
|
179
188
|
return { ok: false, code: "BUILD_SPK_FAILED", message: build.errors.join(", ") };
|