pkgbld 1.26.0 → 1.27.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/README.md CHANGED
@@ -178,6 +178,14 @@ pkgbld --format-package-json
178
178
 
179
179
  Formats package.json file.
180
180
 
181
+ ### no-pack
182
+
183
+ Do not setup pack script in package.json
184
+
185
+ ```
186
+ pkgbld --no-pack
187
+ ```
188
+
181
189
  ### prune (command)
182
190
 
183
191
  ```
@@ -186,6 +194,18 @@ pkgbld prune
186
194
 
187
195
  prune devDependencies and redundunt scripts from package.json
188
196
 
197
+ ### flatten
198
+
199
+ ```
200
+ pkgbld prune --flatten=<directory>
201
+ ```
202
+
203
+ Flattens file structure by moving all files from `dist` or other directory to the root directory and updating package.json.
204
+
205
+ If the directory is not specified it is guessed from package.json.
206
+
207
+ If files cannot be copied because of name conflicts the command will fail.
208
+
189
209
  ## Plugin API
190
210
 
191
211
  `pkgbld` reads all installed packages named `pkgbld-plugin-*` and assumes they are plugins
package/dist/index.js CHANGED
@@ -141,6 +141,11 @@ const cliFlags = {
141
141
  type: Boolean,
142
142
  description: 'Format package.json',
143
143
  default: cliFlagsDefaults.formatPackageJson
144
+ },
145
+ noPack: {
146
+ type: Boolean,
147
+ description: 'Do not pack',
148
+ default: false
144
149
  }
145
150
  };
146
151
  const packageJsonFieldsOrder = new Set([
@@ -209,6 +214,15 @@ function toFormattedJson(json) {
209
214
  return JSON.stringify(json, null, 2) + '\n';
210
215
  }
211
216
 
217
+ function FlattenParam(value) {
218
+ if (typeof value === 'boolean') {
219
+ return value; // false
220
+ }
221
+ if (value === '') {
222
+ return true; // means auto
223
+ }
224
+ return value; // string
225
+ }
212
226
  function getCliOptions(plugins, pkg) {
213
227
  const cliOptions = cleye.cli({
214
228
  name: 'pkgbld',
@@ -223,6 +237,11 @@ function getCliOptions(plugins, pkg) {
223
237
  type: String,
224
238
  description: 'profile to use',
225
239
  default: 'library'
240
+ },
241
+ flatten: {
242
+ type: FlattenParam,
243
+ description: 'flatten package files',
244
+ default: false
226
245
  }
227
246
  }
228
247
  })
@@ -231,7 +250,8 @@ function getCliOptions(plugins, pkg) {
231
250
  if (cliOptions.command === 'prune') {
232
251
  return {
233
252
  kind: 'prune',
234
- profile: cliOptions.flags.profile
253
+ profile: cliOptions.flags.profile,
254
+ flatten: cliOptions.flags.flatten
235
255
  };
236
256
  }
237
257
  else {
@@ -254,7 +274,8 @@ function getCliOptions(plugins, pkg) {
254
274
  commonjsPattern: flags.commonjsPattern,
255
275
  esPattern: flags.esmPattern,
256
276
  umdPattern: flags.umdPattern,
257
- formatPackageJson: flags.formatPackageJson
277
+ formatPackageJson: flags.formatPackageJson,
278
+ noPack: flags.noPack
258
279
  };
259
280
  for (const plugin of plugins) {
260
281
  plugin.options?.(flags, options);
@@ -695,7 +716,7 @@ function processPackage(pkg, config, plugins) {
695
716
  if (typeof pkg.scripts !== 'object' && pkg.scripts !== null) {
696
717
  pkg.scripts = {};
697
718
  }
698
- if (!('prepack' in pkg.scripts)) {
719
+ if (!config.noPack && !('prepack' in pkg.scripts)) {
699
720
  const binary = typeof pkg.scripts.build === 'string' && pkg.scripts.build?.startsWith('pkgbld-internal') ? 'pkgbld-internal' : 'pkgbld';
700
721
  pkg.scripts.prepack = `${binary} prune`;
701
722
  }
@@ -823,7 +844,7 @@ async function writeJson(path, json) {
823
844
  await fs.writeFile(path, toFormattedJson(json));
824
845
  }
825
846
 
826
- var version = "1.26.0";
847
+ var version = "1.27.0";
827
848
  var name = "pkgbld";
828
849
  var license = "MIT";
829
850
  var author = "Konstantin Shutkin";
@@ -862,10 +883,10 @@ var dependencies = {
862
883
  rollup: "^4.0.0",
863
884
  "rollup-plugin-typescript2": "^0.36.0",
864
885
  "rollup-plugin-preprocess": "^0.0.4",
865
- "@rollup/plugin-commonjs": "^25.0.5",
886
+ "@rollup/plugin-commonjs": "^25.0.7",
866
887
  "@rollup/plugin-terser": "^0.4.4",
867
888
  "@rollup/plugin-json": "^6.0.1",
868
- "@rollup/plugin-node-resolve": "^15.2.2",
889
+ "@rollup/plugin-node-resolve": "^15.2.3",
869
890
  "@rollup-extras/plugin-clean": "^1.3.8",
870
891
  "@rollup-extras/plugin-binify": "^1.1.9",
871
892
  "@rollup-extras/plugin-externals": "^1.2.0",
@@ -874,7 +895,8 @@ var dependencies = {
874
895
  "is-builtin-module": "^3.2.1",
875
896
  terser: "^5.21.0",
876
897
  kleur: "^4.1.5",
877
- cleye: "^1.3.2"
898
+ cleye: "^1.3.2",
899
+ jsonata: "^2.0.3"
878
900
  };
879
901
  var devDependencies = {
880
902
  "@types/lodash": "^4.14.199",
@@ -1049,31 +1071,186 @@ function loadPlugins(pkg) {
1049
1071
  .map(packageName => import(packageName)));
1050
1072
  }
1051
1073
 
1052
- const scriptsToKeep = new Set([
1053
- 'preinstall',
1054
- 'install',
1055
- 'postinstall',
1056
- 'prepublish',
1057
- 'preprepare',
1058
- 'prepare',
1059
- 'postprepare'
1060
- ]);
1061
- function prunePkg(pkg, options) {
1074
+ async function prunePkg(pkg, options, logger) {
1062
1075
  if (options.kind !== 'prune') {
1063
1076
  throw new Error('prunePkg should only be called in prune mode');
1064
1077
  }
1065
- if (options.profile !== 'library') {
1066
- throw new Error('only library profile is supported');
1078
+ const scriptsToKeep = getScriptsData();
1079
+ const keys = scriptsToKeep[options.profile];
1080
+ if (!keys) {
1081
+ throw new Error(`unknown profile ${options.profile}`);
1067
1082
  }
1068
1083
  delete pkg.devDependencies;
1069
1084
  for (const key of Object.keys(pkg.scripts)) {
1070
- if (!scriptsToKeep.has(key)) {
1085
+ if (!keys.has(key)) {
1071
1086
  delete pkg.scripts[key];
1072
1087
  }
1073
1088
  }
1074
1089
  if (Object.keys(pkg.scripts).length === 0) {
1075
1090
  delete pkg.scripts;
1076
1091
  }
1092
+ if (options.flatten) {
1093
+ await flatten(pkg, options.flatten, logger);
1094
+ }
1095
+ }
1096
+ async function flatten(pkg, flatten, logger) {
1097
+ const { default: jsonata } = await import('jsonata');
1098
+ // find out where is the dist folder
1099
+ const expression = jsonata('[bin, main, module, unpkg, umd, types, typings, exports[].*.*, typesVersions.*.*]');
1100
+ const allReferences = (await expression.evaluate(pkg));
1101
+ let distDir;
1102
+ if (flatten === true) {
1103
+ let commonSegments;
1104
+ for (const entry of allReferences) {
1105
+ if (typeof entry !== 'string') {
1106
+ continue;
1107
+ }
1108
+ const dirname = path.dirname(entry);
1109
+ const cleanedSegments = dirname.split('/').filter(path => path && path !== '.');
1110
+ if (!commonSegments) {
1111
+ commonSegments = cleanedSegments;
1112
+ }
1113
+ else {
1114
+ for (let i = 0; i < commonSegments.length; ++i) {
1115
+ if (commonSegments[i] !== cleanedSegments[i]) {
1116
+ commonSegments.length = i;
1117
+ break;
1118
+ }
1119
+ }
1120
+ }
1121
+ }
1122
+ distDir = commonSegments?.join('/');
1123
+ }
1124
+ else {
1125
+ distDir = flatten;
1126
+ }
1127
+ if (!distDir) {
1128
+ throw new Error('could not find dist folder');
1129
+ }
1130
+ logger.update(`flattening ${distDir}...`);
1131
+ // check if dist can be flattened
1132
+ const relativeDistDir = './' + distDir;
1133
+ const existsPromises = [];
1134
+ const filesInDist = await walkDir(relativeDistDir);
1135
+ for (const file of filesInDist) {
1136
+ // check file is not in root dir
1137
+ const relativePath = path.relative(relativeDistDir, file);
1138
+ existsPromises.push(isExists(relativePath));
1139
+ }
1140
+ const exists = await Promise.all(existsPromises);
1141
+ const filesAlreadyExist = exists.filter(Boolean);
1142
+ if (filesAlreadyExist.length) {
1143
+ throw new Error(`dist folder cannot be flattened because files already exist: ${filesAlreadyExist.join(', ')}`);
1144
+ }
1145
+ // move files to root dir (rename)
1146
+ const renamePromises = [];
1147
+ const newFiles = [];
1148
+ for (const file of filesInDist) {
1149
+ // check file is not in root dir
1150
+ const relativePath = path.relative(relativeDistDir, file);
1151
+ newFiles.push(relativePath);
1152
+ renamePromises.push(fs.rename(file, relativePath));
1153
+ }
1154
+ await Promise.all(renamePromises);
1155
+ // remove dist folder
1156
+ try {
1157
+ await fs.rm(relativeDistDir, { recursive: true, force: true });
1158
+ }
1159
+ catch (e) {
1160
+ // ignore
1161
+ }
1162
+ const allReferencesSet = new Set(allReferences);
1163
+ // update package.json
1164
+ const stringToReplace = distDir + '/';
1165
+ const pkgClone = cloneAndUpdate(pkg, value => allReferencesSet.has(value) ? value.replace(stringToReplace, '') : value);
1166
+ Object.assign(pkg, pkgClone);
1167
+ // update files
1168
+ let files = pkg.files ?? [];
1169
+ files = files.filter(file => {
1170
+ let fileNormilized = path.normalize(file);
1171
+ if (fileNormilized.endsWith('/')) {
1172
+ // remove trailing slash
1173
+ fileNormilized = fileNormilized.slice(0, -1);
1174
+ }
1175
+ return fileNormilized !== distDir;
1176
+ });
1177
+ files.push(...newFiles);
1178
+ pkg.files = [...files];
1179
+ }
1180
+ function cloneAndUpdate(pkg, updater) {
1181
+ if (typeof pkg === 'string') {
1182
+ return updater(pkg);
1183
+ }
1184
+ if (Array.isArray(pkg)) {
1185
+ return pkg.map(value => cloneAndUpdate(value, updater));
1186
+ }
1187
+ if (typeof pkg === 'object' && pkg !== null) {
1188
+ const clone = {};
1189
+ for (const key of Object.keys(pkg)) {
1190
+ clone[key] = cloneAndUpdate(pkg[key], updater);
1191
+ }
1192
+ return clone;
1193
+ }
1194
+ return pkg;
1195
+ }
1196
+ async function isExists(file) {
1197
+ try {
1198
+ await fs.access(file);
1199
+ }
1200
+ catch (e) {
1201
+ if (typeof e === 'object' && e != null && 'code' in e && e.code === 'ENOENT') {
1202
+ return false;
1203
+ }
1204
+ throw e;
1205
+ }
1206
+ return file;
1207
+ }
1208
+ async function walkDir(dir) {
1209
+ const entries = await fs.readdir(dir, { withFileTypes: true });
1210
+ const files = [];
1211
+ await Promise.all(entries.map(entry => {
1212
+ const childPath = path.join(dir, entry.name);
1213
+ if (entry.isDirectory()) {
1214
+ return walkDir(childPath)
1215
+ .then(childFiles => {
1216
+ files.push(...childFiles);
1217
+ });
1218
+ }
1219
+ else {
1220
+ files.push(childPath);
1221
+ }
1222
+ }).filter(Boolean));
1223
+ return files;
1224
+ }
1225
+ function getScriptsData() {
1226
+ const libraryScripts = new Set([
1227
+ 'preinstall',
1228
+ 'install',
1229
+ 'postinstall',
1230
+ 'prepublish',
1231
+ 'preprepare',
1232
+ 'prepare',
1233
+ 'postprepare'
1234
+ ]);
1235
+ const appScripts = new Set([
1236
+ ...libraryScripts,
1237
+ 'prestart',
1238
+ 'start',
1239
+ 'poststart',
1240
+ 'prerestart',
1241
+ 'restart',
1242
+ 'postrestart',
1243
+ 'prestop',
1244
+ 'stop',
1245
+ 'poststop',
1246
+ 'pretest',
1247
+ 'test',
1248
+ 'posttest'
1249
+ ]);
1250
+ return {
1251
+ library: libraryScripts,
1252
+ app: appScripts
1253
+ };
1077
1254
  }
1078
1255
 
1079
1256
  execute();
@@ -1091,7 +1268,7 @@ async function execute() {
1091
1268
  process.stdout.moveCursor?.(0, -1);
1092
1269
  const options = getCliOptions(plugins, pkg);
1093
1270
  if (options.kind === 'prune') {
1094
- prunePkg(pkg, options);
1271
+ await prunePkg(pkg, options, mainLogger);
1095
1272
  await writeJson(pkgPath, pkg);
1096
1273
  process.exit(0);
1097
1274
  }
@@ -1,4 +1,5 @@
1
- import type { CliOptions, PackageJson, PkgbldRollupPlugin, Provider } from './types';
1
+ import type { CliOptions, PkgbldRollupPlugin, Provider } from './types';
2
+ import type { PackageJson } from 'options';
2
3
  import type { RollupOptions } from 'rollup';
3
4
  import { getHelpers } from './helpers';
4
5
  export declare function createEjectProvider(preimportMap: Map<string, Promise<never>>): Promise<[Provider, PkgbldRollupPlugin[]]>;
@@ -1,4 +1,5 @@
1
- import { PackageJson, PkgbldPlugin } from './types';
1
+ import { PkgbldPlugin } from './types';
2
+ import { PackageJson } from 'options';
2
3
  export declare function getCliOptions(plugins: Partial<PkgbldPlugin>[], pkg: PackageJson): {
3
4
  kind: 'build';
4
5
  umdInputs: string[];
@@ -18,7 +19,9 @@ export declare function getCliOptions(plugins: Partial<PkgbldPlugin>[], pkg: Pac
18
19
  esPattern: string;
19
20
  umdPattern: string;
20
21
  formatPackageJson: boolean;
22
+ noPack: boolean;
21
23
  } | {
22
24
  readonly kind: "prune";
23
25
  readonly profile: string;
26
+ readonly flatten: string | boolean;
24
27
  };
@@ -1,5 +1,5 @@
1
1
  import { OutputOptions } from 'rollup';
2
- import { PackageJson } from './types';
2
+ import { PackageJson } from 'options';
3
3
  export declare function getHelpers(pkgName: string): {
4
4
  getGlobalName: (anInput: string) => string;
5
5
  getExternalGlobalName: (id: string) => string;
@@ -1,2 +1,3 @@
1
- import { PackageJson, PkgbldPlugin } from './types';
1
+ import { PackageJson } from 'options';
2
+ import { PkgbldPlugin } from './types';
2
3
  export declare function loadPlugins(pkg: PackageJson): Promise<Partial<PkgbldPlugin>[]>;
@@ -1,5 +1,7 @@
1
- import { PackageJson } from './types';
1
+ import { Logger } from '@niceties/logger';
2
+ import { PackageJson } from 'options';
2
3
  export declare function prunePkg(pkg: PackageJson, options: {
3
4
  kind: 'prune';
4
5
  profile: string;
5
- }): void;
6
+ flatten: string | boolean;
7
+ }, logger: Logger): Promise<void>;
@@ -1,17 +1,10 @@
1
1
  import type { Plugin, InternalModuleFormat, OutputOptions } from 'rollup';
2
2
  import type { getCliOptions } from './get-cli-options';
3
3
  import { Logger } from '@niceties/logger';
4
+ import { PackageJson } from 'options';
4
5
  export type Json = null | string | number | boolean | Json[] | {
5
6
  [name: string]: Json;
6
7
  };
7
- export type PackageJson = {
8
- name: string;
9
- version: string;
10
- dependencies?: Record<string, string>;
11
- devDependencies?: Record<string, string>;
12
- peerDependencies: Record<string, string>;
13
- scripts?: Record<string, string>;
14
- };
15
8
  export declare const enum Priority {
16
9
  preprocess = 1000,
17
10
  cleanup = 1000,
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.26.0",
2
+ "version": "1.27.0",
3
3
  "name": "pkgbld",
4
4
  "license": "MIT",
5
5
  "author": "Konstantin Shutkin",
@@ -33,10 +33,10 @@
33
33
  "rollup": "^4.0.0",
34
34
  "rollup-plugin-typescript2": "^0.36.0",
35
35
  "rollup-plugin-preprocess": "^0.0.4",
36
- "@rollup/plugin-commonjs": "^25.0.5",
36
+ "@rollup/plugin-commonjs": "^25.0.7",
37
37
  "@rollup/plugin-terser": "^0.4.4",
38
38
  "@rollup/plugin-json": "^6.0.1",
39
- "@rollup/plugin-node-resolve": "^15.2.2",
39
+ "@rollup/plugin-node-resolve": "^15.2.3",
40
40
  "@rollup-extras/plugin-clean": "^1.3.8",
41
41
  "@rollup-extras/plugin-binify": "^1.1.9",
42
42
  "@rollup-extras/plugin-externals": "^1.2.0",
@@ -45,7 +45,8 @@
45
45
  "is-builtin-module": "^3.2.1",
46
46
  "terser": "^5.21.0",
47
47
  "kleur": "^4.1.5",
48
- "cleye": "^1.3.2"
48
+ "cleye": "^1.3.2",
49
+ "jsonata": "^2.0.3"
49
50
  },
50
51
  "peerDependencies": {
51
52
  "typescript": "^5.2.2"