@digigov/cli-build 2.0.0-e7d30530 → 2.0.0-eaf330f5

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,39 +1,86 @@
1
- import { logger } from '@digigov/cli/lib';
2
- import path from 'path';
3
- import fs from 'fs-extra';
4
- import { SyntaxKind, Project as TsMorphProject } from 'ts-morph';
5
- import assert from 'assert';
6
-
7
- import { getProjectTsconfig } from './common.js';
8
-
9
- /** @typedef {Object} Project - Represents the project to be built
10
- * @property {string} root - The project root directory
11
- * @property {string} name - The project name as in package.json
12
- * @property {string} distDir - The project build directory
1
+ import { logger } from "@digigov/cli/lib";
2
+ import path from "path";
3
+ import fs from "fs-extra";
4
+ import { SyntaxKind, Project as TsMorphProject } from "ts-morph";
5
+ import assert from "assert";
6
+
7
+ import { getProjectTsconfig } from "./common.js";
8
+
9
+ /**
10
+ * Generate registry files for the given project
11
+ *
12
+ * @param {object} project - The project object
13
+ * @param {string} project.root - The project root directory
14
+ * @param {string} project.distDir - The project build directory
15
+ * @param {string} project.name - The project name as in package.json
16
+ * @param {string[]} filePaths - The paths of the files to include in the registry
17
+ * @param {boolean} shouldGenerateStoriesRegistry - Whether to export stories in the registry
18
+ * @returns {Promise<[string, string]>} - The paths of the generated registry files
13
19
  */
20
+ export async function generateRegistryFiles(
21
+ project,
22
+ filePaths,
23
+ shouldGenerateStoriesRegistry = false,
24
+ ) {
25
+ const registryPath = ensureRegistryPath(project, "registry.js");
26
+ const lazyRegistryPath = ensureRegistryPath(project, "lazy.js");
27
+
28
+ const registry = generateRegistryFileContent(
29
+ project,
30
+ filePaths,
31
+ shouldGenerateStoriesRegistry,
32
+ );
33
+
34
+ const componentPathsOnly = filePaths.filter(
35
+ (path) => !path.includes("stories"),
36
+ );
37
+ const lazyRegistry = generateLazyFileContent(project, componentPathsOnly);
38
+
39
+ await Promise.all([
40
+ fs.writeFile(registryPath, registry),
41
+ fs.writeFile(lazyRegistryPath, lazyRegistry),
42
+ ]);
43
+
44
+ return [registryPath, lazyRegistryPath];
45
+ }
14
46
 
15
47
  /**
16
- * Generate registry file for the given project
48
+ * Ensure that the registry file does not already exist at the given path
17
49
  *
18
- * @param {Project} project - The project object
19
- * @param {string} [registryFilename="registry.js"] - The name of the registry file
50
+ * @param {object} project - The project object
51
+ * @param {string} project.root - The project root directory
52
+ * @param {string} project.distDir - The project build directory
53
+ * @param {string} fileName - The name of the registry file
54
+ */
55
+ function ensureRegistryPath(project, fileName) {
56
+ const registryPath = path.join(project.root, project.distDir, fileName);
57
+ if (fs.existsSync(registryPath))
58
+ throw new Error(`A "${fileName}" file already exists at ${registryPath}.`);
59
+ return registryPath;
60
+ }
61
+
62
+ /**
63
+ * Generate registry file content for the given files
64
+ *
65
+ * @param {object} project - The project object
66
+ * @param {string} project.root - The project root directory
67
+ * @param {string} project.name - The project name as in package.json
20
68
  * @param {string[]} absoluteFilePaths - The absolute paths of the files to include in the registry
21
- * @returns {Promise<string>} - The path to the generated registry file
69
+ * @param {boolean} includeStories - Whether to include stories in the registry
70
+ * @returns {string} - The registry file content or null if no components are found
22
71
  */
