@normed/bundle 4.1.0 → 4.2.1

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
@@ -6,6 +6,15 @@ Given a version number MAJOR.MINOR.PATCH, increment the:
6
6
  2. MINOR version when you add functionality in a backwards compatible manner, and
7
7
  3. PATCH version when you make backwards compatible bug fixes.
8
8
 
9
+ # 4.2.1
10
+
11
+ * PATCH: Fixes missing path in load_less.
12
+
13
+ # 4.2.0
14
+
15
+ * MINOR: supports a range of plugins, but these are undocumented.
16
+ * MINOR: supports slightly better error returning, but this is not implemented across the board.
17
+
9
18
  # 4.1.0
10
19
 
11
20
  * MINOR: fixes building of entypoint pug files.
@@ -68580,6 +68580,34 @@ function groupBy(objs, extractSubgroupFuncs) {
68580
68580
  }
68581
68581
  return groups;
68582
68582
  }
68583
+ function keyBy(objs, extractKeyFuncs) {
68584
+ const result = /* @__PURE__ */ new Map();
68585
+ const knownKeys = [];
68586
+ for (const obj of objs) {
68587
+ const key = {};
68588
+ for (const [keyName, extractKeyFunc] of Object.entries(extractKeyFuncs)) {
68589
+ key[keyName] = extractKeyFunc(obj);
68590
+ }
68591
+ let knownKey = knownKeys.find(
68592
+ (knownKey2) => Object.keys(knownKey2).length === Object.keys(key).length && Object.keys(knownKey2).every(
68593
+ (k) => knownKey2[k] === key[k]
68594
+ )
68595
+ );
68596
+ if (!knownKey) {
68597
+ knownKey = key;
68598
+ knownKeys.push(key);
68599
+ result.set(knownKey, [obj]);
68600
+ } else {
68601
+ const group = result.get(knownKey);
68602
+ if (group) {
68603
+ group.push(obj);
68604
+ } else {
68605
+ throw new Error(`Keying failed in keyBy`);
68606
+ }
68607
+ }
68608
+ }
68609
+ return result;
68610
+ }
68583
68611
  function divide(list, divider) {
68584
68612
  const a = [];
68585
68613
  const b = [];
@@ -68876,6 +68904,68 @@ function mergeDeep(into, from) {
68876
68904
  }
68877
68905
 
68878
68906
  // pnp:/builds/normed/bundle/packages/bundle/src/errors.ts
68907
+ function combineErrorLogs(...logs) {
68908
+ const combined = {
68909
+ errors: [],
68910
+ warnings: []
68911
+ };
68912
+ for (const log of logs) {
68913
+ if (log.errors) {
68914
+ combined.errors.push(...log.errors);
68915
+ }
68916
+ if (log.warnings) {
68917
+ combined.warnings.push(...log.warnings);
68918
+ }
68919
+ }
68920
+ return combined;
68921
+ }
68922
+ var WrappedErrors = class _WrappedErrors extends AggregateError {
68923
+ constructor(errors, message, meta) {
68924
+ var __super = (...args) => {
68925
+ super(...args);
68926
+ this.meta = meta;
68927
+ return this;
68928
+ };
68929
+ if (Array.isArray(errors)) {
68930
+ __super(errors, message);
68931
+ } else {
68932
+ __super(errors.errors ?? [], message);
68933
+ this.warnings = errors.warnings ?? [];
68934
+ }
68935
+ this.name = "WrappedError";
68936
+ }
68937
+ warnings;
68938
+ static fromErrorLog(errorLog, message, meta) {
68939
+ return new _WrappedErrors(errorLog, message, meta);
68940
+ }
68941
+ static fromError(error, message, meta) {
68942
+ return new _WrappedErrors([error], message, meta);
68943
+ }
68944
+ static fromErrors(errors, message, meta) {
68945
+ return new _WrappedErrors(errors, message, meta);
68946
+ }
68947
+ static fromValue(value, message, meta) {
68948
+ const error = asError(value);
68949
+ return new _WrappedErrors([error], message, meta);
68950
+ }
68951
+ static fromValues(values, message, meta) {
68952
+ const errors = values.map(asError);
68953
+ return new _WrappedErrors(errors, message, meta);
68954
+ }
68955
+ };
68956
+ function asError(value, meta) {
68957
+ let error;
68958
+ if (!(value instanceof Error)) {
68959
+ error = new Error(String(value));
68960
+ } else {
68961
+ error = value;
68962
+ }
68963
+ if (meta) {
68964
+ let existingMeta = error.meta ?? {};
68965
+ error.meta = { ...existingMeta, ...meta };
68966
+ }
68967
+ return error;
68968
+ }
68879
68969
  var NoMatchingBuilder = class extends Error {
68880
68970
  file;
68881
68971
  ext;
@@ -68900,6 +68990,14 @@ var copyBuilder = {
68900
68990
  copy(infile.absolute, outfile.absolute);
68901
68991
  })
68902
68992
  );
