slim-package-json 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.prettierrc ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "tabWidth": 4,
3
+ "useTabs": false,
4
+ "trailingComma": "all",
5
+ "singleQuote": true
6
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
4
+ }
package/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Slim Package Json
2
+
3
+ A cli tool for creating generating a package.json for containers that only includes the dependencies that were actually used
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # global install
9
+ npm i -g slim-package-json
10
+
11
+ # local install
12
+ npm i slim-package-json
13
+ ```
14
+
15
+ ## Cli-Usage
16
+
17
+ ```bash
18
+ # get complete list of options
19
+ slim-package-json --help
20
+
21
+ # basic usage
22
+ slim-package-json --package-json ./package.json --dir ./path/to/output/dir
23
+ slim-package-json -P ./package.json -D ./path/to/output/dir
24
+
25
+ # 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
+ ```
29
+
30
+ ## TS Usage
31
+
32
+ ```ts
33
+ import { generatePackageJson } from 'slim-package-json';
34
+
35
+ generatePackageJson({
36
+ packageJson: './package.json',
37
+ dir: './path/to/output/dir',
38
+ });
39
+ ```
@@ -0,0 +1,10 @@
1
+ import { defineBuildConfig } from 'unbuild';
2
+
3
+ export default defineBuildConfig({
4
+ entries: ['./src/index.ts', './src/cli.ts'],
5
+ outDir: 'dist',
6
+ declaration: true,
7
+ rollup: {
8
+ emitCJS: true,
9
+ },
10
+ });
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "slim-package-json",
3
+ "version": "0.1.0",
4
+ "description": "A cli tool for creating generating a package.json for containers that only includes the dependencies that were actually used",
5
+ "main": "./dist/index.mjs",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.cjs",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "keywords": [],
16
+ "author": "joshmossas",
17
+ "license": "MIT",
18
+ "dependencies": {
19
+ "citty": "^0.2.2",
20
+ "globby": "^16.2.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^25.6.0",
24
+ "prettier": "^3.8.2",
25
+ "unbuild": "^3.6.1"
26
+ },
27
+ "scripts": {
28
+ "build": "unbuild"
29
+ }
30
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { defineCommand, runMain } from 'citty';
2
+ import { generateSlimPackageJson } from '.';
3
+
4
+ const slimPackageJson = defineCommand({
5
+ args: {
6
+ dir: {
7
+ type: 'string',
8
+ alias: 'D',
9
+ required: true,
10
+ description: 'The directory where the built js/ts files are',
11
+ },
12
+ packageJson: {
13
+ type: 'string',
14
+ alias: 'P',
15
+ required: true,
16
+ description:
17
+ 'Location of your package.json that contains all the potential dependencies. Usually this is at the monorepo root.',
18
+ },
19
+ childPackageJson: {
20
+ type: 'string',
21
+ alias: 'C',
22
+ 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
+ },
25
+ },
26
+ async run({ args }) {
27
+ return generateSlimPackageJson(args);
28
+ },
29
+ });
30
+
31
+ void runMain(slimPackageJson);
package/src/index.ts ADDED
@@ -0,0 +1,111 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import { globby } from 'globby';
3
+ import path from 'path';
4
+
5
+ export type PackageJson = {
6
+ [key: string]: unknown;
7
+ dependencies?: Record<string, string>;
8
+ devDependencies?: Record<string, string>;
9
+ };
10
+
11
+ export type GeneratePackageJsonArgs = {
12
+ /**
13
+ * The package json containing all the potential dependencies
14
+ */
15
+ packageJson: string;
16
+ /**
17
+ * package.json of a sub package in the monorepo that you want to inherit properties from
18
+ */
19
+ childPackageJson?: string;
20
+ /**
21
+ * directory to check for used dependencies
22
+ */
23
+ dir: string;
24
+ };
25
+
26
+ export async function generateSlimPackageJson(args: GeneratePackageJsonArgs) {
27
+ console.info(`Loading file(s)`);
28
+ const workspacePackageJson = JSON.parse(
29
+ await readFile(path.resolve(args.packageJson), {
30
+ encoding: 'utf8',
31
+ }),
32
+ ) as PackageJson;
33
+ const projectPackageJson = args.childPackageJson
34
+ ? (JSON.parse(
35
+ await readFile(path.resolve(args.childPackageJson), {
36
+ encoding: 'utf8',
37
+ }),
38
+ ) as PackageJson)
39
+ : {};
40
+ const files = await globby(
41
+ [
42
+ '**/*.js',
43
+ '**/*.jsx',
44
+ '**/*.ts',
45
+ '**/*.tsx',
46
+ '**/*.mjs',
47
+ '**/*.mts',
48
+ '**/*.cjs',
49
+ '**/*.cts',
50
+ ],
51
+ { cwd: path.resolve(args.dir) },
52
+ );
53
+ console.info(`Found ${files.length} file(s)`);
54
+ console.info(`Detecting used dependencies`);
55
+ const tasks = files.map(async (file) => {
56
+ const fileContent = await readFile(path.resolve(args.dir, file), {
57
+ encoding: 'utf8',
58
+ });
59
+ addUsedDependencies(
60
+ fileContent,
61
+ workspacePackageJson,
62
+ projectPackageJson,
63
+ );
64
+ });
65
+ await Promise.all(tasks);
66
+ console.info(
67
+ `Detected ${Object.keys(projectPackageJson.dependencies ?? {}).length} used dependencies`,
68
+ );
69
+ const outputFile = path.resolve(args.dir, 'package.json');
70
+ await writeFile(outputFile, JSON.stringify(projectPackageJson), {
71
+ encoding: 'utf8',
72
+ });
73
+ console.info(`Successfully wrote package.json to ${outputFile}`);
74
+ }
75
+
76
+ function addUsedDependencies(
77
+ fileContent: string,
78
+ rootPackageJson: PackageJson,
79
+ childPackageJson: PackageJson,
80
+ ) {
81
+ for (const [key, val] of Object.entries(
82
+ rootPackageJson.dependencies ?? {},
83
+ )) {
84
+ if (
85
+ fileContent.includes(`from '${key}`) ||
86
+ fileContent.includes(`from "${key}`) ||
87
+ fileContent.includes(`require('${key}`) ||
88
+ fileContent.includes(`require("${key})`)
89
+ ) {
90
+ if (!childPackageJson.dependencies) {
91
+ childPackageJson.dependencies = {};
92
+ }
93
+ childPackageJson.dependencies[key] = val;
94
+ }
95
+ }
96
+ for (const [key, val] of Object.entries(
97
+ rootPackageJson.devDependencies ?? {},
98
+ )) {
99
+ if (
100
+ fileContent.includes(`from '${key}`) ||
101
+ fileContent.includes(`from "${key}`) ||
102
+ fileContent.includes(`require('${key}`) ||
103
+ fileContent.includes(`require("${key})`)
104
+ ) {
105
+ if (!childPackageJson.dependencies) {
106
+ childPackageJson.dependencies = {};
107
+ }
108
+ childPackageJson.dependencies[key] = val;
109
+ }
110
+ }
111
+ }