isolate-package 1.0.0-beta.0 → 1.0.0-beta.10

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 CHANGED
@@ -1,7 +1,8 @@
1
1
  # Isolate Package
2
2
 
3
3
  Isolate a monorepo workspace package so that it can be deployed as a completely
4
- self-contained directory with the sources of all local dependencies included.
4
+ self-contained directory with the sources of all its local dependencies
5
+ included.
5
6
 
6
7
  **NOTE**: This package has only been tested with [PNPM](https://pnpm.io/) but it
7
8
  was designed to be compatible with NPM and Yarn. That being said, I am
@@ -12,44 +13,43 @@ a try.
12
13
 
13
14
  This solution was developed out of a desire to deploy to
14
15
  [Firebase](https://firebase.google.com/) from a monorepo without resorting to
15
- hacks, shell scripts and manual tasks. You can read more about this issue
16
- [here](#the-problem-with-firebase-in-monorepos).
16
+ hacks, shell scripts and manual tasks. I have written an article explaining the
17
+ issue [here](https://medium.com/p/e685de39025e).
17
18
 
18
19
  There is nothing Firebase specific to this solution but I am currently not aware
19
- of any other reason to isolate a workspace package. If you find a different
20
+ of other reasons to isolate a workspace package. If you find a different
20
21
  use-case, I would love to hear about it.
21
22
 
22
23
  ## Features
23
24
 
24
- These are the key aspects that set this approach apart from other solutions:
25
-
26
- - Zero-config for the majority of use-cases. No manual steps involved.
25
+ - Zero-config for the vast majority of use-cases, with no manual steps involved.
27
26
  - Designed to support NPM, Yarn and PNPM workspaces.
28
- - Compatible with the firebase CLI.
29
- - Uses a pack/unpack approach to only isolate files that would have been part of
30
- the published package, so the resulting output only contains the necessary
31
- files.
27
+ - Compatible with the Firebase tools CLI.
28
+ - Uses a pack/unpack approach to isolate only those files that would have been
29
+ part of a published package, so the resulting output contains a minimal amount
30
+ of files.
32
31
  - Isolates dependencies recursively. If package A depends on local package B
33
32
  which depends on local package C, all of them will be isolated.
34
- - Include and adjust the lockfile so you can be sure the isolated deployment is
35
- using the exact same versions.
36
- - Optionally include dev dependencies in the isolated output.
33
+ - Include and (in the case of PNPM) update the lockfile so the isolated
34
+ deployment should be deterministic.
35
+ - Optionally choose to include dev dependencies in the isolated output.
37
36
 
38
37
  ## Usage
39
38
 
40
- Run `pnpm add isolate-package -D` or do the equivalent for `yarn` or `npm`.
39
+ Run `npm install isolate-package --dev` or do the equivalent for `yarn` or
40
+ `pnpm`.
41
41
 
42
42
  This package exposes the `isolate` executable. Once installed you can run `npx
43
- isolate` in any package directory _after_ you have build the source files, and
44
- by default this will produce a directory at `./isolate`.
43
+ isolate` in any package directory _after_ you have build the source files. By
44
+ default this will produce a directory at `./isolate` but this can be configured.
45
45
 
46
46
  You will probably want to add the output directory to your `.gitignore` file.
47
47
 
48
- ### Deploy to Firebase
48
+ ### Deploying to Firebase
49
49
 
50
- This solution allows you to deploy to Firebase from multiple packages in your
51
- monorepo, so I advise you to co-locate your `firebase.json` file with the
52
- package, and not place it in the root of the monorepo.
50
+ You can deploy to Firebase from multiple packages in your monorepo, so I advise
51
+ you to co-locate your `firebase.json` file with the source code, and not place
52
+ it in the root of the monorepo.
53
53
 
54
54
  In order to deploy to Firebase, the `functions.source` setting in
55
55
  `firebase.json` needs to point to the isolated output folder, which would be
@@ -57,9 +57,10 @@ In order to deploy to Firebase, the `functions.source` setting in
57
57
 
58
58
  The `predeploy` phase should first build and then isolate the output.
59
59
 
60
- Here's an example using [Turborepo](https://turbo.build/) for the build process:
60
+ Here's an example using [Turborepo](https://turbo.build/):
61
61
 
62
62
  ```json
63
+ // firebase.json
63
64
  {
64
65
  "functions": {
65
66
  "source": "./isolate",
@@ -68,8 +69,8 @@ Here's an example using [Turborepo](https://turbo.build/) for the build process:
68
69
  }
69
70
  ```
70
71
 
71
- With this configuration you can run `firebase deploy --only functions` from the
72
- package you isolated.
72
+ With this configuration you can then run `firebase deploy --only functions` from
73
+ the package.
73
74
 
74
75
  If you like to deploy to Firebase Functions from multiple packages you will also
75
76
  need to configure a unique `codebase` identifier for each of them. For more
@@ -96,12 +97,26 @@ affected by this setting. If you want to debug the configuration set
96
97
 
97
98
  Type: `string`, default: `"../.."`
98
99
 
99
- The relative path, from the package you want to isolate to the root of the
100
- workspace / monorepo.
100
+ The relative path to the root of the workspace / monorepo. In a typical
101
+ repository you will have a `packages` and possibly an `apps` directory, and both
102
+ contain packages, so any package you would want to isolate is located 2 levels
103
+ up from the root.
104
+
105
+ For example
101
106
 
102
- In a typical monorepo you will have a `packages` and possibly an `apps`
103
- directory in the root of the workspace, so any package you want to isolate would
104
- be 2 levels up from the root.
107
+ ```
108
+ apps
109
+ ├─ api
110
+ │ ├─ package.json
111
+ │ └─ .eslintrc.js
112
+ └─ web
113
+ ├─ package.json
114
+ └─ .eslintrc.js
115
+ packages
116
+ └─ eslint-config-custom
117
+ ├─ index.js
118
+ └─ package.json
119
+ ```
105
120
 
106
121
  ### workspacePackages
107
122
 
@@ -145,52 +160,46 @@ Type: `string | undefined`, default: `undefined`
145
160
  When you are not using Typescript you can use this setting to specify where the
146
161
  build output files are located.
147
162
 
148
- ## TODO
163
+ ## Troubleshooting
164
+
165
+ If something is not working the first thing to do is add a `isolate.config.json`
166
+ file in the package you are trying to isolate, and set `"logLevel"` to
167
+ `"debug"`. This should give you detailed feedback.
168
+
169
+ In addition you can trigger the isolate manually with `npx isolate` and possibly
170
+ use debug the configuration by setting the env variable before running isolate:
171
+ `ISOLATE_CONFIG_LOG_LEVEL=debug npx isolate`
172
+
173
+ ## Lockfiles
149
174
 
150
- - [ ] Alter the pnpm lockfile
151
- - [ ] Add support for Yarn and NPM lock files
175
+ I inspected the NPM lockfiles as well as the Yarn v1 and v3 lockfiles and they
176
+ seem to have a flat structure unrelated to the workspace packages structure, so
177
+ I made the assumption that they can be copied as-is.
178
+
179
+ The PNPM lockfile clearly has a structure describing the different packages by
180
+ their relative paths, and so to correct the lockfile it is adapted before being
181
+ copied to the isolate directory.
182
+
183
+ I am not sure the Firebase deploy pipeline is actually detecting a
184
+ pnpm-lock.yaml file and using PNPM to install packages. This needs to be
185
+ verified...
152
186
 
153
187
  ## Used Terminology
154
188
 
155
189
  The various package managers, while being very similar, seem to use a different
156
190
  definition for the term "workspace". If you want to read the code it might be
157
- good to know that I consider the workspace to be the monorepo itself. The
158
- overall structure that holds all the packages. Also, in the code you see the
159
- word manifest a lot. It refers to the contents of a package.json file.
160
-
161
- ## The problem with Firebase in monorepos
162
-
163
- When deploying to Firebase it expects a folder with source files together with a
164
- package.json file. This folder will be zipped and uploaded after which Firebase
165
- will run an npm or yarn install in the cloud as part of the deployment pipeline.
166
-
167
- In a private monorepo your Firebase package(s) typically have one or more shared
168
- local dependencies that are never published to NPM. When Firebase tries to look
169
- up those dependencies from the package.json they can not be found and deployment
170
- fails.
171
-
172
- In order to solve this you could try to use a bundler like Webpack to include
173
- dependencies code in the bundle and then strip those packages from the list in
174
- the package.json that is sent to Firebase, so doesn't know about them, but this
175
- strategy quickly falls apart. If the shared packages themselves do not bundle
176
- all of their dependencies in their build output, then those dependencies will
177
- still need to be installed, and Firebase wouldn't know about it.
178
-
179
- Without Firebase natively supporting monorepos, the only solution seems to be to
180
- bundle each shared workspace dependency in a way that its build output, together
181
- with its package.json file, becomes part of the overall bundle that is uploaded
182
- in the Firebase deployment. This way, Firebase can find each shared package
183
- source code, and also know what dependencies need to be installed to make that
184
- source code work.
185
-
186
- There are many different hacks that people have come up with [discussing this
187
- issue](https://github.com/firebase/firebase-tools/issues/653) but they all seem
188
- to come down to this:
189
-
190
- - Copy the shared packages to some deployment folder
191
- - Create a modified package.json file for the deployment that points all local
192
- dependencies to the copied files for each shared dependency.
193
- - Point the Firebase deploy process to that folder
194
-
195
- The `isolate` process from this solution takes a similar approach but is more
196
- sophisticated and hides all complexity from the user.
191
+ good to know that I consider the workspace to be the monorepo itself, in other
192
+ words, the overall structure that holds all the packages.
193
+
194
+ Also, in the code you see the word manifest a lot. It refers to the contents of
195
+ a package.json file.
196
+
197
+ ## Binary as ESM module
198
+
199
+ The `isolate` binary is an ES module. It is required to have the `.mjs` file
200
+ extension, otherwise a non-ESM workspace will try to execute it as commonJS. For
201
+ details on this read [this article from Alex
202
+ Rauschmayer](https://exploringjs.com/nodejs-shell-scripting/ch_creating-shell-scripts.html#node.js-esm-modules-as-standalone-shell-scripts-on-unix)
203
+
204
+ Also, I found that for PNPM the hashbang at the top of the script was not required, but Yarn
205
+ 3 didn't want to execute without it.
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.mjs ADDED
@@ -0,0 +1,602 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import fs13 from "fs-extra";
5
+ import assert3 from "node:assert";
6
+ import path13 from "node:path";
7
+ import sourceMaps from "source-map-support";
8
+
9
+ // src/helpers/adapt-manifest-files.ts
10
+ import fs from "fs-extra";
11
+ import path from "node:path";
12
+ async function adaptManifestFiles(localDependencies, packagesRegistry, isolateDir) {
13
+ await Promise.all(
14
+ localDependencies.map(async (packageName) => {
15
+ const { manifest, rootRelativeDir } = packagesRegistry[packageName];
16
+ const outputManifest = adaptManifestWorkspaceDeps(
17
+ { manifest, packagesRegistry },
18
+ { includeDevDependencies: getConfig().includeDevDependencies }
19
+ );
20
+ await fs.writeFile(
21
+ path.join(isolateDir, rootRelativeDir, "package.json"),
22
+ JSON.stringify(outputManifest, null, 2)
23
+ );
24
+ })
25
+ );
26
+ }
27
+
28
+ // src/helpers/adapt-manifest-workspace-deps.ts
29
+ import { omit } from "lodash-es";
30
+
31
+ // src/utils/filter-object-undefined.ts
32
+ function filterObjectUndefined(object) {
33
+ return Object.fromEntries(
34
+ Object.entries(object).filter(([_, value]) => value !== void 0)
35
+ );
36
+ }
37
+
38
+ // src/utils/get-relative-path.ts
39
+ function getRelativePath(path14, relativeTo) {
40
+ return path14.replace(relativeTo, "");
41
+ }
42
+
43
+ // src/utils/inspect-value.ts
44
+ import { inspect } from "node:util";
45
+ function inspectValue(value) {
46
+ return inspect(value, false, 4, true);
47
+ }
48
+
49
+ // src/utils/json.ts
50
+ import fs2 from "fs-extra";
51
+ function readTypedJsonSync(filePath) {
52
+ const rawContent = fs2.readFileSync(filePath, "utf-8");
53
+ const data = JSON.parse(rawContent);
54
+ return data;
55
+ }
56
+ async function readTypedJson(filePath) {
57
+ const rawContent = await fs2.readFile(filePath, "utf-8");
58
+ const data = JSON.parse(rawContent);
59
+ return data;
60
+ }
61
+
62
+ // src/utils/logger.ts
63
+ import chalk from "chalk";
64
+ function createLogger(logLevel) {
65
+ return {
66
+ debug(...args) {
67
+ if (logLevel === "debug") {
68
+ console.log(chalk.blue("debug"), ...args);
69
+ }
70
+ },
71
+ info(...args) {
72
+ if (logLevel === "debug" || logLevel === "info") {
73
+ console.log(chalk.green("info"), ...args);
74
+ }
75
+ },
76
+ warn(...args) {
77
+ if (logLevel === "debug" || logLevel === "info" || logLevel === "warn") {
78
+ console.log(chalk.yellow("warning"), ...args);
79
+ }
80
+ },
81
+ error(...args) {
82
+ console.log(chalk.red("error"), ...args);
83
+ }
84
+ };
85
+ }
86
+
87
+ // src/utils/pack.ts
88
+ import { exec } from "node:child_process";
89
+ import path2 from "node:path";
90
+ async function pack(srcDir, destDir, packageManager) {
91
+ const log2 = createLogger(getConfig().logLevel);
92
+ const cwd = process.cwd();
93
+ process.chdir(srcDir);
94
+ switch (packageManager) {
95
+ case "pnpm": {
96
+ const stdout = await new Promise((resolve, reject) => {
97
+ exec(`pnpm pack --pack-destination ${destDir}`, (err, stdout2) => {
98
+ if (err) {
99
+ return reject(err);
100
+ }
101
+ resolve(stdout2);
102
+ });
103
+ });
104
+ const packedFilePath = stdout.trim();
105
+ log2.debug("Packed", path2.basename(packedFilePath));
106
+ process.chdir(cwd);
107
+ return packedFilePath;
108
+ }
109
+ case "yarn":
110
+ case "npm": {
111
+ const stdout = await new Promise((resolve, reject) => {
112
+ exec(`npm pack --pack-destination ${destDir}`, (err, stdout2) => {
113
+ if (err) {
114
+ return reject(err);
115
+ }
116
+ resolve(stdout2);
117
+ });
118
+ });
119
+ const packedFileName = stdout.trim();
120
+ log2.debug("Packed", packedFileName);
121
+ process.chdir(cwd);
122
+ return path2.join(destDir, packedFileName);
123
+ }
124
+ }
125
+ }
126
+
127
+ // src/utils/unpack.ts
128
+ import fs3 from "fs-extra";
129
+ import tar from "tar-fs";
130
+ import { createGunzip } from "zlib";
131
+ async function unpack(filePath, unpackDir) {
132
+ await new Promise((resolve, reject) => {
133
+ fs3.createReadStream(filePath).pipe(createGunzip()).pipe(tar.extract(unpackDir)).on("finish", () => resolve()).on("error", (err) => reject(err));
134
+ });
135
+ }
136
+
137
+ // src/utils/yaml.ts
138
+ import fs4 from "fs-extra";
139
+ import yaml from "yaml";
140
+ function readTypedYamlSync(filePath) {
141
+ const rawContent = fs4.readFileSync(filePath, "utf-8");
142
+ const data = yaml.parse(rawContent);
143
+ return data;
144
+ }
145
+ function writeTypedYamlSync(filePath, content) {
146
+ fs4.writeFileSync(filePath, yaml.stringify(content), "utf-8");
147
+ }
148
+
149
+ // src/helpers/adapt-manifest-workspace-deps.ts
150
+ function adaptManifestWorkspaceDeps({
151
+ manifest,
152
+ packagesRegistry
153
+ }, opts = {}) {
154
+ return Object.assign(
155
+ omit(manifest, ["scripts", "devDependencies"]),
156
+ filterObjectUndefined({
157
+ dependencies: manifest.dependencies ? patchWorkspaceEntries(manifest.dependencies, packagesRegistry) : void 0,
158
+ devDependencies: opts.includeDevDependencies && manifest.devDependencies ? patchWorkspaceEntries(manifest.devDependencies, packagesRegistry) : void 0
159
+ })
160
+ );
161
+ }
162
+
163
+ // src/helpers/adapt-target-package-manifest.ts
164
+ import fs5 from "fs-extra";
165
+ import path3 from "node:path";
166
+ async function adaptTargetPackageManifest(manifest, packagesRegistry, isolateDir) {
167
+ const outputManifest = adaptManifestWorkspaceDeps(
168
+ {
169
+ manifest,
170
+ packagesRegistry
171
+ },
172
+ { includeDevDependencies: getConfig().includeDevDependencies }
173
+ );
174
+ await fs5.writeFile(
175
+ path3.join(isolateDir, "package.json"),
176
+ JSON.stringify(outputManifest, null, 2)
177
+ );
178
+ }
179
+
180
+ // src/helpers/config.ts
181
+ import fs6 from "fs-extra";
182
+ import { isEmpty } from "lodash-es";
183
+ import path4 from "node:path";
184
+ var configDefaults = {
185
+ logLevel: "info",
186
+ workspaceRoot: "../..",
187
+ isolateOutDir: "./isolate",
188
+ includeDevDependencies: false,
189
+ tsconfigPath: "./tsconfig.json",
190
+ workspacePackages: void 0,
191
+ buildOutputDir: void 0
192
+ };
193
+ var __config;
194
+ var validConfigKeys = Object.keys(configDefaults);
195
+ var CONFIG_FILE_NAME = "isolate.config.json";
196
+ function getConfig() {
197
+ if (__config) {
198
+ return __config;
199
+ }
200
+ const log2 = createLogger(
201
+ process.env.ISOLATE_CONFIG_LOG_LEVEL ?? "warn"
202
+ );
203
+ const configFilePath = path4.join(process.cwd(), CONFIG_FILE_NAME);
204
+ log2.debug(`Attempting to load config from ${configFilePath}`);
205
+ const configFromFile = fs6.existsSync(configFilePath) ? readTypedJsonSync(configFilePath) : {};
206
+ const foreignKeys = Object.keys(configFromFile).filter(
207
+ (key) => !validConfigKeys.includes(key)
208
+ );
209
+ if (!isEmpty(foreignKeys)) {
210
+ log2.warn(`Found invalid config settings:`, foreignKeys.join(", "));
211
+ }
212
+ const config2 = Object.assign(
213
+ {},
214
+ configDefaults,
215
+ configFromFile
216
+ );
217
+ log2.debug("Using configuration:", inspectValue(config2));
218
+ __config = config2;
219
+ return config2;
220
+ }
221
+
222
+ // src/helpers/create-packages-registry.ts
223
+ import fs8 from "fs-extra";
224
+ import { globSync } from "glob";
225
+ import { set } from "lodash-es";
226
+ import path7 from "node:path";
227
+
228
+ // src/helpers/find-packages-globs.ts
229
+ import path6 from "node:path";
230
+
231
+ // src/helpers/detect-package-manager.ts
232
+ import fs7 from "fs-extra";
233
+ import path5 from "node:path";
234
+ function detectPackageManager(workspaceRoot) {
235
+ if (fs7.existsSync(path5.join(workspaceRoot, "pnpm-lock.yaml"))) {
236
+ return "pnpm";
237
+ }
238
+ if (fs7.existsSync(path5.join(workspaceRoot, "yarn.lock"))) {
239
+ return "yarn";
240
+ }
241
+ if (fs7.existsSync(path5.join(workspaceRoot, "package-lock.json"))) {
242
+ return "npm";
243
+ }
244
+ throw new Error(`Failed to detect package manager`);
245
+ }
246
+
247
+ // src/helpers/find-packages-globs.ts
248
+ function findPackagesGlobs(workspaceRootDir) {
249
+ const log2 = createLogger(getConfig().logLevel);
250
+ const packageManager = detectPackageManager(workspaceRootDir);
251
+ switch (packageManager) {
252
+ case "pnpm": {
253
+ const { packages: globs } = readTypedYamlSync(
254
+ path6.join(workspaceRootDir, "pnpm-workspace.yaml")
255
+ );
256
+ log2.debug("Detected pnpm packages globs:", inspectValue(globs));
257
+ return globs;
258
+ }
259
+ case "yarn":
260
+ case "npm": {
261
+ const workspaceRootManifestPath = path6.join(
262
+ workspaceRootDir,
263
+ "package.json"
264
+ );
265
+ const { workspaces } = readTypedJsonSync(
266
+ workspaceRootManifestPath
267
+ );
268
+ if (!workspaces) {
269
+ throw new Error(
270
+ `No workspaces field found in ${workspaceRootManifestPath}`
271
+ );
272
+ }
273
+ return workspaces;
274
+ }
275
+ }
276
+ }
277
+
278
+ // src/helpers/create-packages-registry.ts
279
+ async function createPackagesRegistry(workspaceRootDir, workspacePackagesOverride) {
280
+ const log2 = createLogger(getConfig().logLevel);
281
+ if (workspacePackagesOverride) {
282
+ log2.debug(
283
+ `Override workspace packages via config: ${workspacePackagesOverride}`
284
+ );
285
+ }
286
+ const packagesGlobs = workspacePackagesOverride ?? findPackagesGlobs(workspaceRootDir);
287
+ const cwd = process.cwd();
288
+ process.chdir(workspaceRootDir);
289
+ const allPackages = packagesGlobs.flatMap((glob) => globSync(glob)).filter((dir) => fs8.lstatSync(dir).isDirectory());
290
+ const registry = (await Promise.all(
291
+ allPackages.map(async (rootRelativeDir) => {
292
+ const manifestPath = path7.join(rootRelativeDir, "package.json");
293
+ if (!fs8.existsSync(manifestPath)) {
294
+ log2.warn(
295
+ `Ignoring directory ${rootRelativeDir} because it does not contain a package.json file`
296
+ );
297
+ return;
298
+ } else {
299
+ log2.debug(`Registering package ${rootRelativeDir}`);
300
+ const manifest = await readTypedJson(
301
+ path7.join(rootRelativeDir, "package.json")
302
+ );
303
+ return {
304
+ manifest,
305
+ rootRelativeDir,
306
+ absoluteDir: path7.join(workspaceRootDir, rootRelativeDir)
307
+ };
308
+ }
309
+ })
310
+ )).reduce(
311
+ (acc, info) => info ? set(acc, info.manifest.name, info) : acc,
312
+ {}
313
+ );
314
+ process.chdir(cwd);
315
+ return registry;
316
+ }
317
+
318
+ // src/helpers/find-build-output-dir.ts
319
+ import fs9 from "fs-extra";
320
+ import path8 from "node:path";
321
+ import process2 from "node:process";
322
+ async function findBuildOutputDir(targetPackageDir) {
323
+ const config2 = getConfig();
324
+ const log2 = createLogger(getConfig().logLevel);
325
+ if (config2.buildOutputDir) {
326
+ log2.debug("Using buildOutputDir from config:", config2.buildOutputDir);
327
+ return path8.join(targetPackageDir, config2.buildOutputDir);
328
+ }
329
+ const tsconfigPath = path8.join(targetPackageDir, config2.tsconfigPath);
330
+ if (fs9.existsSync(tsconfigPath)) {
331
+ const tsconfig = await readTypedJson(tsconfigPath);
332
+ const outDir = tsconfig.compilerOptions?.outDir;
333
+ if (outDir) {
334
+ return path8.join(targetPackageDir, outDir);
335
+ }
336
+ }
337
+ log2.error(`Failed to find outDir in tsconfig at ${tsconfigPath}
338
+ Without an isolate.config.json file specifying the buildOutputDir, or outDir provided by tsconfig, we can't know where the build output directory is located. Please configure one of these options.`);
339
+ process2.exit(1);
340
+ }
341
+
342
+ // src/helpers/list-local-dependencies.ts
343
+ function listLocalDependencies(manifest, packagesRegistry, { includeDevDependencies = false } = {}) {
344
+ const allWorkspacePackageNames = Object.keys(packagesRegistry);
345
+ const localDependencyPackageNames = (includeDevDependencies ? [
346
+ ...Object.keys(manifest.dependencies ?? {}),
347
+ ...Object.keys(manifest.devDependencies ?? {})
348
+ ] : Object.keys(manifest.dependencies ?? {})).filter((name) => allWorkspacePackageNames.includes(name));
349
+ const nestedLocalDependencies = localDependencyPackageNames.flatMap(
350
+ (packageName) => listLocalDependencies(
351
+ packagesRegistry[packageName].manifest,
352
+ packagesRegistry,
353
+ { includeDevDependencies }
354
+ )
355
+ );
356
+ return localDependencyPackageNames.concat(nestedLocalDependencies);
357
+ }
358
+
359
+ // src/helpers/manifest.ts
360
+ import path9 from "node:path";
361
+
362
+ // src/helpers/pack-dependencies.ts
363
+ import assert from "node:assert";
364
+ async function packDependencies({
365
+ /**
366
+ * All packages found in the monorepo by workspaces declaration
367
+ */
368
+ packagesRegistry,
369
+ /**
370
+ * The package names that appear to be local dependencies
371
+ */
372
+ localDependencies,
373
+ /**
374
+ * The directory where the isolated package and all its dependencies will end
375
+ * up. This is also the directory from where the package will be deployed. By
376
+ * default it is a subfolder in targetPackageDir called "isolate" but you can
377
+ * configure it.
378
+ */
379
+ packDestinationDir,
380
+ packageManager
381
+ }) {
382
+ const config2 = getConfig();
383
+ const log2 = createLogger(config2.logLevel);
384
+ const packedFileByName = {};
385
+ for (const dependency of localDependencies) {
386
+ const def = packagesRegistry[dependency];
387
+ assert(dependency, `Failed to find package definition for ${dependency}`);
388
+ const { name } = def.manifest;
389
+ if (packedFileByName[name]) {
390
+ log2.debug(`Skipping ${name} because it has already been packed`);
391
+ continue;
392
+ }
393
+ packedFileByName[name] = await pack(
394
+ def.absoluteDir,
395
+ packDestinationDir,
396
+ packageManager
397
+ );
398
+ }
399
+ return packedFileByName;
400
+ }
401
+
402
+ // src/helpers/patch-workspace-entries.ts
403
+ function patchWorkspaceEntries(dependencies, packagesRegistry) {
404
+ const log2 = createLogger(getConfig().logLevel);
405
+ const allWorkspacePackageNames = Object.keys(packagesRegistry);
406
+ return Object.fromEntries(
407
+ Object.entries(dependencies).map(([key, value]) => {
408
+ if (allWorkspacePackageNames.includes(key)) {
409
+ const def = packagesRegistry[key];
410
+ log2.debug(`Linking dependency ${key} to file:${def.rootRelativeDir}`);
411
+ return [key, `file:${def.rootRelativeDir}`];
412
+ } else {
413
+ return [key, value];
414
+ }
415
+ })
416
+ );
417
+ }
418
+
419
+ // src/helpers/process-build-output-files.ts
420
+ import fs10 from "fs-extra";
421
+ import path10 from "node:path";
422
+ async function processBuildOutputFiles({
423
+ targetPackageDir,
424
+ tmpDir,
425
+ packageManager,
426
+ isolateDir
427
+ }) {
428
+ const packedFilePath = await pack(targetPackageDir, tmpDir, packageManager);
429
+ const unpackDir = path10.join(tmpDir, "target");
430
+ await unpack(packedFilePath, unpackDir);
431
+ await fs10.copy(path10.join(unpackDir, "package"), isolateDir);
432
+ }
433
+
434
+ // src/helpers/process-lockfile.ts
435
+ import fs11 from "fs-extra";
436
+ import assert2 from "node:assert";
437
+ import path11 from "node:path";
438
+ function getLockfileFileName(packageManager) {
439
+ switch (packageManager) {
440
+ case "pnpm":
441
+ return "pnpm-lock.yaml";
442
+ case "yarn":
443
+ return "yarn.lock";
444
+ case "npm":
445
+ return "package-lock.json";
446
+ }
447
+ }
448
+ function processLockfile({
449
+ workspaceRootDir,
450
+ targetPackageName,
451
+ packagesRegistry,
452
+ isolateDir,
453
+ packageManager
454
+ }) {
455
+ const log2 = createLogger(getConfig().logLevel);
456
+ const targetPackageRelativeDir = packagesRegistry[targetPackageName].rootRelativeDir;
457
+ const fileName = getLockfileFileName(packageManager);
458
+ const lockfileSrcPath = path11.join(workspaceRootDir, fileName);
459
+ const lockfileDstPath = path11.join(isolateDir, fileName);
460
+ switch (packageManager) {
461
+ case "npm":
462
+ case "yarn": {
463
+ fs11.copyFileSync(lockfileSrcPath, lockfileDstPath);
464
+ log2.debug("Copied lockfile to", lockfileDstPath);
465
+ return;
466
+ }
467
+ case "pnpm": {
468
+ const origLockfile = readTypedYamlSync(lockfileSrcPath);
469
+ log2.debug("Read PNPM lockfile, version:", origLockfile.lockfileVersion);
470
+ const adaptedLockfile = structuredClone(origLockfile);
471
+ const targetPackageDef = adaptedLockfile.importers[targetPackageRelativeDir];
472
+ assert2(
473
+ targetPackageDef,
474
+ `Failed to find target package in lockfile at importers[${targetPackageRelativeDir}]`
475
+ );
476
+ adaptedLockfile.importers["."] = targetPackageDef;
477
+ delete adaptedLockfile.importers[targetPackageRelativeDir];
478
+ writeTypedYamlSync(lockfileDstPath, adaptedLockfile);
479
+ log2.debug("Stored adapted lockfile at", lockfileDstPath);
480
+ return;
481
+ }
482
+ }
483
+ }
484
+
485
+ // src/helpers/unpack-dependencies.ts
486
+ import fs12 from "fs-extra";
487
+ import path12, { join } from "node:path";
488
+ async function unpackDependencies(packedFilesByName, packagesRegistry, tmpDir, isolateDir) {
489
+ const log2 = createLogger(getConfig().logLevel);
490
+ await Promise.all(
491
+ Object.entries(packedFilesByName).map(async ([packageName, filePath]) => {
492
+ const dir = packagesRegistry[packageName].rootRelativeDir;
493
+ const unpackDir = join(tmpDir, dir);
494
+ await unpack(filePath, unpackDir);
495
+ log2.debug("Unpacked", path12.basename(filePath));
496
+ const destinationDir = join(isolateDir, dir);
497
+ await fs12.ensureDir(destinationDir);
498
+ await fs12.move(join(unpackDir, "package"), destinationDir, {
499
+ overwrite: true
500
+ });
501
+ log2.debug(
502
+ `Moved package files to isolate ${getRelativePath(
503
+ destinationDir,
504
+ isolateDir
505
+ )}`
506
+ );
507
+ })
508
+ );
509
+ }
510
+
511
+ // src/index.ts
512
+ var config = getConfig();
513
+ var log = createLogger(config.logLevel);
514
+ sourceMaps.install();
515
+ async function start() {
516
+ const targetPackageDir = process.cwd();
517
+ const buildOutputDir = await findBuildOutputDir(targetPackageDir);
518
+ assert3(
519
+ fs13.existsSync(buildOutputDir),
520
+ `Failed to find build output path at ${buildOutputDir}. Please make sure you build the source before isolating it.`
521
+ );
522
+ const workspaceRootDir = path13.join(
523
+ targetPackageDir,
524
+ config.workspaceRoot,
525
+ "/"
526
+ );
527
+ log.debug("Workspace root", workspaceRootDir);
528
+ log.debug(
529
+ "Isolate target package",
530
+ getRelativePath(targetPackageDir, workspaceRootDir)
531
+ );
532
+ const packageManager = detectPackageManager(workspaceRootDir);
533
+ const isolateDir = path13.join(targetPackageDir, config.isolateOutDir);
534
+ log.debug(
535
+ "Isolate output dir",
536
+ getRelativePath(isolateDir, workspaceRootDir)
537
+ );
538
+ await fs13.ensureDir(isolateDir);
539
+ const packagesRegistry = await createPackagesRegistry(
540
+ workspaceRootDir,
541
+ config.workspacePackages
542
+ );
543
+ const tmpDir = path13.join(isolateDir, "__tmp");
544
+ await fs13.ensureDir(tmpDir);
545
+ if (packageManager === "pnpm") {
546
+ log.debug("Using pnpm to pack dependencies");
547
+ } else {
548
+ log.debug("Using npm to pack dependencies");
549
+ }
550
+ const manifest = await readTypedJson(
551
+ path13.join(targetPackageDir, "package.json")
552
+ );
553
+ const localDependencies = listLocalDependencies(manifest, packagesRegistry, {
554
+ includeDevDependencies: config.includeDevDependencies
555
+ });
556
+ const packedFilesByName = await packDependencies({
557
+ localDependencies,
558
+ packagesRegistry,
559
+ packDestinationDir: tmpDir,
560
+ packageManager
561
+ });
562
+ await unpackDependencies(
563
+ packedFilesByName,
564
+ packagesRegistry,
565
+ tmpDir,
566
+ isolateDir
567
+ );
568
+ await adaptManifestFiles(localDependencies, packagesRegistry, isolateDir);
569
+ await processBuildOutputFiles({
570
+ targetPackageDir,
571
+ tmpDir,
572
+ packageManager,
573
+ isolateDir
574
+ });
575
+ await adaptTargetPackageManifest(manifest, packagesRegistry, isolateDir);
576
+ await processLockfile({
577
+ workspaceRootDir,
578
+ targetPackageName: manifest.name,
579
+ isolateDir,
580
+ packagesRegistry,
581
+ packageManager
582
+ });
583
+ log.debug(
584
+ "Deleting temporary directory",
585
+ getRelativePath(tmpDir, workspaceRootDir)
586
+ );
587
+ await fs13.remove(tmpDir);
588
+ log.info(
589
+ "Isolate completed at",
590
+ path13.join("./", getRelativePath(isolateDir, targetPackageDir))
591
+ );
592
+ }
593
+ start().catch((err) => {
594
+ if (err instanceof Error) {
595
+ log.error(err.stack);
596
+ process.exit(1);
597
+ } else {
598
+ console.error(err);
599
+ }
600
+ });
601
+ process.on("unhandledRejection", log.error);
602
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/helpers/adapt-manifest-files.ts","../src/helpers/adapt-manifest-workspace-deps.ts","../src/utils/filter-object-undefined.ts","../src/utils/get-relative-path.ts","../src/utils/inspect-value.ts","../src/utils/json.ts","../src/utils/logger.ts","../src/utils/pack.ts","../src/utils/unpack.ts","../src/utils/yaml.ts","../src/helpers/adapt-target-package-manifest.ts","../src/helpers/config.ts","../src/helpers/create-packages-registry.ts","../src/helpers/find-packages-globs.ts","../src/helpers/detect-package-manager.ts","../src/helpers/find-build-output-dir.ts","../src/helpers/list-local-dependencies.ts","../src/helpers/manifest.ts","../src/helpers/pack-dependencies.ts","../src/helpers/patch-workspace-entries.ts","../src/helpers/process-build-output-files.ts","../src/helpers/process-lockfile.ts","../src/helpers/unpack-dependencies.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport fs from \"fs-extra\";\nimport assert from \"node:assert\";\nimport path from \"node:path\";\nimport sourceMaps from \"source-map-support\";\nimport {\n PackageManifestMinimum,\n adaptManifestFiles,\n adaptTargetPackageManifest,\n createPackagesRegistry,\n detectPackageManager,\n findBuildOutputDir,\n getConfig,\n listLocalDependencies,\n packDependencies,\n processBuildOutputFiles,\n processLockfile,\n unpackDependencies,\n} from \"~/helpers\";\nimport { createLogger, getRelativePath, readTypedJson } from \"~/utils\";\n\nconst config = getConfig();\nconst log = createLogger(config.logLevel);\n\nsourceMaps.install();\n\nasync function start() {\n const targetPackageDir = process.cwd();\n\n const buildOutputDir = await findBuildOutputDir(targetPackageDir);\n\n assert(\n fs.existsSync(buildOutputDir),\n `Failed to find build output path at ${buildOutputDir}. Please make sure you build the source before isolating it.`\n );\n\n /**\n * We want a trailing slash here. Functionally it doesn't matter, but it makes\n * the relative paths print correctly in the cli output.\n */\n const workspaceRootDir = path.join(\n targetPackageDir,\n config.workspaceRoot,\n \"/\"\n );\n\n log.debug(\"Workspace root\", workspaceRootDir);\n log.debug(\n \"Isolate target package\",\n getRelativePath(targetPackageDir, workspaceRootDir)\n );\n\n const packageManager = detectPackageManager(workspaceRootDir);\n\n const isolateDir = path.join(targetPackageDir, config.isolateOutDir);\n\n log.debug(\n \"Isolate output dir\",\n getRelativePath(isolateDir, workspaceRootDir)\n );\n\n /**\n * Make sure the isolate dir exists so we can write to it\n */\n await fs.ensureDir(isolateDir);\n\n /**\n * Build a packages registry so we can find the workspace packages by name and\n * have access to their manifest files and relative paths.\n */\n const packagesRegistry = await createPackagesRegistry(\n workspaceRootDir,\n config.workspacePackages\n );\n\n const tmpDir = path.join(isolateDir, \"__tmp\");\n await fs.ensureDir(tmpDir);\n\n /**\n * PNPM pack seems to be much faster than NPM pack so we use that when PNPM is\n * detected. We log it here because the pack function will be called\n * recursively.\n */\n if (packageManager === \"pnpm\") {\n log.debug(\"Using pnpm to pack dependencies\");\n } else {\n log.debug(\"Using npm to pack dependencies\");\n }\n\n const manifest = await readTypedJson<PackageManifestMinimum>(\n path.join(targetPackageDir, \"package.json\")\n );\n\n const localDependencies = listLocalDependencies(manifest, packagesRegistry, {\n includeDevDependencies: config.includeDevDependencies,\n });\n\n const packedFilesByName = await packDependencies({\n localDependencies,\n packagesRegistry,\n packDestinationDir: tmpDir,\n packageManager,\n });\n\n await unpackDependencies(\n packedFilesByName,\n packagesRegistry,\n tmpDir,\n isolateDir\n );\n\n /**\n * Adapt the manifest files for all the unpacked local dependencies\n */\n await adaptManifestFiles(localDependencies, packagesRegistry, isolateDir);\n\n /**\n * Pack the target package directory, and unpack it in the isolate location\n */\n await processBuildOutputFiles({\n targetPackageDir,\n tmpDir,\n packageManager,\n isolateDir,\n });\n\n /**\n * Copy the target manifest file to the isolate location and adapt its\n * workspace dependencies to point to the isolated packages.\n */\n await adaptTargetPackageManifest(manifest, packagesRegistry, isolateDir);\n\n /**\n * Copy and adapt the lockfile\n */\n await processLockfile({\n workspaceRootDir,\n targetPackageName: manifest.name,\n isolateDir,\n packagesRegistry,\n packageManager,\n });\n\n /**\n * Clean up\n */\n log.debug(\n \"Deleting temporary directory\",\n getRelativePath(tmpDir, workspaceRootDir)\n );\n await fs.remove(tmpDir);\n\n log.info(\n \"Isolate completed at\",\n path.join(\"./\", getRelativePath(isolateDir, targetPackageDir))\n );\n}\n\nstart().catch((err) => {\n if (err instanceof Error) {\n log.error(err.stack);\n process.exit(1);\n } else {\n console.error(err);\n }\n});\n\nprocess.on(\"unhandledRejection\", log.error);\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport {\n PackagesRegistry,\n adaptManifestWorkspaceDeps,\n getConfig,\n} from \"~/helpers\";\n\nexport async function adaptManifestFiles(\n localDependencies: string[],\n packagesRegistry: PackagesRegistry,\n isolateDir: string,\n) {\n await Promise.all(\n localDependencies.map(async (packageName) => {\n const { manifest, rootRelativeDir } = packagesRegistry[packageName];\n\n const outputManifest = adaptManifestWorkspaceDeps(\n { manifest, packagesRegistry },\n { includeDevDependencies: getConfig().includeDevDependencies },\n );\n\n await fs.writeFile(\n path.join(isolateDir, rootRelativeDir, \"package.json\"),\n JSON.stringify(outputManifest, null, 2),\n );\n }),\n );\n}\n","import { omit } from \"lodash-es\";\nimport { filterObjectUndefined } from \"~/utils\";\nimport {\n PackageManifestMinimum,\n PackagesRegistry,\n patchWorkspaceEntries,\n} from \".\";\n\nexport function adaptManifestWorkspaceDeps(\n {\n manifest,\n packagesRegistry,\n }: {\n manifest: PackageManifestMinimum;\n packagesRegistry: PackagesRegistry;\n },\n opts: { includeDevDependencies?: boolean } = {},\n): PackageManifestMinimum {\n return Object.assign(\n omit(manifest, [\"scripts\", \"devDependencies\"]),\n filterObjectUndefined({\n dependencies: manifest.dependencies\n ? patchWorkspaceEntries(manifest.dependencies, packagesRegistry)\n : undefined,\n devDependencies:\n opts.includeDevDependencies && manifest.devDependencies\n ? patchWorkspaceEntries(manifest.devDependencies, packagesRegistry)\n : undefined,\n }),\n );\n}\n","export function filterObjectUndefined(object: Record<string, unknown>) {\n return Object.fromEntries(\n Object.entries(object).filter(([_, value]) => value !== undefined),\n );\n}\n","export function getRelativePath(path: string, relativeTo: string) {\n return path.replace(relativeTo, \"\");\n}\n","import { inspect } from \"node:util\";\nimport { JsonValue } from \"type-fest\";\n\nexport function inspectValue(value: JsonValue) {\n return inspect(value, false, 4, true);\n}\n","import fs from \"fs-extra\";\n\n/**\n * @TODO pass in zod schema and validate\n */\nexport function readTypedJsonSync<T>(filePath: string) {\n const rawContent = fs.readFileSync(filePath, \"utf-8\");\n const data = JSON.parse(rawContent) as T;\n return data;\n}\n\nexport async function readTypedJson<T>(filePath: string) {\n const rawContent = await fs.readFile(filePath, \"utf-8\");\n const data = JSON.parse(rawContent) as T;\n return data;\n}\n","import chalk from \"chalk\";\nimport { IsolateConfigResolved } from \"~/helpers\";\n\nexport type Logger = {\n debug(...args: any[]): void;\n info(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n};\n\nexport function createLogger(\n logLevel: IsolateConfigResolved[\"logLevel\"]\n): Logger {\n return {\n debug(...args: any[]) {\n if (logLevel === \"debug\") {\n console.log(chalk.blue(\"debug\"), ...args);\n }\n },\n info(...args: any[]) {\n if (logLevel === \"debug\" || logLevel === \"info\") {\n console.log(chalk.green(\"info\"), ...args);\n }\n },\n warn(...args: any[]) {\n if (logLevel === \"debug\" || logLevel === \"info\" || logLevel === \"warn\") {\n console.log(chalk.yellow(\"warning\"), ...args);\n }\n },\n error(...args: any[]) {\n console.log(chalk.red(\"error\"), ...args);\n },\n };\n}\n","import { exec } from \"node:child_process\";\nimport path from \"node:path\";\nimport { PackageManager, getConfig } from \"~/helpers\";\nimport { createLogger } from \"./logger\";\n\nexport async function pack(\n srcDir: string,\n destDir: string,\n packageManager: PackageManager,\n) {\n const log = createLogger(getConfig().logLevel);\n const cwd = process.cwd();\n process.chdir(srcDir);\n\n /**\n * PNPM pack seems to be a lot faster than NPM pack, so when PNPM is detected we\n * use that instead.\n */\n switch (packageManager) {\n case \"pnpm\": {\n const stdout = await new Promise<string>((resolve, reject) => {\n exec(`pnpm pack --pack-destination ${destDir}`, (err, stdout) => {\n if (err) {\n return reject(err);\n }\n\n resolve(stdout);\n });\n });\n\n /**\n * Trim newlines and whitespace\n */\n const packedFilePath = stdout.trim();\n\n log.debug(\"Packed\", path.basename(packedFilePath));\n\n process.chdir(cwd);\n return packedFilePath;\n }\n\n case \"yarn\":\n case \"npm\": {\n const stdout = await new Promise<string>((resolve, reject) => {\n exec(`npm pack --pack-destination ${destDir}`, (err, stdout) => {\n if (err) {\n return reject(err);\n }\n\n resolve(stdout);\n });\n });\n\n /**\n * Trim newlines and whitespace\n */\n const packedFileName = stdout.trim();\n\n log.debug(\"Packed\", packedFileName);\n\n process.chdir(cwd);\n return path.join(destDir, packedFileName);\n }\n }\n}\n","import fs from \"fs-extra\";\nimport tar from \"tar-fs\";\nimport { createGunzip } from \"zlib\";\n\nexport async function unpack(filePath: string, unpackDir: string) {\n await new Promise<void>((resolve, reject) => {\n fs.createReadStream(filePath)\n .pipe(createGunzip())\n .pipe(tar.extract(unpackDir))\n .on(\"finish\", () => resolve())\n .on(\"error\", (err) => reject(err));\n });\n}\n","import fs from \"fs-extra\";\nimport yaml from \"yaml\";\n\nexport function readTypedYamlSync<T>(filePath: string) {\n const rawContent = fs.readFileSync(filePath, \"utf-8\");\n const data = yaml.parse(rawContent);\n /**\n * @TODO add some zod validation maybe\n */\n return data as T;\n}\n\nexport function writeTypedYamlSync<T>(filePath: string, content: T) {\n /**\n * @TODO add some zod validation maybe\n */\n fs.writeFileSync(filePath, yaml.stringify(content), \"utf-8\");\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport {\n PackageManifestMinimum,\n PackagesRegistry,\n adaptManifestWorkspaceDeps,\n getConfig,\n} from \"~/helpers\";\n\nexport async function adaptTargetPackageManifest(\n manifest: PackageManifestMinimum,\n packagesRegistry: PackagesRegistry,\n isolateDir: string,\n) {\n const outputManifest = adaptManifestWorkspaceDeps(\n {\n manifest,\n packagesRegistry,\n },\n { includeDevDependencies: getConfig().includeDevDependencies },\n );\n\n await fs.writeFile(\n path.join(isolateDir, \"package.json\"),\n JSON.stringify(outputManifest, null, 2),\n );\n}\n","import fs from \"fs-extra\";\nimport { isEmpty } from \"lodash-es\";\nimport path from \"node:path\";\nimport { createLogger, inspectValue, readTypedJsonSync } from \"~/utils\";\n\nexport type IsolateConfigResolved = {\n logLevel: \"info\" | \"debug\" | \"warn\" | \"error\";\n workspaceRoot: string;\n workspacePackages?: string[];\n isolateOutDir: string;\n includeDevDependencies: boolean;\n tsconfigPath: string;\n buildOutputDir?: string;\n};\n\nexport type IsolateConfig = Partial<IsolateConfigResolved>;\n\nconst configDefaults: IsolateConfigResolved = {\n logLevel: \"info\",\n workspaceRoot: \"../..\",\n isolateOutDir: \"./isolate\",\n includeDevDependencies: false,\n tsconfigPath: \"./tsconfig.json\",\n workspacePackages: undefined,\n buildOutputDir: undefined,\n};\n\n/**\n * Only initialize the configuration once, and keeping it here for subsequent\n * calls to getConfig.\n */\nlet __config: IsolateConfigResolved | undefined;\n\nconst validConfigKeys = Object.keys(configDefaults);\n\nconst CONFIG_FILE_NAME = \"isolate.config.json\";\n\ntype LogLevel = IsolateConfigResolved[\"logLevel\"];\n\nexport function getConfig(): IsolateConfigResolved {\n if (__config) {\n return __config;\n }\n\n /**\n * Since the logLevel is set via config we can't use it to determine if we\n * should output verbose logging as part of the config loading process. Using\n * the env var ISOLATE_CONFIG_LOG_LEVEL you have the option to log debug\n * output.\n */\n const log = createLogger(\n (process.env.ISOLATE_CONFIG_LOG_LEVEL as LogLevel) ?? \"warn\"\n );\n\n const configFilePath = path.join(process.cwd(), CONFIG_FILE_NAME);\n\n log.debug(`Attempting to load config from ${configFilePath}`);\n\n const configFromFile = fs.existsSync(configFilePath)\n ? readTypedJsonSync<IsolateConfig>(configFilePath)\n : {};\n\n const foreignKeys = Object.keys(configFromFile).filter(\n (key) => !validConfigKeys.includes(key)\n );\n\n if (!isEmpty(foreignKeys)) {\n log.warn(`Found invalid config settings:`, foreignKeys.join(\", \"));\n }\n\n const config = Object.assign(\n {},\n configDefaults,\n configFromFile\n ) satisfies IsolateConfigResolved;\n\n log.debug(\"Using configuration:\", inspectValue(config));\n\n __config = config;\n return config;\n}\n","import fs from \"fs-extra\";\nimport { globSync } from \"glob\";\nimport { set } from \"lodash-es\";\nimport path from \"node:path\";\nimport { createLogger, readTypedJson } from \"~/utils\";\nimport { getConfig } from \"./config\";\nimport { findPackagesGlobs } from \"./find-packages-globs\";\n\nexport type PackageManifestMinimum = {\n name: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n main: string;\n module?: string;\n exports?: Record<string, { require: string; import: string }>;\n files: string[];\n version?: string;\n typings?: string;\n scripts?: Record<string, string>;\n};\n\nexport type WorkspacePackageInfo = {\n absoluteDir: string;\n /**\n * The path of the package relative to the workspace root. This is the path\n * referenced in the lock file.\n */\n rootRelativeDir: string;\n /**\n * The package.json file contents\n */\n manifest: PackageManifestMinimum;\n};\n\nexport type PackagesRegistry = Record<string, WorkspacePackageInfo>;\n\n/**\n * Build a list of all packages in the workspace, depending on the package\n * manager used, with a possible override from the config file. The list contains\n * the manifest with some directory info mapped by module name.\n */\nexport async function createPackagesRegistry(\n workspaceRootDir: string,\n workspacePackagesOverride: string[] | undefined\n): Promise<PackagesRegistry> {\n const log = createLogger(getConfig().logLevel);\n\n if (workspacePackagesOverride) {\n log.debug(\n `Override workspace packages via config: ${workspacePackagesOverride}`\n );\n }\n\n const packagesGlobs =\n workspacePackagesOverride ?? findPackagesGlobs(workspaceRootDir);\n\n const cwd = process.cwd();\n process.chdir(workspaceRootDir);\n\n const allPackages = packagesGlobs\n .flatMap((glob) => globSync(glob))\n /**\n * Make sure to filter any loose files that might hang around.\n */\n .filter((dir) => fs.lstatSync(dir).isDirectory());\n\n const registry: PackagesRegistry = (\n await Promise.all(\n allPackages.map(async (rootRelativeDir) => {\n const manifestPath = path.join(rootRelativeDir, \"package.json\");\n\n if (!fs.existsSync(manifestPath)) {\n log.warn(\n `Ignoring directory ${rootRelativeDir} because it does not contain a package.json file`\n );\n return;\n } else {\n log.debug(`Registering package ${rootRelativeDir}`);\n\n const manifest = await readTypedJson<PackageManifestMinimum>(\n path.join(rootRelativeDir, \"package.json\")\n );\n\n return {\n manifest,\n rootRelativeDir,\n absoluteDir: path.join(workspaceRootDir, rootRelativeDir),\n };\n }\n })\n )\n ).reduce<PackagesRegistry>(\n (acc, info) => (info ? set(acc, info.manifest.name, info) : acc),\n {}\n );\n\n process.chdir(cwd);\n\n return registry;\n}\n","import path from \"node:path\";\nimport {\n createLogger,\n inspectValue,\n readTypedJsonSync,\n readTypedYamlSync,\n} from \"~/utils\";\nimport { getConfig } from \"./config\";\nimport { detectPackageManager } from \"./detect-package-manager\";\n\n/**\n * Find the globs that define where the packages are located within the\n * monorepo. This configuration is dependent on the package manager used, and I\n * don't know if we're covering all cases yet...\n */\nexport function findPackagesGlobs(workspaceRootDir: string) {\n const log = createLogger(getConfig().logLevel);\n\n const packageManager = detectPackageManager(workspaceRootDir);\n\n switch (packageManager) {\n case \"pnpm\": {\n const { packages: globs } = readTypedYamlSync<{ packages: string[] }>(\n path.join(workspaceRootDir, \"pnpm-workspace.yaml\"),\n );\n\n log.debug(\"Detected pnpm packages globs:\", inspectValue(globs));\n return globs;\n }\n case \"yarn\":\n case \"npm\": {\n const workspaceRootManifestPath = path.join(\n workspaceRootDir,\n \"package.json\",\n );\n\n const { workspaces } = readTypedJsonSync<{ workspaces: string[] }>(\n workspaceRootManifestPath,\n );\n\n if (!workspaces) {\n throw new Error(\n `No workspaces field found in ${workspaceRootManifestPath}`,\n );\n }\n\n return workspaces;\n }\n }\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\n\nexport type PackageManager = \"pnpm\" | \"yarn\" | \"npm\";\n\nexport function detectPackageManager(workspaceRoot: string): PackageManager {\n if (fs.existsSync(path.join(workspaceRoot, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n\n if (fs.existsSync(path.join(workspaceRoot, \"yarn.lock\"))) {\n return \"yarn\";\n }\n\n if (fs.existsSync(path.join(workspaceRoot, \"package-lock.json\"))) {\n return \"npm\";\n }\n\n throw new Error(`Failed to detect package manager`);\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { an } from \"vitest/dist/types-e3c9754d\";\nimport { getConfig } from \"~/helpers\";\nimport { createLogger, readTypedJson } from \"~/utils\";\n\n/**\n * Find the build output dir by reading the tsconfig.json file or if that\n * doesn't exist by looking for a dist, build, or output directory.\n */\nexport async function findBuildOutputDir(targetPackageDir: string) {\n const config = getConfig();\n const log = createLogger(getConfig().logLevel);\n\n if (config.buildOutputDir) {\n log.debug(\"Using buildOutputDir from config:\", config.buildOutputDir);\n return path.join(targetPackageDir, config.buildOutputDir);\n }\n\n const tsconfigPath = path.join(targetPackageDir, config.tsconfigPath);\n\n if (fs.existsSync(tsconfigPath)) {\n const tsconfig = await readTypedJson<{\n compilerOptions?: { outDir?: string };\n }>(tsconfigPath);\n\n const outDir = tsconfig.compilerOptions?.outDir;\n\n if (outDir) {\n return path.join(targetPackageDir, outDir);\n }\n }\n\n log.error(`Failed to find outDir in tsconfig at ${tsconfigPath}\nWithout an isolate.config.json file specifying the buildOutputDir, or outDir provided by tsconfig, we can't know where the build output directory is located. Please configure one of these options.`);\n\n process.exit(1);\n\n // throw new Error(`Failed to find outDir in tsconfig at ${tsconfigPath}\n // Without an isolate.config.json file specifying the buildOutputDir, or outDir provided by tsconfig, we can't know where the build output directory is located. Please configure one of these options.`);\n}\n","import {\n PackageManifestMinimum,\n PackagesRegistry,\n} from \"./create-packages-registry\";\n\n/**\n * Recursively list the packages from dependencies (and optionally\n * devDependencies) that are found in the workspace.\n *\n * Here we do not need to rely on packages being declared as \"workspace:\" in the\n * manifest. We can simply compare the package names with the list of packages\n * that were found via the workspace glob patterns and added to the registry.\n */\nexport function listLocalDependencies(\n manifest: PackageManifestMinimum,\n packagesRegistry: PackagesRegistry,\n { includeDevDependencies = false } = {},\n): string[] {\n const allWorkspacePackageNames = Object.keys(packagesRegistry);\n\n const localDependencyPackageNames = (\n includeDevDependencies\n ? [\n ...Object.keys(manifest.dependencies ?? {}),\n ...Object.keys(manifest.devDependencies ?? {}),\n ]\n : Object.keys(manifest.dependencies ?? {})\n ).filter((name) => allWorkspacePackageNames.includes(name));\n\n const nestedLocalDependencies = localDependencyPackageNames.flatMap(\n (packageName) =>\n listLocalDependencies(\n packagesRegistry[packageName].manifest,\n packagesRegistry,\n { includeDevDependencies },\n ),\n );\n\n return localDependencyPackageNames.concat(nestedLocalDependencies);\n}\n","import path from \"node:path\";\nimport { readTypedJson } from \"~/utils\";\nimport { PackageManifestMinimum } from \"./create-packages-registry\";\n\nexport async function importManifest(packageDir: string) {\n return readTypedJson<PackageManifestMinimum>(\n path.join(packageDir, \"package.json\"),\n );\n}\n","import assert from \"node:assert\";\nimport { createLogger, pack } from \"~/utils\";\nimport { getConfig } from \"./config\";\nimport { PackagesRegistry } from \"./create-packages-registry\";\nimport { PackageManager } from \"./detect-package-manager\";\n\n/**\n * Pack dependencies so that we extract only the files that are supposed to be\n * published by the packages.\n *\n * @returns A map of package names to the path of the packed file\n */\nexport async function packDependencies({\n /**\n * All packages found in the monorepo by workspaces declaration\n */\n packagesRegistry,\n /**\n * The package names that appear to be local dependencies\n */\n localDependencies,\n /**\n * The directory where the isolated package and all its dependencies will end\n * up. This is also the directory from where the package will be deployed. By\n * default it is a subfolder in targetPackageDir called \"isolate\" but you can\n * configure it.\n */\n packDestinationDir,\n\n packageManager,\n}: {\n packagesRegistry: PackagesRegistry;\n localDependencies: string[];\n packDestinationDir: string;\n packageManager: PackageManager;\n}) {\n const config = getConfig();\n const log = createLogger(config.logLevel);\n\n const packedFileByName: Record<string, string> = {};\n\n for (const dependency of localDependencies) {\n const def = packagesRegistry[dependency];\n\n assert(dependency, `Failed to find package definition for ${dependency}`);\n\n const { name } = def.manifest;\n\n /**\n * If this dependency has already been packed, we skip it. It could happen\n * because we are packing workspace dependencies recursively.\n */\n if (packedFileByName[name]) {\n log.debug(`Skipping ${name} because it has already been packed`);\n continue;\n }\n\n packedFileByName[name] = await pack(\n def.absoluteDir,\n packDestinationDir,\n packageManager,\n );\n\n /**\n * @TODO call recursively\n */\n }\n\n return packedFileByName;\n}\n","import { createLogger } from \"~/utils\";\nimport { getConfig } from \"./config\";\nimport { PackagesRegistry } from \"./create-packages-registry\";\n\nexport function patchWorkspaceEntries(\n dependencies: Record<string, string>,\n packagesRegistry: PackagesRegistry,\n) {\n const log = createLogger(getConfig().logLevel);\n const allWorkspacePackageNames = Object.keys(packagesRegistry);\n\n return Object.fromEntries(\n Object.entries(dependencies).map(([key, value]) => {\n if (allWorkspacePackageNames.includes(key)) {\n const def = packagesRegistry[key];\n\n /**\n * The rootRelativeDir is the package location in the monorepo. In the\n * isolate folder we keep the same structure so we can use the same\n * relative path.\n */\n log.debug(`Linking dependency ${key} to file:${def.rootRelativeDir}`);\n\n return [key, `file:${def.rootRelativeDir}`];\n } else {\n return [key, value];\n }\n }),\n );\n}\n","import fs from \"fs-extra\";\nimport path from \"node:path\";\nimport { PackageManager } from \"~/helpers\";\nimport { pack, unpack } from \"~/utils\";\n\nexport async function processBuildOutputFiles({\n targetPackageDir,\n tmpDir,\n packageManager,\n isolateDir,\n}: {\n targetPackageDir: string;\n tmpDir: string;\n packageManager: PackageManager;\n isolateDir: string;\n}) {\n const packedFilePath = await pack(targetPackageDir, tmpDir, packageManager);\n const unpackDir = path.join(tmpDir, \"target\");\n await unpack(packedFilePath, unpackDir);\n await fs.copy(path.join(unpackDir, \"package\"), isolateDir);\n}\n","import fs from \"fs-extra\";\nimport assert from \"node:assert\";\nimport path from \"node:path\";\nimport { createLogger, readTypedYamlSync, writeTypedYamlSync } from \"~/utils\";\nimport { getConfig } from \"./config\";\nimport { PackagesRegistry } from \"./create-packages-registry\";\nimport { PackageManager } from \"./detect-package-manager\";\n\ntype PackagePath = string;\n\ntype PnpmLockfile = {\n lockfileVersion: string;\n importers: Record<\n PackagePath,\n {\n dependencies?: Record<string, unknown>;\n devDependencies?: Record<string, unknown>;\n }\n >;\n};\n\nexport function getLockfileFileName(packageManager: PackageManager) {\n switch (packageManager) {\n case \"pnpm\":\n return \"pnpm-lock.yaml\";\n case \"yarn\":\n return \"yarn.lock\";\n case \"npm\":\n return \"package-lock.json\";\n }\n}\n\n/**\n * Adapt the lockfile and write it to the isolate directory. Because we keep the\n * structure of packages in the isolate directory the same as they were in the\n * monorepo, the lockfile is largely still correct. The only things that need to\n * be done is to remove the root dependencies and devDependencies, and rename\n * the path to the target package to act as the new root.\n */\nexport function processLockfile({\n workspaceRootDir,\n targetPackageName,\n packagesRegistry,\n isolateDir,\n packageManager,\n}: {\n workspaceRootDir: string;\n targetPackageName: string;\n packagesRegistry: PackagesRegistry;\n isolateDir: string;\n packageManager: PackageManager;\n}) {\n const log = createLogger(getConfig().logLevel);\n\n const targetPackageRelativeDir =\n packagesRegistry[targetPackageName].rootRelativeDir;\n\n const fileName = getLockfileFileName(packageManager);\n\n const lockfileSrcPath = path.join(workspaceRootDir, fileName);\n const lockfileDstPath = path.join(isolateDir, fileName);\n\n switch (packageManager) {\n /**\n * It seems that for Yarn v1 and NPM v3 lockfile the content is not\n * dependent on the workspace packages structure, so I am assuming we can\n * just copy it over.\n */\n case \"npm\":\n case \"yarn\": {\n fs.copyFileSync(lockfileSrcPath, lockfileDstPath);\n log.debug(\"Copied lockfile to\", lockfileDstPath);\n return;\n }\n case \"pnpm\": {\n const origLockfile = readTypedYamlSync<PnpmLockfile>(lockfileSrcPath);\n\n log.debug(\"Read PNPM lockfile, version:\", origLockfile.lockfileVersion);\n\n const adaptedLockfile = structuredClone(origLockfile);\n\n const targetPackageDef =\n adaptedLockfile.importers[targetPackageRelativeDir];\n\n assert(\n targetPackageDef,\n `Failed to find target package in lockfile at importers[${targetPackageRelativeDir}]`\n );\n /**\n * Overwrite the root importer with the target package importer contents\n */\n adaptedLockfile.importers[\".\"] = targetPackageDef;\n\n /**\n * Delete the target package original importer. Not really necessary.\n */\n delete adaptedLockfile.importers[targetPackageRelativeDir];\n\n writeTypedYamlSync(lockfileDstPath, adaptedLockfile);\n\n log.debug(\"Stored adapted lockfile at\", lockfileDstPath);\n\n return;\n }\n\n // case \"npm\": {\n // /**\n // * Assuming a v3 lockfile.\n // */\n // const origLockfile = readTypedJsonSync<NpmLockfile_v3>(lockfileSrcPath);\n\n // /**\n // * Overwrite the root importer with the target package importer contents\n // */\n // const adaptedLockfile = structuredClone(origLockfile);\n\n // const targetPackageDef =\n // adaptedLockfile.packages[targetPackageRelativeDir];\n\n // assert(\n // targetPackageDef,\n // `Failed to find target package in lockfile at packages[${targetPackageRelativeDir}]`\n // );\n\n // /**\n // * The root in the NPM lockfile seems to be marked by an empty string\n // */\n // adaptedLockfile.packages[\"\"] = targetPackageDef;\n\n // /**\n // * Delete the target package original importer. Not really necessary.\n // */\n // delete adaptedLockfile.packages[targetPackageRelativeDir];\n\n // writeTypedYamlSync(lockfileDstPath, adaptedLockfile);\n\n // log.debug(\"Stored adapted lockfile at\", lockfileDstPath);\n // }\n }\n}\n","import fs from \"fs-extra\";\nimport path, { join } from \"node:path\";\nimport { getRelativePath } from \"~/utils\";\nimport { createLogger } from \"~/utils/logger\";\nimport { PackagesRegistry, getConfig } from \".\";\nimport { unpack } from \"../utils/unpack\";\n\nexport async function unpackDependencies(\n packedFilesByName: Record<string, string>,\n packagesRegistry: PackagesRegistry,\n tmpDir: string,\n isolateDir: string,\n) {\n const log = createLogger(getConfig().logLevel);\n await Promise.all(\n Object.entries(packedFilesByName).map(async ([packageName, filePath]) => {\n const dir = packagesRegistry[packageName].rootRelativeDir;\n\n const unpackDir = join(tmpDir, dir);\n\n await unpack(filePath, unpackDir);\n\n log.debug(\"Unpacked\", path.basename(filePath));\n\n const destinationDir = join(isolateDir, dir);\n\n await fs.ensureDir(destinationDir);\n\n await fs.move(join(unpackDir, \"package\"), destinationDir, {\n overwrite: true,\n });\n\n log.debug(\n `Moved package files to isolate ${getRelativePath(\n destinationDir,\n isolateDir,\n )}`,\n );\n }),\n );\n}\n"],"mappings":"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","names":["fs","assert","path","path","fs","path","log","stdout","path","fs","fs","fs","path","fs","path","fs","path","log","path","fs","config","fs","path","path","fs","path","log","path","log","fs","path","fs","path","process","config","log","path","fs","process","path","config","log","log","fs","path","path","fs","fs","assert","path","log","path","fs","assert","fs","path","log","path","fs","assert","fs","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isolate-package",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.10",
4
4
  "description": "Isolate a monorepo package by bundling the build output with its shared workspace packages and lock file to form a self-contained directory.",
5
5
  "author": "Thijs Koerselman",
6
6
  "license": "MIT",
@@ -17,12 +17,12 @@
17
17
  "npm"
18
18
  ],
19
19
  "type": "module",
20
- "module": "dist/index.js",
20
+ "module": "dist/index.mjs",
21
21
  "files": [
22
22
  "dist"
23
23
  ],
24
24
  "bin": {
25
- "isolate": "dist/index.js"
25
+ "isolate": "dist/index.mjs"
26
26
  },
27
27
  "dependencies": {
28
28
  "chalk": "^5.2.0",
@@ -41,6 +41,7 @@
41
41
  "@types/tar-fs": "^2.0.1",
42
42
  "tsup": "^6.7.0",
43
43
  "type-fest": "^3.9.0",
44
+ "typescript": "^5.0.4",
44
45
  "vitest": "^0.30.1"
45
46
  },
46
47
  "scripts": {