@roots/bud-build 6.16.1 → 6.18.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
@@ -109,12 +109,12 @@ However, the amount of effort needed to maintain and develop new features and pr
109
109
  <a href="https://wordpress.com/">
110
110
  <img src="https://cdn.roots.io/app/uploads/wordpress.svg" alt="WordPress.com" width="200" height="150"/>
111
111
  </a>
112
- <a href="https://pantheon.io/">
113
- <img src="https://cdn.roots.io/app/uploads/pantheon.svg" alt="Pantheon" width="200" height="150"/>
114
- </a>
115
112
  <a href="https://worksitesafety.ca/careers/">
116
113
  <img src="https://cdn.roots.io/app/uploads/worksite-safety.svg" alt="Worksite Safety" width="200" height="150"/>
117
114
  </a>
118
115
  <a href="https://www.copiadigital.com/">
119
116
  <img src="https://cdn.roots.io/app/uploads/copia-digital.svg" alt="Copia Digital" width="200" height="150"/>
120
117
  </a>
118
+ <a href="https://www.freave.com/">
119
+ <img src="https://cdn.roots.io/app/uploads/freave.svg" alt="Freave" width="200" height="150"/>
120
+ </a>
@@ -1,4 +1,25 @@
1
+ import { ConfigError } from '@roots/bud-support/errors';
1
2
  import isUndefined from '@roots/bud-support/lodash/isUndefined';
