@fontoxml/fontoxml-development-tools 3.9.0-beta.6 → 3.10.0-beta.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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@fontoxml/fontoxml-development-tools",
3
- "version": "3.9.0-beta.6",
3
+ "version": "3.10.0-beta.1",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@fontoxml/fontoxml-development-tools",
9
- "version": "3.9.0-beta.6",
9
+ "version": "3.10.0-beta.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@babel/core": "7.14.6",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fontoxml/fontoxml-development-tools",
3
3
  "description": "Development tools for Fonto.",
4
- "version": "3.9.0-beta.6",
4
+ "version": "3.10.0-beta.1",
5
5
  "author": "The Fonto Team",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -1,3 +1,4 @@
1
+ import correlationIdRepository from './correlationIdRepository.js';
1
2
  import DevelopmentCms from './stores/DevelopmentCms.js';
2
3
 
3
4
  export default function (config) {
@@ -6,6 +7,10 @@ export default function (config) {
6
7
  return (req, _res, next) => {
7
8
  req.cms = cms;
8
9
 
10
+ req.repositories = {
11
+ correlationId: correlationIdRepository,
12
+ };
13
+
9
14
  next();
10
15
  };
11
16
  }
@@ -16,7 +16,7 @@ export default function getPatternsForSpecialFileType(type) {
16
16
  return ['src/*.@(js|jsx|ts|tsx)', '!src/*.d.ts'];
17
17
  case 'unitTestSpecs':
18
18
  return ['test/**/*.tests.@(js|ts)'];
19
- case 'unitTestUseConfigurationManager':
19
+ case 'unitTestConfigurationManager':
20
20
  return [];
21
21
  default:
22
22
  throw new Error(`Unsupported special file type "${type}".`);
@@ -10,6 +10,7 @@ import webpack from 'webpack';
10
10
 
11
11
  import normalisePath from '../src/helpers/normalisePath.js';
12
12
  import getNamesAndPaths from './helpers/getNamesAndPaths.js';
13
+ import CheckDeepImportsResolvePlugin from './webpackPlugins/CheckDeepImportsResolvePlugin.js';
13
14
  import CopyPlugin from './webpackPlugins/CopyPlugin.js';
14
15
  import DependenciesInLoadOrderPlugin from './webpackPlugins/DependenciesInLoadOrderPlugin.js';
15
16
  import FdtOutputPlugin from './webpackPlugins/FdtOutputPlugin.js';
@@ -44,6 +45,9 @@ export default function getWebpackConfig(appConfig, appManifest, options) {
44
45
  generatedFile: picomatch.makeRe(paths.generatedFile),
45
46
 
46
47
  // Folders
48
+ config: picomatch.makeRe(`${paths.configFolder}**/*`),
49
+ packages: picomatch.makeRe(`${paths.packagesFolder}**/*`),
50
+ packagesShared: picomatch.makeRe(`${paths.packagesSharedFolder}**/*`),
47
51
  platform: picomatch.makeRe(`${paths.platformFolder}**/*`),
48
52
  platformVendors: picomatch.makeRe(`${paths.platformVendorsFolder}**/*`),
49
53
  platformLinkedVendors: picomatch.makeRe(
@@ -51,8 +55,25 @@ export default function getWebpackConfig(appConfig, appManifest, options) {
51
55
  ),
52
56
  srcFolder: picomatch.makeRe(`${paths.srcFolder}**/*`),
53
57
  testAssets: picomatch.makeRe(`${paths.testAssetsFolder}**/*`),
58
+
59
+ // Deep imports
60
+ platformDeepImport: picomatch.makeRe(
61
+ `${paths.platformFolder}*/src/*/**/*`
62
+ ),
63
+ platformLinkedDeepImport: picomatch.makeRe(
64
+ `${paths.platformLinkedFolder}*/src/*/**/*`
65
+ ),
54
66
  };
55
67
 
68
+ // Used to share some state between (resolve) plugins.
69
+ const fdtOutputPlugin =
70
+ !appConfig.verbose && options.fdtResponse
71
+ ? new FdtOutputPlugin({
72
+ inDevelopmentMode: options.inDevelopmentMode,
73
+ res: options.fdtResponse,
74
+ })
75
+ : null;
76
+
56
77
  return {
57
78
  context: paths.srcFolder,
58
79
  entry: !options.unitTest ? paths.entryFile : undefined,
@@ -88,23 +109,23 @@ export default function getWebpackConfig(appConfig, appManifest, options) {
88
109
  !regExps.json.test(resource)),
89
110
  type: 'asset/source',
90
111
  },
91
- {
92
- test: (resource) =>
93
- regExps.platform.test(resource) &&
94
- !regExps.platformVendors.test(resource) &&
95
- !regExps.assets.test(resource) &&
96
- regExps.code.test(resource),
97
- use: [
98
- {
99
- loader: paths.platformSourceMapLoader,
100
- options: {
101
- platformFolder: paths.platformFolder,
102
- platformSourceMapFile:
103
- paths.platformSourceMapFile,
104
- },
105
- },
106
- ],
107
- },
112
+ // {
113
+ // test: (resource) =>
114
+ // regExps.platform.test(resource) &&
115
+ // !regExps.platformVendors.test(resource) &&
116
+ // !regExps.assets.test(resource) &&
117
+ // regExps.code.test(resource),
118
+ // use: [
119
+ // {
120
+ // loader: paths.platformSourceMapLoader,
121
+ // options: {
122
+ // platformFolder: paths.platformFolder,
123
+ // platformSourceMapFile:
124
+ // paths.platformSourceMapFile,
125
+ // },
126
+ // },
127
+ // ],
128
+ // },
108
129
  {
109
130
  test: (resource) =>
110
131
  regExps.platformLinkedVendors.test(resource) &&
@@ -297,13 +318,8 @@ export default function getWebpackConfig(appConfig, appManifest, options) {
297
318
  new MiniCssExtractPlugin({
298
319
  filename: names.outputCssFile,
299
320
  }),
300
- appConfig.verbose
301
- ? !options.unitTest && new webpack.ProgressPlugin()
302
- : !!options.fdtResponse &&
303
- new FdtOutputPlugin({
304
- inDevelopmentMode: options.inDevelopmentMode,
305
- res: options.fdtResponse,
306
- }),
321
+ fdtOutputPlugin ||
322
+ (!options.unitTest && new webpack.ProgressPlugin()),
307
323
  !options.unitTest &&
308
324
  new HtmlWebpackPlugin({
309
325
  editor: {
@@ -354,7 +370,22 @@ export default function getWebpackConfig(appConfig, appManifest, options) {
354
370
  new RemoveExplicitExtensionResolvePlugin({
355
371
  extensions: resolveExtensions,
356
372
  }),
357
- ],
373
+ !options.unitTest &&
374
+ new CheckDeepImportsResolvePlugin({
375
+ extensions: resolveExtensions,
376
+ contextFolder: paths.contextFolder,
377
+ issuerRegExps: [
378
+ regExps.packages,
379
+ regExps.packagesShared,
380
+ regExps.config,
381
+ ],
382
+ importPathRegExps: [
383
+ regExps.platformDeepImport,
384
+ regExps.platformLinkedDeepImport,
385
+ ],
386
+ fdtOutputPlugin,
387
+ }),
388
+ ].filter(Boolean),
358
389
  // Module resolution is attempted in the order defined here.
359
390
  modules: paths.packageRootFolders,
360
391
  symlinks: false,
@@ -113,7 +113,7 @@ export default function getNamesAndPaths(appConfig, options) {
113
113
  platformSourceMapLoader: path.posix.join(
114
114
  srcFolder,
115
115
  'webpackLoaders',
116
- 'vendorsSourceMapLoader.cjs'
116
+ 'platformSourceMapLoader.cjs'
117
117
  ),
118
118
  srcFolder,
119
119
  symbolLoader: path.posix.join(
@@ -129,7 +129,7 @@ export default function getNamesAndPaths(appConfig, options) {
129
129
  vendorsSourceMapLoader: path.posix.join(
130
130
  srcFolder,
131
131
  'webpackLoaders',
132
- 'platformSourceMapLoader.cjs'
132
+ 'vendorsSourceMapLoader.cjs'
133
133
  ),
134
134
  };
135
135
  paths.generatedFile = path.posix.join(paths.templatesFolder, 'generated');
@@ -311,7 +311,7 @@ async function handleUnitTest({
311
311
  code = statements
312
312
  .map((statement) => `import '${statement.path}';`)
313
313
  .join('\n');
314
- } else if (type === 'unitTestUseConfigurationManager') {
314
+ } else if (type === 'unitTestConfigurationManager') {
315
315
  // packagesInfoInLoadOrder is filtered for the unit test types, so get them all again.
316
316
  const allPackagesInfoInLoadOrder =
317
317
  loaderContext._compilation.packagesInfoInLoadOrder;
@@ -323,7 +323,9 @@ async function handleUnitTest({
323
323
  );
324
324
 
325
325
  const useConfigurationManager = !!dependsOnFontoxmlConfigurationPackage;
326
- code = `export default ${useConfigurationManager};`;
326
+ code = useConfigurationManager
327
+ ? `export { default } from 'fontoxml-configuration/src/configurationManager';`
328
+ : `export default null;`;
327
329
  }
328
330
 
329
331
  code = code.trim();
@@ -386,7 +388,7 @@ module.exports = async function generatedLoader(input, inputMap) {
386
388
  case 'unitTestConfiguration':
387
389
  case 'unitTestSmokeTest':
388
390
  case 'unitTestSpecs':
389
- case 'unitTestUseConfigurationManager':
391
+ case 'unitTestConfigurationManager':
390
392
  return handleUnitTest(handlerOptions);
391
393
  case 'versionInfo':
392
394
  return handleVersionInfo(handlerOptions);
@@ -0,0 +1,123 @@
1
+ import path from 'path';
2
+
3
+ import normalisePath from '../helpers/normalisePath.js';
4
+
5
+ /** @typedef {import('enhanced-resolve').Resolver} Resolver */
6
+
7
+ const firstPathSegmentRegExp = /^.+?\//;
8
+
9
+ /**
10
+ * Converts the given path to something that approximates its import identifier.
11
+ *
12
+ * @param {string} targetPath
13
+ * @returns {string}
14
+ */
15
+ function getApproximateImportIdentifierForPath(targetPath) {
16
+ const parsedTargetPath = path.parse(targetPath);
17
+
18
+ targetPath = normalisePath(
19
+ path.join(parsedTargetPath.dir, parsedTargetPath.name)
20
+ );
21
+
22
+ return targetPath.replace(firstPathSegmentRegExp, '');
23
+ }
24
+
25
+ class DeepImportWarning extends Error {
26
+ /**
27
+ * @param {string} message
28
+ * @param {string} file
29
+ */
30
+ constructor(message, file) {
31
+ super(message);
32
+
33
+ this.file = file;
34
+ }
35
+
36
+ toString() {
37
+ return this.file
38
+ ? `WARNING in ${this.file}:\n${this.message}`
39
+ : `WARNING: ${this.message}`;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * This plugin generates a warning for imports to platform/ or platform-linked/ from from config/,
45
+ * packages/ or packages-shared/ that do not point to something in a package's 'src' folder.
46
+ */
47
+ export default class CheckDeepImportsResolvePlugin {
48
+ constructor(options = {}) {
49
+ this.options = options;
50
+ }
51
+
52
+ /**
53
+ * @param {Resolver} resolver
54
+ */
55
+ apply(resolver) {
56
+ resolver
57
+ .getHook('resolved')
58
+ .tapAsync(
59
+ CheckDeepImportsResolvePlugin.name,
60
+ (request, _resolveContext, callback) => {
61
+ // Can only check if there's an issuer and a resolved path.
62
+ // Issuer: path to the file from which the import originates.
63
+ // Path: path to the file to which the import resolves.
64
+ if (
65
+ !request.context ||
66
+ !request.context.issuer ||
67
+ !request.path
68
+ ) {
69
+ return callback();
70
+ }
71
+
72
+ if (
73
+ // Only check imports to code (i.e. .js, .ts, .jsx, .tsx).
74
+ // The .xqm and .svg files are transformed by a loader which do a deep
75
+ // import to XQueryModule and SVGModule respectively, for which no warning
76
+ // is needed.
77
+ this.options.extensions.includes(
78
+ path.posix.extname(request.context.issuer)
79
+ ) &&
80
+ // Only check certain issuers (i.e. packages/, packages-shared/, config/).
81
+ this.options.issuerRegExps.some((regExp) =>
82
+ regExp.test(request.context.issuer)
83
+ ) &&
84
+ // Does the import target an undesired path?
85
+ this.options.importPathRegExps.some((regExp) =>
86
+ regExp.test(request.path)
87
+ )
88
+ ) {
89
+ // Make the absolute paths easier to read.
90
+ const relativePath = path.relative(
91
+ this.options.contextFolder,
92
+ request.path
93
+ );
94
+ const relativeIssuer = path.relative(
95
+ this.options.contextFolder,
96
+ request.context.issuer
97
+ );
98
+
99
+ // We don't have access to the import identifier matching the resolved path
100
+ // at this point, so approximate it for the warning message. Should be about
101
+ // right most of the time, but we can't say for sure.
102
+ const importIdentifier =
103
+ getApproximateImportIdentifierForPath(relativePath);
104
+
105
+ // Pass the warning to the output plugin so it can properly output it after
106
+ // the compilation finishes.
107
+ const warning = new DeepImportWarning(
108
+ `Import "${importIdentifier}" is not supported and might cause problems in future versions.`,
109
+ relativeIssuer
110
+ );
111
+ if (this.options.fdtOutputPlugin) {
112
+ this.options.fdtOutputPlugin.warn(warning);
113
+ } else {
114
+ console.warn(`\n${warning.toString()}`);
115
+ }
116
+ }
117
+
118
+ // We do not need to mutate the request, so call the callback without arguments.
119
+ return callback();
120
+ }
121
+ );
122
+ }
123
+ }
@@ -24,10 +24,18 @@ export default class FdtOutputPlugin {
24
24
  this.resetState();
25
25
  }
26
26
 
27
+ /**
28
+ * @param {Error} warning
29
+ */
30
+ warn(warning) {
31
+ this.warnings.push(warning);
32
+ }
33
+
27
34
  resetState() {
28
35
  this.previousBuildMessageTimestamp = 0;
29
36
  this.previousProgressIsBuild = false;
30
37
  this.previousRoundedPercentage = null;
38
+ this.warnings = [];
31
39
  }
32
40
 
33
41
  /**
@@ -80,7 +88,10 @@ export default class FdtOutputPlugin {
80
88
  }ms`
81
89
  : `Build done at ${endTimestamp}`;
82
90
 
83
- if (stats && (stats.hasErrors() || stats.hasWarnings())) {
91
+ if (
92
+ stats &&
93
+ (stats.hasErrors() || stats.hasWarnings() || this.warnings.length)
94
+ ) {
84
95
  this.res.needsClearing = true;
85
96
  this.res.clearIfNeeded();
86
97
 
@@ -91,8 +102,16 @@ export default class FdtOutputPlugin {
91
102
  moduleTrace: true,
92
103
  warnings: true,
93
104
  });
94
- this.res.raw(errorsAndWarnings);
95
- this.res.raw(os.EOL + os.EOL);
105
+ if (errorsAndWarnings) {
106
+ this.res.raw(errorsAndWarnings);
107
+ this.res.raw(os.EOL);
108
+ }
109
+ if (this.warnings.length) {
110
+ for (const warning of this.warnings) {
111
+ this.res.notice(warning.toString());
112
+ this.res.raw(os.EOL);
113
+ }
114
+ }
96
115
 
97
116
  this.res[stats.hasErrors() ? 'error' : 'notice'](
98
117
  stats.hasErrors() && stats.hasWarnings()