@gtkx/cli 1.0.0 → 1.2.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 +1 -1
- package/dist/builder.d.ts +1 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +20 -3
- package/dist/builder.js.map +1 -1
- package/dist/cli.js +6 -2
- package/dist/cli.js.map +1 -1
- package/dist/codegen/freshness.js +2 -2
- package/dist/codegen/freshness.js.map +1 -1
- package/dist/codegen/report.d.ts.map +1 -1
- package/dist/codegen/report.js +3 -0
- package/dist/codegen/report.js.map +1 -1
- package/dist/codegen/run-codegen.d.ts +9 -5
- package/dist/codegen/run-codegen.d.ts.map +1 -1
- package/dist/codegen/run-codegen.js +31 -20
- package/dist/codegen/run-codegen.js.map +1 -1
- package/dist/codegen/store-resolver.d.ts +1 -1
- package/dist/codegen/store-resolver.d.ts.map +1 -1
- package/dist/codegen/store-resolver.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +5 -6
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/codegen.d.ts.map +1 -1
- package/dist/commands/codegen.js +11 -1
- package/dist/commands/codegen.js.map +1 -1
- package/dist/commands/deploy.d.ts +22 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +44 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +4 -4
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/docs.d.ts +2 -2
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +28 -4
- package/dist/commands/docs.js.map +1 -1
- package/dist/deploy/depends.d.ts +8 -0
- package/dist/deploy/depends.d.ts.map +1 -0
- package/dist/deploy/depends.js +27 -0
- package/dist/deploy/depends.js.map +1 -0
- package/dist/deploy/download.d.ts +20 -0
- package/dist/deploy/download.d.ts.map +1 -0
- package/dist/deploy/download.js +98 -0
- package/dist/deploy/download.js.map +1 -0
- package/dist/deploy/freedesktop/copyright.d.ts +4 -0
- package/dist/deploy/freedesktop/copyright.d.ts.map +1 -0
- package/dist/deploy/freedesktop/copyright.js +33 -0
- package/dist/deploy/freedesktop/copyright.js.map +1 -0
- package/dist/deploy/freedesktop/dbus-service.d.ts +4 -0
- package/dist/deploy/freedesktop/dbus-service.d.ts.map +1 -0
- package/dist/deploy/freedesktop/dbus-service.js +15 -0
- package/dist/deploy/freedesktop/dbus-service.js.map +1 -0
- package/dist/deploy/freedesktop/desktop-entry.d.ts +4 -0
- package/dist/deploy/freedesktop/desktop-entry.d.ts.map +1 -0
- package/dist/deploy/freedesktop/desktop-entry.js +73 -0
- package/dist/deploy/freedesktop/desktop-entry.js.map +1 -0
- package/dist/deploy/freedesktop/ini.d.ts +7 -0
- package/dist/deploy/freedesktop/ini.d.ts.map +1 -0
- package/dist/deploy/freedesktop/ini.js +22 -0
- package/dist/deploy/freedesktop/ini.js.map +1 -0
- package/dist/deploy/freedesktop/metainfo-sections.d.ts +13 -0
- package/dist/deploy/freedesktop/metainfo-sections.d.ts.map +1 -0
- package/dist/deploy/freedesktop/metainfo-sections.js +73 -0
- package/dist/deploy/freedesktop/metainfo-sections.js.map +1 -0
- package/dist/deploy/freedesktop/metainfo.d.ts +4 -0
- package/dist/deploy/freedesktop/metainfo.d.ts.map +1 -0
- package/dist/deploy/freedesktop/metainfo.js +29 -0
- package/dist/deploy/freedesktop/metainfo.js.map +1 -0
- package/dist/deploy/freedesktop/mime-package.d.ts +4 -0
- package/dist/deploy/freedesktop/mime-package.d.ts.map +1 -0
- package/dist/deploy/freedesktop/mime-package.js +16 -0
- package/dist/deploy/freedesktop/mime-package.js.map +1 -0
- package/dist/deploy/freedesktop/validate.d.ts +4 -0
- package/dist/deploy/freedesktop/validate.d.ts.map +1 -0
- package/dist/deploy/freedesktop/validate.js +81 -0
- package/dist/deploy/freedesktop/validate.js.map +1 -0
- package/dist/deploy/freedesktop/xml.d.ts +11 -0
- package/dist/deploy/freedesktop/xml.d.ts.map +1 -0
- package/dist/deploy/freedesktop/xml.js +33 -0
- package/dist/deploy/freedesktop/xml.js.map +1 -0
- package/dist/deploy/git.d.ts +4 -0
- package/dist/deploy/git.d.ts.map +1 -0
- package/dist/deploy/git.js +17 -0
- package/dist/deploy/git.js.map +1 -0
- package/dist/deploy/install-hints.d.ts +5 -0
- package/dist/deploy/install-hints.d.ts.map +1 -0
- package/dist/deploy/install-hints.js +88 -0
- package/dist/deploy/install-hints.js.map +1 -0
- package/dist/deploy/nfpm/config.d.ts +8 -0
- package/dist/deploy/nfpm/config.d.ts.map +1 -0
- package/dist/deploy/nfpm/config.js +119 -0
- package/dist/deploy/nfpm/config.js.map +1 -0
- package/dist/deploy/nfpm/contents.d.ts +12 -0
- package/dist/deploy/nfpm/contents.d.ts.map +1 -0
- package/dist/deploy/nfpm/contents.js +48 -0
- package/dist/deploy/nfpm/contents.js.map +1 -0
- package/dist/deploy/nfpm/description.d.ts +5 -0
- package/dist/deploy/nfpm/description.d.ts.map +1 -0
- package/dist/deploy/nfpm/description.js +5 -0
- package/dist/deploy/nfpm/description.js.map +1 -0
- package/dist/deploy/nfpm/optional.d.ts +5 -0
- package/dist/deploy/nfpm/optional.d.ts.map +1 -0
- package/dist/deploy/nfpm/optional.js +4 -0
- package/dist/deploy/nfpm/optional.js.map +1 -0
- package/dist/deploy/nfpm/pack.d.ts +5 -0
- package/dist/deploy/nfpm/pack.d.ts.map +1 -0
- package/dist/deploy/nfpm/pack.js +32 -0
- package/dist/deploy/nfpm/pack.js.map +1 -0
- package/dist/deploy/node-runtime/download.d.ts +3 -0
- package/dist/deploy/node-runtime/download.d.ts.map +1 -0
- package/dist/deploy/node-runtime/download.js +39 -0
- package/dist/deploy/node-runtime/download.js.map +1 -0
- package/dist/deploy/node-runtime/elf.d.ts +7 -0
- package/dist/deploy/node-runtime/elf.d.ts.map +1 -0
- package/dist/deploy/node-runtime/elf.js +100 -0
- package/dist/deploy/node-runtime/elf.js.map +1 -0
- package/dist/deploy/node-runtime/guard.d.ts +4 -0
- package/dist/deploy/node-runtime/guard.d.ts.map +1 -0
- package/dist/deploy/node-runtime/guard.js +22 -0
- package/dist/deploy/node-runtime/guard.js.map +1 -0
- package/dist/deploy/node-runtime/index.d.ts +4 -0
- package/dist/deploy/node-runtime/index.d.ts.map +1 -0
- package/dist/deploy/node-runtime/index.js +61 -0
- package/dist/deploy/node-runtime/index.js.map +1 -0
- package/dist/deploy/payload/copy-tree.d.ts +7 -0
- package/dist/deploy/payload/copy-tree.d.ts.map +1 -0
- package/dist/deploy/payload/copy-tree.js +36 -0
- package/dist/deploy/payload/copy-tree.js.map +1 -0
- package/dist/deploy/payload/icons.d.ts +6 -0
- package/dist/deploy/payload/icons.d.ts.map +1 -0
- package/dist/deploy/payload/icons.js +53 -0
- package/dist/deploy/payload/icons.js.map +1 -0
- package/dist/deploy/payload/launcher.d.ts +5 -0
- package/dist/deploy/payload/launcher.d.ts.map +1 -0
- package/dist/deploy/payload/launcher.js +22 -0
- package/dist/deploy/payload/launcher.js.map +1 -0
- package/dist/deploy/payload/schemas.d.ts +4 -0
- package/dist/deploy/payload/schemas.d.ts.map +1 -0
- package/dist/deploy/payload/schemas.js +17 -0
- package/dist/deploy/payload/schemas.js.map +1 -0
- package/dist/deploy/payload/stage.d.ts +15 -0
- package/dist/deploy/payload/stage.d.ts.map +1 -0
- package/dist/deploy/payload/stage.js +100 -0
- package/dist/deploy/payload/stage.js.map +1 -0
- package/dist/deploy/registry.d.ts +7 -0
- package/dist/deploy/registry.d.ts.map +1 -0
- package/dist/deploy/registry.js +30 -0
- package/dist/deploy/registry.js.map +1 -0
- package/dist/deploy/run-deploy.d.ts +11 -0
- package/dist/deploy/run-deploy.d.ts.map +1 -0
- package/dist/deploy/run-deploy.js +157 -0
- package/dist/deploy/run-deploy.js.map +1 -0
- package/dist/deploy/settings/arch.d.ts +4 -0
- package/dist/deploy/settings/arch.d.ts.map +1 -0
- package/dist/deploy/settings/arch.js +13 -0
- package/dist/deploy/settings/arch.js.map +1 -0
- package/dist/deploy/settings/categories.d.ts +4 -0
- package/dist/deploy/settings/categories.d.ts.map +1 -0
- package/dist/deploy/settings/categories.js +29 -0
- package/dist/deploy/settings/categories.js.map +1 -0
- package/dist/deploy/settings/exec.d.ts +6 -0
- package/dist/deploy/settings/exec.d.ts.map +1 -0
- package/dist/deploy/settings/exec.js +20 -0
- package/dist/deploy/settings/exec.js.map +1 -0
- package/dist/deploy/settings/identity.d.ts +18 -0
- package/dist/deploy/settings/identity.d.ts.map +1 -0
- package/dist/deploy/settings/identity.js +73 -0
- package/dist/deploy/settings/identity.js.map +1 -0
- package/dist/deploy/settings/index.d.ts +11 -0
- package/dist/deploy/settings/index.d.ts.map +1 -0
- package/dist/deploy/settings/index.js +103 -0
- package/dist/deploy/settings/index.js.map +1 -0
- package/dist/deploy/settings/package-manifest.d.ts +16 -0
- package/dist/deploy/settings/package-manifest.d.ts.map +1 -0
- package/dist/deploy/settings/package-manifest.js +42 -0
- package/dist/deploy/settings/package-manifest.js.map +1 -0
- package/dist/deploy/settings/paths.d.ts +9 -0
- package/dist/deploy/settings/paths.d.ts.map +1 -0
- package/dist/deploy/settings/paths.js +82 -0
- package/dist/deploy/settings/paths.js.map +1 -0
- package/dist/deploy/settings/screenshots.d.ts +8 -0
- package/dist/deploy/settings/screenshots.d.ts.map +1 -0
- package/dist/deploy/settings/screenshots.js +79 -0
- package/dist/deploy/settings/screenshots.js.map +1 -0
- package/dist/deploy/settings/starter.d.ts +4 -0
- package/dist/deploy/settings/starter.d.ts.map +1 -0
- package/dist/deploy/settings/starter.js +28 -0
- package/dist/deploy/settings/starter.js.map +1 -0
- package/dist/deploy/settings/version.d.ts +9 -0
- package/dist/deploy/settings/version.d.ts.map +1 -0
- package/dist/deploy/settings/version.js +37 -0
- package/dist/deploy/settings/version.js.map +1 -0
- package/dist/deploy/targets/appimage.d.ts +4 -0
- package/dist/deploy/targets/appimage.d.ts.map +1 -0
- package/dist/deploy/targets/appimage.js +105 -0
- package/dist/deploy/targets/appimage.js.map +1 -0
- package/dist/deploy/targets/deb.d.ts +4 -0
- package/dist/deploy/targets/deb.d.ts.map +1 -0
- package/dist/deploy/targets/deb.js +4 -0
- package/dist/deploy/targets/deb.js.map +1 -0
- package/dist/deploy/targets/flatpak-manifest.d.ts +6 -0
- package/dist/deploy/targets/flatpak-manifest.d.ts.map +1 -0
- package/dist/deploy/targets/flatpak-manifest.js +48 -0
- package/dist/deploy/targets/flatpak-manifest.js.map +1 -0
- package/dist/deploy/targets/flatpak-pnpm.d.ts +15 -0
- package/dist/deploy/targets/flatpak-pnpm.d.ts.map +1 -0
- package/dist/deploy/targets/flatpak-pnpm.js +69 -0
- package/dist/deploy/targets/flatpak-pnpm.js.map +1 -0
- package/dist/deploy/targets/flatpak-prebuilt.d.ts +8 -0
- package/dist/deploy/targets/flatpak-prebuilt.d.ts.map +1 -0
- package/dist/deploy/targets/flatpak-prebuilt.js +43 -0
- package/dist/deploy/targets/flatpak-prebuilt.js.map +1 -0
- package/dist/deploy/targets/flatpak-source.d.ts +5 -0
- package/dist/deploy/targets/flatpak-source.d.ts.map +1 -0
- package/dist/deploy/targets/flatpak-source.js +119 -0
- package/dist/deploy/targets/flatpak-source.js.map +1 -0
- package/dist/deploy/targets/flatpak-sources.d.ts +19 -0
- package/dist/deploy/targets/flatpak-sources.d.ts.map +1 -0
- package/dist/deploy/targets/flatpak-sources.js +122 -0
- package/dist/deploy/targets/flatpak-sources.js.map +1 -0
- package/dist/deploy/targets/flatpak.d.ts +4 -0
- package/dist/deploy/targets/flatpak.d.ts.map +1 -0
- package/dist/deploy/targets/flatpak.js +113 -0
- package/dist/deploy/targets/flatpak.js.map +1 -0
- package/dist/deploy/targets/nfpm-target.d.ts +5 -0
- package/dist/deploy/targets/nfpm-target.d.ts.map +1 -0
- package/dist/deploy/targets/nfpm-target.js +26 -0
- package/dist/deploy/targets/nfpm-target.js.map +1 -0
- package/dist/deploy/targets/rpm.d.ts +4 -0
- package/dist/deploy/targets/rpm.d.ts.map +1 -0
- package/dist/deploy/targets/rpm.js +4 -0
- package/dist/deploy/targets/rpm.js.map +1 -0
- package/dist/deploy/tools.d.ts +20 -0
- package/dist/deploy/tools.d.ts.map +1 -0
- package/dist/deploy/tools.js +106 -0
- package/dist/deploy/tools.js.map +1 -0
- package/dist/deploy/types.d.ts +140 -0
- package/dist/deploy/types.d.ts.map +1 -0
- package/dist/deploy/types.js +2 -0
- package/dist/deploy/types.js.map +1 -0
- package/dist/deploy/vendored/appimagetool.d.ts +7 -0
- package/dist/deploy/vendored/appimagetool.d.ts.map +1 -0
- package/dist/deploy/vendored/appimagetool.js +42 -0
- package/dist/deploy/vendored/appimagetool.js.map +1 -0
- package/dist/deploy/vendored/nfpm.d.ts +3 -0
- package/dist/deploy/vendored/nfpm.d.ts.map +1 -0
- package/dist/deploy/vendored/nfpm.js +60 -0
- package/dist/deploy/vendored/nfpm.js.map +1 -0
- package/dist/dev/change-queue.d.ts +11 -0
- package/dist/dev/change-queue.d.ts.map +1 -0
- package/dist/dev/change-queue.js +34 -0
- package/dist/dev/change-queue.js.map +1 -0
- package/dist/dev/failure-tracker.d.ts +10 -0
- package/dist/dev/failure-tracker.d.ts.map +1 -0
- package/dist/dev/failure-tracker.js +61 -0
- package/dist/dev/failure-tracker.js.map +1 -0
- package/dist/dev/missing-import.d.ts +4 -0
- package/dist/dev/missing-import.d.ts.map +1 -0
- package/dist/dev/missing-import.js +23 -0
- package/dist/dev/missing-import.js.map +1 -0
- package/dist/dev/runner-deps.d.ts.map +1 -1
- package/dist/dev/runner-deps.js +25 -6
- package/dist/dev/runner-deps.js.map +1 -1
- package/dist/dev/runner.d.ts +8 -4
- package/dist/dev/runner.d.ts.map +1 -1
- package/dist/dev/runner.js +334 -66
- package/dist/dev/runner.js.map +1 -1
- package/dist/dev/supervisor.d.ts +1 -2
- package/dist/dev/supervisor.d.ts.map +1 -1
- package/dist/dev/supervisor.js +1 -1
- package/dist/dev/supervisor.js.map +1 -1
- package/dist/dev/vite-dev-server.d.ts +13 -2
- package/dist/dev/vite-dev-server.d.ts.map +1 -1
- package/dist/dev/vite-dev-server.js +30 -2
- package/dist/dev/vite-dev-server.js.map +1 -1
- package/dist/internal/entry-arg.d.ts +1 -7
- package/dist/internal/entry-arg.d.ts.map +1 -1
- package/dist/internal/entry-arg.js +18 -11
- package/dist/internal/entry-arg.js.map +1 -1
- package/dist/internal/module-loads.d.ts +7 -0
- package/dist/internal/module-loads.d.ts.map +1 -0
- package/dist/internal/module-loads.js +21 -0
- package/dist/internal/module-loads.js.map +1 -0
- package/dist/internal/prepare-project.d.ts +16 -0
- package/dist/internal/prepare-project.d.ts.map +1 -0
- package/dist/internal/prepare-project.js +15 -0
- package/dist/internal/prepare-project.js.map +1 -0
- package/dist/internal/run-cli-tool.d.ts +2 -1
- package/dist/internal/run-cli-tool.d.ts.map +1 -1
- package/dist/internal/run-cli-tool.js +15 -6
- package/dist/internal/run-cli-tool.js.map +1 -1
- package/dist/internal/staging-dir.d.ts +8 -1
- package/dist/internal/staging-dir.d.ts.map +1 -1
- package/dist/internal/staging-dir.js +38 -2
- package/dist/internal/staging-dir.js.map +1 -1
- package/dist/mcp/serialize-widget.d.ts +2 -1
- package/dist/mcp/serialize-widget.d.ts.map +1 -1
- package/dist/mcp/serialize-widget.js +1 -1
- package/dist/mcp/serialize-widget.js.map +1 -1
- package/dist/mcp/testing-loader.d.ts +5 -2
- package/dist/mcp/testing-loader.d.ts.map +1 -1
- package/dist/mcp/testing-loader.js +7 -3
- package/dist/mcp/testing-loader.js.map +1 -1
- package/dist/refresh-runtime.d.ts +2 -1
- package/dist/refresh-runtime.d.ts.map +1 -1
- package/dist/refresh-runtime.js +32 -2
- package/dist/refresh-runtime.js.map +1 -1
- package/dist/settings/schema.d.ts +1 -2
- package/dist/settings/schema.d.ts.map +1 -1
- package/dist/settings/schema.js +1 -1
- package/dist/settings/schema.js.map +1 -1
- package/dist/vite-plugins/asset-extensions.d.ts +2 -1
- package/dist/vite-plugins/asset-extensions.d.ts.map +1 -1
- package/dist/vite-plugins/asset-extensions.js +2 -1
- package/dist/vite-plugins/asset-extensions.js.map +1 -1
- package/dist/vite-plugins/asset-imports.d.ts +4 -0
- package/dist/vite-plugins/asset-imports.d.ts.map +1 -0
- package/dist/vite-plugins/asset-imports.js +88 -0
- package/dist/vite-plugins/asset-imports.js.map +1 -0
- package/dist/vite-plugins/asset-specifier.d.ts +5 -0
- package/dist/vite-plugins/asset-specifier.d.ts.map +1 -0
- package/dist/vite-plugins/asset-specifier.js +7 -0
- package/dist/vite-plugins/asset-specifier.js.map +1 -0
- package/dist/vite-plugins/esm-extension.d.ts +4 -0
- package/dist/vite-plugins/esm-extension.d.ts.map +1 -0
- package/dist/vite-plugins/esm-extension.js +4 -0
- package/dist/vite-plugins/esm-extension.js.map +1 -0
- package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts +1 -3
- package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts.map +1 -1
- package/dist/vite-plugins/fast-refresh/swc-refresh.js +1 -1
- package/dist/vite-plugins/fast-refresh/swc-refresh.js.map +1 -1
- package/dist/vite-plugins/index.d.ts.map +1 -1
- package/dist/vite-plugins/index.js +4 -0
- package/dist/vite-plugins/index.js.map +1 -1
- package/dist/vite-plugins/resource-shared.d.ts +2 -1
- package/dist/vite-plugins/resource-shared.d.ts.map +1 -1
- package/dist/vite-plugins/resource-shared.js +2 -1
- package/dist/vite-plugins/resource-shared.js.map +1 -1
- package/dist/vite-plugins/resources.d.ts.map +1 -1
- package/dist/vite-plugins/resources.js +30 -29
- package/dist/vite-plugins/resources.js.map +1 -1
- package/dist/vite-plugins/self-contained.d.ts +4 -0
- package/dist/vite-plugins/self-contained.d.ts.map +1 -0
- package/dist/vite-plugins/self-contained.js +244 -0
- package/dist/vite-plugins/self-contained.js.map +1 -0
- package/dist/vite-plugins/settings.d.ts.map +1 -1
- package/dist/vite-plugins/settings.js +19 -40
- package/dist/vite-plugins/settings.js.map +1 -1
- package/dist/vite-plugins/store-links.d.ts +4 -0
- package/dist/vite-plugins/store-links.d.ts.map +1 -0
- package/dist/vite-plugins/store-links.js +19 -0
- package/dist/vite-plugins/store-links.js.map +1 -0
- package/dist/vite-plugins/undeclared-library.d.ts.map +1 -1
- package/dist/vite-plugins/undeclared-library.js +51 -12
- package/dist/vite-plugins/undeclared-library.js.map +1 -1
- package/dist/vite-plugins/worker.d.ts.map +1 -1
- package/dist/vite-plugins/worker.js +3 -1
- package/dist/vite-plugins/worker.js.map +1 -1
- package/env.d.ts +106 -25
- package/package.json +20 -13
- package/src/builder.ts +22 -4
- package/src/cli.ts +7 -2
- package/src/codegen/freshness.ts +2 -2
- package/src/codegen/report.ts +4 -0
- package/src/codegen/run-codegen.ts +48 -24
- package/src/codegen/store-resolver.ts +1 -1
- package/src/commands/build.ts +5 -6
- package/src/commands/codegen.ts +14 -1
- package/src/commands/deploy.ts +47 -0
- package/src/commands/dev.ts +4 -4
- package/src/commands/docs.ts +40 -4
- package/src/deploy/depends.ts +42 -0
- package/src/deploy/download.ts +148 -0
- package/src/deploy/freedesktop/copyright.ts +41 -0
- package/src/deploy/freedesktop/dbus-service.ts +19 -0
- package/src/deploy/freedesktop/desktop-entry.ts +102 -0
- package/src/deploy/freedesktop/ini.ts +39 -0
- package/src/deploy/freedesktop/metainfo-sections.ts +116 -0
- package/src/deploy/freedesktop/metainfo.ts +46 -0
- package/src/deploy/freedesktop/mime-package.ts +28 -0
- package/src/deploy/freedesktop/validate.ts +124 -0
- package/src/deploy/freedesktop/xml.ts +53 -0
- package/src/deploy/git.ts +20 -0
- package/src/deploy/install-hints.ts +111 -0
- package/src/deploy/nfpm/config.ts +153 -0
- package/src/deploy/nfpm/contents.ts +69 -0
- package/src/deploy/nfpm/description.ts +11 -0
- package/src/deploy/nfpm/optional.ts +8 -0
- package/src/deploy/nfpm/pack.ts +44 -0
- package/src/deploy/node-runtime/download.ts +48 -0
- package/src/deploy/node-runtime/elf.ts +145 -0
- package/src/deploy/node-runtime/guard.ts +29 -0
- package/src/deploy/node-runtime/index.ts +80 -0
- package/src/deploy/payload/copy-tree.ts +51 -0
- package/src/deploy/payload/icons.ts +80 -0
- package/src/deploy/payload/launcher.ts +27 -0
- package/src/deploy/payload/schemas.ts +27 -0
- package/src/deploy/payload/stage.ts +145 -0
- package/src/deploy/registry.ts +40 -0
- package/src/deploy/run-deploy.ts +241 -0
- package/src/deploy/settings/arch.ts +18 -0
- package/src/deploy/settings/categories.ts +39 -0
- package/src/deploy/settings/exec.ts +29 -0
- package/src/deploy/settings/identity.ts +133 -0
- package/src/deploy/settings/index.ts +189 -0
- package/src/deploy/settings/package-manifest.ts +68 -0
- package/src/deploy/settings/paths.ts +115 -0
- package/src/deploy/settings/screenshots.ts +125 -0
- package/src/deploy/settings/starter.ts +41 -0
- package/src/deploy/settings/version.ts +59 -0
- package/src/deploy/targets/appimage.ts +140 -0
- package/src/deploy/targets/deb.ts +6 -0
- package/src/deploy/targets/flatpak-manifest.ts +61 -0
- package/src/deploy/targets/flatpak-pnpm.ts +115 -0
- package/src/deploy/targets/flatpak-prebuilt.ts +59 -0
- package/src/deploy/targets/flatpak-source.ts +181 -0
- package/src/deploy/targets/flatpak-sources.ts +198 -0
- package/src/deploy/targets/flatpak.ts +144 -0
- package/src/deploy/targets/nfpm-target.ts +33 -0
- package/src/deploy/targets/rpm.ts +6 -0
- package/src/deploy/tools.ts +156 -0
- package/src/deploy/types.ts +174 -0
- package/src/deploy/vendored/appimagetool.ts +57 -0
- package/src/deploy/vendored/nfpm.ts +79 -0
- package/src/dev/change-queue.ts +59 -0
- package/src/dev/failure-tracker.ts +92 -0
- package/src/dev/missing-import.ts +32 -0
- package/src/dev/runner-deps.ts +34 -6
- package/src/dev/runner.ts +506 -102
- package/src/dev/supervisor.ts +0 -3
- package/src/dev/vite-dev-server.ts +54 -3
- package/src/internal/entry-arg.ts +25 -11
- package/src/internal/module-loads.ts +32 -0
- package/src/internal/prepare-project.ts +23 -0
- package/src/internal/run-cli-tool.ts +22 -6
- package/src/internal/staging-dir.ts +57 -2
- package/src/mcp/serialize-widget.ts +3 -2
- package/src/mcp/testing-loader.ts +19 -4
- package/src/refresh-runtime.ts +48 -2
- package/src/settings/schema.ts +0 -1
- package/src/vite-plugins/asset-extensions.ts +2 -1
- package/src/vite-plugins/asset-imports.ts +134 -0
- package/src/vite-plugins/asset-specifier.ts +9 -0
- package/src/vite-plugins/esm-extension.ts +4 -0
- package/src/vite-plugins/fast-refresh/swc-refresh.ts +1 -1
- package/src/vite-plugins/index.ts +4 -0
- package/src/vite-plugins/resource-shared.ts +2 -0
- package/src/vite-plugins/resources.ts +33 -33
- package/src/vite-plugins/self-contained.ts +352 -0
- package/src/vite-plugins/settings.ts +21 -48
- package/src/vite-plugins/store-links.ts +25 -0
- package/src/vite-plugins/undeclared-library.ts +74 -12
- package/src/vite-plugins/worker.ts +4 -1
- package/dist/internal.d.ts +0 -3
- package/dist/internal.d.ts.map +0 -1
- package/dist/internal.js +0 -3
- package/dist/internal.js.map +0 -1
- package/src/internal.ts +0 -2
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { info, warn } from "@gtkx/utils";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
|
|
7
|
+
type DigestRequest = {
|
|
8
|
+
url: string;
|
|
9
|
+
dest: string;
|
|
10
|
+
assetName: string;
|
|
11
|
+
subject: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type DownloadRequest = {
|
|
15
|
+
url: string;
|
|
16
|
+
dest: string;
|
|
17
|
+
label: string;
|
|
18
|
+
sha256: string;
|
|
19
|
+
freshSha256?: (() => Promise<string>) | undefined;
|
|
20
|
+
mode?: number | undefined;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const CACHE_NAMESPACE = "gtkx";
|
|
24
|
+
const DIGEST_PATTERN = /^[\da-f]{64}$/;
|
|
25
|
+
|
|
26
|
+
const cacheRoot = (): string => {
|
|
27
|
+
const base = process.env.XDG_CACHE_HOME;
|
|
28
|
+
|
|
29
|
+
return join(base !== undefined && base.length > 0 ? base : join(homedir(), ".cache"), CACHE_NAMESPACE);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const cacheDir = (segments: string[]): string => {
|
|
33
|
+
const dir = join(cacheRoot(), ...segments);
|
|
34
|
+
mkdirSync(dir, { recursive: true });
|
|
35
|
+
|
|
36
|
+
return dir;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getDigest = (contents: Buffer): string => createHash("sha256").update(contents).digest("hex");
|
|
40
|
+
|
|
41
|
+
const assertDigest = (url: string, contents: Buffer, expected: string): void => {
|
|
42
|
+
const actual = getDigest(contents);
|
|
43
|
+
|
|
44
|
+
if (actual !== expected) {
|
|
45
|
+
throw new Error(`Checksum mismatch for ${url}\n expected ${expected}\n received ${actual}`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const fetchBytes = async (url: string): Promise<Buffer> => {
|
|
50
|
+
const response = await fetch(url);
|
|
51
|
+
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
throw new Error(`Cannot download ${url}: HTTP ${String(response.status)} ${response.statusText}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return Buffer.from(await response.arrayBuffer());
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const fetchText = async (url: string): Promise<string> => {
|
|
60
|
+
const bytes = await fetchBytes(url);
|
|
61
|
+
|
|
62
|
+
return bytes.toString("utf8");
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const readCachedDigest = (dest: string): string | undefined => {
|
|
66
|
+
try {
|
|
67
|
+
const cached = readFileSync(dest, "utf8").trim();
|
|
68
|
+
|
|
69
|
+
return DIGEST_PATTERN.test(cached) ? cached : undefined;
|
|
70
|
+
} catch {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const writeAtomically = (dest: string, contents: string): void => {
|
|
76
|
+
const staging = `${dest}.partial`;
|
|
77
|
+
writeFileSync(staging, contents);
|
|
78
|
+
renameSync(staging, dest);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const publishedDigest = async (request: DigestRequest): Promise<string> => {
|
|
82
|
+
const checksums = await fetchText(request.url);
|
|
83
|
+
const digest = digestFromChecksums(checksums, request.assetName, request.subject);
|
|
84
|
+
|
|
85
|
+
if (!DIGEST_PATTERN.test(digest)) {
|
|
86
|
+
throw new Error(`${request.subject} published a malformed checksum for ${request.assetName}: "${digest}"`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
writeAtomically(request.dest, digest);
|
|
90
|
+
|
|
91
|
+
return digest;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const cachedDigest = async (request: DigestRequest): Promise<string> => {
|
|
95
|
+
const cached = readCachedDigest(request.dest);
|
|
96
|
+
|
|
97
|
+
return cached ?? publishedDigest(request);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const isCacheUsable = (dest: string, sha256: string): boolean => {
|
|
101
|
+
if (!existsSync(dest)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (getDigest(readFileSync(dest)) === sha256) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
warn(`Discarding the cached ${dest}: its checksum no longer matches`);
|
|
110
|
+
|
|
111
|
+
return false;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const downloadFile = async (request: DownloadRequest): Promise<string> => {
|
|
115
|
+
const { url, dest, label, sha256, mode } = request;
|
|
116
|
+
|
|
117
|
+
if (isCacheUsable(dest, sha256)) {
|
|
118
|
+
return dest;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
info(`Downloading ${label}`);
|
|
122
|
+
const expected = request.freshSha256 === undefined ? sha256 : await request.freshSha256();
|
|
123
|
+
const contents = await fetchBytes(url);
|
|
124
|
+
assertDigest(url, contents, expected);
|
|
125
|
+
const staging = `${dest}.partial`;
|
|
126
|
+
writeFileSync(staging, contents);
|
|
127
|
+
|
|
128
|
+
if (mode !== undefined) {
|
|
129
|
+
chmodSync(staging, mode);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
renameSync(staging, dest);
|
|
133
|
+
|
|
134
|
+
return dest;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const digestFromChecksums = (checksums: string, assetName: string, subject: string): string => {
|
|
138
|
+
const line = checksums.split("\n").find((entry) => entry.trim().endsWith(` ${assetName}`));
|
|
139
|
+
const digest = line?.trim().split(/\s+/, 1)[0];
|
|
140
|
+
|
|
141
|
+
if (digest === undefined) {
|
|
142
|
+
throw new Error(`${subject} publishes no checksum for ${assetName}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return digest;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export { cacheDir, cachedDigest, type DigestRequest, downloadFile, publishedDigest };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import type { DeploySettings } from "../types.js";
|
|
3
|
+
|
|
4
|
+
const FORMAT_URL = "https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/";
|
|
5
|
+
const CONTINUATION_BLANK = " .";
|
|
6
|
+
|
|
7
|
+
const indentLicenseBody = (body: string): string[] =>
|
|
8
|
+
body
|
|
9
|
+
.split("\n")
|
|
10
|
+
.map((line) => (line.trim().length === 0 ? CONTINUATION_BLANK : ` ${line}`));
|
|
11
|
+
|
|
12
|
+
const licenseBody = (licenseFile: string | null): string[] => {
|
|
13
|
+
if (licenseFile === null) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
return indentLicenseBody(readFileSync(licenseFile, "utf8").trimEnd());
|
|
19
|
+
} catch {
|
|
20
|
+
return [];
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const headerLines = (settings: DeploySettings): string[] => [
|
|
25
|
+
`Format: ${FORMAT_URL}`,
|
|
26
|
+
`Upstream-Name: ${settings.name}`,
|
|
27
|
+
...(settings.homepage === null ? [] : [`Source: ${settings.homepage}`]),
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const renderCopyright = (settings: DeploySettings): string =>
|
|
31
|
+
[
|
|
32
|
+
...headerLines(settings),
|
|
33
|
+
"",
|
|
34
|
+
"Files: *",
|
|
35
|
+
`Copyright: ${settings.copyright}`,
|
|
36
|
+
`License: ${settings.license}`,
|
|
37
|
+
...licenseBody(settings.paths.licenseFile),
|
|
38
|
+
"",
|
|
39
|
+
].join("\n");
|
|
40
|
+
|
|
41
|
+
export { renderCopyright };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { posix } from "node:path";
|
|
2
|
+
import type { DeploySettings } from "../types.js";
|
|
3
|
+
import { renderIni } from "./ini.js";
|
|
4
|
+
|
|
5
|
+
const SERVICE_GROUP = "D-BUS Service";
|
|
6
|
+
const SERVICE_FLAG = "--gapplication-service";
|
|
7
|
+
|
|
8
|
+
const renderDbusService = (settings: DeploySettings, prefix: string): string =>
|
|
9
|
+
renderIni([
|
|
10
|
+
{
|
|
11
|
+
name: SERVICE_GROUP,
|
|
12
|
+
entries: [
|
|
13
|
+
["Name", settings.applicationId],
|
|
14
|
+
["Exec", `${posix.join(prefix, "bin", settings.binaryName)} ${SERVICE_FLAG}`],
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export { renderDbusService };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { DeployDesktopAction, DeploySettings } from "../types.js";
|
|
2
|
+
import { type IniGroup, renderIni } from "./ini.js";
|
|
3
|
+
|
|
4
|
+
type Entries = [string, string | string[]][];
|
|
5
|
+
|
|
6
|
+
const DESKTOP_ENTRY_GROUP = "Desktop Entry";
|
|
7
|
+
const EXEC_QUOTED_CHARACTERS = /["`$\\]/g;
|
|
8
|
+
const EXEC_RESERVED_CHARACTERS = /[\s"'\\><~|&;$*?#()`]/;
|
|
9
|
+
|
|
10
|
+
const RESERVED_KEYS = new Map([
|
|
11
|
+
["DBusActivatable", "use `deploy.isDbusActivatable` instead"],
|
|
12
|
+
["Version", "it names the desktop entry spec version, not the application's"],
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
const quoteExecToken = (token: string): string => {
|
|
16
|
+
const escaped = token.replaceAll("%", "%%");
|
|
17
|
+
|
|
18
|
+
if (!EXEC_RESERVED_CHARACTERS.test(escaped)) {
|
|
19
|
+
return escaped;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const quoted = escaped.replaceAll(EXEC_QUOTED_CHARACTERS, (character) => `\\${character}`);
|
|
23
|
+
|
|
24
|
+
return `"${quoted}"`;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const execLine = (settings: DeploySettings): string =>
|
|
28
|
+
[
|
|
29
|
+
...[settings.binaryName, ...settings.execArgs].map((part) => quoteExecToken(part)),
|
|
30
|
+
settings.execToken ?? "",
|
|
31
|
+
]
|
|
32
|
+
.filter((part) => part.length > 0)
|
|
33
|
+
.join(" ");
|
|
34
|
+
|
|
35
|
+
const optionalEntry = (key: string, value: string | null): Entries => (value === null ? [] : [[key, value]]);
|
|
36
|
+
const listEntry = (key: string, values: string[]): Entries => (values.length === 0 ? [] : [[key, values]]);
|
|
37
|
+
|
|
38
|
+
const assertNoReservedOverrides = (settings: DeploySettings): void => {
|
|
39
|
+
for (const key of Object.keys(settings.desktopEntry)) {
|
|
40
|
+
const remedy = RESERVED_KEYS.get(key);
|
|
41
|
+
|
|
42
|
+
if (remedy !== undefined) {
|
|
43
|
+
throw new Error(`Cannot set "${key}" through \`deploy.desktopEntry\`: gtkx deploy writes it, ${remedy}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const baseEntries = (settings: DeploySettings): Entries => [
|
|
49
|
+
["Type", "Application"],
|
|
50
|
+
["Name", settings.name],
|
|
51
|
+
...optionalEntry("GenericName", settings.genericName),
|
|
52
|
+
["Comment", settings.summary],
|
|
53
|
+
["Exec", execLine(settings)],
|
|
54
|
+
["Icon", settings.applicationId],
|
|
55
|
+
["Terminal", "false"],
|
|
56
|
+
...listEntry("Categories", settings.categories),
|
|
57
|
+
...listEntry("Keywords", settings.keywords),
|
|
58
|
+
...listEntry("MimeType", settings.mimeTypes),
|
|
59
|
+
["StartupNotify", "true"],
|
|
60
|
+
["StartupWMClass", settings.applicationId],
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const actionEntries = (settings: DeploySettings): Entries =>
|
|
64
|
+
settings.desktopActions.length === 0 ? [] : [["Actions", settings.desktopActions.map((action) => action.id)]];
|
|
65
|
+
|
|
66
|
+
const activationEntries = (settings: DeploySettings): Entries =>
|
|
67
|
+
settings.isDbusActivatable ? [["DBusActivatable", "true"]] : [];
|
|
68
|
+
|
|
69
|
+
const actionGroup = (settings: DeploySettings, action: DeployDesktopAction): IniGroup => ({
|
|
70
|
+
name: `Desktop Action ${action.id}`,
|
|
71
|
+
entries: [
|
|
72
|
+
["Name", action.name],
|
|
73
|
+
["Exec", [settings.binaryName, ...action.args].map((part) => quoteExecToken(part)).join(" ")],
|
|
74
|
+
...optionalEntry("Icon", action.icon),
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const mergeEntries = (entries: Entries, overrides: Entries): Entries => {
|
|
79
|
+
const merged = new Map(entries);
|
|
80
|
+
|
|
81
|
+
for (const [key, value] of overrides) {
|
|
82
|
+
merged.set(key, value);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return merged.entries().toArray();
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const renderDesktopEntry = (settings: DeploySettings): string => {
|
|
89
|
+
assertNoReservedOverrides(settings);
|
|
90
|
+
|
|
91
|
+
const main: IniGroup = {
|
|
92
|
+
name: DESKTOP_ENTRY_GROUP,
|
|
93
|
+
entries: mergeEntries(
|
|
94
|
+
[...baseEntries(settings), ...actionEntries(settings), ...activationEntries(settings)],
|
|
95
|
+
Object.entries(settings.desktopEntry),
|
|
96
|
+
),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return renderIni([main, ...settings.desktopActions.map((action) => actionGroup(settings, action))]);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export { renderDesktopEntry };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type IniGroup = {
|
|
2
|
+
name: string;
|
|
3
|
+
entries: [string, string | string[]][];
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
const FORBIDDEN_VALUE_CHARACTERS = /[\n\r]/;
|
|
7
|
+
|
|
8
|
+
const assertValue = (key: string, value: string): void => {
|
|
9
|
+
if (FORBIDDEN_VALUE_CHARACTERS.test(value)) {
|
|
10
|
+
throw new Error(`Cannot write "${key}" into a desktop entry: its value contains a line break`);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const escapeValue = (key: string, value: string): string => {
|
|
15
|
+
assertValue(key, value);
|
|
16
|
+
|
|
17
|
+
return value.replaceAll("\\", "\\\\");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const escapeListItem = (key: string, value: string): string => escapeValue(key, value).replaceAll(";", String.raw`\;`);
|
|
21
|
+
|
|
22
|
+
const renderList = (key: string, values: string[]): string =>
|
|
23
|
+
values.length === 0 ? "" : `${values.map((item) => escapeListItem(key, item)).join(";")};`;
|
|
24
|
+
|
|
25
|
+
const renderValue = (key: string, value: string | string[]): string =>
|
|
26
|
+
Array.isArray(value) ? renderList(key, value) : escapeValue(key, value);
|
|
27
|
+
|
|
28
|
+
const renderEntry = ([key, value]: [string, string | string[]]): string => `${key}=${renderValue(key, value)}`;
|
|
29
|
+
|
|
30
|
+
const renderGroup = (group: IniGroup): string[] => [
|
|
31
|
+
`[${group.name}]`,
|
|
32
|
+
...group.entries.map((entry) => renderEntry(entry)),
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const renderIni = (groups: IniGroup[]): string =>
|
|
36
|
+
[...groups.flatMap((group, index) => (index === 0 ? renderGroup(group) : ["", ...renderGroup(group)])), ""]
|
|
37
|
+
.join("\n");
|
|
38
|
+
|
|
39
|
+
export { type IniGroup, renderIni };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import type { DeployRelease, DeploySettings } from "../types.js";
|
|
2
|
+
import { element, text, type XmlNode } from "./xml.js";
|
|
3
|
+
|
|
4
|
+
const CONTENT_RATING_TYPE = "oars-1.1";
|
|
5
|
+
const DEFAULT_SCREENSHOT_TYPE = "default";
|
|
6
|
+
const PRIMARY_COLOR = "primary";
|
|
7
|
+
|
|
8
|
+
const developerSection = (settings: DeploySettings): XmlNode[] => {
|
|
9
|
+
const attributes = settings.developer.id === null ? {} : { id: settings.developer.id };
|
|
10
|
+
|
|
11
|
+
return [element("developer", attributes, [text("name", settings.developer.name)])];
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const descriptionSection = (settings: DeploySettings): XmlNode[] => [
|
|
15
|
+
element("description", {}, settings.description.map((paragraph) => text("p", paragraph))),
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const providesSection = (settings: DeploySettings): XmlNode[] => [
|
|
19
|
+
element("provides", {}, [
|
|
20
|
+
text("binary", settings.binaryName),
|
|
21
|
+
...settings.mimeTypes.map((mimeType) => text("mediatype", mimeType)),
|
|
22
|
+
]),
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const listSection = (tag: string, itemTag: string, values: string[]): XmlNode[] =>
|
|
26
|
+
values.length === 0 ? [] : [element(tag, {}, values.map((value) => text(itemTag, value)))];
|
|
27
|
+
|
|
28
|
+
const urlsSection = (settings: DeploySettings): XmlNode[] => {
|
|
29
|
+
const homepage = settings.homepage === null ? [] : [{ tag: "homepage", url: settings.homepage }];
|
|
30
|
+
const rest = Object.entries(settings.urls).map(([tag, url]) => ({ tag, url }));
|
|
31
|
+
|
|
32
|
+
return [...homepage, ...rest].map((entry) => ({ tag: "url", attributes: { type: entry.tag }, text: entry.url }));
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const screenshotsSection = (settings: DeploySettings): XmlNode[] => {
|
|
36
|
+
if (settings.screenshots.length === 0) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const entries = settings.screenshots.map((screenshot) =>
|
|
41
|
+
element(
|
|
42
|
+
"screenshot",
|
|
43
|
+
screenshot.isDefault ? { type: DEFAULT_SCREENSHOT_TYPE } : {},
|
|
44
|
+
[
|
|
45
|
+
text("image", screenshot.url),
|
|
46
|
+
...(screenshot.caption === null ? [] : [text("caption", screenshot.caption)]),
|
|
47
|
+
],
|
|
48
|
+
));
|
|
49
|
+
|
|
50
|
+
return [element("screenshots", {}, entries)];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const releaseAttributes = (release: DeployRelease): Record<string, string> => ({
|
|
54
|
+
version: release.version,
|
|
55
|
+
date: release.date,
|
|
56
|
+
...(release.type !== null && { type: release.type }),
|
|
57
|
+
...(release.urgency !== null && { urgency: release.urgency }),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const releaseChildren = (release: DeployRelease): XmlNode[] => [
|
|
61
|
+
...(release.url === null ? [] : [{ tag: "url", attributes: { type: "details" }, text: release.url }]),
|
|
62
|
+
...(release.notes.length === 0
|
|
63
|
+
? []
|
|
64
|
+
: [element("description", {}, release.notes.map((note) => text("p", note)))]),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
const releasesSection = (settings: DeploySettings): XmlNode[] => {
|
|
68
|
+
if (settings.releases.length === 0) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const entries = settings.releases.map((release) =>
|
|
73
|
+
element("release", releaseAttributes(release), releaseChildren(release)));
|
|
74
|
+
|
|
75
|
+
return [element("releases", {}, entries)];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const contentRatingSection = (settings: DeploySettings): XmlNode[] => [
|
|
79
|
+
element(
|
|
80
|
+
"content_rating",
|
|
81
|
+
{ type: CONTENT_RATING_TYPE },
|
|
82
|
+
Object.entries(settings.contentRating).map(([id, intensity]) => ({
|
|
83
|
+
tag: "content_attribute",
|
|
84
|
+
attributes: { id },
|
|
85
|
+
text: intensity,
|
|
86
|
+
})),
|
|
87
|
+
),
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
const brandingSection = (settings: DeploySettings): XmlNode[] => {
|
|
91
|
+
const branding = settings.branding;
|
|
92
|
+
|
|
93
|
+
if (branding === null) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const color = (scheme: string, value: string): XmlNode => ({
|
|
98
|
+
tag: "color",
|
|
99
|
+
attributes: { type: PRIMARY_COLOR, scheme_preference: scheme },
|
|
100
|
+
text: value,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return [element("branding", {}, [color("light", branding.light), color("dark", branding.dark)])];
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
brandingSection,
|
|
108
|
+
contentRatingSection,
|
|
109
|
+
descriptionSection,
|
|
110
|
+
developerSection,
|
|
111
|
+
listSection,
|
|
112
|
+
providesSection,
|
|
113
|
+
releasesSection,
|
|
114
|
+
screenshotsSection,
|
|
115
|
+
urlsSection,
|
|
116
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DeploySettings } from "../types.js";
|
|
2
|
+
import {
|
|
3
|
+
brandingSection,
|
|
4
|
+
contentRatingSection,
|
|
5
|
+
descriptionSection,
|
|
6
|
+
developerSection,
|
|
7
|
+
listSection,
|
|
8
|
+
providesSection,
|
|
9
|
+
releasesSection,
|
|
10
|
+
screenshotsSection,
|
|
11
|
+
urlsSection,
|
|
12
|
+
} from "./metainfo-sections.js";
|
|
13
|
+
import { element, renderDocument, text, type XmlNode } from "./xml.js";
|
|
14
|
+
|
|
15
|
+
const COMPONENT_TYPE = "desktop-application";
|
|
16
|
+
const DESKTOP_SUFFIX = ".desktop";
|
|
17
|
+
|
|
18
|
+
const launchable = (applicationId: string): XmlNode => ({
|
|
19
|
+
tag: "launchable",
|
|
20
|
+
attributes: { type: "desktop-id" },
|
|
21
|
+
text: `${applicationId}${DESKTOP_SUFFIX}`,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const renderMetainfo = (settings: DeploySettings): string =>
|
|
25
|
+
renderDocument(
|
|
26
|
+
element("component", { type: COMPONENT_TYPE }, [
|
|
27
|
+
text("id", settings.applicationId),
|
|
28
|
+
text("name", settings.name),
|
|
29
|
+
text("summary", settings.summary),
|
|
30
|
+
text("metadata_license", settings.metadataLicense),
|
|
31
|
+
text("project_license", settings.license),
|
|
32
|
+
...developerSection(settings),
|
|
33
|
+
...descriptionSection(settings),
|
|
34
|
+
launchable(settings.applicationId),
|
|
35
|
+
...providesSection(settings),
|
|
36
|
+
...listSection("categories", "category", settings.categories),
|
|
37
|
+
...listSection("keywords", "keyword", settings.keywords),
|
|
38
|
+
...urlsSection(settings),
|
|
39
|
+
...screenshotsSection(settings),
|
|
40
|
+
...releasesSection(settings),
|
|
41
|
+
...contentRatingSection(settings),
|
|
42
|
+
...brandingSection(settings),
|
|
43
|
+
]),
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
export { renderMetainfo };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DeployFileAssociation, DeploySettings } from "../types.js";
|
|
2
|
+
import { element, renderDocument, text, type XmlNode } from "./xml.js";
|
|
3
|
+
|
|
4
|
+
/* eslint-disable-next-line sonarjs/no-clear-text-protocols, unicorn/prefer-https --
|
|
5
|
+
An XML namespace is a fixed identifier, not a URL to fetch: shared-mime-info only recognizes this exact string. */
|
|
6
|
+
const MIME_INFO_NAMESPACE = "http://www.freedesktop.org/standards/shared-mime-info";
|
|
7
|
+
|
|
8
|
+
const mimeTypeNode = (association: DeployFileAssociation): XmlNode =>
|
|
9
|
+
element("mime-type", { type: association.mimeType }, [
|
|
10
|
+
...(association.description === null ? [] : [text("comment", association.description)]),
|
|
11
|
+
{ tag: "glob", attributes: { pattern: `*.${association.extension}` } },
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
const renderMimePackage = (settings: DeploySettings): string | null => {
|
|
15
|
+
if (settings.fileAssociations.length === 0) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return renderDocument(
|
|
20
|
+
element(
|
|
21
|
+
"mime-info",
|
|
22
|
+
{ xmlns: MIME_INFO_NAMESPACE },
|
|
23
|
+
settings.fileAssociations.map((entry) => mimeTypeNode(entry)),
|
|
24
|
+
),
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { renderMimePackage };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { resolveExecutable, sortStrings, warn } from "@gtkx/utils";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
|
|
4
|
+
type ToolResult = {
|
|
5
|
+
output: string;
|
|
6
|
+
status: number;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type MetainfoResult = {
|
|
10
|
+
subject: string;
|
|
11
|
+
output: string;
|
|
12
|
+
status: number;
|
|
13
|
+
errors: string[];
|
|
14
|
+
warnings: string[];
|
|
15
|
+
areWarningsFatal: boolean;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type ToolRequest = {
|
|
19
|
+
tool: string;
|
|
20
|
+
args: string[];
|
|
21
|
+
subject: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const DIAGNOSTIC = /^(?<severity>[EIPW]): \S+ (?<rule>[\w-]+)/;
|
|
25
|
+
const ERROR_SEVERITY = "E";
|
|
26
|
+
const WARNING_SEVERITY = "W";
|
|
27
|
+
const INFO_SEVERITY = "I";
|
|
28
|
+
|
|
29
|
+
const REMEDY_FOR_RULE: Record<string, string> = {
|
|
30
|
+
"component-summary-missing": "set `deploy.summary`",
|
|
31
|
+
"description-first-para-too-short": "open `deploy.description` with a paragraph longer than 80 characters",
|
|
32
|
+
"developer-info-missing": "set `deploy.developer.name`",
|
|
33
|
+
"metainfo-legacy-path": "this file is generated; report it as a gtkx bug",
|
|
34
|
+
"summary-has-dot-suffix": "drop the trailing period from `deploy.summary`",
|
|
35
|
+
"summary-too-long": "shorten `deploy.summary`",
|
|
36
|
+
"url-homepage-missing": "set `deploy.homepage`, or `homepage` in package.json",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const runTool = ({ tool, args, subject }: ToolRequest): ToolResult => {
|
|
40
|
+
const result = spawnSync(resolveExecutable(tool), args, { encoding: "utf8" });
|
|
41
|
+
|
|
42
|
+
if (result.error !== undefined) {
|
|
43
|
+
throw new Error(`${subject} could not be validated: ${result.error.message}`, { cause: result.error });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { output: [result.stdout, result.stderr].join("\n").trim(), status: result.status ?? 0 };
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const rulesIn = (output: string, severities: string[]): string[] =>
|
|
50
|
+
output
|
|
51
|
+
.split("\n")
|
|
52
|
+
.map((line) => DIAGNOSTIC.exec(line)?.groups)
|
|
53
|
+
.filter((groups) => groups !== undefined && severities.includes(groups.severity ?? ""))
|
|
54
|
+
.map((groups) => groups?.rule ?? "");
|
|
55
|
+
|
|
56
|
+
const remedyLines = (rules: string[]): string[] => {
|
|
57
|
+
const remedies = sortStrings([...new Set(rules)])
|
|
58
|
+
.filter((rule) => REMEDY_FOR_RULE[rule] !== undefined)
|
|
59
|
+
.map((rule) => ` ${rule}: ${REMEDY_FOR_RULE[rule] ?? ""}`);
|
|
60
|
+
|
|
61
|
+
return remedies.length === 0 ? [] : ["", "Fix it in gtkx.config.ts:", ...remedies];
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const invalid = (subject: string, output: string, rules: string[]): Error =>
|
|
65
|
+
new Error([`${subject} is not valid:`, output.length > 0 ? output : "no output", ...remedyLines(rules)].join("\n"));
|
|
66
|
+
|
|
67
|
+
const isFatalResult = ({ status, errors, warnings, areWarningsFatal }: MetainfoResult): boolean => {
|
|
68
|
+
if (errors.length > 0) {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (areWarningsFatal && warnings.length > 0) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return status !== 0 && warnings.length === 0;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const assertNotFatal = (result: MetainfoResult): void => {
|
|
80
|
+
if (isFatalResult(result)) {
|
|
81
|
+
throw invalid(result.subject, result.output, [...result.errors, ...result.warnings]);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const describeRule = (rule: string): string => {
|
|
86
|
+
const remedy = REMEDY_FOR_RULE[rule];
|
|
87
|
+
|
|
88
|
+
return remedy === undefined ? rule : `${rule} — ${remedy}`;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const reportDiagnostics = (subject: string, rules: string[]): void => {
|
|
92
|
+
for (const rule of rules) {
|
|
93
|
+
warn(`${subject}: ${describeRule(rule)}`);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const validateDesktopEntry = (path: string): void => {
|
|
98
|
+
const { output, status } = runTool({
|
|
99
|
+
tool: "desktop-file-validate",
|
|
100
|
+
args: [path],
|
|
101
|
+
subject: "The desktop entry",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (status !== 0 || output.length > 0) {
|
|
105
|
+
throw invalid("The desktop entry", output, []);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const validateMetainfo = (path: string, areWarningsFatal: boolean): void => {
|
|
110
|
+
const subject = "The AppStream metainfo";
|
|
111
|
+
|
|
112
|
+
const { output, status } = runTool({
|
|
113
|
+
tool: "appstreamcli",
|
|
114
|
+
args: ["validate", "--no-net", "--explain", path],
|
|
115
|
+
subject,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const errors = rulesIn(output, [ERROR_SEVERITY]);
|
|
119
|
+
const warnings = rulesIn(output, [WARNING_SEVERITY]);
|
|
120
|
+
assertNotFatal({ subject, output, status, errors, warnings, areWarningsFatal });
|
|
121
|
+
reportDiagnostics(subject, [...warnings, ...rulesIn(output, [INFO_SEVERITY])]);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export { validateDesktopEntry, validateMetainfo };
|