2
- export const dependencies = async ({ hooks, root, }) => hooks
3
- .filter(`build.dependencies`, [])
4
- .filter(label => !isUndefined(root.children[label]));
3
+ export const dependencies = async ({ hooks, label, root, }) => {
4
+ const dependencies = hooks
5
+ .filter(`build.dependencies`, [])
6
+ ?.filter(dependency => {
7
+ const defined = !isUndefined(root.children?.[dependency]);
8
+ if (!defined) {
9
+ throw ConfigError.normalize(`${dependency} is not a registered instance of bud.js.`, {
10
+ details: root.children
11
+ ? `Available instances are: ${Object.values(root.children)
12
+ .map(child => child.label)
13
+ .join(`, `)}`
14
+ : `We would tell you what the available instances are, but there are none registered.`,
15
+ docs: new URL(`https://bud.js.org/learn/general-use/multi-instance`),
16
+ instance: label,
17
+ thrownBy: `@roots/bud-build/config/dependencies`,
18
+ });
19
+ }
20
+ return true;
21
+ });
22
+ if (!dependencies || dependencies?.length < 1)
23
+ return undefined;
24
+ return dependencies;
25
+ };
@@ -1 +1,9 @@
1
- export const entry = async ({ hooks }) => hooks.filter(`build.entry`, { main: { import: [`index`] } });
1
+ export const entry = async ({ hooks }) => {
2
+ const entrypoints = hooks.filter(`build.entry`, {
3
+ main: { import: [`index`] },
4
+ });
5
+ return Object.entries(entrypoints).reduce((acc, [key, value]) => {
6
+ value.import = [...new Set(value.import)];
7
+ return { ...acc, [key]: value };
8
+ }, {});
9
+ };
@@ -3,16 +3,16 @@ export const infrastructureLogging = async (bud) => bud.hooks.filter(`build.infr
3
3
  console: bud.hooks.filter(`build.infrastructureLogging.console`, {
4
4
  ...console,
5
5
  error: (...args) => {
6
- logger.scope(bud.label, `webpack`).error(...args);
6
+ logger.unscope().error(...args);
7
7
  },
8
8
  info: (...args) => {
9
- logger.scope(bud.label, `webpack`).info(...args);
9
+ logger.unscope().info(...args);
10
10
  },
11
11
  log: (...args) => {
12
- logger.scope(bud.label, `webpack`).log(...args);
12
+ logger.unscope().log(...args);
13
13
  },
14
14
  warn: (...args) => {
15
- logger.scope(bud.label, `webpack`).info(...args);
15
+ logger.unscope().info(...args);
16
16
  },
17
17
  }),
18
18
  level: bud.hooks.filter(`build.infrastructureLogging.level`, `log`),
@@ -21,7 +21,12 @@ export const output = async ({ hooks: { filter }, isProduction, path, relPath, }
21
21
  * @see {@link https://medium.com/@kenneth_chau/speeding-up-webpack-typescript-incremental-builds-by-7x-3912ba4c1d15}
22
22
  */
23
23
  pathinfo: filter(`build.output.pathinfo`, false),
24
- publicPath: filter(`build.output.publicPath`, `auto`),
24
+ publicPath: (() => {
25
+ const value = filter(`build.output.publicPath`, `auto`);
26
+ if ([``, `auto`].includes(value))
27
+ return value;
28
+ return value.endsWith(`/`) ? value : `${value}/`;
29
+ })(),
25
30
  scriptType: filter(`build.output.scriptType`, undefined),
26
31
  uniqueName: filter(`build.output.uniqueName`, `@roots/bud`),
27
32
  });
package/lib/item/index.js CHANGED
@@ -4,6 +4,7 @@ import Registrable from '@roots/bud-build/helpers/registrable';
4
4
  import Loader from '@roots/bud-build/loader';
5
5
  import { bind } from '@roots/bud-support/decorators/bind';
6
6
  import isString from '@roots/bud-support/lodash/isString';
7
+ import logger from '@roots/bud-support/logger';
7
8
  /**
8
9
  * Item class
9
10
  */
@@ -98,7 +99,7 @@ class Item extends Registrable {
98
99
  output.ident = this.getIdent();
99
100
  }
100
101
  if (!output.loader) {
101
- this.app.error(`error in ${this.ident}`, `no loader registered`);
102
+ logger.error(`error in ${this.ident}`, `no loader registered`);
102
103
  }
103
104
  return Object.entries(output).reduce((output, [key, value]) => ({
104
105
  ...(output ?? {}),
@@ -16,7 +16,9 @@ async function register(bud) {
16
16
  bud.build.items.precss = bud.isProduction
17
17
  ? bud.build.items.minicss
18
18
  : bud.build.items.style;
19
- Object.entries(rules).map(makeRegister(bud, bud.build.setRule));
19
+ await Promise.all(Object.entries(rules).map(makeRegister(bud, bud.build.setRule))).catch(e => {
20
+ throw e;
21
+ });
20
22
  }
21
23
  /**
22
24
  * Registry factory
package/lib/rule/index.js CHANGED
@@ -3,6 +3,7 @@ import Registrable from '@roots/bud-build/helpers/registrable';
3
3
  import { bind } from '@roots/bud-support/decorators/bind';
4
4
  import isFunction from '@roots/bud-support/lodash/isFunction';
5
5
  import isString from '@roots/bud-support/lodash/isString';
6
+ import logger from '@roots/bud-support/logger';
6
7
  /**
7
8
  * RuleSetRule
8
9
  */
@@ -206,7 +207,7 @@ class Rule extends Registrable {
206
207
  return a;
207
208
  return { ...a, [k]: v };
208
209
  }, {});
209
- this.app.info(`built rule`, output);
210
+ logger.info(`built rule`, output);
210
211
  return output;
211
212
  }
212
213
  }
@@ -1,5 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import type { Factory } from '@roots/bud-build/registry';
3
2
  declare const inlineSvg: Factory;
4
- declare const dataUrl: (data: Buffer) => string;
3
+ declare const dataUrl: (data: Uint8Array) => string;
5
4
  export { dataUrl, inlineSvg as default };
@@ -55,22 +55,32 @@ class Build extends Service {
55
55
  async make() {
56
56
  this.logger.log(`bud.build.make called`);
57
57
  await this.app.hooks.fire(`build.before`, this.app);
58
- await import(`@roots/bud-build/config`).then(async (records) => await Promise.all(Object.entries(records).map(async ([prop, factory]) => {
59
- try {
60
- const value = await factory(this.app);
61
- if (isUndefined(value))
62
- return;
63
- this.config[prop] = value;
64
- this.logger.success(`built`, prop);
58
+ await import(`@roots/bud-build/config`)
59
+ .then(async (records) => await Promise.all(Object.entries(records).map(async ([prop, factory]) => {
60
+ const value = await factory(this.app).catch(this.catch);
61
+ if (isUndefined(value)) {
62
+ this.logger.success(`omitting:`, prop, `(undefined)`);
63
+ return;
65
64
  }
66
- catch (error) {
67
- throw error;
68
- }
69
- })));
70
- this.logger.success(`configuration successfully built`);
65
+ Object.defineProperty(this.config, prop, {
66
+ configurable: true,
67
+ enumerable: true,
68
+ value,
69
+ writable: true,
70
+ });
71
+ this.logger
72
+ .success(`defined:`, prop, `(${typeof this.config[prop]})`)
73
+ .info(prop, `info:`, this.config[prop]);
74
+ })))
75
+ .catch(this.catch);
76
+ this.logger.success(`configuration built`);
71
77
  this.logger.info(this.config);
72
- await this.app.hooks.fire(`build.after`, this.app);
73
- return this.config;
78
+ await this.app.hooks.fire(`build.after`, this.app).catch(this.catch);
79
+ return Object.entries(this.config).reduce((a, [k, v]) => {
80
+ if (isUndefined(v))
81
+ return a;
82
+ return { ...a, [k]: v };
83
+ }, {});
74
84
  }
75
85
  /**
76
86
  * {@link BudBuild.makeItem}
@@ -94,6 +104,7 @@ class Build extends Service {
94
104
  * {@link BudBuild.setItem}
95
105
  */
96
106
  setItem(ident, definition) {
107
+ this.logger.log(`build.setItem`, ident);
97
108
  const maybeOptionsCallback = isUndefined(definition)
98
109
  ? { ident, loader: ident }
99
110
  : definition;
@@ -101,36 +112,41 @@ class Build extends Service {
101
112
  ? maybeOptionsCallback(this.makeItem())
102
113
  : this.makeItem(maybeOptionsCallback);
103
114
  this.items[ident] = item;
104
- this.logger.info(`set item`, item);
115
+ this.logger.info(item);
105
116
  return this;
106
117
  }
107
118
  /**
108
119
  * {@link BudBuild.setLoader}
109
120
  */
110
121
  setLoader(name, definition) {
122
+ this.logger.log(`build.setLoader`, name);
111
123
  const loader = isUndefined(definition)
112
124
  ? this.makeLoader(name)
113
125
  : definition instanceof Loader
114
126
  ? definition
115
127
  : this.makeLoader(definition);
116
128
  this.loaders[name] = loader;
117
- this.logger.info(`set loader`, loader);
129
+ this.logger.info(loader);
118
130
  return this;
119
131
  }
120
132
  /**
121
133
  * {@link BudBuild.setRule}
122
134
  */
123
135
  setRule(name, definition) {
136
+ this.logger.log(`build.setRule`, name);
124
137
  const rule = definition instanceof Rule
125
138
  ? definition
126
139
  : isFunction(definition)
127
140
  ? definition(this.makeRule())
128
141
  : this.makeRule(definition);
129
142
  this.rules[name] = rule;
130
- this.logger.info(`set rule`, rule);
143
+ this.logger.info(rule);
131
144
  return this;
132
145
  }
133
146
  }
147
+ __decorate([
148
+ bind
149
+ ], Build.prototype, "bootstrap", null);
134
150
  __decorate([
135
151
  bind
136
152
  ], Build.prototype, "getItem", null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@roots/bud-build",
3
- "version": "6.16.1",
3
+ "version": "6.18.0",
4
4
  "description": "bud.js core module",
5
5
  "engines": {
6
6
  "node": ">=16"
@@ -169,14 +169,14 @@
169
169
  "types": "./lib/index.d.ts",
170
170
  "module": "./lib/index.js",
171
171
  "devDependencies": {
172
- "@roots/bud-api": "6.16.1",
173
- "@roots/bud-hooks": "6.16.1",
172
+ "@roots/bud-api": "6.18.0",
173
+ "@roots/bud-hooks": "6.18.0",
174
174
  "@skypack/package-check": "0.2.2",
175
- "@types/node": "18.17.9"
175
+ "@types/node": "20.9.0"
176
176
  },
177
177
  "dependencies": {
178
- "@roots/bud-framework": "6.16.1",
179
- "@roots/bud-support": "6.16.1",
178
+ "@roots/bud-framework": "6.18.0",
179
+ "@roots/bud-support": "6.18.0",
180
180
  "tslib": "2.6.2"
181
181
  },
182
182
  "volta": {
@@ -1,11 +1,40 @@
1
1
  import type {Factory} from '@roots/bud-build/config'
2
2
 
3
+ import {ConfigError} from '@roots/bud-support/errors'
3
4
  import isUndefined from '@roots/bud-support/lodash/isUndefined'
4
5
 
5
6
  export const dependencies: Factory<`dependencies`> = async ({
6
7
  hooks,
8
+ label,
7
9
  root,
8
- }) =>
9
- hooks
10
+ }) => {
11
+ const dependencies = hooks
10
12
  .filter(`build.dependencies`, [])
11
- .filter(label => !isUndefined(root.children[label]))
13
+ ?.filter(dependency => {
14
+ const defined = !isUndefined(root.children?.[dependency])
15
+
16
+ if (!defined) {
17
+ throw ConfigError.normalize(
18
+ `${dependency} is not a registered instance of bud.js.`,
19
+ {
20
+ details: root.children
21
+ ? `Available instances are: ${Object.values(root.children)
22
+ .map(child => child.label)
23
+ .join(`, `)}`
24
+ : `We would tell you what the available instances are, but there are none registered.`,
25
+ docs: new URL(
26
+ `https://bud.js.org/learn/general-use/multi-instance`,
27
+ ),
28
+ instance: label,
29
+ thrownBy: `@roots/bud-build/config/dependencies`,
30
+ },
31
+ )
32
+ }
33
+
34
+ return true
35
+ })
36
+
37
+ if (!dependencies || dependencies?.length < 1) return undefined
38
+
39
+ return dependencies
40
+ }
@@ -1,4 +1,12 @@
1
1
  import type {Factory} from '@roots/bud-build/config'