23
- export async function generateRegistry(
72
+ export function generateRegistryFileContent(
24
73
  project,
25
74
  absoluteFilePaths,
26
- registryFilename = 'registry.js'
75
+ includeStories = false,
27
76
  ) {
28
- const registryPath = ensureRegistryPath(project, registryFilename);
29
-
30
77
  const relativePaths = absoluteFilePaths.map((path) => {
31
78
  assert(
32
79
  path.startsWith(project.root),
33
- 'Expected path to be in project root'
80
+ "Expected path to be in project root",
34
81
  );
35
82
  return toNodeResolvablePath(
36
- path.replace(`${project.root}/src/`, `${project.name}/`)
83
+ path.replace(`${project.root}/src/`, `${project.name}/`),
37
84
  );
38
85
  });
39
86
  let registryPaths = relativePaths.map((path) => ({
@@ -43,22 +90,25 @@ export async function generateRegistry(
43
90
 
44
91
  if (registryPaths.length === 0)
45
92
  throw new Error(
46
- 'Could not generate registry. No exportable modules found.'
93
+ "Could not generate registry. No exportable modules found.",
47
94
  );
48
95
 
49
96
  const importStatements = registryPaths.map(
50
- (file) => `import * as ${file.uid} from "${file.path}";`
97
+ (file) => `import * as ${file.uid} from "${file.path}";`,
51
98
  );
52
- const componentsToExport = registryPaths.map(
53
- (file) => ` '${file.path}': lazyImport(${file.uid})`
99
+ const exportStatements = registryPaths.map(
100
+ (file) => ` '${file.path}': lazyImport(${file.uid})`,
54
101
  );
55
102
 
56
- logger.debug(
57
- `Including ${componentsToExport.length} items in ${registryPath}`
58
- );
103
+ const [components, stories] = splitStoriesExports(exportStatements);
104
+ logger.debug(`Including ${components.length} component modules in registry`);
59
105
 
60
- let registryFileContent = `
61
- ${importStatements.join('\n')}
106
+ if (includeStories) {
107
+ logger.debug(`Including ${stories.length} stories in registry`);
108
+ }
109
+
110
+ let out = `
111
+ ${importStatements.join("\n")}
62
112
  function lazyImport(pkgImport) {
63
113
  return new Proxy(
64
114
  {},
@@ -78,29 +128,73 @@ function lazyImport(pkgImport) {
78
128
  )
79
129
  }
80
130
  export default {
81
- ${componentsToExport.join(',\n')}
131
+ ${components.join(",\n")}
82
132
  };
83
133
  `;
84
- await fs.writeFile(registryPath, registryFileContent);
85
134
 
86
- return registryPath;
135
+ if (includeStories) {
136
+ out += `
137
+
138
+ export const stories = {
139
+ ${stories.join(",\n")}
140
+ };
141
+ `;
142
+ }
143
+ return out;
87
144
  }
88
145
 
89
146
  /**
90
- * Generate a lazy registry file for the given project
147
+ * Extract a node-resolvable path
91
148
  *
92
- * @param {Project} project - The project object
93
- * @param {string[]} filePaths - The files whose exports will be included in the lazy registry
94
- * @param {string} [lazyFilename="lazy.js"] - The name of the registry file
95
- * @returns {Promise<string>} - The path to the generated lazy registry file
149
+ * @param {string} inputPath - The file path
150
+ * @returns {string} - The node-resolvable path
96
151
  */
97
- export async function generateLazyRegistry(
98
- project,
99
- filePaths,
100
- lazyFilename = 'lazy.js'
101
- ) {
102
- const lazyPath = ensureRegistryPath(project, lazyFilename);
152
+ export function toNodeResolvablePath(inputPath) {
153
+ const dir = path.dirname(inputPath);
154
+ const base = path.basename(inputPath, path.extname(inputPath));
155
+
156
+ return base === "index" ? dir : path.join(dir, base);
157
+ }
158
+
159
+ /**
160
+ * Create a UID from a path
161
+ *
162
+ * @param {string} inputPath - The path
163
+ * @returns {string} - The UID
164
+ */
165
+ export function createUid(inputPath) {
166
+ return inputPath.replace(/[\/@\-.]/g, "_");
167
+ }
103
168
 
169
+ /**
170
+ * Split the given files into components and stories
171
+ *
172
+ * @param {string[]} exportStatements - The export statements
173
+ * @returns {[string[], string[]]} - The split components and stories exports
174
+ */
175
+ export function splitStoriesExports(exportStatements) {
176
+ const stories = [];
177
+ const components = [];
178
+ for (const exportStatement of exportStatements) {
179
+ if (exportStatement.includes("_stories")) {
180
+ stories.push(exportStatement);
181
+ } else {
182
+ components.push(exportStatement);
183
+ }
184
+ }
185
+ return [components, stories];
186
+ }
187
+
188
+ /**
189
+ * Generate lazy component registry file content for the given project
190
+ *
191
+ * @param {object} project - The project object
192
+ * @param {string} project.root - The project root directory
193
+ * @param {string} project.name - The project name as in package.json
194
+ * @param {string[]} filePaths - The files whose exports will be included in the lazy registry
195
+ * @returns {string} - The lazy component registry file content or null if no components are found
196
+ */
197
+ export function generateLazyFileContent(project, filePaths) {
104
198
  const tsMorphProject = new TsMorphProject({
105
199
  tsConfigFilePath: getProjectTsconfig(project.root),
106
200
  });
@@ -117,7 +211,7 @@ export async function generateLazyRegistry(
117
211
 
118
212
  for (const exportedComponent of exports) {
119
213
  if (
120
- exportedComponent !== 'default' &&
214
+ exportedComponent !== "default" &&
121
215
  exportedComponent.match(/^[A-Z]/)
122
216
  ) {
123
217
  if (
@@ -125,7 +219,7 @@ export async function generateLazyRegistry(
125
219
  allComponents[exportedComponent].length < filePath.length // Make import path more specific
126
220
  ) {
127
221
  allComponents[exportedComponent] = toNodeResolvablePath(
128
- filePath.replace(`${project.root}/src/`, `${project.name}/`)
222
+ filePath.replace(`${project.root}/src/`, `${project.name}/`),
129
223
  );
130
224
  }
131
225
  }
@@ -136,63 +230,23 @@ export async function generateLazyRegistry(
136
230
 
137
231
  if (componentCount === 0)
138
232
  throw new Error(
139
- 'Could not generate lazy registry. No exportable components found.'
233
+ "Could not generate lazy registry. No exportable components found.",
140
234
  );
141
235
 
142
- logger.debug(`Including ${componentCount} components in ${lazyPath}`);
236
+ logger.debug(`Including ${componentCount} components in lazy registry`);
143
237
 
144
- const componentsToExport = Object.entries(allComponents)
238
+ const content = Object.entries(allComponents)
145
239
  .map(
146
240
  ([component, filePath]) =>
147
- ` '${component}': lazy(() => import('${filePath}').then((module) => ({ default: module['${component}'] })))`
241
+ ` '${component}': lazy(() => import('${filePath}').then((module) => ({ default: module['${component}'] })))`,
148
242
  )
149
- .join(',\n');
243
+ .join(",\n");
150
244
 
151
- const lazyFileContent = `import { lazy } from 'react';
245
+ return `import { lazy } from 'react';
152
246
  export default {
153
- ${componentsToExport}
247
+ ${content}
154
248
  };
155
249
  `;
156
-
157
- await fs.writeFile(lazyPath, lazyFileContent);
158
-
159
- return lazyPath;
160
- }
161
-
162
- /**
163
- * Ensure that the registry file does not already exist at the given path
164
- *
165
- * @param {Project} project - The project object
166
- * @param {string} fileName - The name of the registry file
167
- */
168
- function ensureRegistryPath(project, fileName) {
169
- const registryPath = path.join(project.root, project.distDir, fileName);
170
- if (fs.existsSync(registryPath))
171
- throw new Error(`A "${fileName}" file already exists at ${registryPath}.`);
172
- return registryPath;
173
- }
174
-
175
- /**
176
- * Extract a node-resolvable path
177
- *
178
- * @param {string} inputPath - The file path
179
- * @returns {string} - The node-resolvable path
180
- */
181
- function toNodeResolvablePath(inputPath) {
182
- const dir = path.dirname(inputPath);
183
- const base = path.basename(inputPath, path.extname(inputPath));
184
-
185
- return base === 'index' ? dir : path.join(dir, base);
186
- }
187
-
188
- /**
189
- * Create a UID from a path
190
- *
191
- * @param {string} inputPath - The path
192
- * @returns {string} - The UID
193
- */
194
- function createUid(inputPath) {
195
- return inputPath.replace(/[/@\-.]/g, '_');
196
250
  }
197
251
 
198
252
  /**
package/index.js CHANGED
@@ -1,36 +1,36 @@
1
- import { DigigovCommand, resolveProject, logger } from '@digigov/cli/lib';
2
- import { buildFormat, generateTypeDeclarationFiles } from './build.js';
3
- import { generateLazyRegistry, generateRegistry } from './generate-registry.js';
4
- import copyFiles from './copy-files.js';
1
+ import { DigigovCommand, resolveProject, logger } from "@digigov/cli/lib";
2
+ import { buildFormat, generateTypeDeclarationFiles } from "./build.js";
3
+ import { generateRegistryFiles } from "./generate-registry.js";
4
+ import copyFiles from "./copy-files.js";
5
5
 
6
- import { Option } from 'commander';
7
- import path from 'path';
8
- import glob from 'globby';
9
- import assert from 'assert';
10
- import { getProjectTsconfig } from './common.js';
6
+ import { Option } from "commander";
7
+ import path from "path";
8
+ import glob from "globby";
9
+ import assert from "assert";
10
+ import { getProjectTsconfig } from "./common.js";
11
11
 
12
- const command = new DigigovCommand('build', import.meta.url)
12
+ const command = new DigigovCommand("build", import.meta.url)
13
13
  .option(
14
- '--generate-registry',
15
- 'Generate a registry file for the build output'
14
+ "--generate-registry",
15
+ "Generate a registry file for the build output",
16
16
  )
17
17
  .addOption(
18
- new Option('--include-stories', 'Include stories in the output').implies({
18
+ new Option("--include-stories", "Include stories in the output").implies({
19
19
  generateRegistry: true,
20
- })
20
+ }),
21
21
  )
22
22
  .action(main);
23
23
  export default command;
24
24
 
25
- const SRC_GLOB = 'src/**/*.{tsx,ts,js,jsx}';
25
+ const SRC_GLOB = "src/**/*.{tsx,ts,js,jsx}";
26
26
  const TEST_GLOBS = [
27
- '**/*.test.{js,jsx,ts,tsx}',
28
- '**/*.spec.{js,jsx,ts,tsx}',
29
- '**/__tests__/**/*.{js,jsx,ts,tsx}',
27
+ "**/*.test.{js,jsx,ts,tsx}",
28
+ "**/*.spec.{js,jsx,ts,tsx}",
29
+ "**/__tests__/**/*.{js,jsx,ts,tsx}",
30
30
  ];
31
31
  const STORIES_GLOBS = [
32
- '**/*.stories.{js,jsx,ts,tsx}',
33
- '**/__stories__/**/*.{js,jsxts,tsx}',
32
+ "**/*.stories.{js,jsx,ts,tsx}",
33
+ "**/__stories__/**/*.{js,jsxts,tsx}",
34
34
  ];
35
35
 
36
36
  /**
@@ -42,7 +42,7 @@ const STORIES_GLOBS = [
42
42
  async function main(options, ctx) {
43
43
  const project = resolveProject();
44
44
 
45
- await ctx.exec('rimraf', [project.distDir]);
45
+ await ctx.exec("rimraf", [project.distDir]);
46
46
 
47
47
  /**
48
48
  * The project tsconfig, or undefined if the project is not using TypeScript
@@ -51,68 +51,56 @@ async function main(options, ctx) {
51
51
  let tsconfig;
52
52
  if (project.isTs) {
53
53
  tsconfig = getProjectTsconfig(project.root);
54
- assert(tsconfig, 'Expected tsconfig to be in project');
54
+ assert(tsconfig, "Expected tsconfig to be in project");
55
55
  await generateTypeDeclarationFiles(project, tsconfig, ctx);
56
56
  }
57
57
 
58
- const ignore = [...TEST_GLOBS, ...STORIES_GLOBS];
58
+ const ignore = [...TEST_GLOBS];
59
+ if (options.includeStories) {
60
+ logger.debug("Including stories in the build");
61
+ } else {
62
+ ignore.push(...STORIES_GLOBS);
63
+ }
59
64
  const filesToBuild = await glob(path.join(project.root, SRC_GLOB), {
60
65
  ignore,
61
66
  });
62
- logger.debug('Bundling ESM and CJS...');
67
+ logger.debug("Bundling ESM and CJS...");
63
68
  await Promise.all([
64
69
  buildFormat({
65
70
  files: filesToBuild,
66
71
  tsconfig: tsconfig,
67
- format: 'cjs',
68
- outdir: project.distDir + '/cjs',
72
+ format: "cjs",
73
+ outdir: project.distDir + "/cjs",
69
74
  }),
70
75
  buildFormat({
71
76
  files: filesToBuild,
72
77
  tsconfig,
73
- format: 'esm',
78
+ format: "esm",
74
79
  outdir: project.distDir,
75
80
  }),
76
81
  ]);
77
- logger.debug('Bundling done.');
82
+ logger.debug("Bundling done.");
78
83
 
79
84
  if (options.generateRegistry) {
80
- logger.debug('Generating registry files...');
81
-
82
- const filesToIncludeInRegistry = filesToBuild.filter(
83
- (file) => !(file.includes('native') || file.endsWith('.d.ts'))
85
+ const registryFiles = filesToBuild.filter(
86
+ (file) => !(file.includes("native") || file.endsWith(".d.ts")),
84
87
  );
85
- let storiesFiles = null;
86
- if (options.includeStories) {
87
- logger.debug('Including stories in the registry...');
88
-
89
- storiesFiles = await glob(
90
- STORIES_GLOBS.map((glob) => path.join(project.root, project.src, glob)),
91
- {
92
- ignore: ['**/*.native.*, **/*.d.ts'],
93
- }
94
- );
95
- }
96
-
97
- const [, ...registryFilePaths] = await Promise.all([
98
- storiesFiles
99
- ? generateRegistry(project, storiesFiles, 'stories-registry.js')
100
- : null,
101
- generateRegistry(project, filesToIncludeInRegistry),
102
- generateLazyRegistry(project, filesToIncludeInRegistry),
103
- ]);
104
-
105
- buildFormat({
88
+ logger.debug("Generating registry files...");
89
+ const registryFilePaths = await generateRegistryFiles(
90
+ project,
91
+ registryFiles,
92
+ options.includeStories,
93
+ );
94
+ await buildFormat({
106
95
  files: registryFilePaths,
107
96
  tsconfig: tsconfig,
108
- format: 'cjs',
109
- outdir: project.distDir + '/cjs',
110
- noLogs: true,
97
+ format: "cjs",
98
+ outdir: project.distDir + "/cjs",
111
99
  });
112
- logger.log('Generated registry files');
100
+ logger.log("Generated registry files");
113
101
  }
114
102
 
115
- logger.debug('Copying files to build directory...');
103
+ logger.debug("Copying files to build directory...");
116
104
  copyFiles();
117
- logger.debug('Files copied.');
105
+ logger.debug("Files copied.");
118
106
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digigov/cli-build",
3
- "version": "2.0.0-e7d30530",
3
+ "version": "2.0.0-eaf330f5",
4
4
  "description": "Build plugin for Digigov CLI",
5
5
  "main": "./index.js",
6
6
  "type": "module",
@@ -8,8 +8,27 @@
8
8
  "license": "BSD-2-Clause",
9
9
  "private": false,
10
10
  "dependencies": {
11
+ "@babel/cli": "7.12.1",
12
+ "@babel/compat-data": "7.12.5",
13
+ "@babel/core": "7.26.0",
14
+ "@babel/helper-validator-identifier": "7.9.5",
15
+ "@babel/plugin-proposal-class-properties": "7.12.1",
16
+ "@babel/plugin-proposal-object-rest-spread": "7.12.1",
17
+ "@babel/plugin-transform-object-assign": "7.12.1",
18
+ "@babel/plugin-transform-runtime": "7.12.1",
19
+ "@babel/preset-env": "7.12.13",
20
+ "@babel/preset-react": "7.12.13",
21
+ "@babel/preset-typescript": "7.12.1",
22
+ "babel-plugin-inline-import-data-uri": "1.0.1",
23
+ "babel-plugin-module-resolver": "4.0.0",
24
+ "babel-plugin-optimize-clsx": "1.1.1",
25
+ "babel-plugin-react-remove-properties": "0.3.0",
26
+ "babel-plugin-transform-dev-warning": "0.1.1",
27
+ "babel-plugin-transform-react-constant-elements": "6.23.0",
28
+ "babel-plugin-transform-react-remove-prop-types": "0.4.24",
11
29
  "fs-extra": "11.2.0",
12
30
  "globby": "11.0.0",
31
+ "babel-plugin-istanbul": "7.0.0",
13
32
  "publint": "0.1.8",
14
33
  "rimraf": "3.0.2",
15
34
  "esbuild": "0.23.0",
@@ -17,19 +36,15 @@
17
36
  "ts-morph": "25.0.0"
18
37
  },
19
38
  "devDependencies": {
20
- "@digigov/cli": "2.0.0-e7d30530",
21
- "@digigov/cli-lint": "2.0.0-e7d30530",
22
39
  "publint": "0.1.8",
23
40
  "vitest": "2.1.3",
24
- "@digigov/cli-test": "2.0.0-e7d30530",
41
+ "@digigov/cli-test": "2.0.0-eaf330f5",
25
42
  "@types/fs-extra": "11.0.4",
26
- "@types/node": "20.17.24",
27
- "typescript": "5.6.2",
28
- "eslint": "9.16.0",
29
- "prettier": "3.4.2"
43
+ "@types/node": "18.19.0",
44
+ "typescript": "5.6.2"
30
45
  },
31
46
  "peerDependencies": {
32
- "@digigov/cli": "2.0.0-e7d30530",
47
+ "@digigov/cli": "2.0.0-eaf330f5",
33
48
  "next": "13.1.1"
34
49
  },
35
50
  "peerDependenciesMeta": {
@@ -38,8 +53,6 @@
38
53
  }
39
54
  },
40
55
  "scripts": {
41
- "publint": "publint",
42
- "lint": "digigov lint",
43
- "typecheck": "tsc"
56
+ "publint": "publint"
44
57
  }
45
58
  }
package/tsconfig.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "extends": "@digigov/cli/tsconfig.cli",
3
3
  "compilerOptions": {
4
- "types": ["vitest/globals"]
4
+ "types": [
5
+ "vitest/globals"
6
+ ]
5
7
  },
6
- "include": ["./*.js", "__tests__"],
7
- "exclude": ["eslint.config.js", ".prettierrc.cjs"]
8
+ "include": [
9
+ "./*.js",
10
+ "__tests__"
11
+ ]
8
12
  }
package/.prettierrc.cjs DELETED
@@ -1 +0,0 @@
1
- module.exports = require('@digigov/cli-lint/prettierrc')();
package/eslint.config.js DELETED
@@ -1,3 +0,0 @@
1
- import config from '@digigov/cli-lint/eslint.config';
2
-
3
- export default [...config];