@digigov/cli-build 2.0.0-0c4be34e → 2.0.0-13876dba
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/.rush/temp/shrinkwrap-deps.json +8 -2
- package/build.js +93 -0
- package/common.js +20 -0
- package/copy-files.js +18 -13
- package/generate-registry.js +214 -0
- package/index.js +95 -62
- package/package.json +11 -5
- package/tsconfig.base.json +4 -1
- package/tsconfig.json +12 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"../../tooling/cli-build": "../../tooling/cli-build:
|
|
2
|
+
"../../tooling/cli-build": "../../tooling/cli-build:Vw6D9T0+Q/2ssdaimPBkW4R+RpyibLUNtG8bJGmVg/o=:",
|
|
3
3
|
"/@babel/cli@7.12.1(@babel/core@7.26.0)": "Missing shrinkwrap entry!",
|
|
4
4
|
"/@babel/compat-data@7.12.5": "Missing shrinkwrap entry!",
|
|
5
5
|
"/@babel/core@7.26.0": "Missing shrinkwrap entry!",
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"/@babel/preset-env@7.12.13(@babel/core@7.26.0)": "Missing shrinkwrap entry!",
|
|
12
12
|
"/@babel/preset-react@7.12.13(@babel/core@7.26.0)": "Missing shrinkwrap entry!",
|
|
13
13
|
"/@babel/preset-typescript@7.12.1(@babel/core@7.26.0)": "Missing shrinkwrap entry!",
|
|
14
|
+
"/@types/fs-extra@11.0.4": "Missing shrinkwrap entry!",
|
|
15
|
+
"/@types/node@18.19.0": "Missing shrinkwrap entry!",
|
|
14
16
|
"/babel-plugin-inline-import-data-uri@1.0.1": "Missing shrinkwrap entry!",
|
|
15
17
|
"/babel-plugin-istanbul@7.0.0": "Missing shrinkwrap entry!",
|
|
16
18
|
"/babel-plugin-module-resolver@4.0.0": "Missing shrinkwrap entry!",
|
|
@@ -19,10 +21,14 @@
|
|
|
19
21
|
"/babel-plugin-transform-dev-warning@0.1.1": "Missing shrinkwrap entry!",
|
|
20
22
|
"/babel-plugin-transform-react-constant-elements@6.23.0": "Missing shrinkwrap entry!",
|
|
21
23
|
"/babel-plugin-transform-react-remove-prop-types@0.4.24": "Missing shrinkwrap entry!",
|
|
24
|
+
"/commander@12.1.0": "Missing shrinkwrap entry!",
|
|
22
25
|
"/esbuild@0.23.0": "Missing shrinkwrap entry!",
|
|
23
26
|
"/fs-extra@11.2.0": "Missing shrinkwrap entry!",
|
|
24
27
|
"/globby@11.0.0": "Missing shrinkwrap entry!",
|
|
25
28
|
"/next@13.1.1(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": "Missing shrinkwrap entry!",
|
|
26
29
|
"/publint@0.1.8": "Missing shrinkwrap entry!",
|
|
27
|
-
"/rimraf@3.0.2": "Missing shrinkwrap entry!"
|
|
30
|
+
"/rimraf@3.0.2": "Missing shrinkwrap entry!",
|
|
31
|
+
"/ts-morph@25.0.0": "Missing shrinkwrap entry!",
|
|
32
|
+
"/typescript@5.6.2": "Missing shrinkwrap entry!",
|
|
33
|
+
"/vitest@2.1.3(@types/node@18.19.0)(jsdom@25.0.1)(lightningcss@1.27.0)(sass-embedded@1.86.0)(terser@5.39.0)": "Missing shrinkwrap entry!"
|
|
28
34
|
}
|
package/build.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { DigigovCommand, logger } from "@digigov/cli/lib";
|
|
2
|
+
|
|
3
|
+
import assert from "assert";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import fs from "fs-extra";
|
|
6
|
+
import baseEsbuild from "esbuild";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generate TypeScript declaration files
|
|
10
|
+
*
|
|
11
|
+
* @param {object} project - The project object
|
|
12
|
+
* @param {string} project.root - The project root directory
|
|
13
|
+
* @param {string} project.src - The project source directory
|
|
14
|
+
* @param {string} project.distDir - The project build directory
|
|
15
|
+
* @param {string} tsconfig - The tsconfig path
|
|
16
|
+
* @param {DigigovCommand} ctx - The command context
|
|
17
|
+
*/
|
|
18
|
+
export async function generateTypeDeclarationFiles(project, tsconfig, ctx) {
|
|
19
|
+
logger.debug("Building types...");
|
|
20
|
+
|
|
21
|
+
const distDir = path.resolve(project.root, project.distDir);
|
|
22
|
+
const projectBasename = path.basename(project.root);
|
|
23
|
+
|
|
24
|
+
await ctx.exec("tsc", [
|
|
25
|
+
"--emitDeclarationOnly",
|
|
26
|
+
"--outDir",
|
|
27
|
+
"dist",
|
|
28
|
+
"--project",
|
|
29
|
+
tsconfig,
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
const projectBasePath = path.join(distDir, projectBasename);
|
|
33
|
+
logger.debug("Project base path", projectBasePath);
|
|
34
|
+
if (await fs.exists(projectBasePath)) {
|
|
35
|
+
const typesIncluded = await fs.readdir(path.join(distDir));
|
|
36
|
+
const srcPath = path.join(distDir, projectBasename, project.src);
|
|
37
|
+
const paths = await fs.readdir(srcPath);
|
|
38
|
+
|
|
39
|
+
await Promise.all([
|
|
40
|
+
// Move src files to dist
|
|
41
|
+
...paths.map((p) => {
|
|
42
|
+
logger.debug("Moving types file", p);
|
|
43
|
+
fs.move(path.join(srcPath, p), path.join(distDir, p));
|
|
44
|
+
}),
|
|
45
|
+
// Remove dirs
|
|
46
|
+
...typesIncluded.map((typesDir) => {
|
|
47
|
+
logger.debug("Removing types directory", typesDir);
|
|
48
|
+
fs.rm(path.join(distDir, typesDir), { recursive: true });
|
|
49
|
+
}),
|
|
50
|
+
]).catch((err) => {
|
|
51
|
+
logger.error("Error while building types", err);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
logger.debug("Types built.");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Run esbuild for the given options
|
|
59
|
+
*
|
|
60
|
+
* @param {object} options - The build options
|
|
61
|
+
* @param {string[]} options.files - The files to build
|
|
62
|
+
* @param {string | undefined} options.tsconfig - The tsconfig path
|
|
63
|
+
* @param {"esm" | "cjs"} options.format - The module format
|
|
64
|
+
* @param {string} options.outdir - The output directory
|
|
65
|
+
* @param {boolean | undefined} [options.noLogs] - Whether to log debug information
|
|
66
|
+
*/
|
|
67
|
+
export function buildFormat({
|
|
68
|
+
files: entryPoints,
|
|
69
|
+
tsconfig,
|
|
70
|
+
format,
|
|
71
|
+
outdir,
|
|
72
|
+
noLogs,
|
|
73
|
+
}) {
|
|
74
|
+
assert(format === "esm" || format === "cjs", "Invalid format");
|
|
75
|
+
|
|
76
|
+
if (!noLogs)
|
|
77
|
+
logger.log(`Running: esbuild for ${format.toUpperCase()} format`);
|
|
78
|
+
return baseEsbuild.build({
|
|
79
|
+
...BASE_OPTIONS,
|
|
80
|
+
entryPoints,
|
|
81
|
+
tsconfig,
|
|
82
|
+
format,
|
|
83
|
+
outdir,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @type {baseEsbuild.BuildOptions} */
|
|
88
|
+
export const BASE_OPTIONS = {
|
|
89
|
+
logLevel: "error",
|
|
90
|
+
platform: "node",
|
|
91
|
+
sourcemap: true,
|
|
92
|
+
target: ["esnext"],
|
|
93
|
+
};
|
package/common.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
const POSSIBLE_TS_CONFIGS = ["tsconfig.production.json", "tsconfig.json"];
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Get the tsconfig path for the given project
|
|
8
|
+
*
|
|
9
|
+
* @param {string} projectRoot - The project root
|
|
10
|
+
* @returns {string | undefined} - The tsconfig path or undefined if not found
|
|
11
|
+
*/
|
|
12
|
+
export function getProjectTsconfig(projectRoot) {
|
|
13
|
+
for (const tsconfig of POSSIBLE_TS_CONFIGS) {
|
|
14
|
+
const tsconfigPath = path.join(projectRoot, tsconfig);
|
|
15
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
16
|
+
return tsconfigPath;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return;
|
|
20
|
+
}
|
package/copy-files.js
CHANGED
|
@@ -4,11 +4,8 @@ import path from "path";
|
|
|
4
4
|
import glob from "globby";
|
|
5
5
|
|
|
6
6
|
const packagePath = process.cwd();
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const project = resolveProject();
|
|
10
|
-
return path.join(project.root, project.distDir);
|
|
11
|
-
}
|
|
7
|
+
const project = resolveProject();
|
|
8
|
+
const buildPath = path.join(project.root, project.distDir);
|
|
12
9
|
|
|
13
10
|
/**
|
|
14
11
|
* Copy a file from the package to the build directory
|
|
@@ -17,10 +14,20 @@ function getBuildPath() {
|
|
|
17
14
|
*/
|
|
18
15
|
function includeFileInBuild(file) {
|
|
19
16
|
const sourcePath = path.resolve(packagePath, file);
|
|
20
|
-
const buildPath = getBuildPath();
|
|
21
17
|
const targetPath = path.resolve(buildPath, path.basename(file));
|
|
22
18
|
fs.copySync(sourcePath, targetPath);
|
|
23
|
-
logger.
|
|
19
|
+
logger.debug(`Copied ${sourcePath} to build directory`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function copyRegistryFilesToSrc() {
|
|
23
|
+
const registryPath = path.resolve(buildPath, "registry/index.js");
|
|
24
|
+
const lazyPath = path.resolve(buildPath, "lazy/index.js");
|
|
25
|
+
if (!fs.existsSync(registryPath) || !fs.existsSync(lazyPath)) return;
|
|
26
|
+
|
|
27
|
+
const srcPath = path.resolve(buildPath, "src");
|
|
28
|
+
logger.debug(`Copying registry and lazy files to ${srcPath}`);
|
|
29
|
+
fs.copySync(registryPath, path.resolve(srcPath, "registry.js"));
|
|
30
|
+
fs.copySync(lazyPath, path.resolve(srcPath, "lazy.js"));
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
/**
|
|
@@ -40,11 +47,10 @@ function createRootPackageFile() {
|
|
|
40
47
|
module: "./index.js",
|
|
41
48
|
typings: "./index.d.ts",
|
|
42
49
|
};
|
|
43
|
-
const buildPath = getBuildPath();
|
|
44
50
|
const targetPath = path.resolve(buildPath, "./package.json");
|
|
45
51
|
|
|
46
52
|
fs.writeFileSync(targetPath, JSON.stringify(newPackageData, null, 2), "utf8");
|
|
47
|
-
logger.
|
|
53
|
+
logger.debug(`Created package.json in build directory`);
|
|
48
54
|
|
|
49
55
|
return newPackageData;
|
|
50
56
|
}
|
|
@@ -54,7 +60,6 @@ function createRootPackageFile() {
|
|
|
54
60
|
*
|
|
55
61
|
*/
|
|
56
62
|
function createNestedPackageFiles() {
|
|
57
|
-
const buildPath = getBuildPath();
|
|
58
63
|
const indexPaths = glob.sync(path.join(buildPath, "**/index.js"), {
|
|
59
64
|
ignore: [path.join(buildPath, "cjs/**")],
|
|
60
65
|
});
|
|
@@ -86,6 +91,7 @@ function createNestedPackageFiles() {
|
|
|
86
91
|
function prepend(file, string) {
|
|
87
92
|
const data = fs.readFileSync(file, "utf8");
|
|
88
93
|
fs.writeFileSync(file, string + data, "utf8");
|
|
94
|
+
logger.debug(`Prepended license to ${file}`);
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
/**
|
|
@@ -94,7 +100,6 @@ function prepend(file, string) {
|
|
|
94
100
|
* @param {object} packageData - The package data
|
|
95
101
|
*/
|
|
96
102
|
function addLicense(packageData) {
|
|
97
|
-
const buildPath = getBuildPath();
|
|
98
103
|
const license = `/** @license Digigov v${packageData["version"]}
|
|
99
104
|
*
|
|
100
105
|
* This source code is licensed under the BSD-2-Clause license found in the
|
|
@@ -111,7 +116,7 @@ function addLicense(packageData) {
|
|
|
111
116
|
"code" in err &&
|
|
112
117
|
err.code === "ENOENT"
|
|
113
118
|
) {
|
|
114
|
-
logger.
|
|
119
|
+
logger.debug(`Skipped license for ${file}`);
|
|
115
120
|
} else {
|
|
116
121
|
throw err;
|
|
117
122
|
}
|
|
@@ -123,7 +128,6 @@ function addLicense(packageData) {
|
|
|
123
128
|
* Create separate index modules for each directory
|
|
124
129
|
*/
|
|
125
130
|
function createSeparateIndexModules() {
|
|
126
|
-
const buildPath = getBuildPath();
|
|
127
131
|
const files = glob.sync(path.join(buildPath, "**/*.js"), {
|
|
128
132
|
ignore: [path.join(buildPath, "**/index.js")],
|
|
129
133
|
});
|
|
@@ -141,6 +145,7 @@ export default function run() {
|
|
|
141
145
|
const packageData = createRootPackageFile();
|
|
142
146
|
createSeparateIndexModules();
|
|
143
147
|
createNestedPackageFiles();
|
|
148
|
+
copyRegistryFilesToSrc();
|
|
144
149
|
|
|
145
150
|
[
|
|
146
151
|
// use enhanced readme from workspace root for `@digigov/ui`
|
|
@@ -0,0 +1,214 @@
|
|
|
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
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate registry file for the given project
|
|
17
|
+
*
|
|
18
|
+
* @param {Project} project - The project object
|
|
19
|
+
* @param {string} [registryFilename="registry.js"] - The name of the registry file
|
|
20
|
+
* @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
|
|
22
|
+
*/
|
|
23
|
+
export async function generateRegistry(
|
|
24
|
+
project,
|
|
25
|
+
absoluteFilePaths,
|
|
26
|
+
registryFilename = "registry.js",
|
|
27
|
+
) {
|
|
28
|
+
const registryPath = ensureRegistryPath(project, registryFilename);
|
|
29
|
+
|
|
30
|
+
const relativePaths = absoluteFilePaths.map((path) => {
|
|
31
|
+
assert(
|
|
32
|
+
path.startsWith(project.root),
|
|
33
|
+
"Expected path to be in project root",
|
|
34
|
+
);
|
|
35
|
+
return toNodeResolvablePath(
|
|
36
|
+
path.replace(`${project.root}/src/`, `${project.name}/`),
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
let registryPaths = relativePaths.map((path) => ({
|
|
40
|
+
path,
|
|
41
|
+
uid: createUid(path),
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
if (registryPaths.length === 0)
|
|
45
|
+
throw new Error(
|
|
46
|
+
"Could not generate registry. No exportable modules found.",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const importStatements = registryPaths.map(
|
|
50
|
+
(file) => `import * as ${file.uid} from "${file.path}";`,
|
|
51
|
+
);
|
|
52
|
+
const componentsToExport = registryPaths.map(
|
|
53
|
+
(file) => ` '${file.path}': lazyImport(${file.uid})`,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
logger.debug(
|
|
57
|
+
`Including ${componentsToExport.length} items in ${registryPath}`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
let registryFileContent = `
|
|
61
|
+
${importStatements.join("\n")}
|
|
62
|
+
function lazyImport(pkgImport) {
|
|
63
|
+
return new Proxy(
|
|
64
|
+
{},
|
|
65
|
+
{
|
|
66
|
+
get: (_target, name) => {
|
|
67
|
+
if (name === '__esModule' || name === 'default') {
|
|
68
|
+
return pkgImport.default;
|
|
69
|
+
} else if(
|
|
70
|
+
name === '*'
|
|
71
|
+
) {
|
|
72
|
+
return pkgImport;
|
|
73
|
+
} else {
|
|
74
|
+
return pkgImport[name];
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
export default {
|
|
81
|
+
${componentsToExport.join(",\n")}
|
|
82
|
+
};
|
|
83
|
+
`;
|
|
84
|
+
await fs.writeFile(registryPath, registryFileContent);
|
|
85
|
+
|
|
86
|
+
return registryPath;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Generate a lazy registry file for the given project
|
|
91
|
+
*
|
|
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
|
|
96
|
+
*/
|
|
97
|
+
export async function generateLazyRegistry(
|
|
98
|
+
project,
|
|
99
|
+
filePaths,
|
|
100
|
+
lazyFilename = "lazy.js",
|
|
101
|
+
) {
|
|
102
|
+
const lazyPath = ensureRegistryPath(project, lazyFilename);
|
|
103
|
+
|
|
104
|
+
const tsMorphProject = new TsMorphProject({
|
|
105
|
+
tsConfigFilePath: getProjectTsconfig(project.root),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
/** @type {Record<string, string>} */
|
|
109
|
+
let allComponents = {};
|
|
110
|
+
|
|
111
|
+
for (const filePath of filePaths) {
|
|
112
|
+
const sourceFile = tsMorphProject.addSourceFileAtPath(filePath);
|
|
113
|
+
const exports = sourceFile
|
|
114
|
+
.getExportSymbols()
|
|
115
|
+
.filter(isJsExport)
|
|
116
|
+
.map((symbol) => symbol.getName());
|
|
117
|
+
|
|
118
|
+
for (const exportedComponent of exports) {
|
|
119
|
+
if (
|
|
120
|
+
exportedComponent !== "default" &&
|
|
121
|
+
exportedComponent.match(/^[A-Z]/)
|
|
122
|
+
) {
|
|
123
|
+
if (
|
|
124
|
+
!allComponents[exportedComponent] ||
|
|
125
|
+
allComponents[exportedComponent].length < filePath.length // Make import path more specific
|
|
126
|
+
) {
|
|
127
|
+
allComponents[exportedComponent] = toNodeResolvablePath(
|
|
128
|
+
filePath.replace(`${project.root}/src/`, `${project.name}/`),
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const componentCount = Object.keys(allComponents).length;
|
|
136
|
+
|
|
137
|
+
if (componentCount === 0)
|
|
138
|
+
throw new Error(
|
|
139
|
+
"Could not generate lazy registry. No exportable components found.",
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
logger.debug(`Including ${componentCount} components in ${lazyPath}`);
|
|
143
|
+
|
|
144
|
+
const componentsToExport = Object.entries(allComponents)
|
|
145
|
+
.map(
|
|
146
|
+
([component, filePath]) =>
|
|
147
|
+
` '${component}': lazy(() => import('${filePath}').then((module) => ({ default: module['${component}'] })))`,
|
|
148
|
+
)
|
|
149
|
+
.join(",\n");
|
|
150
|
+
|
|
151
|
+
const lazyFileContent = `import { lazy } from 'react';
|
|
152
|
+
export default {
|
|
153
|
+
${componentsToExport}
|
|
154
|
+
};
|
|
155
|
+
`;
|
|
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
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Check if a symbol is a JS export
|
|
200
|
+
*
|
|
201
|
+
* @param {import("ts-morph").Symbol} symbol - The symbol to check
|
|
202
|
+
*/
|
|
203
|
+
function isJsExport(symbol) {
|
|
204
|
+
const declarations = symbol.getDeclarations();
|
|
205
|
+
return declarations.some((declaration) => {
|
|
206
|
+
const kind = declaration.getKind();
|
|
207
|
+
return (
|
|
208
|
+
kind === SyntaxKind.FunctionDeclaration ||
|
|
209
|
+
kind === SyntaxKind.ClassDeclaration ||
|
|
210
|
+
kind === SyntaxKind.VariableDeclaration ||
|
|
211
|
+
kind === SyntaxKind.ExportSpecifier
|
|
212
|
+
);
|
|
213
|
+
});
|
|
214
|
+
}
|
package/index.js
CHANGED
|
@@ -1,85 +1,118 @@
|
|
|
1
|
-
import { DigigovCommand, resolveProject } from "@digigov/cli/lib";
|
|
1
|
+
import { DigigovCommand, resolveProject, logger } from "@digigov/cli/lib";
|
|
2
|
+
import { buildFormat, generateTypeDeclarationFiles } from "./build.js";
|
|
3
|
+
import { generateLazyRegistry, generateRegistry } from "./generate-registry.js";
|
|
2
4
|
import copyFiles from "./copy-files.js";
|
|
3
5
|
|
|
4
|
-
import
|
|
6
|
+
import { Option } from "commander";
|
|
5
7
|
import path from "path";
|
|
6
|
-
import esbuild from "esbuild";
|
|
7
8
|
import glob from "globby";
|
|
9
|
+
import assert from "assert";
|
|
10
|
+
import { getProjectTsconfig } from "./common.js";
|
|
8
11
|
|
|
9
|
-
const command = new DigigovCommand("build", import.meta.url)
|
|
12
|
+
const command = new DigigovCommand("build", import.meta.url)
|
|
13
|
+
.option(
|
|
14
|
+
"--generate-registry",
|
|
15
|
+
"Generate a registry file for the build output",
|
|
16
|
+
)
|
|
17
|
+
.addOption(
|
|
18
|
+
new Option("--include-stories", "Include stories in the output").implies({
|
|
19
|
+
generateRegistry: true,
|
|
20
|
+
}),
|
|
21
|
+
)
|
|
22
|
+
.action(main);
|
|
10
23
|
export default command;
|
|
11
24
|
|
|
25
|
+
const SRC_GLOB = "src/**/*.{tsx,ts,js,jsx}";
|
|
26
|
+
const TEST_GLOBS = [
|
|
27
|
+
"**/*.test.{js,jsx,ts,tsx}",
|
|
28
|
+
"**/*.spec.{js,jsx,ts,tsx}",
|
|
29
|
+
"**/__tests__/**/*.{js,jsx,ts,tsx}",
|
|
30
|
+
];
|
|
31
|
+
const STORIES_GLOBS = [
|
|
32
|
+
"**/*.stories.{js,jsx,ts,tsx}",
|
|
33
|
+
"**/__stories__/**/*.{js,jsxts,tsx}",
|
|
34
|
+
];
|
|
35
|
+
|
|
12
36
|
/**
|
|
37
|
+
* @param {object} options - The command options
|
|
38
|
+
* @param {boolean} options.generateRegistry - Generate a registry file for the build output
|
|
39
|
+
* @param {boolean} options.includeStories - Include stories in the generated registry file
|
|
13
40
|
* @param {DigigovCommand} ctx
|
|
14
41
|
*/
|
|
15
|
-
async function
|
|
16
|
-
await ctx.exec("rimraf", ["dist"]);
|
|
42
|
+
async function main(options, ctx) {
|
|
17
43
|
const project = resolveProject();
|
|
18
44
|
|
|
19
|
-
|
|
20
|
-
const basename = path.basename(project.root);
|
|
45
|
+
await ctx.exec("rimraf", [project.distDir]);
|
|
21
46
|
|
|
47
|
+
/**
|
|
48
|
+
* The project tsconfig, or undefined if the project is not using TypeScript
|
|
49
|
+
* @type {string | undefined}
|
|
50
|
+
*/
|
|
51
|
+
let tsconfig;
|
|
22
52
|
if (project.isTs) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
);
|
|
27
|
-
/** @type {string[]} */
|
|
28
|
-
const tsArgs = [];
|
|
29
|
-
if (fs.existsSync(tsconfigProduction)) {
|
|
30
|
-
tsArgs.push("--project", tsconfigProduction);
|
|
31
|
-
}
|
|
32
|
-
await ctx.exec("tsc", [
|
|
33
|
-
"--emitDeclarationOnly",
|
|
34
|
-
"--outDir",
|
|
35
|
-
"dist",
|
|
36
|
-
...tsArgs,
|
|
37
|
-
]);
|
|
38
|
-
if (fs.existsSync(path.join(distDir, basename))) {
|
|
39
|
-
const typesIncluded = fs.readdirSync(path.join(distDir));
|
|
40
|
-
const paths = fs.readdirSync(path.join(distDir, basename, project.src));
|
|
41
|
-
paths.forEach((p) => {
|
|
42
|
-
fs.renameSync(
|
|
43
|
-
path.join(distDir, basename, project.src, p),
|
|
44
|
-
path.join(distDir, p),
|
|
45
|
-
);
|
|
46
|
-
});
|
|
47
|
-
typesIncluded.forEach((typesDir) => {
|
|
48
|
-
fs.rmSync(path.join(distDir, typesDir), { recursive: true });
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const files = glob.sync(
|
|
54
|
-
path.join(project.root, "src", "**/*.{tsx,ts,js,jsx}"),
|
|
55
|
-
{
|
|
56
|
-
ignore: ["**/*.{spec,test}.{ts,tsx,js,jsx}"],
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
const commonBuildOptions = {
|
|
60
|
-
entryPoints: files,
|
|
61
|
-
platform: "node",
|
|
62
|
-
sourcemap: true,
|
|
63
|
-
target: ["esnext"],
|
|
64
|
-
logLevel: "error",
|
|
65
|
-
};
|
|
66
|
-
if (fs.existsSync(path.join(project.root, "tsconfig.production.json"))) {
|
|
67
|
-
commonBuildOptions["tsconfig"] = "tsconfig.production.json";
|
|
68
|
-
} else if (fs.existsSync(path.join(project.root, "tsconfig.json"))) {
|
|
69
|
-
commonBuildOptions["tsconfig"] = "tsconfig.json";
|
|
53
|
+
tsconfig = getProjectTsconfig(project.root);
|
|
54
|
+
assert(tsconfig, "Expected tsconfig to be in project");
|
|
55
|
+
await generateTypeDeclarationFiles(project, tsconfig, ctx);
|
|
70
56
|
}
|
|
71
57
|
|
|
58
|
+
const ignore = [...TEST_GLOBS, ...STORIES_GLOBS];
|
|
59
|
+
const filesToBuild = await glob(path.join(project.root, SRC_GLOB), {
|
|
60
|
+
ignore,
|
|
61
|
+
});
|
|
62
|
+
logger.debug("Bundling ESM and CJS...");
|
|
72
63
|
await Promise.all([
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
buildFormat({
|
|
65
|
+
files: filesToBuild,
|
|
66
|
+
tsconfig: tsconfig,
|
|
67
|
+
format: "cjs",
|
|
68
|
+
outdir: project.distDir + "/cjs",
|
|
69
|
+
}),
|
|
70
|
+
buildFormat({
|
|
71
|
+
files: filesToBuild,
|
|
72
|
+
tsconfig,
|
|
75
73
|
format: "esm",
|
|
76
|
-
outdir:
|
|
74
|
+
outdir: project.distDir,
|
|
77
75
|
}),
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
]);
|
|
77
|
+
logger.debug("Bundling done.");
|
|
78
|
+
|
|
79
|
+
if (options.generateRegistry) {
|
|
80
|
+
logger.debug("Generating registry files...");
|
|
81
|
+
|
|
82
|
+
const filesToIncludeInRegistry = filesToBuild.filter(
|
|
83
|
+
(file) => !(file.includes("native") || file.endsWith(".d.ts")),
|
|
84
|
+
);
|
|
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({
|
|
106
|
+
files: registryFilePaths,
|
|
107
|
+
tsconfig: tsconfig,
|
|
80
108
|
format: "cjs",
|
|
81
|
-
outdir:
|
|
109
|
+
outdir: project.distDir + "/cjs",
|
|
110
|
+
noLogs: true,
|
|
82
111
|
}),
|
|
83
|
-
|
|
112
|
+
logger.log("Generated registry files");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
logger.debug("Copying files to build directory...");
|
|
84
116
|
copyFiles();
|
|
117
|
+
logger.debug("Files copied.");
|
|
85
118
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digigov/cli-build",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-13876dba",
|
|
4
4
|
"description": "Build plugin for Digigov CLI",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -28,17 +28,23 @@
|
|
|
28
28
|
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
|
29
29
|
"fs-extra": "11.2.0",
|
|
30
30
|
"globby": "11.0.0",
|
|
31
|
-
"@digigov/babel-ts-to-proptypes": "1.1.0-rc.23",
|
|
32
31
|
"babel-plugin-istanbul": "7.0.0",
|
|
33
32
|
"publint": "0.1.8",
|
|
34
33
|
"rimraf": "3.0.2",
|
|
35
|
-
"esbuild": "0.23.0"
|
|
34
|
+
"esbuild": "0.23.0",
|
|
35
|
+
"commander": "12.1.0",
|
|
36
|
+
"ts-morph": "25.0.0"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"publint": "0.1.8"
|
|
39
|
+
"publint": "0.1.8",
|
|
40
|
+
"vitest": "2.1.3",
|
|
41
|
+
"@digigov/cli-test": "2.0.0-13876dba",
|
|
42
|
+
"@types/fs-extra": "11.0.4",
|
|
43
|
+
"@types/node": "18.19.0",
|
|
44
|
+
"typescript": "5.6.2"
|
|
39
45
|
},
|
|
40
46
|
"peerDependencies": {
|
|
41
|
-
"@digigov/cli": "2.0.0-
|
|
47
|
+
"@digigov/cli": "2.0.0-13876dba",
|
|
42
48
|
"next": "13.1.1"
|
|
43
49
|
},
|
|
44
50
|
"peerDependenciesMeta": {
|
package/tsconfig.base.json
CHANGED
|
@@ -33,7 +33,10 @@
|
|
|
33
33
|
"@digigov/react-experimental/*": ["../libs-ui/react-experimental/src/*"],
|
|
34
34
|
"@digigov/react-experimental/": ["../libs-ui/react-experimental/src"],
|
|
35
35
|
"@digigov/react-experimental": ["../libs-ui/react-experimental/src"],
|
|
36
|
-
"@digigov/storybook/*": ["../examples/storybook/stories/*"]
|
|
36
|
+
"@digigov/storybook/*": ["../examples/storybook/stories/*"],
|
|
37
|
+
"@uides/stepwise/*": ["./stepwise/src/*"],
|
|
38
|
+
"@uides/stepwise/": ["./stepwise/src"],
|
|
39
|
+
"@uides/stepwise": ["./stepwise/src"]
|
|
37
40
|
}
|
|
38
41
|
},
|
|
39
42
|
"include": [
|