@synopackageland/cli 0.4.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/authorization-sdk.d.ts +5 -0
- package/dist/authorization-sdk.js +5 -0
- 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 +132 -32
- 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 +62 -3
- package/dist/host/dsm-port-profile.d.ts +1 -1
- package/dist/host/dsm-port-profile.js +1 -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 +126 -16
- package/dist/inspect.d.ts +3 -0
- package/dist/inspect.js +15 -3
- package/dist/standalone/authorization-window.d.ts +2 -0
- package/dist/standalone/authorization-window.js +28 -0
- package/dist/standalone/authorization.d.ts +48 -0
- package/dist/standalone/authorization.js +116 -0
- 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 +54 -10
- package/dist/standalone/dsm-window.js +10 -3
- 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 +29 -11
- 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 +21 -6
- package/dist/standalone/inspect-spk.d.ts +1 -1
- package/dist/standalone/inspect-spk.js +211 -7
- package/dist/standalone/job-diagnostics.d.ts +1 -0
- package/dist/standalone/job-diagnostics.js +49 -0
- package/dist/standalone/lifecycle-helper.d.ts +1 -1
- package/dist/standalone/lifecycle-helper.js +2 -2
- package/dist/standalone/lifecycle.d.ts +1 -1
- package/dist/standalone/lifecycle.js +14 -4
- 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-ops.d.ts +2 -0
- package/dist/standalone/root-ops.js +10 -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 +4 -0
- package/dist/standalone/spk.js +47 -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/_authorization/main.go +104 -0
- package/dist/templates/_authorization/main_test.go +35 -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/native-go/README.md +118 -5
- package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
- package/dist/templates/native-go/backend/cmd/app/main.go +25 -6
- package/dist/templates/native-go/backend/cmd/app/sdk_main.go +62 -0
- package/dist/templates/native-go/backend/cmd/background-worker/main.go +38 -0
- package/dist/templates/native-go/backend/cmd/helper/main.go +27 -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/authorization_none.go +5 -0
- 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 +22 -5
- 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 +177 -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 +86 -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/purge.go +115 -0
- package/dist/templates/native-go/backend/internal/helper/purge_test.go +59 -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/revoke.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/revoke_test.go +121 -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 +161 -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 +14 -2
- 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 +2 -2
- package/dist/templates/native-go-authorization/backend/internal/app/authorization.go +298 -0
- package/dist/templates/native-go-authorization/backend/internal/app/authorization_test.go +96 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/AuthorizationGate.vue +89 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/de.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/en.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/es.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/fr.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/index.ts +15 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/it.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/ja.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/ko.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/zh-CN.json +36 -0
- package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/zh-TW.json +36 -0
- package/dist/templates/native-go-authorization/frontend/test/authorization-preview.html +14 -0
- package/dist/templates/native-go-authorization/frontend/test/authorization.test.ts +59 -0
- 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/context.ts +3 -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/types.d.ts +1 -1
- package/dist/validate.js +6 -3
- package/package.json +5 -2
- package/schema/synology-app.schema.json +19 -0
- package/skills/reference/create.md +6 -2
- package/templates/_authorization/main.go +104 -0
- package/templates/_authorization/main_test.go +35 -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/native-go/README.md +118 -5
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
- package/templates/native-go/backend/cmd/app/main.go +25 -6
- package/templates/native-go/backend/cmd/app/sdk_main.go +62 -0
- package/templates/native-go/backend/cmd/background-worker/main.go +38 -0
- package/templates/native-go/backend/cmd/helper/main.go +27 -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/authorization_none.go +5 -0
- 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 +22 -5
- 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 +177 -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 +86 -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/purge.go +115 -0
- package/templates/native-go/backend/internal/helper/purge_test.go +59 -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/revoke.go +109 -0
- package/templates/native-go/backend/internal/helper/revoke_test.go +121 -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 +161 -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 +14 -2
- 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 +2 -2
- package/templates/native-go-authorization/backend/internal/app/authorization.go +298 -0
- package/templates/native-go-authorization/backend/internal/app/authorization_test.go +96 -0
- package/templates/native-go-authorization/frontend/src/authorization/AuthorizationGate.vue +89 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/de.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/en.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/es.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/fr.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/index.ts +15 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/it.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/ja.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/ko.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/zh-CN.json +36 -0
- package/templates/native-go-authorization/frontend/src/authorization/i18n/zh-TW.json +36 -0
- package/templates/native-go-authorization/frontend/test/authorization-preview.html +14 -0
- package/templates/native-go-authorization/frontend/test/authorization.test.ts +59 -0
- 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/context.ts +3 -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/templates/hello-web/compose.yaml +0 -21
- package/dist/templates/hello-web/html/app.js +0 -1
- package/dist/templates/hello-web/html/index.html +0 -13
- package/dist/templates/hello-web/synology-app.yaml +0 -13
- package/dist/templates/hello-web-page/compose.yaml +0 -21
- package/dist/templates/hello-web-page/html/app.js +0 -1
- package/dist/templates/hello-web-page/html/index.html +0 -13
- package/dist/templates/hello-web-page/synology-app.yaml +0 -13
- package/templates/hello-web/compose.yaml +0 -21
- package/templates/hello-web/html/app.js +0 -1
- package/templates/hello-web/html/index.html +0 -13
- package/templates/hello-web/synology-app.yaml +0 -13
- package/templates/hello-web-page/compose.yaml +0 -21
- package/templates/hello-web-page/html/app.js +0 -1
- package/templates/hello-web-page/html/index.html +0 -13
- package/templates/hello-web-page/synology-app.yaml +0 -13
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { hasHelper } from "./helper-inventory.js";
|
|
1
2
|
import { renderHelperStoppedCheck } from "./lifecycle-helper.js";
|
|
2
|
-
|
|
3
|
+
import { renderBackgroundControl } from "./background.js";
|
|
4
|
+
import { renderPackagePostuninst } from "../build-spk/native-lifecycle.js";
|
|
5
|
+
import { renderSharedFolderScript } from "./shared-folder.js";
|
|
6
|
+
/** Package-UID hooks: root auth withdraws via the trusted socket, then retains the stopped veto. */
|
|
3
7
|
export function renderStandaloneScript(name, manifest) {
|
|
8
|
+
if (name === "postuninst")
|
|
9
|
+
return renderPackagePostuninst(manifest.package);
|
|
10
|
+
if (manifest.sharedFolder && (name === "postinst" || name === "postupgrade"))
|
|
11
|
+
return renderSharedFolderScript(manifest.package, manifest.sharedFolder);
|
|
4
12
|
if (manifest.daemon)
|
|
5
13
|
return renderDaemonScript(name, manifest);
|
|
6
|
-
if (manifest.
|
|
7
|
-
|
|
14
|
+
if (manifest.background && name === "start-stop-status")
|
|
15
|
+
return renderBackgroundControl(manifest.package);
|
|
16
|
+
if (hasHelper(manifest) && ["preupgrade", "preuninst", "start-stop-status"].includes(name)) {
|
|
17
|
+
const check = renderHelperStoppedCheck(manifest.package, manifest.privilege === 'root');
|
|
8
18
|
if (name !== "start-stop-status")
|
|
9
19
|
return `#!/bin/sh\n${check}`;
|
|
10
20
|
return `#!/bin/sh
|
|
@@ -34,7 +44,7 @@ function renderDaemonScript(name, manifest) {
|
|
|
34
44
|
const pkg = manifest.package;
|
|
35
45
|
const control = `"/var/packages/${pkg}/target/daemon/control"`;
|
|
36
46
|
const paths = `"\${SYNOPKG_PKGDEST:-/var/packages/${pkg}/target}" "\${SYNOPKG_PKGVAR:-/var/packages/${pkg}/var}"`;
|
|
37
|
-
const check = manifest
|
|
47
|
+
const check = hasHelper(manifest) ? renderHelperStoppedCheck(pkg, manifest.privilege === 'root') : "";
|
|
38
48
|
if (["preupgrade", "preuninst"].includes(name))
|
|
39
49
|
return `#!/bin/sh\n${check}exec ${control} ${name === "preuninst" && manifest.daemon?.uninstall_args ? "uninstall" : "stop"} ${paths}\n`;
|
|
40
50
|
if (name !== "start-stop-status")
|
|
@@ -3,6 +3,8 @@ import { type Catalogs, type Locale } from "./i18n.js";
|
|
|
3
3
|
import { type RootOp } from "./root-ops.js";
|
|
4
4
|
import { type Integration } from "./helper.js";
|
|
5
5
|
import { type Daemon } from "./daemon.js";
|
|
6
|
+
import { type Background } from "./background.js";
|
|
7
|
+
import { type SharedFolder } from "./shared-folder.js";
|
|
6
8
|
/**
|
|
7
9
|
* `dsm-package.yaml`: a Standalone Package, i.e. an unsigned native SPK that
|
|
8
10
|
* runs as its own DSM package account with a CGI backend and a DSM window UI.
|
|
@@ -47,12 +49,23 @@ export interface StandaloneManifest {
|
|
|
47
49
|
};
|
|
48
50
|
};
|
|
49
51
|
i18n?: StandaloneI18n;
|
|
50
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* `none`: the package account only; an integration then has no helper.
|
|
54
|
+
* `root`: adds DSM-approved root tasks and, with an integration, its helper.
|
|
55
|
+
*/
|
|
51
56
|
privilege: "none" | "root";
|
|
52
|
-
/** `root/<name>.sh`, present exactly when privilege is root. */
|
|
57
|
+
/** `root/<name>.sh`, present exactly when privilege is root (empty for a helper-only integration). */
|
|
53
58
|
rootOps?: RootOp[];
|
|
54
59
|
integration?: Integration;
|
|
55
60
|
daemon?: Daemon;
|
|
61
|
+
background?: Background;
|
|
62
|
+
/**
|
|
63
|
+
* `session`: the package account serves the interactive File Station routes
|
|
64
|
+
* through each caller's own DSM session. No helper, no stored credential.
|
|
65
|
+
*/
|
|
66
|
+
fileStation?: "session";
|
|
67
|
+
/** `install.sharedFolder`: the Shared Folder the install wizard selects or `data-share` creates. */
|
|
68
|
+
sharedFolder?: SharedFolder;
|
|
56
69
|
}
|
|
57
70
|
export interface StandaloneError {
|
|
58
71
|
code: string;
|
|
@@ -5,7 +5,11 @@ import { isNativeArchFamily } from "../build-spk/dsm-arch.js";
|
|
|
5
5
|
import { checkGlossary, isLocale, loadCatalogs } from "./i18n.js";
|
|
6
6
|
import { loadRootOps, ROOT_OPS_DIR } from "./root-ops.js";
|
|
7
7
|
import { readIntegration } from "./helper.js";
|
|
8
|
+
import { hasHelper } from "./helper-inventory.js";
|
|
8
9
|
import { readDaemon } from "./daemon.js";
|
|
10
|
+
import { readBackground } from "./background.js";
|
|
11
|
+
import { DEFAULT_MIN_DSM, isDsmAtLeast } from "../build-spk/dsm-version.js";
|
|
12
|
+
import { readSharedFolder } from "./shared-folder.js";
|
|
9
13
|
/**
|
|
10
14
|
* `dsm-package.yaml`: a Standalone Package, i.e. an unsigned native SPK that
|
|
11
15
|
* runs as its own DSM package account with a CGI backend and a DSM window UI.
|
|
@@ -13,7 +17,7 @@ import { readDaemon } from "./daemon.js";
|
|
|
13
17
|
export const STANDALONE_MANIFEST = "dsm-package.yaml";
|
|
14
18
|
const KNOWN_FIELDS = new Set([
|
|
15
19
|
"schema", "package", "version", "build", "displayname", "description",
|
|
16
|
-
"maintainer", "os_min_ver", "arches", "backend", "ui", "privilege", "i18n", "integration", "daemon",
|
|
20
|
+
"maintainer", "os_min_ver", "arches", "backend", "ui", "privilege", "i18n", "integration", "daemon", "background", "fileStation", "install",
|
|
17
21
|
]);
|
|
18
22
|
const I18N_FIELDS = new Set(["messages", "glossary", "info"]);
|
|
19
23
|
const INFO_TEXT_FIELDS = new Set(["displayname", "description"]);
|
|
@@ -85,7 +89,8 @@ function readManifest(raw, c) {
|
|
|
85
89
|
const privilege = raw.privilege === "none" || raw.privilege === "root"
|
|
86
90
|
? raw.privilege
|
|
87
91
|
: c.fail("STANDALONE_PRIVILEGE_UNSUPPORTED", "privilege 只接受 none(只用套件帳號)或 root(由 DSM 管理員核准的 root 工作);請見 README「Root access」。");
|
|
88
|
-
const
|
|
92
|
+
const integration = readIntegration(raw.integration, c.root, e => c.fail(e.code, e.message));
|
|
93
|
+
const rootOps = privilege && readRootOps(privilege, integration !== undefined, c);
|
|
89
94
|
const packageId = typeof raw.package === "string" && PACKAGE_ID.test(raw.package)
|
|
90
95
|
? raw.package
|
|
91
96
|
: c.fail("STANDALONE_PACKAGE_INVALID", "package 必須以英文字母開頭,只含英數字(2–64 字)。");
|
|
@@ -98,16 +103,24 @@ function readManifest(raw, c) {
|
|
|
98
103
|
const osMinVer = typeof raw.os_min_ver === "string" && OS_MIN_VER.test(raw.os_min_ver)
|
|
99
104
|
? raw.os_min_ver
|
|
100
105
|
: c.fail("STANDALONE_OS_MIN_VER_INVALID", "os_min_ver 格式為 <major>.<minor>-<build>,例如 7.2-64570。");
|
|
106
|
+
if (privilege === "root" && osMinVer && !isDsmAtLeast(osMinVer, DEFAULT_MIN_DSM)) {
|
|
107
|
+
c.fail("STANDALONE_OS_MIN_VER_INVALID", `root templates require DSM ${DEFAULT_MIN_DSM} or later.`);
|
|
108
|
+
}
|
|
101
109
|
const displayname = c.text(raw.displayname, "displayname");
|
|
102
110
|
const description = c.text(raw.description, "description");
|
|
103
111
|
const maintainer = c.text(raw.maintainer, "maintainer");
|
|
104
112
|
const arches = readArches(raw.arches, c);
|
|
105
113
|
const backend = arches && readBackend(raw.backend, arches, c);
|
|
106
114
|
const daemon = arches && readDaemon(raw.daemon, c.root, arches, e => c.fail(e.code, e.message));
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
115
|
+
if (integration && (backend?.kind !== "go" || rootOps?.some(op => op.name.startsWith("helper_")) || (privilege === "none" && !isPackageOnly(integration)))) {
|
|
116
|
+
c.fail("STANDALONE_INTEGRATION_INVALID", "integration 需要 backend.go;helper_ 操作名稱保留給 generator。privilege: none 只提供套件帳號整合(protocol 1、workers 為空,可選 identity),helper 設定需要 privilege: root。");
|
|
117
|
+
}
|
|
118
|
+
const background = readBackground(raw.background, e => c.fail(e.code, e.message));
|
|
119
|
+
if (raw.background !== undefined && (backend?.kind !== "go" || raw.daemon !== undefined || privilege === "root")) {
|
|
120
|
+
c.fail("STANDALONE_BACKGROUND_INVALID", "background 需要 backend.go(worker 由專案的 Go module 編譯)與 privilege: none,且不能與 daemon 並用;套件帳號 integration 可並用,root helper 不行。");
|
|
110
121
|
}
|
|
122
|
+
const fileStation = raw.fileStation === undefined ? undefined : readFileStation(raw.fileStation, backend?.kind === "go" && !hasHelper({ integration, privilege }), c);
|
|
123
|
+
const sharedFolder = raw.install === undefined ? undefined : readSharedFolder(raw.install, e => c.fail(e.code, e.message));
|
|
111
124
|
const ui = readUi(raw.ui, c);
|
|
112
125
|
const i18n = raw.i18n === undefined ? undefined : readI18n(raw.i18n, c);
|
|
113
126
|
if (!packageId || !version || !build || !osMinVer || !displayname || !description || !maintainer
|
|
@@ -132,15 +145,27 @@ function readManifest(raw, c) {
|
|
|
132
145
|
...(rootOps ? { rootOps } : {}),
|
|
133
146
|
...(integration ? { integration } : {}),
|
|
134
147
|
...(daemon ? { daemon } : {}),
|
|
148
|
+
...(background ? { background } : {}),
|
|
149
|
+
...(fileStation ? { fileStation } : {}),
|
|
150
|
+
...(sharedFolder ? { sharedFolder } : {}),
|
|
135
151
|
};
|
|
136
152
|
}
|
|
137
|
-
|
|
153
|
+
/** Without privilege: root there is no helper, so none of its inventory settings apply. */
|
|
154
|
+
function isPackageOnly(integration) {
|
|
155
|
+
return integration.protocol === 1 && Object.keys(integration.workers).length === 0
|
|
156
|
+
&& integration.dataAccess === undefined && integration.sdkWorkers === undefined;
|
|
157
|
+
}
|
|
158
|
+
/** A root integration's helper tasks are generated; it needs no root/ operation of its own. */
|
|
159
|
+
function readRootOps(privilege, hasIntegration, c) {
|
|
138
160
|
const dir = join(c.root, ROOT_OPS_DIR);
|
|
139
161
|
if (privilege === "none") {
|
|
140
162
|
return existsSync(dir)
|
|
141
163
|
? c.fail("STANDALONE_ROOT_OPS_UNUSED", `${ROOT_OPS_DIR}/ 只用在 privilege: root;privilege: none 的套件不會執行它。`)
|
|
142
164
|
: undefined;
|
|
143
165
|
}
|
|
166
|
+
if (hasIntegration && !existsSync(dir)) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
144
169
|
const loaded = loadRootOps(dir);
|
|
145
170
|
if (!loaded.ok) {
|
|
146
171
|
loaded.errors.forEach((e) => c.fail(e.code, e.message));
|
|
@@ -277,3 +302,9 @@ export function findStandaloneRoot(start) {
|
|
|
277
302
|
current = parent;
|
|
278
303
|
}
|
|
279
304
|
}
|
|
305
|
+
function readFileStation(value, allowed, c) {
|
|
306
|
+
if (value === "session" && allowed)
|
|
307
|
+
return "session";
|
|
308
|
+
c.fail("STANDALONE_FILESTATION_INVALID", "fileStation 只接受 session,需要 backend.go,且不能與 root helper integration 並用(helper 有自己的 File Station gate)。");
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { CommandRunner } from './build.js';
|
|
2
|
+
export declare const LAYOUT_ARCHES: {
|
|
3
|
+
readonly x86_64: readonly [2, 62];
|
|
4
|
+
readonly aarch64: readonly [2, 183];
|
|
5
|
+
readonly armv8: readonly [2, 183];
|
|
6
|
+
readonly armv7: readonly [1, 40];
|
|
7
|
+
};
|
|
8
|
+
export type LayoutArch = keyof typeof LAYOUT_ARCHES;
|
|
9
|
+
type Hook = {
|
|
10
|
+
command: string[];
|
|
11
|
+
cwd: string;
|
|
12
|
+
env: Record<string, string>;
|
|
13
|
+
};
|
|
14
|
+
type Toolkit = {
|
|
15
|
+
url: string;
|
|
16
|
+
sha256: string;
|
|
17
|
+
};
|
|
18
|
+
type Binary = {
|
|
19
|
+
path: string;
|
|
20
|
+
linkage: 'static' | 'dynamic';
|
|
21
|
+
arches?: LayoutArch[];
|
|
22
|
+
};
|
|
23
|
+
export interface NativeLayout {
|
|
24
|
+
root: string;
|
|
25
|
+
package: string;
|
|
26
|
+
version: string;
|
|
27
|
+
build: number;
|
|
28
|
+
displayname: string;
|
|
29
|
+
description: string;
|
|
30
|
+
maintainer: string;
|
|
31
|
+
os_min_ver: string;
|
|
32
|
+
privilege: 'none';
|
|
33
|
+
arches: LayoutArch[];
|
|
34
|
+
layout: {
|
|
35
|
+
payload: string;
|
|
36
|
+
metadata: string;
|
|
37
|
+
binaries: Binary[];
|
|
38
|
+
};
|
|
39
|
+
native: {
|
|
40
|
+
prepare?: Hook;
|
|
41
|
+
hook: Hook;
|
|
42
|
+
toolkits: Partial<Record<LayoutArch, Toolkit[]>>;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export declare function isNativeLayout(root: string): boolean;
|
|
46
|
+
export declare function loadNativeLayout(root: string): {
|
|
47
|
+
ok: true;
|
|
48
|
+
manifest: NativeLayout;
|
|
49
|
+
} | {
|
|
50
|
+
ok: false;
|
|
51
|
+
errors: {
|
|
52
|
+
code: string;
|
|
53
|
+
message: string;
|
|
54
|
+
}[];
|
|
55
|
+
};
|
|
56
|
+
export declare function verifyToolkitArchive(path: string, expected: string): void;
|
|
57
|
+
export declare function layoutFiles(root: string): Array<{
|
|
58
|
+
path: string;
|
|
59
|
+
mode: number;
|
|
60
|
+
sha256: string;
|
|
61
|
+
}>;
|
|
62
|
+
export declare function checkLayoutBinary(root: string, b: Binary, arch: LayoutArch): void;
|
|
63
|
+
export declare function checkLayoutMetadata(root: string, inspection?: boolean, packageId?: string): void;
|
|
64
|
+
export declare function buildNativeLayout(options: {
|
|
65
|
+
root: string;
|
|
66
|
+
arches?: string[];
|
|
67
|
+
outDir?: string;
|
|
68
|
+
build?: number;
|
|
69
|
+
run?: CommandRunner;
|
|
70
|
+
}): Promise<{
|
|
71
|
+
outputs: string[];
|
|
72
|
+
}>;
|
|
73
|
+
export declare function inspectNativeLayout(dir: string, payload: string, info: Record<string, string>): string[];
|
|
74
|
+
export {};
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/** Existing native products: the CLI owns archives/INFO, the project owns its layout. */
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
6
|
+
import { parse } from 'yaml';
|
|
7
|
+
import { createReproducibleTar } from '../build-spk/reproducible-archive.js';
|
|
8
|
+
import { runCommand } from './build.js';
|
|
9
|
+
export const LAYOUT_ARCHES = { x86_64: [2, 62], aarch64: [2, 183], armv8: [2, 183], armv7: [1, 40] };
|
|
10
|
+
function fail(message) { throw new Error(`NATIVE_LAYOUT_INVALID: ${message}`); }
|
|
11
|
+
const digest = (bytes) => createHash('sha256').update(bytes).digest('hex');
|
|
12
|
+
function object(value, fields) {
|
|
13
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
14
|
+
fail('expected object');
|
|
15
|
+
const obj = value;
|
|
16
|
+
if (Object.keys(obj).some(k => !fields.includes(k)))
|
|
17
|
+
fail('unknown field');
|
|
18
|
+
return obj;
|
|
19
|
+
}
|
|
20
|
+
function text(value) {
|
|
21
|
+
if (typeof value !== 'string' || !value || /[\r\n"\\\0]/.test(value))
|
|
22
|
+
fail('invalid text');
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function pathText(value) {
|
|
26
|
+
const path = text(value);
|
|
27
|
+
if (isAbsolute(path) || path.split('/').some(p => p === '..' || p === '') || /[{}]/.test(path.replaceAll('{arch}', '')))
|
|
28
|
+
fail('path must stay inside project');
|
|
29
|
+
return path;
|
|
30
|
+
}
|
|
31
|
+
function inside(root, path) {
|
|
32
|
+
const full = resolve(root, path);
|
|
33
|
+
const rel = relative(realpathSync(root), realpathSync(full));
|
|
34
|
+
if (rel === '..' || rel.startsWith('../') || isAbsolute(rel))
|
|
35
|
+
fail('path escapes project');
|
|
36
|
+
return full;
|
|
37
|
+
}
|
|
38
|
+
function hook(value) {
|
|
39
|
+
const h = object(value, ['command', 'cwd', 'env']);
|
|
40
|
+
if (!Array.isArray(h.command) || !h.command.length || !h.command.every((x) => typeof x === 'string' && x.length > 0 && !x.includes('\0')))
|
|
41
|
+
fail('hook requires argv');
|
|
42
|
+
const env = object(h.env ?? {}, Object.keys(h.env ?? {}));
|
|
43
|
+
for (const [key, value] of Object.entries(env))
|
|
44
|
+
if (!/^[A-Z_][A-Z0-9_]*$/.test(key) || typeof value !== 'string' || value.includes('\0') || key.startsWith('SYNOPKGLAND_'))
|
|
45
|
+
fail('invalid hook environment');
|
|
46
|
+
return { command: h.command, cwd: pathText(h.cwd ?? '.'), env };
|
|
47
|
+
}
|
|
48
|
+
export function isNativeLayout(root) {
|
|
49
|
+
try {
|
|
50
|
+
return parse(readFileSync(join(root, 'dsm-package.yaml'), 'utf8'))?.layout !== undefined;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export function loadNativeLayout(root) {
|
|
57
|
+
try {
|
|
58
|
+
const m = object(parse(readFileSync(join(root, 'dsm-package.yaml'), 'utf8')), ['schema', 'package', 'version', 'build', 'displayname', 'description', 'maintainer', 'os_min_ver', 'privilege', 'arches', 'layout', 'native']);
|
|
59
|
+
if (m.schema !== 1 || m.privilege !== 'none')
|
|
60
|
+
fail('schema 1 and privilege: none required');
|
|
61
|
+
if (!/^[A-Za-z][A-Za-z0-9]{1,63}$/.test(text(m.package)) || !/^\d+(\.\d+){0,3}$/.test(text(m.version)) || !/^7\.\d+(\.\d+)?-\d+$/.test(text(m.os_min_ver)))
|
|
62
|
+
fail('invalid package/version/DSM');
|
|
63
|
+
if (!Number.isSafeInteger(m.build) || m.build < 1 || m.build > 2147483647)
|
|
64
|
+
fail('build must be 1..2147483647');
|
|
65
|
+
for (const k of ['displayname', 'description', 'maintainer'])
|
|
66
|
+
text(m[k]);
|
|
67
|
+
if (!Array.isArray(m.arches) || !m.arches.length || new Set(m.arches).size !== m.arches.length || m.arches.some((a) => !Object.hasOwn(LAYOUT_ARCHES, a)))
|
|
68
|
+
fail('invalid architecture list');
|
|
69
|
+
const layout = object(m.layout, ['payload', 'metadata', 'binaries']);
|
|
70
|
+
layout.payload = pathText(layout.payload);
|
|
71
|
+
layout.metadata = pathText(layout.metadata);
|
|
72
|
+
if (!Array.isArray(layout.binaries) || !layout.binaries.length)
|
|
73
|
+
fail('binary assertions required');
|
|
74
|
+
for (const b of layout.binaries) {
|
|
75
|
+
object(b, ['path', 'linkage', 'arches']);
|
|
76
|
+
pathText(b.path);
|
|
77
|
+
if (!['static', 'dynamic'].includes(b.linkage))
|
|
78
|
+
fail('declare binary linkage');
|
|
79
|
+
if (b.arches !== undefined && (!Array.isArray(b.arches) || !b.arches.length || b.arches.some((a) => !m.arches.includes(a))))
|
|
80
|
+
fail('invalid binary arches');
|
|
81
|
+
}
|
|
82
|
+
const native = object(m.native, ['prepare', 'hook', 'toolkits']);
|
|
83
|
+
const toolkits = object(native.toolkits ?? {}, m.arches);
|
|
84
|
+
for (const entries of Object.values(toolkits)) {
|
|
85
|
+
if (!Array.isArray(entries) || !entries.length)
|
|
86
|
+
fail('toolkits require archives');
|
|
87
|
+
for (const t of entries) {
|
|
88
|
+
object(t, ['url', 'sha256']);
|
|
89
|
+
const u = new URL(t.url);
|
|
90
|
+
if (u.protocol !== 'https:' || u.username || u.password || !/^[a-f0-9]{64}$/.test(t.sha256))
|
|
91
|
+
fail('toolkits require HTTPS and SHA-256');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { ok: true, manifest: { ...m, root: resolve(root), native: { hook: hook(native.hook), ...(native.prepare ? { prepare: hook(native.prepare) } : {}), toolkits } } };
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return { ok: false, errors: [{ code: 'NATIVE_LAYOUT_INVALID', message: String(error) }] };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export function verifyToolkitArchive(path, expected) {
|
|
101
|
+
if (!lstatSync(path).isFile() || digest(readFileSync(path)) !== expected)
|
|
102
|
+
fail('toolkit checksum mismatch');
|
|
103
|
+
}
|
|
104
|
+
async function toolkitFor(m, arch, run) {
|
|
105
|
+
const inputs = m.native.toolkits[arch] ?? [];
|
|
106
|
+
if (!inputs.length)
|
|
107
|
+
return '';
|
|
108
|
+
const cache = resolve(process.env.SYNOPKGLAND_CACHE_DIR ?? join(m.root, '.synopkgland-cache'));
|
|
109
|
+
mkdirSync(cache, { recursive: true, mode: 0o700 });
|
|
110
|
+
if (lstatSync(cache).isSymbolicLink() || (lstatSync(cache).mode & 0o022))
|
|
111
|
+
fail('toolkit cache must be owned and private');
|
|
112
|
+
const archives = [];
|
|
113
|
+
for (const input of inputs) {
|
|
114
|
+
const archive = join(cache, `${input.sha256}.txz`);
|
|
115
|
+
if (!existsSync(archive)) {
|
|
116
|
+
const download = mkdtempSync(join(cache, '.download-'));
|
|
117
|
+
try {
|
|
118
|
+
const out = join(download, 'archive');
|
|
119
|
+
const r = run('curl', ['--fail', '--location', '--proto', '=https', '--proto-redir', '=https', '--retry', '2', '--retry-all-errors', '--connect-timeout', '20', '--max-time', '600', '--output', out, input.url], { cwd: m.root, env: { ...process.env } });
|
|
120
|
+
if (r.status !== 0)
|
|
121
|
+
fail('toolkit download failed');
|
|
122
|
+
verifyToolkitArchive(out, input.sha256);
|
|
123
|
+
renameSync(out, archive);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
rmSync(download, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
verifyToolkitArchive(archive, input.sha256);
|
|
130
|
+
archives.push(archive);
|
|
131
|
+
}
|
|
132
|
+
// Re-extract verified bytes: a package-writable marker never authenticates an extracted tree.
|
|
133
|
+
const stage = mkdtempSync(join(cache, `toolkit-${arch}-`));
|
|
134
|
+
try {
|
|
135
|
+
for (const archive of archives) {
|
|
136
|
+
const r = run('tar', ['-xJf', archive, '-C', stage, '--keep-directory-symlink'], { cwd: m.root, env: { ...process.env } });
|
|
137
|
+
if (r.status !== 0)
|
|
138
|
+
fail('toolkit extraction failed');
|
|
139
|
+
}
|
|
140
|
+
return stage;
|
|
141
|
+
}
|
|
142
|
+
catch (e) {
|
|
143
|
+
rmSync(stage, { recursive: true, force: true });
|
|
144
|
+
throw e;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function runHook(m, h, env, run) {
|
|
148
|
+
const [cmd, ...args] = h.command;
|
|
149
|
+
const r = run(cmd, args, { cwd: inside(m.root, h.cwd), env: { ...process.env, ...h.env, ...env } });
|
|
150
|
+
if (r.status !== 0 || r.missing)
|
|
151
|
+
fail(`native hook failed: ${r.stderr}`);
|
|
152
|
+
}
|
|
153
|
+
export function layoutFiles(root) {
|
|
154
|
+
if (!lstatSync(root).isDirectory() || lstatSync(root).isSymbolicLink())
|
|
155
|
+
fail('layout root must be a regular directory');
|
|
156
|
+
const files = [];
|
|
157
|
+
let total = 0;
|
|
158
|
+
const walk = (prefix) => {
|
|
159
|
+
for (const name of readdirSync(join(root, prefix)).sort()) {
|
|
160
|
+
const path = prefix ? `${prefix}/${name}` : name;
|
|
161
|
+
const s = lstatSync(join(root, path));
|
|
162
|
+
if (s.isSymbolicLink() || (!s.isFile() && !s.isDirectory()))
|
|
163
|
+
fail('layout contains symlink or special file');
|
|
164
|
+
if (s.mode & 0o6000)
|
|
165
|
+
fail('privileged file modes are forbidden');
|
|
166
|
+
if (s.isDirectory())
|
|
167
|
+
walk(path);
|
|
168
|
+
else {
|
|
169
|
+
total += s.size;
|
|
170
|
+
if (s.size > 256 * 1024 * 1024 || total > 1024 * 1024 * 1024)
|
|
171
|
+
fail('layout exceeds size bound');
|
|
172
|
+
files.push({ path, mode: s.mode & 0o111 ? 0o755 : 0o644, sha256: digest(readFileSync(join(root, path))) });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
walk('');
|
|
177
|
+
return files;
|
|
178
|
+
}
|
|
179
|
+
export function checkLayoutBinary(root, b, arch) {
|
|
180
|
+
const path = inside(root, b.path);
|
|
181
|
+
const bytes = readFileSync(path);
|
|
182
|
+
const [cls, machine] = LAYOUT_ARCHES[arch];
|
|
183
|
+
if (bytes.length < 64 || bytes.toString('latin1', 0, 4) !== '\x7fELF' || bytes[4] !== cls || bytes[5] !== 1 || bytes.readUInt16LE(18) !== machine || ![2, 3].includes(bytes.readUInt16LE(16)))
|
|
184
|
+
fail(`ELF architecture mismatch: ${b.path}`);
|
|
185
|
+
const offset = cls === 1 ? bytes.readUInt32LE(28) : Number(bytes.readBigUInt64LE(32));
|
|
186
|
+
const size = bytes.readUInt16LE(cls === 1 ? 42 : 54);
|
|
187
|
+
const count = bytes.readUInt16LE(cls === 1 ? 44 : 56);
|
|
188
|
+
if (!count || size < (cls === 1 ? 32 : 56) || !Number.isSafeInteger(offset) || offset + size * count > bytes.length)
|
|
189
|
+
fail('invalid ELF program headers');
|
|
190
|
+
let dynamic = false;
|
|
191
|
+
for (let i = 0; i < count; i++)
|
|
192
|
+
if (bytes.readUInt32LE(offset + size * i) === 3)
|
|
193
|
+
dynamic = true;
|
|
194
|
+
if (dynamic !== (b.linkage === 'dynamic'))
|
|
195
|
+
fail(`ELF linkage mismatch: ${b.path}`);
|
|
196
|
+
if (!(lstatSync(path).mode & 0o111))
|
|
197
|
+
fail(`binary must be executable: ${b.path}`);
|
|
198
|
+
}
|
|
199
|
+
function copyTree(from, to) {
|
|
200
|
+
const entries = layoutFiles(from);
|
|
201
|
+
for (const entry of entries) {
|
|
202
|
+
const out = join(to, entry.path);
|
|
203
|
+
mkdirSync(dirname(out), { recursive: true });
|
|
204
|
+
copyFileSync(join(from, entry.path), out);
|
|
205
|
+
chmodSync(out, entry.mode);
|
|
206
|
+
}
|
|
207
|
+
return entries;
|
|
208
|
+
}
|
|
209
|
+
export function checkLayoutMetadata(root, inspection = false, packageId) {
|
|
210
|
+
const p = JSON.parse(readFileSync(join(root, 'conf/privilege'), 'utf8'));
|
|
211
|
+
if (p.defaults?.['run-as'] !== 'package' || Object.keys(p).some(k => !['defaults', 'username', 'groupname'].includes(k)) || ['username', 'groupname'].some(k => p[k] !== undefined && p[k] !== packageId) || Object.keys(p.defaults).some(k => k !== 'run-as'))
|
|
212
|
+
fail('native layout requires package-only lifecycle privilege');
|
|
213
|
+
if (!existsSync(join(root, 'scripts/start-stop-status')))
|
|
214
|
+
fail('start-stop-status missing');
|
|
215
|
+
if (existsSync(join(root, 'conf/resource'))) {
|
|
216
|
+
const resource = object(JSON.parse(readFileSync(join(root, 'conf/resource'), 'utf8')), ['systemd-unit']);
|
|
217
|
+
if (resource['systemd-unit'] !== undefined && Object.keys(object(resource['systemd-unit'], [])).length)
|
|
218
|
+
fail('unsupported resource worker');
|
|
219
|
+
}
|
|
220
|
+
if (existsSync(join(root, 'conf/systemd'))) {
|
|
221
|
+
for (const entry of layoutFiles(join(root, 'conf/systemd'))) {
|
|
222
|
+
const unit = readFileSync(join(root, 'conf/systemd', entry.path), 'utf8');
|
|
223
|
+
const users = [...unit.matchAll(/^\s*User\s*=\s*(.*?)\s*$/gm)].map(m => m[1]);
|
|
224
|
+
const groups = [...unit.matchAll(/^\s*Group\s*=\s*(.*?)\s*$/gm)].map(m => m[1]);
|
|
225
|
+
if (!packageId || users.length !== 1 || users[0] !== packageId || groups.some(group => group !== packageId) || /^\s*(?:AmbientCapabilities|SupplementaryGroups|PermissionsStartOnly|RootDirectory|RootImage)\s*=/m.test(unit) || /^\s*Exec\w*\s*=\s*[+!]/m.test(unit))
|
|
226
|
+
fail('systemd unit must run only as the package account');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
for (const name of readdirSync(root))
|
|
230
|
+
if (!['conf', 'scripts', 'WIZARD_UIFILES', 'PACKAGE_ICON.PNG', 'PACKAGE_ICON_256.PNG', ...(inspection ? ['INFO', 'package.tgz', 'native-layout.json', 'layout-inspection'] : [])].includes(name))
|
|
231
|
+
fail(`unsupported SPK metadata: ${name}`);
|
|
232
|
+
for (const f of layoutFiles(root)) {
|
|
233
|
+
if (f.path.startsWith('scripts/') && /\bsudo\b|\bchown\s+root\b|chmod\s+[ugo]*\+s\b/.test(readFileSync(join(root, f.path), 'utf8')))
|
|
234
|
+
fail('root lifecycle operation forbidden');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
export async function buildNativeLayout(options) {
|
|
238
|
+
const loaded = loadNativeLayout(options.root);
|
|
239
|
+
if (!loaded.ok)
|
|
240
|
+
fail(loaded.errors.map(e => e.message).join('\n'));
|
|
241
|
+
const m = loaded.manifest;
|
|
242
|
+
if (options.build !== undefined) {
|
|
243
|
+
if (!Number.isSafeInteger(options.build) || options.build < 1 || options.build > 2147483647)
|
|
244
|
+
fail('invalid build override');
|
|
245
|
+
m.build = options.build;
|
|
246
|
+
}
|
|
247
|
+
const arches = options.arches ?? m.arches;
|
|
248
|
+
if (!arches.length || new Set(arches).size !== arches.length || arches.some(a => !m.arches.includes(a)))
|
|
249
|
+
fail('architecture not declared');
|
|
250
|
+
const run = options.run ?? runCommand;
|
|
251
|
+
const version = `${m.version}-${String(m.build).padStart(4, '0')}`;
|
|
252
|
+
const env = { SYNOPKGLAND_PACKAGE: m.package, SYNOPKGLAND_VERSION: m.version, SYNOPKGLAND_BUILD: String(m.build), SYNOPKGLAND_SPK_VERSION: version, SYNOPKGLAND_PROJECT_DIR: m.root };
|
|
253
|
+
if (m.native.prepare)
|
|
254
|
+
runHook(m, m.native.prepare, env, run);
|
|
255
|
+
const outputs = [];
|
|
256
|
+
for (const requested of arches) {
|
|
257
|
+
const arch = requested;
|
|
258
|
+
const toolkit = await toolkitFor(m, arch, run);
|
|
259
|
+
const stage = mkdtempSync(join(tmpdir(), 'synopkgland-layout-'));
|
|
260
|
+
try {
|
|
261
|
+
runHook(m, m.native.hook, { ...env, SYNOPKGLAND_ARCH: arch, SYNOPKGLAND_TOOLKIT_DIR: toolkit }, run);
|
|
262
|
+
const payload = inside(m.root, m.layout.payload.replaceAll('{arch}', arch));
|
|
263
|
+
const metadata = inside(m.root, m.layout.metadata);
|
|
264
|
+
checkLayoutMetadata(metadata, false, m.package);
|
|
265
|
+
layoutFiles(payload);
|
|
266
|
+
const binaries = m.layout.binaries.filter(b => !b.arches || b.arches.includes(arch));
|
|
267
|
+
if (!binaries.length)
|
|
268
|
+
fail("binary assertions required for every architecture");
|
|
269
|
+
for (const b of binaries)
|
|
270
|
+
checkLayoutBinary(payload, b, arch);
|
|
271
|
+
copyTree(metadata, stage);
|
|
272
|
+
const target = join(stage, 'payload');
|
|
273
|
+
mkdirSync(target);
|
|
274
|
+
const files = copyTree(payload, target);
|
|
275
|
+
await createReproducibleTar(target, join(stage, 'package.tgz'), { gzip: true });
|
|
276
|
+
rmSync(target, { recursive: true });
|
|
277
|
+
const fields = { package: m.package, version, arch, os_min_ver: m.os_min_ver, displayname: m.displayname, description: m.description, maintainer: m.maintainer, dsmuidir: 'ui', dsmappname: `SYNO.SDS.${m.package}.Instance`, startable: 'yes', thirdparty: 'yes', checksum: createHash('md5').update(readFileSync(join(stage, 'package.tgz'))).digest('hex') };
|
|
278
|
+
writeFileSync(join(stage, 'INFO'), Object.entries(fields).map(([k, v]) => `${k}="${v}"\n`).join(''));
|
|
279
|
+
writeFileSync(join(stage, 'native-layout.json'), JSON.stringify({ format: 1, arch, binaries: binaries.map(({ path, linkage }) => ({ path, linkage })), files }));
|
|
280
|
+
const output = join(options.outDir ?? join(m.root, 'dist'), `${m.package}-${version}-${arch}.spk`);
|
|
281
|
+
mkdirSync(dirname(output), { recursive: true });
|
|
282
|
+
await createReproducibleTar(stage, output);
|
|
283
|
+
outputs.push(output);
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
rmSync(stage, { recursive: true, force: true });
|
|
287
|
+
if (toolkit)
|
|
288
|
+
rmSync(toolkit, { recursive: true, force: true });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return { outputs };
|
|
292
|
+
}
|
|
293
|
+
export function inspectNativeLayout(dir, payload, info) {
|
|
294
|
+
try {
|
|
295
|
+
const inv = object(JSON.parse(readFileSync(join(dir, 'native-layout.json'), 'utf8')), ['format', 'arch', 'binaries', 'files']);
|
|
296
|
+
if (inv.format !== 1 || inv.arch !== info.arch || !Object.hasOwn(LAYOUT_ARCHES, inv.arch))
|
|
297
|
+
fail('invalid native layout inventory');
|
|
298
|
+
checkLayoutMetadata(dir, true, info.package);
|
|
299
|
+
const actual = layoutFiles(payload);
|
|
300
|
+
if (JSON.stringify(actual) !== JSON.stringify(inv.files))
|
|
301
|
+
fail('payload checksum or mode mismatch');
|
|
302
|
+
if (!Array.isArray(inv.binaries) || !inv.binaries.length)
|
|
303
|
+
fail('missing binary assertions');
|
|
304
|
+
for (const b of inv.binaries) {
|
|
305
|
+
object(b, ['path', 'linkage']);
|
|
306
|
+
pathText(b.path);
|
|
307
|
+
if (!['static', 'dynamic'].includes(b.linkage))
|
|
308
|
+
fail('invalid linkage');
|
|
309
|
+
checkLayoutBinary(payload, b, inv.arch);
|
|
310
|
+
}
|
|
311
|
+
if (createHash('md5').update(readFileSync(join(dir, 'package.tgz'))).digest('hex') !== info.checksum)
|
|
312
|
+
fail('package checksum mismatch');
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
return [String(e)];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Background } from "./background.js";
|
|
2
|
+
import { type SharedFolder } from "./shared-folder.js";
|
|
3
|
+
/**
|
|
4
|
+
* `conf/resource` for a native package: only DSM's official `data-share` and
|
|
5
|
+
* `systemd-user-unit` workers, in a fixed key order. Undefined when neither applies.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderStandaloneResource(m: {
|
|
8
|
+
package: string;
|
|
9
|
+
background?: Background;
|
|
10
|
+
sharedFolder?: SharedFolder;
|
|
11
|
+
}): string | undefined;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { sharedFolderResource } from "./shared-folder.js";
|
|
2
|
+
/**
|
|
3
|
+
* `conf/resource` for a native package: only DSM's official `data-share` and
|
|
4
|
+
* `systemd-user-unit` workers, in a fixed key order. Undefined when neither applies.
|
|
5
|
+
*/
|
|
6
|
+
export function renderStandaloneResource(m) {
|
|
7
|
+
const dataShare = m.sharedFolder && sharedFolderResource(m.package, m.sharedFolder);
|
|
8
|
+
const resource = {
|
|
9
|
+
...(dataShare ? { "data-share": dataShare } : {}),
|
|
10
|
+
...(m.background ? { "systemd-user-unit": {} } : {}),
|
|
11
|
+
};
|
|
12
|
+
return Object.keys(resource).length > 0 ? JSON.stringify(resource) : undefined;
|
|
13
|
+
}
|
|
@@ -11,6 +11,8 @@ export interface RootOp {
|
|
|
11
11
|
body: string;
|
|
12
12
|
/** Internal generator flag for protected helper control output. */
|
|
13
13
|
protectedOutput?: boolean;
|
|
14
|
+
/** Bootstrap wraps public output in a protected directory without hiding it. */
|
|
15
|
+
exposeOutput?: boolean;
|
|
14
16
|
}
|
|
15
17
|
export type RootOpsResult = {
|
|
16
18
|
ok: true;
|
|
@@ -68,6 +68,16 @@ function readRootOp(path, file) {
|
|
|
68
68
|
*/
|
|
69
69
|
export function renderRootTaskScript(manifest, op) {
|
|
70
70
|
const body = op.body.endsWith("\n") ? op.body : `${op.body}\n`;
|
|
71
|
+
// Wrapped helper operations expose no output; don't leave a root-owned
|
|
72
|
+
// output directory or files for an operation whose result is task history.
|
|
73
|
+
if (op.protectedOutput && op.exposeOutput === false)
|
|
74
|
+
return `${rootTaskHeader(manifest.package, op.name)}${manifest.spkVersion}.
|
|
75
|
+
set -eu
|
|
76
|
+
PATH=/usr/sbin:/usr/bin:/sbin:/bin
|
|
77
|
+
export PATH
|
|
78
|
+
/bin/sh -eu <<'${ROOT_OP_END}'
|
|
79
|
+
${body}${ROOT_OP_END}
|
|
80
|
+
`;
|
|
71
81
|
return `${rootTaskHeader(manifest.package, op.name)}${manifest.spkVersion}.
|
|
72
82
|
# Approved by a DSM administrator; runs only when this task is run.
|
|
73
83
|
set -eu
|