2
2
 
3
- export const entry: Factory<`entry`> = async ({hooks}) =>
4
- hooks.filter(`build.entry`, {main: {import: [`index`]}})
3
+ export const entry: Factory<`entry`> = async ({hooks}) => {
4
+ const entrypoints = hooks.filter(`build.entry`, {
5
+ main: {import: [`index`]},
6
+ })
7
+
8
+ return Object.entries(entrypoints).reduce((acc, [key, value]) => {
9
+ value.import = [...new Set(value.import)]
10
+ return {...acc, [key]: value}
11
+ }, {})
12
+ }
@@ -9,16 +9,16 @@ export const infrastructureLogging: Factory<
9
9
  console: bud.hooks.filter(`build.infrastructureLogging.console`, {
10
10
  ...console,
11
11
  error: (...args: any[]) => {
12
- logger.scope(bud.label, `webpack`).error(...args)
12
+ logger.unscope().error(...args)
13
13
  },
14
14
  info: (...args: any[]) => {
15
- logger.scope(bud.label, `webpack`).info(...args)
15
+ logger.unscope().info(...args)
16
16
  },
17
17
  log: (...args: any[]) => {
18
- logger.scope(bud.label, `webpack`).log(...args)
18
+ logger.unscope().log(...args)
19
19
  },
20
20
  warn: (...args: any[]) => {
21
- logger.scope(bud.label, `webpack`).info(...args)
21
+ logger.unscope().info(...args)
22
22
  },
23
23
  }),
