slim-package-json 0.1.0 → 0.1.2

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,6 +1,6 @@
1
1
  # Slim Package Json
2
2
 
3
- A cli tool for creating generating a package.json for containers that only includes the dependencies that were actually used
3
+ A cli tool for creating generating a package.json for docker containers (or other environments) that only includes the dependencies that were actually used
4
4
 
5
5
  ## Installation
6
6
 
@@ -19,12 +19,14 @@ npm i slim-package-json
19
19
  slim-package-json --help
20
20
 
21
21
  # basic usage
22
+ # specify the package json w/ the dependencies and the directory
23
+ # where the built/bundled files are
22
24
  slim-package-json --package-json ./package.json --dir ./path/to/output/dir
23
- slim-package-json -P ./package.json -D ./path/to/output/dir
25
+ slim-package-json -P ./package.json -D ./path/to/build/dir
24
26
 
25
27
  # inherit properties from a child package.json
26
- slim-package-json --package-json ./package.json --child-package-json ./apps/foo/package.json --dir ./apps/foo/dist
27
- slim-package-json -P ./package.json -C ./apps/foo/package.json -D ./apps/foo/dist
28
+ slim-package-json --package-json ./package.json --extend-from ./apps/foo/package.json --dir ./apps/foo/dist
29
+ slim-package-json -P ./package.json -E ./apps/foo/package.json -D ./apps/foo/dist
28
30
  ```
29
31
 
30
32
  ## TS Usage
package/dist/cli.cjs ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const citty = require('citty');
5
+ const index = require('./index.cjs');
6
+ require('fs/promises');
7
+ require('globby');
8
+ require('path');
9
+
10
+ const slimPackageJson = citty.defineCommand({
11
+ args: {
12
+ dir: {
13
+ type: "string",
14
+ alias: "D",
15
+ required: true,
16
+ description: "The directory where the built js/ts files are"
17
+ },
18
+ packageJson: {
19
+ type: "string",
20
+ alias: "P",
21
+ required: true,
22
+ description: "Location of your package.json that contains all the potential dependencies. Usually this is at the monorepo root."
23
+ },
24
+ extendFrom: {
25
+ type: "string",
26
+ alias: "E",
27
+ description: "A package.json that you want to inherit properties from"
28
+ }
29
+ },
30
+ async run({ args }) {
31
+ return index.generateSlimPackageJson(args);
32
+ }
33
+ });
34
+ void citty.runMain(slimPackageJson);
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+
package/dist/cli.mjs ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { defineCommand, runMain } from 'citty';
3
+ import { generateSlimPackageJson } from './index.mjs';
4
+ import 'fs/promises';
5
+ import 'globby';
6
+ import 'path';
7
+
8
+ const slimPackageJson = defineCommand({
9
+ args: {
10
+ dir: {
11
+ type: "string",
12
+ alias: "D",
13
+ required: true,
14
+ description: "The directory where the built js/ts files are"
15
+ },
16
+ packageJson: {
17
+ type: "string",
18
+ alias: "P",
19
+ required: true,
20
+ description: "Location of your package.json that contains all the potential dependencies. Usually this is at the monorepo root."
21
+ },
22
+ extendFrom: {
23
+ type: "string",
24
+ alias: "E",
25
+ description: "A package.json that you want to inherit properties from"
26
+ }
27
+ },
28
+ async run({ args }) {
29
+ return generateSlimPackageJson(args);
30
+ }
31
+ });
32
+ void runMain(slimPackageJson);
package/dist/index.cjs ADDED
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ const promises = require('fs/promises');
4
+ const globby = require('globby');
5
+ const path = require('path');
6
+
7
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
8
+
9
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
10
+
11
+ async function generateSlimPackageJson(args) {
12
+ console.info(`Loading file(s)`);
13
+ const workspacePackageJson = JSON.parse(
14
+ await promises.readFile(path__default.resolve(args.packageJson), {
15
+ encoding: "utf8"
16
+ })
17
+ );
18
+ const projectPackageJson = args.extendFrom ? JSON.parse(
19
+ await promises.readFile(path__default.resolve(args.extendFrom), {
20
+ encoding: "utf8"
21
+ })
22
+ ) : {};
23
+ const files = await globby.globby(
24
+ [
25
+ "**/*.js",
26
+ "**/*.jsx",
27
+ "**/*.ts",
28
+ "**/*.tsx",
29
+ "**/*.mjs",
30
+ "**/*.mts",
31
+ "**/*.cjs",
32
+ "**/*.cts"
33
+ ],
34
+ { cwd: path__default.resolve(args.dir) }
35
+ );
36
+ console.info(`Found ${files.length} file(s)`);
37
+ console.info(`Detecting used dependencies`);
38
+ const tasks = files.map(async (file) => {
39
+ const fileContent = await promises.readFile(path__default.resolve(args.dir, file), {
40
+ encoding: "utf8"
41
+ });
42
+ addUsedDependencies(
43
+ fileContent,
44
+ workspacePackageJson,
45
+ projectPackageJson
46
+ );
47
+ });
48
+ await Promise.all(tasks);
49
+ console.info(
50
+ `Detected ${Object.keys(projectPackageJson.dependencies ?? {}).length} used dependencies`
51
+ );
52
+ const outputFile = path__default.resolve(args.dir, "package.json");
53
+ await promises.writeFile(outputFile, JSON.stringify(projectPackageJson), {
54
+ encoding: "utf8"
55
+ });
56
+ console.info(`Successfully wrote package.json to ${outputFile}`);
57
+ }
58
+ function addUsedDependencies(fileContent, rootPackageJson, childPackageJson) {
59
+ for (const [key, val] of Object.entries(
60
+ rootPackageJson.dependencies ?? {}
61
+ )) {
62
+ if (fileContent.includes(`from '${key}`) || fileContent.includes(`from "${key}`) || fileContent.includes(`require('${key}`) || fileContent.includes(`require("${key}`)) {
63
+ if (!childPackageJson.dependencies) {
64
+ childPackageJson.dependencies = {};
65
+ }
66
+ childPackageJson.dependencies[key] = val;
67
+ }
68
+ }
69
+ for (const [key, val] of Object.entries(
70
+ rootPackageJson.devDependencies ?? {}
71
+ )) {
72
+ if (fileContent.includes(`from '${key}`) || fileContent.includes(`from "${key}`) || fileContent.includes(`require('${key}`) || fileContent.includes(`require("${key})`)) {
73
+ if (!childPackageJson.dependencies) {
74
+ childPackageJson.dependencies = {};
75
+ }
76
+ childPackageJson.dependencies[key] = val;
77
+ }
78
+ }
79
+ }
80
+
81
+ exports.addUsedDependencies = addUsedDependencies;
82
+ exports.generateSlimPackageJson = generateSlimPackageJson;
@@ -0,0 +1,28 @@
1
+ type PackageJson = {
2
+ [key: string]: unknown;
3
+ dependencies?: Record<string, string>;
4
+ devDependencies?: Record<string, string>;
5
+ };
6
+ type GeneratePackageJsonArgs = {
7
+ /**
8
+ * The package json containing all the potential dependencies
9
+ */
10
+ packageJson: string;
11
+ /**
12
+ * Path to a package.json that you want to inherit properties from.
13
+ *
14
+ * You might use this in a monorepo where all the dependencies are listed at the root but
15
+ * you have properties specific to one package in that package's directory that you want
16
+ * to preserve (such as engines, type, name, version, etc)
17
+ */
18
+ extendFrom?: string;
19
+ /**
20
+ * directory to check for used dependencies
21
+ */
22
+ dir: string;
23
+ };
24
+ declare function generateSlimPackageJson(args: GeneratePackageJsonArgs): Promise<void>;
25
+ declare function addUsedDependencies(fileContent: string, rootPackageJson: PackageJson, childPackageJson: PackageJson): void;
26
+
27
+ export { addUsedDependencies, generateSlimPackageJson };
28
+ export type { GeneratePackageJsonArgs, PackageJson };
@@ -0,0 +1,28 @@
1
+ type PackageJson = {
2
+ [key: string]: unknown;
3
+ dependencies?: Record<string, string>;
4
+ devDependencies?: Record<string, string>;
5
+ };
6
+ type GeneratePackageJsonArgs = {
7
+ /**
8
+ * The package json containing all the potential dependencies
9
+ */
10
+ packageJson: string;
11
+ /**
12
+ * Path to a package.json that you want to inherit properties from.
13
+ *
14
+ * You might use this in a monorepo where all the dependencies are listed at the root but
15
+ * you have properties specific to one package in that package's directory that you want
16
+ * to preserve (such as engines, type, name, version, etc)
17
+ */
18
+ extendFrom?: string;
19
+ /**
20
+ * directory to check for used dependencies
21
+ */
22
+ dir: string;
23
+ };
24
+ declare function generateSlimPackageJson(args: GeneratePackageJsonArgs): Promise<void>;
25
+ declare function addUsedDependencies(fileContent: string, rootPackageJson: PackageJson, childPackageJson: PackageJson): void;
26
+
27
+ export { addUsedDependencies, generateSlimPackageJson };
28
+ export type { GeneratePackageJsonArgs, PackageJson };
@@ -0,0 +1,28 @@
1
+ type PackageJson = {
2
+ [key: string]: unknown;
3
+ dependencies?: Record<string, string>;
4
+ devDependencies?: Record<string, string>;
5
+ };
6
+ type GeneratePackageJsonArgs = {
7
+ /**
8
+ * The package json containing all the potential dependencies
9
+ */
10
+ packageJson: string;
11
+ /**
12
+ * Path to a package.json that you want to inherit properties from.
13
+ *
14
+ * You might use this in a monorepo where all the dependencies are listed at the root but
15
+ * you have properties specific to one package in that package's directory that you want
16
+ * to preserve (such as engines, type, name, version, etc)
17
+ */
18
+ extendFrom?: string;
19
+ /**
20
+ * directory to check for used dependencies
21
+ */
22
+ dir: string;
23
+ };
24
+ declare function generateSlimPackageJson(args: GeneratePackageJsonArgs): Promise<void>;
25
+ declare function addUsedDependencies(fileContent: string, rootPackageJson: PackageJson, childPackageJson: PackageJson): void;
26
+
27
+ export { addUsedDependencies, generateSlimPackageJson };
28
+ export type { GeneratePackageJsonArgs, PackageJson };
package/dist/index.mjs ADDED
@@ -0,0 +1,75 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import { globby } from 'globby';
3
+ import path from 'path';
4
+
5
+ async function generateSlimPackageJson(args) {
6
+ console.info(`Loading file(s)`);
7
+ const workspacePackageJson = JSON.parse(
8
+ await readFile(path.resolve(args.packageJson), {
9
+ encoding: "utf8"
10
+ })
11
+ );
12
+ const projectPackageJson = args.extendFrom ? JSON.parse(
13
+ await readFile(path.resolve(args.extendFrom), {
14
+ encoding: "utf8"
15
+ })
16
+ ) : {};
17
+ const files = await globby(
18
+ [
19
+ "**/*.js",
20
+ "**/*.jsx",
21
+ "**/*.ts",
22
+ "**/*.tsx",
23
+ "**/*.mjs",
24
+ "**/*.mts",
25
+ "**/*.cjs",
26
+ "**/*.cts"
27
+ ],
28
+ { cwd: path.resolve(args.dir) }
29
+ );
30
+ console.info(`Found ${files.length} file(s)`);
31
+ console.info(`Detecting used dependencies`);
32
+ const tasks = files.map(async (file) => {
33
+ const fileContent = await readFile(path.resolve(args.dir, file), {
34
+ encoding: "utf8"
35
+ });
36
+ addUsedDependencies(
37
+ fileContent,
38
+ workspacePackageJson,
39
+ projectPackageJson
40
+ );
41
+ });
42
+ await Promise.all(tasks);
43
+ console.info(
44
+ `Detected ${Object.keys(projectPackageJson.dependencies ?? {}).length} used dependencies`
45
+ );
46
+ const outputFile = path.resolve(args.dir, "package.json");
47
+ await writeFile(outputFile, JSON.stringify(projectPackageJson), {
48
+ encoding: "utf8"
49
+ });
50
+ console.info(`Successfully wrote package.json to ${outputFile}`);
51
+ }
52
+ function addUsedDependencies(fileContent, rootPackageJson, childPackageJson) {
53
+ for (const [key, val] of Object.entries(
54
+ rootPackageJson.dependencies ?? {}
55
+ )) {
56
+ if (fileContent.includes(`from '${key}`) || fileContent.includes(`from "${key}`) || fileContent.includes(`require('${key}`) || fileContent.includes(`require("${key}`)) {
57
+ if (!childPackageJson.dependencies) {
58
+ childPackageJson.dependencies = {};
59
+ }
60
+ childPackageJson.dependencies[key] = val;
61
+ }
62
+ }
63
+ for (const [key, val] of Object.entries(
64
+ rootPackageJson.devDependencies ?? {}
65
+ )) {
66
+ if (fileContent.includes(`from '${key}`) || fileContent.includes(`from "${key}`) || fileContent.includes(`require('${key}`) || fileContent.includes(`require("${key})`)) {
67
+ if (!childPackageJson.dependencies) {
68
+ childPackageJson.dependencies = {};
69
+ }
70
+ childPackageJson.dependencies[key] = val;
71
+ }
72
+ }
73
+ }
74
+
75
+ export { addUsedDependencies, generateSlimPackageJson };
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "slim-package-json",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A cli tool for creating generating a package.json for containers that only includes the dependencies that were actually used",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
7
7
  "type": "module",