68993
+ return {
68994
+ warnings: [],
68995
+ errors: [],
68996
+ watchFiles: entrypoints.map((e) => e.infile),
68997
+ watchDirs: [],
68998
+ producedFiles: entrypoints.map((e) => e.outfile),
68999
+ completed: true
69000
+ };
68903
69001
  }
68904
69002
  };
68905
69003
 
@@ -68982,14 +69080,20 @@ var plugin = {
68982
69080
  build2.onResolve(
68983
69081
  { filter: filter2 },
68984
69082
  async (args) => {
68985
- return {
68986
- sideEffects: false,
68987
- pluginData: Object.assign({}, args.pluginData, {
68988
- [name]: {
68989
- entrypoint: args.kind === "entry-point"
68990
- }
68991
- })
68992
- };
69083
+ const resolvedPath = import_path4.default.resolve(args.resolveDir, args.path);
69084
+ if (import_fs3.default.existsSync(resolvedPath)) {
69085
+ return {
69086
+ sideEffects: false,
69087
+ path: import_path4.default.resolve(args.resolveDir, args.path),
69088
+ pluginData: Object.assign({}, args.pluginData, {
69089
+ [name]: {
69090
+ entrypoint: args.kind === "entry-point"
69091
+ }
69092
+ })
69093
+ };
69094
+ } else {
69095
+ return {};
69096
+ }
68993
69097
  }
68994
69098
  );
68995
69099
  build2.onLoad(
@@ -69028,6 +69132,30 @@ var load_less_default = plugin;
69028
69132
  var import_pug = __toESM(require_lib14());
69029
69133
  var import_fs4 = __toESM(require("fs"));
69030
69134
  var import_path5 = __toESM(require("path"));
69135
+ function pugTransformer(test, onFound) {
69136
+ return {
69137
+ preCodeGen(ast) {
69138
+ const pending = [...ast?.nodes || []];
69139
+ const found = [];
69140
+ while (pending.length > 0) {
69141
+ const node = pending.shift();
69142
+ if (!node) continue;
69143
+ if (node.block?.nodes) {
69144
+ pending.push(...node.block.nodes);
69145
+ }
69146
+ if (!test(node)) continue;
69147
+ found.push(node);
69148
+ }
69149
+ if (found.length) {
69150
+ onFound(found);
69151
+ }
69152
+ return ast;
69153
+ }
69154
+ };
69155
+ }
69156
+ function isScriptNodeWithSrcAttr(node) {
69157
+ return node.name === "script" && node.attrs.some((attr) => attr.name === "src");
69158
+ }
69031
69159
  async function loadAsText2(_filepath) {
69032
69160
  return {
69033
69161
  loader: "text"
@@ -69052,19 +69180,29 @@ async function loadAsHtml(filepath, options2) {
69052
69180
  const contents = import_pug.default.render(fileData, {
69053
69181
  name: "render",
69054
69182
  filename: filepath,
69055
- basedir: options2.outbase
69183
+ basedir: options2.outbase,
69184
+ plugins: [
69185
+ pugTransformer(isScriptNodeWithSrcAttr, (nodes) => {
69186
+ nodes;
69187
+ })
69188
+ ]
69056
69189
  });
69057
69190
  return {
69058
69191
  contents,
69059
69192
  loader: "js"
69060
69193
  };
69061
69194
  }
69062
- async function loadAsCopy(filepath, options2) {
69195
+ async function loadAsEntrypoint(filepath, options2) {
69063
69196
  const fileData = await import_fs4.default.promises.readFile(filepath, "utf8");
69064
69197
  const contents = import_pug.default.render(fileData, {
69065
69198
  filename: filepath,
69066
69199
  basedir: options2.outbase,
69067
- name: "render"
69200
+ name: "render",
69201
+ plugins: [
69202
+ pugTransformer(isScriptNodeWithSrcAttr, (nodes) => {
69203
+ nodes;
69204
+ })
69205
+ ]
69068
69206
  });
69069
69207
  return {
69070
69208
  contents,
@@ -69116,7 +69254,7 @@ var plugin2 = {
69116
69254
  }) => {
69117
69255
  const isEntryPoint = pluginData?.[name2]?.entrypoint;
69118
69256
  if (isEntryPoint) {
69119
- return loadAsCopy(filepath, build2.initialOptions);
69257
+ return loadAsEntrypoint(filepath, build2.initialOptions);
69120
69258
  }
69121
69259
  const type = withArg?.["type"] ?? "js";
69122
69260
  switch (type) {
@@ -69434,6 +69572,18 @@ var esbuilder = {
69434
69572
  }
69435
69573
  await Promise.all(promises);
69436
69574
  }
69575
+ return {
69576
+ // TODO: rewrite to return warnings
69577
+ warnings: [],
69578
+ // TODO: rewrite to return errors
69579
+ errors: [],
69580
+ watchFiles: entrypoints.map((e) => e.infile),
69581
+ watchDirs: [],
69582
+ // TODO: these are not the correct files
69583
+ producedFiles: entrypoints.map((e) => e.outfile),
69584
+ // TODO: rewrite to only return true if all builds were successful
69585
+ completed: true
69586
+ };
69437
69587
  }
69438
69588
  };
69439
69589
  async function compileToTypeDeclarations(fileNames, options2) {
@@ -70283,7 +70433,7 @@ async function getEntrypoints(buildConfig, manuallySpecified) {
70283
70433
  }
70284
70434
 
70285
70435
  // pnp:/builds/normed/bundle/packages/bundle/src/bundle.ts
70286
- async function bundle(options2 = {}) {
70436
+ async function getBuildConfig(options2) {
70287
70437
  const buildConfig = {
70288
70438
  dir: {
70289
70439
  in: getInDir(options2),
@@ -70397,125 +70547,116 @@ async function bundle(options2 = {}) {
70397
70547
  "Build Config - post reading package.json",
70398
70548
  JSON.stringify(buildConfig.baseConfig, null, 2)
70399
70549
  );
70400
- const [raw_entrypoints, missingBuilders] = divide(
70401
- await getEntrypoints(buildConfig, options2.entrypoints),
70402
- (v) => {
70403
- return !(v instanceof NoMatchingBuilder);
70404
- }
70405
- );
70406
- const [allContextEntrypoints, entrypoints] = divide(
70407
- raw_entrypoints,
70408
- (e) => e.origin === "discovered" && e.infile.modifiers.includes("context")
70550
+ return buildConfig;
70551
+ }
70552
+ async function discoverEntrypoints(buildConfig, entrypoints, plugins = {}) {
70553
+ let initialEntrypoints = await getEntrypoints(buildConfig, entrypoints);
70554
+ initialEntrypoints = await plugins.initialEntrypoints?.(initialEntrypoints) ?? initialEntrypoints;
70555
+ const [missing, found] = divide(
70556
+ initialEntrypoints,
70557
+ (e) => e instanceof NoMatchingBuilder
70409
70558
  );
70410
- let skippedContextFile = false;
70411
- await Promise.all(
70412
- allContextEntrypoints.map(async (contextEntrypoint) => {
70413
- if (4 > 1) {
70414
- if (!skippedContextFile) {
70415
- log_default.warn(`Context files are not yet supported`);
70416
- skippedContextFile = true;
70417
- }
70418
- log_default.warn(` - skipping ${contextEntrypoint.infile.relative}`);
70419
- return;
70559
+ if (missing.length) {
70560
+ const missingBuilders = missing.filter((v, i, a) => a.indexOf(v) === i);
70561
+ return WrappedErrors.fromErrors(
70562
+ missing,
70563
+ "Missing builders for entrypoints",
70564
+ {
70565
+ missingBuilders: missingBuilders.map((b) => b.name),
70566
+ missingBuilders_count: missingBuilders.length
70420
70567
  }
70421
- skippedContextFile = false;
70422
- const matchingEntrypoints = entrypoints.filter(
70423
- (e) => e.infile.bare === contextEntrypoint.infile.bare
70424
- );
70425
- if (!matchingEntrypoints.length) {
70426
- log_default.warn(
70427
- `Context file ${contextEntrypoint.infile.bare} is not used by any entrypoint`
70428
- );
70429
- return;
70430
- }
70431
- log_default.verbose(
70432
- `Context file ${contextEntrypoint.infile.bare} is used by ${matchingEntrypoints.length} entrypoints`
70433
- );
70434
- async function compile(_v) {
70435
- throw new Error("Function not implemented.");
70436
- }
70437
- const compiled = await compile(contextEntrypoint);
70438
- const { context } = await compiled.run();
70439
- if (!context) {
70440
- log_default.warn(
70441
- `Context file ${contextEntrypoint.infile.bare} did not export a context function`
70442
- );
70443
- return;
70444
- }
70445
- const contextResult = await context();
70446
- if (!contextResult) {
70447
- log_default.warn(
70448
- `Context file ${contextEntrypoint.infile.bare} did not return a context object`
70449
- );
70450
- return;
70451
- }
70452
- const builderNames = matchingEntrypoints.map((e) => e.builder.name).filter((v, i, a) => a.indexOf(v) === i);
70453
- const builderNamesWithContexts = builderNames.filter(
70454
- (name3) => contextResult[name3]
70455
- );
70456
- if (!builderNamesWithContexts.length) {
70457
- log_default.warn(
70458
- `Context file ${contextEntrypoint.infile.bare} did not return any context for any of the builders: ${builderNames.join(", ")}`
70459
- );
70460
- return;
70461
- }
70462
- for (const builderName of builderNamesWithContexts) {
70463
- await Promise.all(
70464
- matchingEntrypoints.filter((e) => e.builder.name === builderName).map(async (entrypoint) => {
70465
- const func = contextResult[builderName];
70466
- if (!func) {
70467
- log_default.warn(
70468
- `Context file ${contextEntrypoint.infile.bare} did not return a context for builder ${builderName}`
70469
- );
70470
- return;
70471
- }
70472
- entrypoint.context = await func();
70473
- })
70474
- );
70475
- }
70476
- })
70568
+ );
70569
+ }
70570
+ return plugins.discoveredEntrypoints?.(found) ?? found;
70571
+ }
70572
+ async function bundle(options2 = {}, plugins = {}) {
70573
+ const start = Date.now();
70574
+ const buildConfig = await getBuildConfig(options2);
70575
+ const entrypoints = await discoverEntrypoints(
70576
+ buildConfig,
70577
+ options2.entrypoints,
70578
+ plugins
70477
70579
  );
70478
- log_default.warn(missingBuilders.map((missing) => missing.message).join("\n"));
70479
- log_default.info(entrypoints.length + " entrypoints");
70480
- const grouped = entrypoints.reduce((acc, entryPoint) => {
70481
- const index = buildConfig.builders.indexOf(entryPoint.builder);
70482
- if (!acc[index]) {
70483
- acc[index] = [];
70484
- }
70485
- acc[index]?.push(entryPoint);
70486
- return acc;
70487
- }, []);
70488
- for (const index in grouped) {
70489
- const group = grouped[index];
70490
- const builder = buildConfig.builders[index];
70491
- if (!builder) {
70492
- continue;
70493
- }
70494
- log_default.info(
70495
- builder.color(
70496
- `${builder.name}:
70497
- ${group?.map((i) => `${i.infile.relative} => ${i.outfile.relative}`).join("\n ")}`
70498
- )
70580
+ if (entrypoints instanceof WrappedErrors) {
70581
+ return WrappedErrors.fromError(
70582
+ entrypoints,
70583
+ "Failed to discover entrypoints"
70499
70584
  );
70500
70585
  }
70501
- const results = await Promise.all(
70502
- grouped.map(
70503
- (entrypoints2, index) => (async () => {
70504
- const start = Date.now();
70505
- await buildConfig.builders[index]?.build(entrypoints2);
70506
- const duration = Math.floor((Date.now() - start) / 10) / 100;
70507
- const builder = buildConfig.builders[index];
70508
- if (!builder) {
70509
- log_default.info(`Unknown builder: ${duration} seconds`);
70510
- } else {
70511
- log_default.info(builder.color(`${builder.name}: ${duration} seconds`));
70586
+ let grouped = keyBy(entrypoints, {
70587
+ builder: (entrypoint) => entrypoint.builder
70588
+ });
70589
+ grouped = await plugins.preBuild?.(grouped) ?? grouped;
70590
+ const results = await Promise.allSettled(
70591
+ Array.from(grouped.entries()).map(
70592
+ async ([
70593
+ { builder },
70594
+ entrypoints2
70595
+ ]) => {
70596
+ const start2 = Date.now();
70597
+ const annotations = {
70598
+ entrypoints: entrypoints2,
70599
+ builder,
70600
+ duration_ms: -1
70601
+ };
70602
+ let result;
70603
+ try {
70604
+ result = await builder.build(entrypoints2);
70605
+ } catch (e) {
70606
+ result = {
70607
+ warnings: [],
70608
+ errors: [WrappedErrors.fromValue(e, "Builder failed to build")],
70609
+ watchFiles: entrypoints2.map((e2) => e2.infile),
70610
+ watchDirs: [],
70611
+ producedFiles: [],
70612
+ completed: false
70613
+ };
70614
+ } finally {
70615
+ annotations.duration_ms = Date.now() - start2;
70512
70616
  }
70513
- })().catch((e) => e)
70617
+ result = await plugins.postBuild?.(result, annotations) ?? result;
70618
+ return {
70619
+ ...result,
70620
+ ...annotations
70621
+ };
70622
+ }
70514
70623
  )
70515
70624
  );
70516
- const errors = results.filter(Boolean).concat(missingBuilders);
70517
- if (errors.length) return Promise.reject(errors);
70518
- return;
70625
+ const [rejected, fulfilled] = divide(
70626
+ results,
70627
+ (r) => r.status === "rejected"
70628
+ );
70629
+ const [uncompleted, completed] = divide(fulfilled, (r) => r.value.completed);
70630
+ const errorLogs = combineErrorLogs(
70631
+ ...uncompleted.map((r) => r.value),
70632
+ ...completed.map((r) => r.value)
70633
+ );
70634
+ const errors = [
70635
+ rejected.length ? WrappedErrors.fromValues(
70636
+ rejected.map((r) => r.reason),
70637
+ "Some builders encountered errors when running",
70638
+ {
70639
+ rejected_count: rejected.length,
70640
+ entrypoints: entrypoints.map((e) => e.infile.relative),
70641
+ builders: Array.from(grouped.keys()).map(
70642
+ ({ builder }) => builder.name
70643
+ )
70644
+ }
70645
+ ) : void 0,
70646
+ ...errorLogs.errors ?? []
70647
+ ];
70648
+ const warnings = errorLogs.warnings ?? [];
70649
+ return {
70650
+ completed: rejected.length === 0 && uncompleted.length === 0,
70651
+ errors: errors.filter(isNot.undefined),
70652
+ warnings,
70653
+ watchFiles: fulfilled.flatMap((r) => r.value.watchFiles),
70654
+ watchDirs: fulfilled.flatMap((r) => r.value.watchDirs),
70655
+ producedFiles: fulfilled.flatMap((r) => r.value.producedFiles),
70656
+ entrypoints,
70657
+ duration_ms: Date.now() - start,
70658
+ children: fulfilled.map((r) => r.value)
70659
+ };
70519
70660
  }
70520
70661
 
70521
70662
  // pnp:/builds/normed/bundle/packages/bundle/src/index.ts
@@ -70649,7 +70790,47 @@ if (optClean) {
70649
70790
  }
70650
70791
  if (optBuild) {
70651
70792
  log_default.info(`Building`);
70652
- tasks.push(bundle2(options));
70793
+ tasks.push(
70794
+ bundle2(options, {
70795
+ preBuild(builderMap) {
70796
+ const builders2 = [...builderMap.entries()].sort(
70797
+ ([
70798
+ {
70799
+ builder: { name: a }
70800
+ }
70801
+ ], [
70802
+ {
70803
+ builder: { name: b }
70804
+ }
70805
+ ]) => {
70806
+ return a.localeCompare(b);
70807
+ }
70808
+ );
70809
+ for (const [{ builder }, entrypoints] of builders2) {
70810
+ log_default.info(
70811
+ builder.color(
70812
+ `${builder.name}:
70813
+ ${entrypoints.map((i) => i.infile.relative).join("\n ")}`
70814
+ )
70815
+ );
70816
+ }
70817
+ return builderMap;
70818
+ },
70819
+ postBuild(success, { builder, duration_ms }) {
70820
+ const duration = Math.floor(duration_ms / 10) / 100;
70821
+ if (success) {
70822
+ log_default.info(builder.color(`${builder.name}: ${duration} seconds`));
70823
+ } else {
70824
+ log_default.error(
70825
+ builder.color(`${builder.name}: Failed after ${duration} seconds`)
70826
+ );
70827
+ exitCode = 1;
70828
+ }
70829
+ return success;
70830
+ }
70831
+ }).then(() => {
70832
+ })
70833
+ );
70653
70834
  }
70654
70835
  function errorPrinter(error, index) {
70655
70836
  if (Array.isArray(error)) {