24
24
  level: bud.hooks.filter(`build.infrastructureLogging.level`, `log`),
@@ -30,7 +30,11 @@ export const output: Factory<`output`> = async ({
30
30
  * @see {@link https://medium.com/@kenneth_chau/speeding-up-webpack-typescript-incremental-builds-by-7x-3912ba4c1d15}
31
31
  */
32
32
  pathinfo: filter(`build.output.pathinfo`, false),
33
- publicPath: filter(`build.output.publicPath`, `auto`),
33
+ publicPath: (() => {
34
+ const value = filter(`build.output.publicPath`, `auto`)
35
+ if ([``, `auto`].includes(value)) return value
36
+ return value.endsWith(`/`) ? value : `${value}/`
37
+ })(),
34
38
  scriptType: filter(`build.output.scriptType`, undefined),
35
39
  uniqueName: filter(`build.output.uniqueName`, `@roots/bud`),
36
40
  })
package/src/item/index.ts CHANGED
@@ -7,6 +7,7 @@ import Registrable from '@roots/bud-build/helpers/registrable'
7
7
  import Loader from '@roots/bud-build/loader'
8
8
  import {bind} from '@roots/bud-support/decorators/bind'
9
9
  import isString from '@roots/bud-support/lodash/isString'
10
+ import logger from '@roots/bud-support/logger'
10
11
 
11
12
  export type ConstructorOptions = Build.Item.ConstructorOptions
12
13
 
@@ -139,7 +140,7 @@ class Item extends Registrable implements Build.Item {
139
140
  }
140
141
 
141
142
  if (!output.loader) {
142
- this.app.error(`error in ${this.ident}`, `no loader registered`)
143
+ logger.error(`error in ${this.ident}`, `no loader registered`)
143
144
  }
144
145
 
145
146
  return Object.entries(output).reduce(
@@ -36,7 +36,11 @@ async function register(bud: Bud) {
36
36
  ? bud.build.items.minicss
37
37
  : bud.build.items.style
38
38
 
39
- Object.entries(rules).map(makeRegister(bud, bud.build.setRule))
39
+ await Promise.all(
40
+ Object.entries(rules).map(makeRegister(bud, bud.build.setRule)),
41
+ ).catch(e => {
42
+ throw e
43
+ })
40
44
  }
41
45
 
42
46
  /**
package/src/rule/index.ts CHANGED
@@ -11,6 +11,7 @@ import Registrable from '@roots/bud-build/helpers/registrable'
11
11
  import {bind} from '@roots/bud-support/decorators/bind'
12
12
  import isFunction from '@roots/bud-support/lodash/isFunction'
13
13
  import isString from '@roots/bud-support/lodash/isString'
14
+ import logger from '@roots/bud-support/logger'
14
15
 
15
16
  /**
16
17
  * RuleSetRule
@@ -273,7 +274,7 @@ class Rule extends Registrable implements Interface {
273
274
  return {...a, [k]: v}
274
275
  }, {})
275
276
 
276
- this.app.info(`built rule`, output)
277
+ logger.info(`built rule`, output)
277
278
 
278
279
  return output
279
280
  }
@@ -10,6 +10,6 @@ const inlineSvg: Factory = async ({filter, makeRule, path}) =>
10
10
  .setGenerator({dataUrl})
11
11
  .setType(`asset/inline`)
12
12
 
13
- const dataUrl = (data: Buffer) => dataUri(data.toString())
13
+ const dataUrl = (data: Uint8Array) => dataUri(data.toString())
14
14
 
15
15
  export {dataUrl, inlineSvg as default}
@@ -1,4 +1,3 @@
1
- import type {Records} from '@roots/bud-build/config'
2
1
  import type {Bud, Build as BudBuild} from '@roots/bud-framework'
3
2
  import type {Items, Loaders, Rules} from '@roots/bud-framework'
4
3
  import type {Configuration} from '@roots/bud-framework/config'
@@ -44,6 +43,7 @@ class Build extends Service implements BudBuild {
44
43
  /**
45
44
  * {@link Service.register}
46
45
  */
46
+ @bind
47
47
  public override async bootstrap?(app: Bud) {
48
48
  this.items = {} as Items
49
49
  this.loaders = {} as Loaders
@@ -92,28 +92,41 @@ class Build extends Service implements BudBuild {
92
92
  this.logger.log(`bud.build.make called`)
93
93
  await this.app.hooks.fire(`build.before`, this.app)
94
94
 
95
- await import(`@roots/bud-build/config`).then(
96
- async (records: Records) =>
97
- await Promise.all(
98
- Object.entries(records).map(async ([prop, factory]) => {
99
- try {
100
- const value = await factory(this.app)
101
- if (isUndefined(value)) return
102
-
103
- this.config[prop] = value
104
- this.logger.success(`built`, prop)
105
- } catch (error) {
106
- throw error
107
- }
108
- }),
109
- ),
110
- )
111
-
112
- this.logger.success(`configuration successfully built`)
95
+ await import(`@roots/bud-build/config`)
96
+ .then(
97
+ async records =>
98
+ await Promise.all(
99
+ Object.entries(records).map(async ([prop, factory]) => {
100
+ const value = await factory(this.app).catch(this.catch)
101
+ if (isUndefined(value)) {
102
+ this.logger.success(`omitting:`, prop, `(undefined)`)
103
+ return
104
+ }
105
+
106
+ Object.defineProperty(this.config, prop, {
107
+ configurable: true,
108
+ enumerable: true,
109
+ value,
110
+ writable: true,
111
+ })
112
+
113
+ this.logger
114
+ .success(`defined:`, prop, `(${typeof this.config[prop]})`)
115
+ .info(prop, `info:`, this.config[prop])
116
+ }),
117
+ ),
118
+ )
119
+ .catch(this.catch)
120
+
121
+ this.logger.success(`configuration built`)
113
122
  this.logger.info(this.config)
114
- await this.app.hooks.fire(`build.after`, this.app)
115
123
 
116
- return this.config
124
+ await this.app.hooks.fire(`build.after`, this.app).catch(this.catch)
125
+
126
+ return Object.entries(this.config).reduce((a, [k, v]) => {
127
+ if (isUndefined(v)) return a
128
+ return {...a, [k]: v}
129
+ }, {})
117
130
  }
118
131
 
119
132
  /**
@@ -148,6 +161,7 @@ class Build extends Service implements BudBuild {
148
161
  ident: K,
149
162
  definition?: ((item: Items[K]) => Items[K]) | Items[K],
150
163
  ): this {
164
+ this.logger.log(`build.setItem`, ident)
151
165
  const maybeOptionsCallback = isUndefined(definition)
152
166
  ? {ident, loader: ident}
153
167
  : definition
@@ -157,7 +171,7 @@ class Build extends Service implements BudBuild {
157
171
  : this.makeItem(maybeOptionsCallback)
158
172
 
159
173
  this.items[ident] = item
160
- this.logger.info(`set item`, item)
174
+ this.logger.info(item)
161
175
 
162
176
  return this
163
177
  }
@@ -170,14 +184,15 @@ class Build extends Service implements BudBuild {
170
184
  name: K,
171
185
  definition?: any,
172
186
  ): this {
187
+ this.logger.log(`build.setLoader`, name)
173
188
  const loader = isUndefined(definition)
174
189
  ? this.makeLoader(name)
175
190
  : definition instanceof Loader
176
- ? definition
177
- : this.makeLoader(definition)
191
+ ? definition
192
+ : this.makeLoader(definition)
178
193
 
179
194
  this.loaders[name] = loader
180
- this.logger.info(`set loader`, loader)
195
+ this.logger.info(loader)
181
196
 
182
197
  return this
183
198
  }
@@ -190,15 +205,16 @@ class Build extends Service implements BudBuild {
190
205
  name: K,
191
206
  definition?: Rule | RuleOptions,
192
207
  ): this {
208
+ this.logger.log(`build.setRule`, name)
193
209
  const rule =
194
210
  definition instanceof Rule
195
211
  ? definition
196
212
  : isFunction(definition)
197
- ? definition(this.makeRule())
198
- : this.makeRule(definition as any)
213
+ ? definition(this.makeRule())
214
+ : this.makeRule(definition as any)
199
215
 
200
216
  this.rules[name] = rule
201
- this.logger.info(`set rule`, rule)
217
+ this.logger.info(rule)
202
218
 
203
219
  return this
204
220
  }