| @@ -1,5 +1,5 @@ |
| 1 | 1 | import { spawn } from "node:child_process"; |
| 2 | | −import { existsSync } from "node:fs"; |
| 2 | +import { existsSync, readFileSync } from "node:fs"; |
| 3 | 3 | import { chmod, cp, mkdir, rename, rm, writeFile } from "node:fs/promises"; |
| 4 | 4 | import { createRequire } from "node:module"; |
| 5 | 5 | import { dirname, join, resolve } from "node:path"; |
| @@ -23,6 +23,12 @@ export type DistributionPackageArtifact = { · 17 unmodified lines |
| 23 | 23 | resourcesDir: string; |
| 24 | 24 | }; |
| 25 | 25 | |
| 26 | +type BundledDependency = { |
| 27 | + name: string; |
| 28 | + version: string; |
| 29 | + packageDir: string; |
| 30 | +}; |
| 31 | + |
| 26 | 32 | type CommandInput = { |
| 27 | 33 | command: string; |
| 28 | 34 | args: ReadonlyArray<string>; |
| @@ -90,6 +96,56 @@ const resolveQuickJsWasmPath = (): string => { · 61 unmodified lines |
| 90 | 96 | return wasmPath; |
| 91 | 97 | }; |
| 92 | 98 | |
| 99 | +const resolveInstalledPackage = (input: { |
| 100 | + packageName: string; |
| 101 | + fromPackageJsonPath: string; |
| 102 | +}): BundledDependency => { |
| 103 | + const requireFromPackage = createRequire(input.fromPackageJsonPath); |
| 104 | + const packageEntrypointPath = requireFromPackage.resolve(input.packageName); |
| 105 | + let packageDir = dirname(packageEntrypointPath); |
| 106 | + let packageJsonPath = join(packageDir, "package.json"); |
| 107 | + |
| 108 | + while (!existsSync(packageJsonPath)) { |
| 109 | + const parentDir = dirname(packageDir); |
| 110 | + if (parentDir === packageDir) { |
| 111 | + throw new Error(`Unable to locate package.json for ${input.packageName} from ${packageEntrypointPath}`); |
| 112 | + } |
| 113 | + packageDir = parentDir; |
| 114 | + packageJsonPath = join(packageDir, "package.json"); |
| 115 | + } |
| 116 | + |
| 117 | + const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8")) as { |
| 118 | + name?: string; |
| 119 | + version?: string; |
| 120 | + }; |
| 121 | + |
| 122 | + if (!packageJson.name || !packageJson.version) { |
| 123 | + throw new Error(`Invalid package metadata at ${packageJsonPath}`); |
| 124 | + } |
| 125 | + |
| 126 | + return { |
| 127 | + name: packageJson.name, |
| 128 | + version: packageJson.version, |
| 129 | + packageDir, |
| 130 | + }; |
| 131 | +}; |
| 132 | + |
| 133 | +const resolveBundledDependencies = (): ReadonlyArray<BundledDependency> => { |
| 134 | + const onePasswordSdk = resolveInstalledPackage({ |
| 135 | + packageName: "@1password/sdk", |
| 136 | + fromPackageJsonPath: join(repoRoot, "plugins/onepassword/sdk/package.json"), |
| 137 | + }); |
| 138 | + const onePasswordSdkCore = resolveInstalledPackage({ |
| 139 | + packageName: "@1password/sdk-core", |
| 140 | + fromPackageJsonPath: join(onePasswordSdk.packageDir, "package.json"), |
| 141 | + }); |
| 142 | + |
| 143 | + return [ |
| 144 | + onePasswordSdk, |
| 145 | + onePasswordSdkCore, |
| 146 | + ]; |
| 147 | +}; |
| 148 | + |
| 93 | 149 | |
| 94 | 150 | const createPackageJson = (input: { |
| 95 | 151 | packageName: string; |
| @@ -105,6 +161,8 @@ const createPackageJson = (input: { · 9 unmodified lines |
| 105 | 161 | url?: string; |
| 106 | 162 | }; |
| 107 | 163 | license?: string; |
| 164 | + dependencies?: Readonly<Record<string, string>>; |
| 165 | + bundleDependencies?: ReadonlyArray<string>; |
| 108 | 166 | }) => { |
| 109 | 167 | const packageJson = { |
| 110 | 168 | name: input.packageName, |
| @@ -122,6 +180,7 @@ const createPackageJson = (input: { · 11 unmodified lines |
| 122 | 180 | }, |
| 123 | 181 | files: [ |
| 124 | 182 | "bin", |
| 183 | + "node_modules", |
| 125 | 184 | "resources", |
| 126 | 185 | "README.md", |
| 127 | 186 | "package.json", |
| @@ -129,6 +188,8 @@ const createPackageJson = (input: { · 1 unmodified line |
| 129 | 188 | engines: { |
| 130 | 189 | node: ">=20", |
| 131 | 190 | }, |
| 191 | + dependencies: input.dependencies, |
| 192 | + bundleDependencies: input.bundleDependencies, |
| 132 | 193 | }; |
| 133 | 194 | |
| 134 | 195 | return JSON.stringify(packageJson, null, 2) + "\n"; |
| @@ -195,6 +256,7 @@ const buildCliBundle = async (input: { · 60 unmodified lines |
| 195 | 256 | "node", |
| 196 | 257 | "--outdir", |
| 197 | 258 | input.binDir, |
| 259 | + "--external=@1password/sdk", |
| 198 | 260 | ], |
| 199 | 261 | cwd: repoRoot, |
| 200 | 262 | }); |
| @@ -217,7 +279,9 @@ export const buildDistributionPackage = async ( · 16 unmodified lines |
| 217 | 279 | const webDir = join(resourcesDir, "web"); |
| 218 | 280 | const bundlePath = join(binDir, "executor.mjs"); |
| 219 | 281 | const launcherPath = join(binDir, "executor.js"); |
| 282 | + const nodeModulesDir = join(packageDir, "node_modules"); |
| 220 | 283 | const quickJsWasmPath = resolveQuickJsWasmPath(); |
| 284 | + const bundledDependencies = resolveBundledDependencies(); |
| 221 | 285 | |
| 222 | 286 | const webDistDir = join(repoRoot, "apps/web/dist"); |
| 223 | 287 | const readmePath = join(repoRoot, "README.md"); |
| @@ -225,6 +289,7 @@ export const buildDistributionPackage = async ( · 1 unmodified line |
| 225 | 289 | const packageVersion = options.packageVersion ?? defaults.version; |
| 226 | 290 | await rm(packageDir, { recursive: true, force: true }); |
| 227 | 291 | await mkdir(binDir, { recursive: true }); |
| 292 | + await mkdir(nodeModulesDir, { recursive: true }); |
| 228 | 293 | await mkdir(resourcesDir, { recursive: true }); |
| 229 | 294 | |
| 230 | 295 | if ((options.buildWeb ?? true) || !existsSync(webDistDir)) { |
| @@ -245,6 +310,11 @@ export const buildDistributionPackage = async ( · 14 unmodified lines |
| 245 | 310 | }); |
| 246 | 311 | |
| 247 | 312 | await cp(webDistDir, webDir, { recursive: true }); |
| 313 | + for (const dependency of bundledDependencies) { |
| 314 | + const destinationDir = join(nodeModulesDir, ...dependency.name.split("/")); |
| 315 | + await mkdir(dirname(destinationDir), { recursive: true }); |
| 316 | + await cp(dependency.packageDir, destinationDir, { recursive: true }); |
| 317 | + } |
| 248 | 318 | await cp(quickJsWasmPath, join(binDir, "emscripten-module.wasm")); |
| 249 | 319 | await cp( |
| 250 | 320 | join(repoRoot, "packages/kernel/runtime-deno-subprocess/src/deno-subprocess-worker.mjs"), |
| @@ -271,6 +341,10 @@ export const buildDistributionPackage = async ( · 20 unmodified lines |
| 271 | 341 | bugs: defaults.bugs, |
| 272 | 342 | repository: defaults.repository, |
| 273 | 343 | license: defaults.license, |
| 344 | + dependencies: Object.fromEntries( |
| 345 | + bundledDependencies.map((dependency) => [dependency.name, dependency.version]), |
| 346 | + ), |
| 347 | + bundleDependencies: bundledDependencies.map((dependency) => dependency.name), |
| 274 | 348 | })); |
| 275 | 349 | await cp(readmePath, join(packageDir, "README.md")); |
| 276 | 350 | await writeFile(launcherPath, createLauncherSource()); |