@procore/hammer-lib-tsup 0.6.0 → 0.7.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @procore/hammer-lib-tsup
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 59a4b08: Upgrades tsup, esbuild, and other dependencies.
8
+ - 32ad5d2: Add validate command to libs-tsup
9
+
10
+ ### Patch Changes
11
+
12
+ - 59a4b08: Upgrades `picocolors` to 1.1.1.
13
+ - 5dd6e18: Fixes interface for `lib:validate` command.
14
+ - Updated dependencies [59a4b08]
15
+ - Updated dependencies [59a4b08]
16
+ - Updated dependencies [5dd6e18]
17
+ - Updated dependencies [32ad5d2]
18
+ - @procore/hammer-utils@0.2.0
19
+ - @procore/hammer-types@0.5.1
20
+
3
21
  ## 0.6.0
4
22
 
5
23
  ### Minor Changes
package/README.md CHANGED
@@ -46,9 +46,25 @@ This project uses [`yarn`][yarn], and supports the following commands:
46
46
  - `lint:types`: uses [`TypeScript`][typescript] to validate types.
47
47
  - `test`: runs the unit test suite.
48
48
  - `test:ci`: run the unit test suite, reporting coverage.
49
+ - `lib:build --analyze`: builds the library and generates metadata for bundle analysis.
49
50
 
51
+ ### Using `lib:build --analyze`
52
+
53
+ When you run `hammer lib:build --analyze`, it generates the following output files:
54
+
55
+ - `metafile-esm.json`: Metadata for the ESM (ECMAScript Module) output.
56
+ - `metafile-cjs.json`: Metadata for the CJS (CommonJS) output.
57
+
58
+ These files can be used to analyze the bundle, understand the size of individual modules, and identify optimizations.
59
+
60
+ For more detailed information on how the metadata works, refer to the [Tsup Metafile Documentation][tsup-metafile].
61
+
62
+ Additionally, you can use tools like [Bundle Buddy][bundle-buddy] to visualize the output and track down duplicate dependencies or optimize your bundle for better performance.
63
+
64
+ [bundle-buddy]: https://www.bundle-buddy.com/esbuild
50
65
  [eslint]: https://eslint.org/
51
66
  [prettier]: https://prettier.io/
52
67
  [tsup]: https://tsup.egoist.dev/
68
+ [tsup-metafile]: https://tsup.egoist.dev/#metafile
53
69
  [typescript]: https://www.typescriptlang.org/
54
70
  [yarn]: https://classic.yarnpkg.com/
package/dist/index.js CHANGED
@@ -148,10 +148,138 @@ async function performBuild(buildOptions) {
148
148
  }
149
149
 
150
150
  // src/index.ts
151
+ var import_hammer_utils2 = require("@procore/hammer-utils");
152
+
153
+ // src/validate-package.ts
151
154
  var import_hammer_utils = require("@procore/hammer-utils");