8
+ "bin": {
9
+ "slim-package-json": "./dist/cli.mjs"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
13
  "import": "./dist/index.mjs",
@@ -22,7 +25,8 @@
22
25
  "devDependencies": {
23
26
  "@types/node": "^25.6.0",
24
27
  "prettier": "^3.8.2",
25
- "unbuild": "^3.6.1"
28
+ "unbuild": "^3.6.1",
29
+ "vitest": "^4.1.4"
26
30
  },
27
31
  "scripts": {
28
32
  "build": "unbuild"
@@ -0,0 +1,2 @@
1
+ allowBuilds:
2
+ esbuild: true
package/src/cli.ts CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import { defineCommand, runMain } from 'citty';
2
3
  import { generateSlimPackageJson } from '.';
3
4
 
@@ -16,11 +17,11 @@ const slimPackageJson = defineCommand({
16
17
  description:
17
18
  'Location of your package.json that contains all the potential dependencies. Usually this is at the monorepo root.',
18
19
  },
19
- childPackageJson: {
20
+ extendFrom: {
20
21
  type: 'string',
21
- alias: 'C',
22
+ alias: 'E',
22
23
  description:
23
- 'Location of the package.json for the child project within the monorepo. If specified the generated package json will inherit all the properties from this package json.',
24
+ 'A package.json that you want to inherit properties from',
24
25
  },
25
26
  },
26
27
  async run({ args }) {
@@ -0,0 +1,45 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { addUsedDependencies, PackageJson } from '.';
3
+
4
+ describe('addUsedDependencies', () => {
5
+ test('esm imports', () => {
6
+ const filecontents = [
7
+ `import {foo} from 'foo';`,
8
+ `import { bar } from "bar";`,
9
+ ];
10
+ const packageJson: PackageJson = {
11
+ dependencies: {
12
+ foo: '1.0.0',
13
+ bar: '1.1.1',
14
+ baz: '2.68.0-beta2',
15
+ },
16
+ };
17
+ const projectPackageJson: PackageJson = {};
18
+ for (const content of filecontents) {
19
+ addUsedDependencies(content, packageJson, projectPackageJson);
20
+ }
21
+ expect(projectPackageJson).toStrictEqual({
22
+ dependencies: { foo: '1.0.0', bar: '1.1.1' },
23
+ });
24
+ });
25
+ test('cjs require()', () => {
26
+ const filecontents = [
27
+ `const foo = require('foo');`,
28
+ `const bar = require("bar");`,
29
+ ];
30
+ const packageJson: PackageJson = {
31
+ dependencies: {
32
+ foo: '1.0.0',
33
+ bar: '1.1.1',
34
+ baz: '2.68.0-beta2',
35
+ },
36
+ };
37
+ const projectPackageJson: PackageJson = {};
38
+ for (const content of filecontents) {
39
+ addUsedDependencies(content, packageJson, projectPackageJson);
40
+ }
41
+ expect(projectPackageJson).toStrictEqual({
42
+ dependencies: { foo: '1.0.0', bar: '1.1.1' },
43
+ });
44
+ });
45
+ });
package/src/index.ts CHANGED
@@ -14,9 +14,13 @@ export type GeneratePackageJsonArgs = {
14
14
  */
15
15
  packageJson: string;
16
16
  /**
17
- * package.json of a sub package in the monorepo that you want to inherit properties from
17
+ * Path to a package.json that you want to inherit properties from.
18
+ *
19
+ * You might use this in a monorepo where all the dependencies are listed at the root but
20
+ * you have properties specific to one package in that package's directory that you want
21
+ * to preserve (such as engines, type, name, version, etc)
18
22
  */
19
- childPackageJson?: string;
23
+ extendFrom?: string;
20
24
  /**
21
25
  * directory to check for used dependencies
22
26
  */
@@ -30,9 +34,9 @@ export async function generateSlimPackageJson(args: GeneratePackageJsonArgs) {
30
34
  encoding: 'utf8',
31
35
  }),
32
36
  ) as PackageJson;
33
- const projectPackageJson = args.childPackageJson
37
+ const projectPackageJson = args.extendFrom
34
38
  ? (JSON.parse(
35
- await readFile(path.resolve(args.childPackageJson), {
39
+ await readFile(path.resolve(args.extendFrom), {
36
40
  encoding: 'utf8',
37
41
  }),
38
42
  ) as PackageJson)
@@ -73,7 +77,7 @@ export async function generateSlimPackageJson(args: GeneratePackageJsonArgs) {
73
77
  console.info(`Successfully wrote package.json to ${outputFile}`);
74
78
  }
75
79
 
76
- function addUsedDependencies(
80
+ export function addUsedDependencies(
77
81
  fileContent: string,
78
82
  rootPackageJson: PackageJson,
79
83
  childPackageJson: PackageJson,
@@ -85,7 +89,7 @@ function addUsedDependencies(
85
89
  fileContent.includes(`from '${key}`) ||
86
90
  fileContent.includes(`from "${key}`) ||
87
91
  fileContent.includes(`require('${key}`) ||
88
- fileContent.includes(`require("${key})`)
92
+ fileContent.includes(`require("${key}`)
89
93
  ) {
90
94
  if (!childPackageJson.dependencies) {
91
95
  childPackageJson.dependencies = {};