@gtkx/cli 1.1.0 → 1.2.1
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/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +2 -0
- package/dist/builder.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 +1 -0
- package/dist/codegen/run-codegen.d.ts.map +1 -1
- package/dist/codegen/run-codegen.js +7 -1
- package/dist/codegen/run-codegen.js.map +1 -1
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +1 -0
- package/dist/commands/docs.js.map +1 -1
- package/dist/deploy/freedesktop/copyright.d.ts +2 -2
- package/dist/deploy/freedesktop/copyright.d.ts.map +1 -1
- package/dist/deploy/freedesktop/copyright.js +105 -14
- package/dist/deploy/freedesktop/copyright.js.map +1 -1
- package/dist/deploy/install-hints.d.ts.map +1 -1
- package/dist/deploy/install-hints.js +7 -4
- package/dist/deploy/install-hints.js.map +1 -1
- package/dist/deploy/node-runtime/download.d.ts +5 -1
- package/dist/deploy/node-runtime/download.d.ts.map +1 -1
- package/dist/deploy/node-runtime/download.js +6 -3
- package/dist/deploy/node-runtime/download.js.map +1 -1
- package/dist/deploy/node-runtime/index.d.ts +2 -1
- package/dist/deploy/node-runtime/index.d.ts.map +1 -1
- package/dist/deploy/node-runtime/index.js +10 -9
- package/dist/deploy/node-runtime/index.js.map +1 -1
- package/dist/deploy/node-runtime/license.d.ts +4 -0
- package/dist/deploy/node-runtime/license.d.ts.map +1 -0
- package/dist/deploy/node-runtime/license.js +19 -0
- package/dist/deploy/node-runtime/license.js.map +1 -0
- package/dist/deploy/notices/collect.d.ts +8 -0
- package/dist/deploy/notices/collect.d.ts.map +1 -0
- package/dist/deploy/notices/collect.js +17 -0
- package/dist/deploy/notices/collect.js.map +1 -0
- package/dist/deploy/notices/dependencies.d.ts +5 -0
- package/dist/deploy/notices/dependencies.d.ts.map +1 -0
- package/dist/deploy/notices/dependencies.js +39 -0
- package/dist/deploy/notices/dependencies.js.map +1 -0
- package/dist/deploy/notices/gtkx.d.ts +6 -0
- package/dist/deploy/notices/gtkx.d.ts.map +1 -0
- package/dist/deploy/notices/gtkx.js +68 -0
- package/dist/deploy/notices/gtkx.js.map +1 -0
- package/dist/deploy/notices/libraries.d.ts +4 -0
- package/dist/deploy/notices/libraries.d.ts.map +1 -0
- package/dist/deploy/notices/libraries.js +60 -0
- package/dist/deploy/notices/libraries.js.map +1 -0
- package/dist/deploy/notices/node-runtime.d.ts +4 -0
- package/dist/deploy/notices/node-runtime.d.ts.map +1 -0
- package/dist/deploy/notices/node-runtime.js +78 -0
- package/dist/deploy/notices/node-runtime.js.map +1 -0
- package/dist/deploy/notices/packages.d.ts +13 -0
- package/dist/deploy/notices/packages.d.ts.map +1 -0
- package/dist/deploy/notices/packages.js +115 -0
- package/dist/deploy/notices/packages.js.map +1 -0
- package/dist/deploy/notices/render.d.ts +4 -0
- package/dist/deploy/notices/render.d.ts.map +1 -0
- package/dist/deploy/notices/render.js +41 -0
- package/dist/deploy/notices/render.js.map +1 -0
- package/dist/deploy/notices/text.d.ts +5 -0
- package/dist/deploy/notices/text.d.ts.map +1 -0
- package/dist/deploy/notices/text.js +34 -0
- package/dist/deploy/notices/text.js.map +1 -0
- package/dist/deploy/payload/copy-tree.d.ts +2 -1
- package/dist/deploy/payload/copy-tree.d.ts.map +1 -1
- package/dist/deploy/payload/copy-tree.js +3 -1
- package/dist/deploy/payload/copy-tree.js.map +1 -1
- package/dist/deploy/payload/stage.d.ts +7 -3
- package/dist/deploy/payload/stage.d.ts.map +1 -1
- package/dist/deploy/payload/stage.js +25 -14
- package/dist/deploy/payload/stage.js.map +1 -1
- package/dist/deploy/run-deploy.d.ts.map +1 -1
- package/dist/deploy/run-deploy.js +28 -7
- package/dist/deploy/run-deploy.js.map +1 -1
- package/dist/deploy/settings/extra-files.d.ts +4 -0
- package/dist/deploy/settings/extra-files.d.ts.map +1 -0
- package/dist/deploy/settings/extra-files.js +11 -0
- package/dist/deploy/settings/extra-files.js.map +1 -0
- package/dist/deploy/settings/index.d.ts.map +1 -1
- package/dist/deploy/settings/index.js +2 -1
- package/dist/deploy/settings/index.js.map +1 -1
- package/dist/deploy/settings/package-manifest.d.ts +2 -0
- package/dist/deploy/settings/package-manifest.d.ts.map +1 -1
- package/dist/deploy/settings/package-manifest.js +8 -0
- package/dist/deploy/settings/package-manifest.js.map +1 -1
- package/dist/deploy/settings/paths.d.ts +2 -1
- package/dist/deploy/settings/paths.d.ts.map +1 -1
- package/dist/deploy/settings/paths.js +1 -1
- package/dist/deploy/settings/paths.js.map +1 -1
- package/dist/deploy/targets/flatpak-manifest.d.ts +3 -1
- package/dist/deploy/targets/flatpak-manifest.d.ts.map +1 -1
- package/dist/deploy/targets/flatpak-manifest.js +50 -4
- package/dist/deploy/targets/flatpak-manifest.js.map +1 -1
- 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-source.d.ts.map +1 -1
- package/dist/deploy/targets/flatpak-source.js +70 -7
- package/dist/deploy/targets/flatpak-source.js.map +1 -1
- package/dist/deploy/targets/flatpak-sources.d.ts +5 -3
- package/dist/deploy/targets/flatpak-sources.d.ts.map +1 -1
- package/dist/deploy/targets/flatpak-sources.js +23 -9
- package/dist/deploy/targets/flatpak-sources.js.map +1 -1
- package/dist/deploy/targets/flatpak.d.ts.map +1 -1
- package/dist/deploy/targets/flatpak.js +3 -2
- package/dist/deploy/targets/flatpak.js.map +1 -1
- package/dist/deploy/tools.d.ts +3 -1
- package/dist/deploy/tools.d.ts.map +1 -1
- package/dist/deploy/tools.js +17 -3
- package/dist/deploy/tools.js.map +1 -1
- package/dist/deploy/types.d.ts +22 -2
- package/dist/deploy/types.d.ts.map +1 -1
- package/dist/deploy/types.js.map +1 -1
- package/dist/vite-plugins/bundled-packages.d.ts +5 -0
- package/dist/vite-plugins/bundled-packages.d.ts.map +1 -0
- package/dist/vite-plugins/bundled-packages.js +63 -0
- package/dist/vite-plugins/bundled-packages.js.map +1 -0
- package/package.json +9 -9
- package/src/builder.ts +2 -0
- package/src/codegen/report.ts +4 -0
- package/src/codegen/run-codegen.ts +11 -1
- package/src/commands/docs.ts +1 -0
- package/src/deploy/freedesktop/copyright.ts +153 -18
- package/src/deploy/install-hints.ts +9 -6
- package/src/deploy/node-runtime/download.ts +13 -4
- package/src/deploy/node-runtime/index.ts +17 -11
- package/src/deploy/node-runtime/license.ts +24 -0
- package/src/deploy/notices/collect.ts +26 -0
- package/src/deploy/notices/dependencies.ts +53 -0
- package/src/deploy/notices/gtkx.ts +92 -0
- package/src/deploy/notices/libraries.ts +81 -0
- package/src/deploy/notices/node-runtime.ts +101 -0
- package/src/deploy/notices/packages.ts +168 -0
- package/src/deploy/notices/render.ts +52 -0
- package/src/deploy/notices/text.ts +42 -0
- package/src/deploy/payload/copy-tree.ts +5 -1
- package/src/deploy/payload/stage.ts +40 -16
- package/src/deploy/run-deploy.ts +34 -6
- package/src/deploy/settings/extra-files.ts +21 -0
- package/src/deploy/settings/index.ts +2 -1
- package/src/deploy/settings/package-manifest.ts +12 -0
- package/src/deploy/settings/paths.ts +1 -1
- package/src/deploy/targets/flatpak-manifest.ts +69 -4
- package/src/deploy/targets/flatpak-pnpm.ts +115 -0
- package/src/deploy/targets/flatpak-source.ts +105 -6
- package/src/deploy/targets/flatpak-sources.ts +36 -9
- package/src/deploy/targets/flatpak.ts +3 -2
- package/src/deploy/tools.ts +23 -2
- package/src/deploy/types.ts +27 -1
- package/src/vite-plugins/bundled-packages.ts +95 -0
- package/LICENSE +0 -373
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync, realpathSync } from "node:fs";
|
|
2
|
+
import { posix, relative, resolve } from "node:path";
|
|
2
3
|
import type { DeployPayload, DeploySettings } from "../types.js";
|
|
3
4
|
import { listFilesRecursive } from "../../internal/list-files.js";
|
|
4
5
|
import { BUNDLE_FILENAME } from "../../vite-plugins/esm-extension.js";
|
|
5
6
|
import { renderDbusService } from "../freedesktop/dbus-service.js";
|
|
6
7
|
import { renderDesktopEntry } from "../freedesktop/desktop-entry.js";
|
|
7
8
|
import { renderMetainfo } from "../freedesktop/metainfo.js";
|
|
9
|
+
import { renderMimePackage } from "../freedesktop/mime-package.js";
|
|
8
10
|
import { optional } from "../nfpm/optional.js";
|
|
11
|
+
import { renderNotices } from "../notices/render.js";
|
|
12
|
+
import { executableModeFor } from "../payload/copy-tree.js";
|
|
9
13
|
import { iconPathFor } from "../payload/icons.js";
|
|
10
14
|
import { renderLauncher } from "../payload/launcher.js";
|
|
15
|
+
import { licenseDestination, nodeLicenseDestination, NOTICES_FILENAME, noticesDestination } from "../payload/stage.js";
|
|
16
|
+
import { isInside } from "../settings/paths.js";
|
|
17
|
+
import { pnpmPathFor, type PnpmPin, pnpmSources } from "./flatpak-pnpm.js";
|
|
11
18
|
import { DESTINATION, type FlatpakModule, postInstallCommands, validationCommands } from "./flatpak-prebuilt.js";
|
|
12
19
|
import {
|
|
13
20
|
detectPackageManager,
|
|
@@ -15,9 +22,16 @@ import {
|
|
|
15
22
|
installCommandFor,
|
|
16
23
|
nodeExtensionPathFor,
|
|
17
24
|
type PackageManager,
|
|
25
|
+
pnpmPinFor,
|
|
18
26
|
resolveGitSource,
|
|
19
27
|
} from "./flatpak-sources.js";
|
|
20
28
|
|
|
29
|
+
type InstalledFile = {
|
|
30
|
+
destination: string;
|
|
31
|
+
source: string;
|
|
32
|
+
resolved: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
21
35
|
const LAUNCHER_FILENAME = "launcher.sh";
|
|
22
36
|
const MODULE_BUILD_ROOT = "/run/build";
|
|
23
37
|
const RUNTIME_PREFIX = "/app";
|
|
@@ -25,6 +39,7 @@ const NPM_CACHE_DIR = "flatpak-node/npm-cache";
|
|
|
25
39
|
const YARN_MIRROR_DIR = "flatpak-node/yarn-mirror";
|
|
26
40
|
const PLAIN_ARGUMENT = /^[\w./-]+$/;
|
|
27
41
|
const QUOTE_ESCAPE = String.raw`'\''`;
|
|
42
|
+
const OCTAL_RADIX = 8;
|
|
28
43
|
|
|
29
44
|
const inlineSource = (fileName: string, contents: string): FlatpakModule => ({
|
|
30
45
|
type: "inline",
|
|
@@ -72,6 +87,21 @@ const activationInstallCommands = (settings: DeploySettings): string[] =>
|
|
|
72
87
|
)]
|
|
73
88
|
: [];
|
|
74
89
|
|
|
90
|
+
const mimeSources = (settings: DeploySettings): FlatpakModule[] => {
|
|
91
|
+
const contents = renderMimePackage(settings);
|
|
92
|
+
|
|
93
|
+
return contents === null ? [] : [inlineSource(`${settings.applicationId}.xml`, contents)];
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const mimeInstallCommands = (settings: DeploySettings): string[] =>
|
|
97
|
+
settings.fileAssociations.length === 0
|
|
98
|
+
? []
|
|
99
|
+
: [installCommand(
|
|
100
|
+
`${settings.applicationId}.xml`,
|
|
101
|
+
`${DESTINATION}/share/mime/packages/${settings.applicationId}.xml`,
|
|
102
|
+
"m644",
|
|
103
|
+
)];
|
|
104
|
+
|
|
75
105
|
const metadataInstallCommands = (settings: DeploySettings): string[] => [
|
|
76
106
|
installCommand(
|
|
77
107
|
`${settings.applicationId}.desktop`,
|
|
@@ -84,6 +114,7 @@ const metadataInstallCommands = (settings: DeploySettings): string[] => [
|
|
|
84
114
|
"m644",
|
|
85
115
|
),
|
|
86
116
|
...activationInstallCommands(settings),
|
|
117
|
+
...mimeInstallCommands(settings),
|
|
87
118
|
];
|
|
88
119
|
|
|
89
120
|
const schemaInstallCommands = (settings: DeploySettings): string[] =>
|
|
@@ -118,19 +149,81 @@ const iconInstallCommands = (settings: DeploySettings): string[] => {
|
|
|
118
149
|
return listFilesRecursive(iconsDir).map((icon) => iconInstallCommand(settings, icon.absPath, icon.rel));
|
|
119
150
|
};
|
|
120
151
|
|
|
152
|
+
const assertInsideProject = (settings: DeploySettings, installed: InstalledFile): void => {
|
|
153
|
+
const { resolved } = installed;
|
|
154
|
+
const target = existsSync(resolved) ? realpathSync(resolved) : resolved;
|
|
155
|
+
|
|
156
|
+
if (isInside(settings.paths.root, target)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Cannot install "${installed.destination}" from "${installed.source}": a source-mode manifest builds from ` +
|
|
162
|
+
`your git checkout, so every file it installs has to live inside ${settings.paths.root} and be committed. ` +
|
|
163
|
+
"Move it into the project, or drop it from the source build.",
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const licenseInstallCommands = (settings: DeploySettings): string[] => {
|
|
168
|
+
const licenseFile = settings.paths.licenseFile;
|
|
169
|
+
|
|
170
|
+
if (licenseFile === null) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const destination = licenseDestination(settings);
|
|
175
|
+
assertInsideProject(settings, { destination, source: licenseFile, resolved: licenseFile });
|
|
176
|
+
const target = `${DESTINATION}/${shellArgument(destination)}`;
|
|
177
|
+
|
|
178
|
+
return [installCommand(projectRelative(settings, licenseFile), target, "m644")];
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const noticesInstallCommands = (settings: DeploySettings): string[] => {
|
|
182
|
+
const extensionLicense = `${nodeExtensionPathFor(settings)}/LICENSE`;
|
|
183
|
+
const nodeTarget = `${DESTINATION}/${shellArgument(nodeLicenseDestination(settings))}`;
|
|
184
|
+
|
|
185
|
+
return [
|
|
186
|
+
installCommand(NOTICES_FILENAME, `${DESTINATION}/${shellArgument(noticesDestination(settings))}`, "m644"),
|
|
187
|
+
`test ! -f ${extensionLicense} || ${installCommand(extensionLicense, nodeTarget, "m644")}`,
|
|
188
|
+
];
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const extraFileInstallCommands = (settings: DeploySettings): string[] =>
|
|
192
|
+
settings.extraFiles.map((file) => {
|
|
193
|
+
const resolved = resolve(settings.paths.root, file.source);
|
|
194
|
+
assertInsideProject(settings, { destination: file.destination, source: file.source, resolved });
|
|
195
|
+
const mode = file.mode ?? executableModeFor(resolved);
|
|
196
|
+
|
|
197
|
+
return installCommand(
|
|
198
|
+
projectRelative(settings, resolved),
|
|
199
|
+
`${DESTINATION}/${shellArgument(file.destination)}`,
|
|
200
|
+
`m${mode.toString(OCTAL_RADIX)}`,
|
|
201
|
+
);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const moduleDirFor = (settings: DeploySettings): string => `${MODULE_BUILD_ROOT}/${settings.binaryName}`;
|
|
205
|
+
|
|
121
206
|
const offlineEnvFor = (manager: PackageManager, settings: DeploySettings): Record<string, string> => {
|
|
122
|
-
|
|
207
|
+
if (manager === "pnpm") {
|
|
208
|
+
return {};
|
|
209
|
+
}
|
|
123
210
|
|
|
124
211
|
if (manager === "yarn") {
|
|
125
|
-
return { YARN_OFFLINE_MIRROR: `${
|
|
212
|
+
return { YARN_OFFLINE_MIRROR: `${moduleDirFor(settings)}/${YARN_MIRROR_DIR}` };
|
|
126
213
|
}
|
|
127
214
|
|
|
128
|
-
return { npm_config_cache: `${
|
|
215
|
+
return { npm_config_cache: `${moduleDirFor(settings)}/${NPM_CACHE_DIR}`, npm_config_offline: "true" };
|
|
129
216
|
};
|
|
130
217
|
|
|
218
|
+
const appendPathFor = (settings: DeploySettings, pin: PnpmPin | null, nodeExtensionPath: string): string =>
|
|
219
|
+
pin === null
|
|
220
|
+
? `${nodeExtensionPath}/bin`
|
|
221
|
+
: `${pnpmPathFor(moduleDirFor(settings))}:${nodeExtensionPath}/bin`;
|
|
222
|
+
|
|
131
223
|
const flatpakSourceModule = (payload: DeployPayload): FlatpakModule => {
|
|
132
224
|
const settings = payload.settings;
|
|
133
225
|
const manager = detectPackageManager(settings);
|
|
226
|
+
const pin = pnpmPinFor(settings, manager);
|
|
134
227
|
const postInstall = postInstallCommands(payload);
|
|
135
228
|
const nodeExtensionPath = nodeExtensionPathFor(settings);
|
|
136
229
|
|
|
@@ -138,26 +231,32 @@ const flatpakSourceModule = (payload: DeployPayload): FlatpakModule => {
|
|
|
138
231
|
name: settings.binaryName,
|
|
139
232
|
buildsystem: "simple",
|
|
140
233
|
"build-options": {
|
|
141
|
-
"append-path":
|
|
234
|
+
"append-path": appendPathFor(settings, pin, nodeExtensionPath),
|
|
142
235
|
env: { npm_config_nodedir: nodeExtensionPath, ...offlineEnvFor(manager, settings) },
|
|
143
236
|
strip: false,
|
|
144
237
|
"no-debuginfo": true,
|
|
145
238
|
},
|
|
146
239
|
sources: [
|
|
147
240
|
resolveGitSource(settings),
|
|
241
|
+
...(pin === null ? [] : pnpmSources(pin, moduleDirFor(settings))),
|
|
148
242
|
GENERATED_SOURCES,
|
|
149
243
|
inlineSource(`${settings.applicationId}.desktop`, renderDesktopEntry(settings)),
|
|
150
244
|
inlineSource(`${settings.applicationId}.metainfo.xml`, renderMetainfo(settings)),
|
|
245
|
+
...mimeSources(settings),
|
|
151
246
|
inlineSource(LAUNCHER_FILENAME, renderLauncher(settings)),
|
|
247
|
+
inlineSource(NOTICES_FILENAME, renderNotices(settings, payload.notices)),
|
|
152
248
|
...activationSource(settings),
|
|
153
249
|
],
|
|
154
250
|
"build-commands": [
|
|
155
|
-
installCommandFor(manager),
|
|
251
|
+
installCommandFor(settings, manager),
|
|
156
252
|
"npx gtkx build",
|
|
157
253
|
...runtimeInstallCommands(settings, nodeExtensionPath),
|
|
158
254
|
...metadataInstallCommands(settings),
|
|
159
255
|
...schemaInstallCommands(settings),
|
|
160
256
|
...iconInstallCommands(settings),
|
|
257
|
+
...licenseInstallCommands(settings),
|
|
258
|
+
...noticesInstallCommands(settings),
|
|
259
|
+
...extraFileInstallCommands(settings),
|
|
161
260
|
...(settings.deploy.flatpak?.buildCommands ?? []),
|
|
162
261
|
...validationCommands(settings),
|
|
163
262
|
],
|
|
@@ -5,8 +5,11 @@ import type { DeploySettings } from "../types.js";
|
|
|
5
5
|
import { runCliTool } from "../../internal/run-cli-tool.js";
|
|
6
6
|
import { gitRemoteUrl, runGit } from "../git.js";
|
|
7
7
|
import { optional } from "../nfpm/optional.js";
|
|
8
|
+
import { FLATPAK_NODE_GENERATOR, GENERATOR_PNPM_OPTION } from "../tools.js";
|
|
9
|
+
import { pnpmInstallCommand, type PnpmPin, pnpmStoreVersionFor, resolvePnpmPin } from "./flatpak-pnpm.js";
|
|
8
10
|
|
|
9
11
|
type PackageManager = "npm" | "pnpm" | "yarn";
|
|
12
|
+
type VendoredManager = Exclude<PackageManager, "pnpm">;
|
|
10
13
|
|
|
11
14
|
type GitSource = {
|
|
12
15
|
type: "git";
|
|
@@ -21,7 +24,7 @@ type GitRevision = {
|
|
|
21
24
|
};
|
|
22
25
|
|
|
23
26
|
const GENERATED_SOURCES = "generated-sources.json";
|
|
24
|
-
const
|
|
27
|
+
const COMMIT_PEEL = "^{commit}";
|
|
25
28
|
const FETCHABLE_URL = /^https?:\/\//;
|
|
26
29
|
const DEFAULT_NODE_EXTENSION = "org.freedesktop.Sdk.Extension.node24";
|
|
27
30
|
const NODE_EXTENSION_PREFIX = "org.freedesktop.Sdk.Extension.";
|
|
@@ -33,9 +36,8 @@ const LOCKFILE_BY_MANAGER: Record<PackageManager, string> = {
|
|
|
33
36
|
yarn: "yarn.lock",
|
|
34
37
|
};
|
|
35
38
|
|
|
36
|
-
const INSTALL_COMMAND: Record<
|
|
39
|
+
const INSTALL_COMMAND: Record<VendoredManager, string> = {
|
|
37
40
|
npm: "npm ci --offline",
|
|
38
|
-
pnpm: "pnpm install --offline --frozen-lockfile",
|
|
39
41
|
yarn: "yarn install --offline",
|
|
40
42
|
};
|
|
41
43
|
|
|
@@ -59,7 +61,11 @@ const detectPackageManager = (settings: DeploySettings): PackageManager => {
|
|
|
59
61
|
return found;
|
|
60
62
|
};
|
|
61
63
|
|
|
62
|
-
const
|
|
64
|
+
const pnpmPinFor = (settings: DeploySettings, manager: PackageManager): PnpmPin | null =>
|
|
65
|
+
manager === "pnpm" ? resolvePnpmPin(settings) : null;
|
|
66
|
+
|
|
67
|
+
const installCommandFor = (settings: DeploySettings, manager: PackageManager): string =>
|
|
68
|
+
manager === "pnpm" ? pnpmInstallCommand(resolvePnpmPin(settings)) : INSTALL_COMMAND[manager];
|
|
63
69
|
|
|
64
70
|
const nodeExtensionFor = (settings: DeploySettings): string =>
|
|
65
71
|
settings.deploy.flatpak?.nodeExtension ?? DEFAULT_NODE_EXTENSION;
|
|
@@ -98,6 +104,19 @@ const resolveSourceUrl = (settings: DeploySettings): string => {
|
|
|
98
104
|
return url;
|
|
99
105
|
};
|
|
100
106
|
|
|
107
|
+
const commitForTag = (root: string, tag: string): string => {
|
|
108
|
+
const commit = runGit(root, ["rev-parse", `${tag}${COMMIT_PEEL}`]);
|
|
109
|
+
|
|
110
|
+
if (commit === null) {
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Cannot pin the Flathub source to "${tag}": Flathub builds a fixed tree, not a movable tag, and that ` +
|
|
113
|
+
`tag does not resolve in ${root}. Create or fetch it, or set \`deploy.flatpak.source.commit\`.`,
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return commit;
|
|
118
|
+
};
|
|
119
|
+
|
|
101
120
|
const configuredRevision = (settings: DeploySettings): GitRevision | null => {
|
|
102
121
|
const source = settings.deploy.flatpak?.source ?? {};
|
|
103
122
|
|
|
@@ -105,7 +124,11 @@ const configuredRevision = (settings: DeploySettings): GitRevision | null => {
|
|
|
105
124
|
return { ...optional("tag", source.tag), commit: source.commit };
|
|
106
125
|
}
|
|
107
126
|
|
|
108
|
-
|
|
127
|
+
if (source.tag === undefined) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { tag: source.tag, commit: commitForTag(settings.paths.root, source.tag) };
|
|
109
132
|
};
|
|
110
133
|
|
|
111
134
|
const workingTreeRevision = (settings: DeploySettings): GitRevision => {
|
|
@@ -141,7 +164,10 @@ const isolateLockfile = (root: string, lockfile: string): string => {
|
|
|
141
164
|
return dir;
|
|
142
165
|
};
|
|
143
166
|
|
|
144
|
-
const
|
|
167
|
+
const storeVersionArgs = (pin: PnpmPin | null): string[] =>
|
|
168
|
+
pin === null ? [] : [GENERATOR_PNPM_OPTION, pnpmStoreVersionFor(pin)];
|
|
169
|
+
|
|
170
|
+
const generateNodeSources = (settings: DeploySettings, manager: PackageManager, pin: PnpmPin | null): void => {
|
|
145
171
|
const lockfile = settings.deploy.flatpak?.lockfile ?? LOCKFILE_BY_MANAGER[manager];
|
|
146
172
|
const output = generatedSourcesPath(settings);
|
|
147
173
|
mkdirSync(dirname(output), { recursive: true });
|
|
@@ -149,9 +175,9 @@ const generateNodeSources = (settings: DeploySettings, manager: PackageManager):
|
|
|
149
175
|
|
|
150
176
|
try {
|
|
151
177
|
runCliTool({
|
|
152
|
-
tool:
|
|
153
|
-
args: [manager, join(isolated, basename(lockfile)), "-o", output],
|
|
154
|
-
target: "the offline
|
|
178
|
+
tool: FLATPAK_NODE_GENERATOR.command,
|
|
179
|
+
args: [manager, join(isolated, basename(lockfile)), ...storeVersionArgs(pin), "-o", output],
|
|
180
|
+
target: "the offline dependency sources",
|
|
155
181
|
shouldStream: true,
|
|
156
182
|
});
|
|
157
183
|
} finally {
|
|
@@ -167,5 +193,6 @@ export {
|
|
|
167
193
|
nodeExtensionFor,
|
|
168
194
|
nodeExtensionPathFor,
|
|
169
195
|
type PackageManager,
|
|
196
|
+
pnpmPinFor,
|
|
170
197
|
resolveGitSource,
|
|
171
198
|
};
|
|
@@ -6,7 +6,7 @@ import type { DeployArtifact, DeployManifest, DeployPayload, DeploySettings, Dep
|
|
|
6
6
|
import { runCliTool } from "../../internal/run-cli-tool.js";
|
|
7
7
|
import { APPSTREAMCLI, DESKTOP_FILE_VALIDATE, FLATPAK, FLATPAK_BUILDER } from "../tools.js";
|
|
8
8
|
import { branchFor, renderFlatpakManifest } from "./flatpak-manifest.js";
|
|
9
|
-
import { detectPackageManager, generateNodeSources } from "./flatpak-sources.js";
|
|
9
|
+
import { detectPackageManager, generateNodeSources, pnpmPinFor } from "./flatpak-sources.js";
|
|
10
10
|
|
|
11
11
|
type BuilderInvocation = {
|
|
12
12
|
tool: string;
|
|
@@ -45,7 +45,8 @@ const renderManifests = (payload: DeployPayload): DeployManifest[] => {
|
|
|
45
45
|
const settings = payload.settings;
|
|
46
46
|
|
|
47
47
|
if (isSourceMode(settings)) {
|
|
48
|
-
|
|
48
|
+
const manager = detectPackageManager(settings);
|
|
49
|
+
generateNodeSources(settings, manager, pnpmPinFor(settings, manager));
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
return [{
|
package/src/deploy/tools.ts
CHANGED
|
@@ -10,6 +10,8 @@ type ToolReport = {
|
|
|
10
10
|
|
|
11
11
|
const DETAIL_COLUMN = 26;
|
|
12
12
|
const FLATPAK_BUILDER_REF = "org.flatpak.Builder";
|
|
13
|
+
const FLATPAK_NODE_GENERATOR_COMMAND = "flatpak-node-generator";
|
|
14
|
+
const GENERATOR_PNPM_OPTION = "--pnpm-store-version";
|
|
13
15
|
|
|
14
16
|
const APPSTREAMCLI: DeployTool = {
|
|
15
17
|
command: "appstreamcli",
|
|
@@ -44,11 +46,16 @@ const FLATPAK_BUILDER: DeployTool = {
|
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
const FLATPAK_NODE_GENERATOR: DeployTool = {
|
|
47
|
-
command:
|
|
48
|
-
purpose: "vendors the
|
|
49
|
+
command: FLATPAK_NODE_GENERATOR_COMMAND,
|
|
50
|
+
purpose: "vendors the dependencies a Flathub build installs offline",
|
|
49
51
|
isOptional: false,
|
|
50
52
|
};
|
|
51
53
|
|
|
54
|
+
const FLATPAK_NODE_GENERATOR_PNPM: DeployTool = {
|
|
55
|
+
...FLATPAK_NODE_GENERATOR,
|
|
56
|
+
isPresent: () => hasGeneratorPnpmSupport(),
|
|
57
|
+
};
|
|
58
|
+
|
|
52
59
|
const STRIP: DeployTool = {
|
|
53
60
|
command: "strip",
|
|
54
61
|
purpose: "would shrink the bundled Node.js by removing its symbols",
|
|
@@ -71,6 +78,18 @@ const isFlatpakRefInstalled = (ref: string): boolean => {
|
|
|
71
78
|
return spawnSync(flatpak, ["info", ref], { stdio: "ignore" }).status === 0;
|
|
72
79
|
};
|
|
73
80
|
|
|
81
|
+
const hasGeneratorPnpmSupport = (): boolean => {
|
|
82
|
+
const generator = tryResolveExecutable(FLATPAK_NODE_GENERATOR_COMMAND);
|
|
83
|
+
|
|
84
|
+
if (generator === undefined) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const help = spawnSync(generator, ["--help"], { encoding: "utf8" });
|
|
89
|
+
|
|
90
|
+
return help.error === undefined && help.output.join("").includes(GENERATOR_PNPM_OPTION);
|
|
91
|
+
};
|
|
92
|
+
|
|
74
93
|
const isToolPresent = (tool: DeployTool): boolean =>
|
|
75
94
|
tool.isPresent === undefined ? tryResolveExecutable(tool.command) !== undefined : tool.isPresent();
|
|
76
95
|
|
|
@@ -123,6 +142,8 @@ const warnMissingOptional = (report: ToolReport): void => {
|
|
|
123
142
|
export {
|
|
124
143
|
APPSTREAMCLI,
|
|
125
144
|
FLATPAK_NODE_GENERATOR,
|
|
145
|
+
FLATPAK_NODE_GENERATOR_PNPM,
|
|
146
|
+
GENERATOR_PNPM_OPTION,
|
|
126
147
|
assertTools,
|
|
127
148
|
DESKTOP_FILE_VALIDATE,
|
|
128
149
|
FILE_TOOL,
|
package/src/deploy/types.ts
CHANGED
|
@@ -19,11 +19,27 @@ type StagedFile = {
|
|
|
19
19
|
|
|
20
20
|
type NodeRuntime = {
|
|
21
21
|
path: string;
|
|
22
|
+
licenseFile: string | null;
|
|
22
23
|
version: string;
|
|
23
24
|
glibcFloor: string | null;
|
|
24
25
|
isStripped: boolean;
|
|
25
26
|
};
|
|
26
27
|
|
|
28
|
+
type Notice = {
|
|
29
|
+
subject: string;
|
|
30
|
+
license: string;
|
|
31
|
+
source: string | null;
|
|
32
|
+
copyright: string[];
|
|
33
|
+
text: string | null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type NoticeSection = {
|
|
37
|
+
title: string;
|
|
38
|
+
files: string[];
|
|
39
|
+
summary: string[];
|
|
40
|
+
notices: Notice[];
|
|
41
|
+
};
|
|
42
|
+
|
|
27
43
|
type DeployDeveloper = {
|
|
28
44
|
id: string | null;
|
|
29
45
|
name: string;
|
|
@@ -51,6 +67,12 @@ type DeployFileAssociation = {
|
|
|
51
67
|
description: string | null;
|
|
52
68
|
};
|
|
53
69
|
|
|
70
|
+
type DeployExtraFile = {
|
|
71
|
+
destination: string;
|
|
72
|
+
source: string;
|
|
73
|
+
mode: number | null;
|
|
74
|
+
};
|
|
75
|
+
|
|
54
76
|
type DeployDesktopAction = {
|
|
55
77
|
id: string;
|
|
56
78
|
name: string;
|
|
@@ -118,7 +140,7 @@ type DeploySettings = {
|
|
|
118
140
|
desktopActions: DeployDesktopAction[];
|
|
119
141
|
desktopEntry: Record<string, string>;
|
|
120
142
|
isDbusActivatable: boolean;
|
|
121
|
-
extraFiles:
|
|
143
|
+
extraFiles: DeployExtraFile[];
|
|
122
144
|
versions: DeployVersions;
|
|
123
145
|
arch: DeployArch;
|
|
124
146
|
paths: DeployPaths;
|
|
@@ -130,6 +152,7 @@ type DeployPayload = {
|
|
|
130
152
|
settings: DeploySettings;
|
|
131
153
|
node: NodeRuntime | null;
|
|
132
154
|
stage: StagedFile[];
|
|
155
|
+
notices: NoticeSection[];
|
|
133
156
|
overlays: Record<DeployTargetName, StagedFile[]>;
|
|
134
157
|
};
|
|
135
158
|
|
|
@@ -157,6 +180,7 @@ export type {
|
|
|
157
180
|
DeployConfig,
|
|
158
181
|
DeployDesktopAction,
|
|
159
182
|
DeployDeveloper,
|
|
183
|
+
DeployExtraFile,
|
|
160
184
|
DeployFileAssociation,
|
|
161
185
|
DeployManifest,
|
|
162
186
|
DeployPaths,
|
|
@@ -169,6 +193,8 @@ export type {
|
|
|
169
193
|
DeployTool,
|
|
170
194
|
DeployVersions,
|
|
171
195
|
NodeRuntime,
|
|
196
|
+
Notice,
|
|
197
|
+
NoticeSection,
|
|
172
198
|
PackageFamily,
|
|
173
199
|
StagedFile,
|
|
174
200
|
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import { isRecord, sortStringsBy } from "@gtkx/utils";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
5
|
+
import { stripQuery } from "./strip-query.js";
|
|
6
|
+
|
|
7
|
+
type PackageIdentity = {
|
|
8
|
+
name: string;
|
|
9
|
+
version: string | null;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type RecordedPackage = PackageIdentity & {
|
|
13
|
+
dir: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type PackagesState = {
|
|
17
|
+
outDir: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const BUNDLED_PACKAGES_FILENAME = "gtkx-packages.json";
|
|
21
|
+
const MANIFEST_FILENAME = "package.json";
|
|
22
|
+
const DEFAULT_OUT_DIR = "dist";
|
|
23
|
+
const JSON_INDENT = 4;
|
|
24
|
+
|
|
25
|
+
const identityIn = (dir: string): PackageIdentity | null => {
|
|
26
|
+
try {
|
|
27
|
+
const parsed: unknown = JSON.parse(readFileSync(join(dir, MANIFEST_FILENAME), "utf8"));
|
|
28
|
+
|
|
29
|
+
if (!isRecord(parsed) || typeof parsed.name !== "string") {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { name: parsed.name, version: typeof parsed.version === "string" ? parsed.version : null };
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const packageIn = (dir: string): RecordedPackage | null => {
|
|
40
|
+
const identity = identityIn(dir);
|
|
41
|
+
|
|
42
|
+
if (identity !== null) {
|
|
43
|
+
return { ...identity, dir };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const parent = dirname(dir);
|
|
47
|
+
|
|
48
|
+
return parent === dir ? null : packageIn(parent);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const packageForModule = (id: string): RecordedPackage | null => {
|
|
52
|
+
const path = stripQuery(id);
|
|
53
|
+
|
|
54
|
+
return path.startsWith("/") ? packageIn(dirname(path)) : null;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const keyFor = (entry: RecordedPackage): string => `${entry.name}@${entry.version ?? ""}`;
|
|
58
|
+
|
|
59
|
+
const relativeTo = (outDir: string, entry: RecordedPackage): RecordedPackage => ({
|
|
60
|
+
...entry,
|
|
61
|
+
dir: relative(outDir, entry.dir),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const renderPackages = (outDir: string, ids: string[]): string => {
|
|
65
|
+
const found = ids.map((id) => packageForModule(id)).filter((entry) => entry !== null);
|
|
66
|
+
const unique: Map<string, RecordedPackage> = new Map(found.map((entry) => [keyFor(entry), entry]));
|
|
67
|
+
const packages = sortStringsBy(unique.values(), keyFor).map((entry) => relativeTo(outDir, entry));
|
|
68
|
+
|
|
69
|
+
return `${JSON.stringify({ packages }, null, JSON_INDENT)}\n`;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function gtkxBundledPackages(root: string): Plugin {
|
|
73
|
+
const state: PackagesState = { outDir: join(root, DEFAULT_OUT_DIR) };
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
name: "gtkx:bundled-packages",
|
|
77
|
+
apply: "build",
|
|
78
|
+
|
|
79
|
+
configResolved(config) {
|
|
80
|
+
state.outDir = resolve(config.root, config.build.outDir);
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
generateBundle(_options, bundle) {
|
|
84
|
+
const ids = Object.values(bundle).flatMap((output) => (output.type === "chunk" ? output.moduleIds : []));
|
|
85
|
+
|
|
86
|
+
this.emitFile({
|
|
87
|
+
type: "asset",
|
|
88
|
+
fileName: BUNDLED_PACKAGES_FILENAME,
|
|
89
|
+
source: renderPackages(state.outDir, ids),
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { BUNDLED_PACKAGES_FILENAME, gtkxBundledPackages };
|