155
+ var import_picocolors3 = __toESM(require("picocolors"));
156
+ var import_node_fs = __toESM(require("fs"));
157
+ var errorIsNotExisted = (name) => `The property ${import_picocolors3.default.yellow(name)} doesn't exist in the package.json.`;
158
+ var errorFileIsNotExisted = (name) => `The file from ${import_picocolors3.default.yellow(name)} property doesn't exist in the dist folder.
159
+ `;
160
+ var areDeepFileExist = (value) => {
161
+ let isValid = true;
162
+ if (Array.isArray(value) && isValid) {
163
+ isValid = value.every(import_node_fs.default.existsSync);
164
+ }
165
+ if (typeof value === "object" && !Array.isArray(value) && value !== null && isValid) {
166
+ isValid = Object.values(value).every(
167
+ (file) => areDeepFileExist(file)
168
+ );
169
+ }
170
+ if (typeof value === "string" && isValid) {
171
+ isValid = import_node_fs.default.existsSync(value);
172
+ }
173
+ return isValid;
174
+ };
175
+ var validatePackage = async (rootDir) => {
176
+ const pkg = await (0, import_hammer_utils.readRootPackageJson)(rootDir);
177
+ let isValid = true;
178
+ if (!pkg.type) {
179
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#type";
180
+ process.stderr.write(errorIsNotExisted("type"));
181
+ process.stdout.write(
182
+ `Please specify it as ${import_picocolors3.default.bold('"module" (recommended)')} or read ${import_picocolors3.default.bold(docUrl)}.
183
+ `
184
+ );
185
+ isValid = false;
186
+ }
187
+ if (!pkg.exports) {
188
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#exports";
189
+ const exampleStructure = {
190
+ exports: {
191
+ ".": {
192
+ import: {
193
+ types: "./dist/modern/index.d.ts",
194
+ default: "./dist/modern/index.js"
195
+ },
196
+ require: {
197
+ types: "./dist/modern/index.d.cts",
198
+ default: "./dist/modern/index.cjs"
199
+ }
200
+ },
201
+ "./package.json": "./package.json"
202
+ }
203
+ };
204
+ process.stderr.write(errorIsNotExisted("exports"));
205
+ process.stdout.write(
206
+ `Please specify it as ${import_picocolors3.default.bold(JSON.stringify(exampleStructure, null, 2))} or read ${import_picocolors3.default.bold(docUrl)}.
207
+ `
208
+ );
209
+ isValid = false;
210
+ }
211
+ if (pkg.exports && !areDeepFileExist(pkg.exports)) {
212
+ process.stderr.write(errorFileIsNotExisted("exports"));
213
+ isValid = false;
214
+ }
215
+ if (!pkg.main) {
216
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#main";
217
+ process.stderr.write(errorIsNotExisted("main"));
218
+ process.stdout.write(
219
+ `Please point it on your main file. You can read more in ${import_picocolors3.default.bold(docUrl)}.
220
+ `
221
+ );
222
+ isValid = false;
223
+ }
224
+ if (pkg.main && !import_node_fs.default.existsSync(pkg.main)) {
225
+ process.stderr.write(errorFileIsNotExisted("main"));
226
+ isValid = false;
227
+ }
228
+ if (!pkg.module) {
229
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#package-entry-points";
230
+ process.stderr.write(errorIsNotExisted("module"));
231
+ process.stdout.write(`You can read more in ${import_picocolors3.default.bold(docUrl)}.
232
+ `);
233
+ isValid = false;
234
+ }
235
+ if (pkg.module && !import_node_fs.default.existsSync(pkg.module)) {
236
+ process.stderr.write(errorFileIsNotExisted("module"));
237
+ isValid = false;
238
+ }
239
+ if (!pkg.types) {
240
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#community-conditions-definitions";
241
+ process.stderr.write(errorIsNotExisted("types"));
242
+ process.stdout.write(`You can read more in ${import_picocolors3.default.bold(docUrl)}.
243
+ `);
244
+ isValid = false;
245
+ }
246
+ if (pkg.types && !areDeepFileExist(pkg.types)) {
247
+ process.stderr.write(errorFileIsNotExisted("types"));
248
+ isValid = false;
249
+ }
250
+ if (!pkg.files) {
251
+ const docUrl = "https://classic.yarnpkg.com/lang/en/docs/package-json/#toc-files";
252
+ process.stderr.write(
253
+ `${errorIsNotExisted("files")}
254
+ The optional ${import_picocolors3.default.yellow("files")} field is an array of file patterns that describes the entries to be included when your package is installed as a dependency.
255
+ `
256
+ );
257
+ process.stdout.write(`You can read more in ${import_picocolors3.default.bold(docUrl)}.
258
+ `);
259
+ isValid = false;
260
+ }
261
+ if (pkg.files && !areDeepFileExist(pkg.files)) {
262
+ process.stderr.write(errorFileIsNotExisted("files"));
263
+ isValid = false;
264
+ }
265
+ if (!pkg.sideEffects) {
266
+ process.stderr.write(
267
+ `${errorIsNotExisted("sideEffects")}
268
+ This field helps bundlers make assumptions about packages that improve tree shaking, or pruning files that aren't used and don't have any global side effects.
269
+ `
270
+ );
271
+ isValid = false;
272
+ }
273
+ if (isValid) {
274
+ process.stdout.write(import_picocolors3.default.green(`Validation finished succesfully.
275
+ `));
276
+ }
277
+ };
278
+
279
+ // src/index.ts
152
280
  var { init, build, clean, inspect, start, validate } = {
153
281
  init: async function init2(rootDir, config, options) {
154
- await (0, import_hammer_utils.updatePackageJsonFromTemplate)(rootDir, options.force);
282
+ await (0, import_hammer_utils2.updatePackageJsonFromTemplate)(rootDir, options.force);
155
283
  },
156
284
  build: async function build2(rootDir, config, options) {
157
285
  const pluginOptions = { ...options, config };
@@ -176,7 +304,9 @@ ${highlightedConfig}
176
304
  const buildOptions = await createBuildOptions(base_configs_default, pluginOptions);
177
305
  await performBuild(buildOptions);
178
306
  },
179
- validate: async function validate2() {
307
+ validate: async function validate2(rootDir, config) {
308
+ await this.build(rootDir, config, { analyze: false });
309
+ await validatePackage(rootDir);
180
310
  }
181
311
  };
182
312
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import process2 from "process";
2
+ import process2 from "node:process";
3
3
 
4
4
  // src/base-configs.ts
5
5
  import { postcssModules, sassPlugin } from "esbuild-sass-plugin";
@@ -68,7 +68,7 @@ function toHighlightedString(input) {
68
68
 
69
69
  // src/clean-output.ts
70
70
  import { resolve } from "pathe";
71
- import { rm } from "fs/promises";
71
+ import { rm } from "node:fs/promises";
72
72
  import c from "picocolors";
73
73
  async function cleanOutput(rootDir, buildOptions) {
74
74
  for (const buildOption of buildOptions) {
@@ -110,6 +110,134 @@ async function performBuild(buildOptions) {
110
110
 
111
111
  // src/index.ts
112
112
  import { updatePackageJsonFromTemplate } from "@procore/hammer-utils";
113
+
114
+ // src/validate-package.ts
115
+ import { readRootPackageJson } from "@procore/hammer-utils";
116
+ import c3 from "picocolors";
117
+ import fs from "node:fs";
118
+ var errorIsNotExisted = (name) => `The property ${c3.yellow(name)} doesn't exist in the package.json.`;
119
+ var errorFileIsNotExisted = (name) => `The file from ${c3.yellow(name)} property doesn't exist in the dist folder.
120
+ `;
121
+ var areDeepFileExist = (value) => {
122
+ let isValid = true;
123
+ if (Array.isArray(value) && isValid) {
124
+ isValid = value.every(fs.existsSync);
125
+ }
126
+ if (typeof value === "object" && !Array.isArray(value) && value !== null && isValid) {
127
+ isValid = Object.values(value).every(
128
+ (file) => areDeepFileExist(file)
129
+ );
130
+ }
131
+ if (typeof value === "string" && isValid) {
132
+ isValid = fs.existsSync(value);
133
+ }
134
+ return isValid;
135
+ };
136
+ var validatePackage = async (rootDir) => {
137
+ const pkg = await readRootPackageJson(rootDir);
138
+ let isValid = true;
139
+ if (!pkg.type) {
140
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#type";
141
+ process.stderr.write(errorIsNotExisted("type"));
142
+ process.stdout.write(
143
+ `Please specify it as ${c3.bold('"module" (recommended)')} or read ${c3.bold(docUrl)}.
144
+ `
145
+ );
146
+ isValid = false;
147
+ }
148
+ if (!pkg.exports) {
149
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#exports";
150
+ const exampleStructure = {
151
+ exports: {
152
+ ".": {
153
+ import: {
154
+ types: "./dist/modern/index.d.ts",
155
+ default: "./dist/modern/index.js"
156
+ },
157
+ require: {
158
+ types: "./dist/modern/index.d.cts",
159
+ default: "./dist/modern/index.cjs"
160
+ }
161
+ },
162
+ "./package.json": "./package.json"
163
+ }
164
+ };
165
+ process.stderr.write(errorIsNotExisted("exports"));
166
+ process.stdout.write(
167
+ `Please specify it as ${c3.bold(JSON.stringify(exampleStructure, null, 2))} or read ${c3.bold(docUrl)}.
168
+ `
169
+ );
170
+ isValid = false;
171
+ }
172
+ if (pkg.exports && !areDeepFileExist(pkg.exports)) {
173
+ process.stderr.write(errorFileIsNotExisted("exports"));
174
+ isValid = false;
175
+ }
176
+ if (!pkg.main) {
177
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#main";
178
+ process.stderr.write(errorIsNotExisted("main"));
179
+ process.stdout.write(
180
+ `Please point it on your main file. You can read more in ${c3.bold(docUrl)}.
181
+ `
182
+ );
183
+ isValid = false;
184
+ }
185
+ if (pkg.main && !fs.existsSync(pkg.main)) {
186
+ process.stderr.write(errorFileIsNotExisted("main"));
187
+ isValid = false;
188
+ }
189
+ if (!pkg.module) {
190
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#package-entry-points";
191
+ process.stderr.write(errorIsNotExisted("module"));
192
+ process.stdout.write(`You can read more in ${c3.bold(docUrl)}.
193
+ `);
194
+ isValid = false;
195
+ }
196
+ if (pkg.module && !fs.existsSync(pkg.module)) {
197
+ process.stderr.write(errorFileIsNotExisted("module"));
198
+ isValid = false;
199
+ }
200
+ if (!pkg.types) {
201
+ const docUrl = "https://nodejs.org/docs/latest/api/packages.html#community-conditions-definitions";
202
+ process.stderr.write(errorIsNotExisted("types"));
203
+ process.stdout.write(`You can read more in ${c3.bold(docUrl)}.
204
+ `);
205
+ isValid = false;
206
+ }
207
+ if (pkg.types && !areDeepFileExist(pkg.types)) {
208
+ process.stderr.write(errorFileIsNotExisted("types"));
209
+ isValid = false;
210
+ }
211
+ if (!pkg.files) {
212
+ const docUrl = "https://classic.yarnpkg.com/lang/en/docs/package-json/#toc-files";
213
+ process.stderr.write(
214
+ `${errorIsNotExisted("files")}
215
+ The optional ${c3.yellow("files")} field is an array of file patterns that describes the entries to be included when your package is installed as a dependency.
216
+ `
217
+ );
218
+ process.stdout.write(`You can read more in ${c3.bold(docUrl)}.
219
+ `);
220
+ isValid = false;
221
+ }
222
+ if (pkg.files && !areDeepFileExist(pkg.files)) {
223
+ process.stderr.write(errorFileIsNotExisted("files"));
224
+ isValid = false;
225
+ }
226
+ if (!pkg.sideEffects) {
227
+ process.stderr.write(
228
+ `${errorIsNotExisted("sideEffects")}
229
+ This field helps bundlers make assumptions about packages that improve tree shaking, or pruning files that aren't used and don't have any global side effects.
230
+ `
231
+ );
232
+ isValid = false;
233
+ }
234
+ if (isValid) {
235
+ process.stdout.write(c3.green(`Validation finished succesfully.
236
+ `));
237
+ }
238
+ };
239
+
240
+ // src/index.ts
113
241
  var { init, build, clean, inspect, start, validate } = {
114
242
  init: async function init2(rootDir, config, options) {
115
243
  await updatePackageJsonFromTemplate(rootDir, options.force);
@@ -137,7 +265,9 @@ ${highlightedConfig}
137
265
  const buildOptions = await createBuildOptions(base_configs_default, pluginOptions);
138
266
  await performBuild(buildOptions);
139
267
  },
140
- validate: async function validate2() {
268
+ validate: async function validate2(rootDir, config) {
269
+ await this.build(rootDir, config, { analyze: false });
270
+ await validatePackage(rootDir);
141
271
  }
142
272
  };
143
273
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@procore/hammer-lib-tsup",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Hammer library builder, tsup-style",
5
5
  "author": "Procore Technologies, Inc",
6
6
  "homepage": "https://github.com/procore/hammer/packages/lib-tsup",
@@ -51,29 +51,29 @@
51
51
  }
52
52
  },
53
53
  "dependencies": {
54
- "@procore/hammer-types": "^0.5.0",
55
- "@procore/hammer-utils": "^0.1.0",
54
+ "@procore/hammer-types": "^0.5.1",
55
+ "@procore/hammer-utils": "^0.2.0",
56
56
  "cli-highlight": "^2.1.11",
57
- "esbuild": "^0.23.1",
57
+ "esbuild": "^0.24.0",
58
58
  "esbuild-sass-plugin": "^3.3.1",
59
59
  "pathe": "^1.1.2",
60
- "picocolors": "^1.0.1",
61
- "sass-embedded": "^1.77.5",
62
- "tsup": "^8.3.0"
60
+ "picocolors": "^1.1.1",
61
+ "sass-embedded": "^1.81.0",
62
+ "tsup": "^8.3.5"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@procore/eslint-config": "^15.2.1",
66
66
  "@procore/hammer-test-utils": "^0.0.1",
67
67
  "@procore/prettier-config": "^1.1.1",
68
68
  "@procore/typescript-config": "^2.0.0",
69
- "@types/node": "^20.16.10",
70
- "@vitest/coverage-v8": "^2.1.1",
71
- "del-cli": "^5.1.0",
72
- "eslint": "^8.57.0",
73
- "postcss": "^8.4.39",
69
+ "@types/node": "^20.17.6",
70
+ "@vitest/coverage-v8": "^2.1.5",
71
+ "del-cli": "^6.0.0",
72
+ "eslint": "^9.15.0",
73
+ "postcss": "^8.4.49",
74
74
  "prettier": "^3.3.3",
75
75
  "strip-ansi": "^7.1.0",
76
- "typescript": "^5.5.4",
77
- "vitest": "^2.1.1"
76
+ "typescript": "~5.5.4",
77
+ "vitest": "^2.1.5"
78
78
  }
79
79
  }