akanjs 2.0.0-rc.0 → 2.0.0-rc.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/cli/index.js +16 -6
- package/cli/templates/app/env/env.server.debug.ts.template +1 -4
- package/devkit/executors.ts +6 -3
- package/devkit/transforms/barrelAnalyzer.ts +3 -0
- package/devkit/transforms/barrelImportsPlugin.ts +39 -29
- package/package.json +1 -1
- package/cli/templates/app/tsconfig.spec.json.template +0 -7
- package/cli/templates/libRoot/tsconfig.spec.json.template +0 -7
package/cli/index.js
CHANGED
|
@@ -9346,7 +9346,7 @@ import {
|
|
|
9346
9346
|
fork,
|
|
9347
9347
|
spawn
|
|
9348
9348
|
} from "child_process";
|
|
9349
|
-
import { mkdir as mkdir2, stat as stat2 } from "fs/promises";
|
|
9349
|
+
import { mkdir as mkdir2, readdir as readDirEntries, stat as stat2 } from "fs/promises";
|
|
9350
9350
|
import path7 from "path";
|
|
9351
9351
|
import chalk4 from "chalk";
|
|
9352
9352
|
|
|
@@ -11074,7 +11074,7 @@ class Executor {
|
|
|
11074
11074
|
const fileContent = await this.#applyTemplateFile({ templatePath: prefixTemplatePath, targetPath: path7.join(basePath2, filename), scanInfo, overwrite }, dict, options);
|
|
11075
11075
|
return fileContent ? [fileContent] : [];
|
|
11076
11076
|
} else {
|
|
11077
|
-
const subdirs = await
|
|
11077
|
+
const subdirs = await readDirEntries(templatePath);
|
|
11078
11078
|
const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
|
|
11079
11079
|
const subpath = path7.join(templatePath, subdir);
|
|
11080
11080
|
if ((await stat2(subpath)).isFile()) {
|
|
@@ -11198,6 +11198,9 @@ class WorkspaceExecutor extends Executor {
|
|
|
11198
11198
|
if (type === "lib" || type === "pkg")
|
|
11199
11199
|
rootTsConfig.compilerOptions.paths[`@${name}`] = [`${type}s/${name}/index.ts`];
|
|
11200
11200
|
rootTsConfig.compilerOptions.paths[`@${name}/*`] = [`${type}s/${name}/*`];
|
|
11201
|
+
rootTsConfig.compilerOptions.paths[`@${type}s/${name}/*`] = [`${type}s/${name}/*`];
|
|
11202
|
+
if (type === "lib" || type === "pkg")
|
|
11203
|
+
rootTsConfig.compilerOptions.paths[`@${type}s/${name}`] = [`${type}s/${name}/index.ts`];
|
|
11201
11204
|
if (rootTsConfig.references) {
|
|
11202
11205
|
if (!rootTsConfig.references.some((ref) => ref.path === `./${type}s/${name}/tsconfig.json`))
|
|
11203
11206
|
rootTsConfig.references.push({ path: `./${type}s/${name}/tsconfig.json` });
|
|
@@ -11207,7 +11210,7 @@ class WorkspaceExecutor extends Executor {
|
|
|
11207
11210
|
}
|
|
11208
11211
|
async unsetTsPaths(type, name) {
|
|
11209
11212
|
const rootTsConfig = await this.readJson("tsconfig.json");
|
|
11210
|
-
const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter((key) => !key.startsWith(`@${name}`));
|
|
11213
|
+
const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter((key) => !key.startsWith(`@${name}`) && !key.startsWith(`@${type}s/${name}`));
|
|
11211
11214
|
rootTsConfig.compilerOptions.paths = Object.fromEntries(filteredKeys.map((key) => [key, rootTsConfig.compilerOptions.paths?.[key] ?? []]));
|
|
11212
11215
|
if (rootTsConfig.references) {
|
|
11213
11216
|
rootTsConfig.references = rootTsConfig.references.filter((ref) => !ref.path.startsWith(`./${type}s/${name}`));
|
|
@@ -12737,6 +12740,8 @@ class BarrelAnalyzer {
|
|
|
12737
12740
|
const rel = path12.relative(pkg.pkgDir, absFile);
|
|
12738
12741
|
if (!rel || rel.startsWith("..") || path12.isAbsolute(rel))
|
|
12739
12742
|
return null;
|
|
12743
|
+
if (pkg.preserveFilePath)
|
|
12744
|
+
return `${pkg.pkgName}/${rel.split(path12.sep).join("/")}`;
|
|
12740
12745
|
const noExt = stripKnownExt(rel);
|
|
12741
12746
|
const tail = collapseIndex(noExt);
|
|
12742
12747
|
if (tail === "")
|
|
@@ -12817,7 +12822,7 @@ var collapseIndex = (relPathNoExt) => {
|
|
|
12817
12822
|
|
|
12818
12823
|
import path13 from "path";
|
|
12819
12824
|
import ts3 from "typescript";
|
|
12820
|
-
var createBarrelImportsPlugin = async (app, { skipPath =
|
|
12825
|
+
var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAfter } = {}) => {
|
|
12821
12826
|
const akanConfig2 = await app.getConfig();
|
|
12822
12827
|
const barrels = [...new Set(akanConfig2.barrelImports)].filter(Boolean);
|
|
12823
12828
|
const analyzer = new BarrelAnalyzer({
|
|
@@ -12826,7 +12831,9 @@ var createBarrelImportsPlugin = async (app, { skipPath = (p) => p.includes("node
|
|
|
12826
12831
|
return {
|
|
12827
12832
|
name: "barrel-imports",
|
|
12828
12833
|
setup(build) {
|
|
12829
|
-
build.onLoad({
|
|
12834
|
+
build.onLoad({
|
|
12835
|
+
filter: /^(?:(?!.*[\\/]node_modules[\\/]).*|.*[\\/]node_modules[\\/]akanjs[\\/].*)\.(tsx|ts|jsx|js)(\?v=\d+)?$/
|
|
12836
|
+
}, async (args) => {
|
|
12830
12837
|
const realPath = args.path.replace(/\?v=\d+$/, "");
|
|
12831
12838
|
const loader = loaderFor(realPath);
|
|
12832
12839
|
if (skipPath(realPath)) {
|
|
@@ -12936,6 +12943,9 @@ var createTsconfigPackageResolver = async (app) => {
|
|
|
12936
12943
|
};
|
|
12937
12944
|
};
|
|
12938
12945
|
var CANDIDATE_EXTS2 = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
12946
|
+
var NODE_MODULES_RE = /[\\/]node_modules[\\/]/;
|
|
12947
|
+
var AKANJS_NODE_MODULE_RE = /[\\/]node_modules[\\/]akanjs[\\/]/;
|
|
12948
|
+
var defaultSkipPath = (absPath) => NODE_MODULES_RE.test(absPath) && !AKANJS_NODE_MODULE_RE.test(absPath);
|
|
12939
12949
|
var resolveNodePackageExport = async (workspaceRoot, specifier) => {
|
|
12940
12950
|
const packageName = getPackageName(specifier);
|
|
12941
12951
|
if (!packageName)
|
|
@@ -12955,7 +12965,7 @@ var resolveNodePackageExport = async (workspaceRoot, specifier) => {
|
|
|
12955
12965
|
if (!entryFile)
|
|
12956
12966
|
return null;
|
|
12957
12967
|
const pkgEntryName = specifier;
|
|
12958
|
-
return { pkgName: pkgEntryName, entryFile, pkgDir: path13.dirname(entryFile) };
|
|
12968
|
+
return { pkgName: pkgEntryName, entryFile, pkgDir: path13.dirname(entryFile), preserveFilePath: true };
|
|
12959
12969
|
} catch {
|
|
12960
12970
|
return null;
|
|
12961
12971
|
}
|
package/devkit/executors.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type SpawnOptions,
|
|
8
8
|
spawn,
|
|
9
9
|
} from "node:child_process";
|
|
10
|
-
import { mkdir, stat } from "node:fs/promises";
|
|
10
|
+
import { mkdir, readdir as readDirEntries, stat } from "node:fs/promises";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import {
|
|
13
13
|
capitalize,
|
|
@@ -455,7 +455,7 @@ export class Executor {
|
|
|
455
455
|
);
|
|
456
456
|
return fileContent ? [fileContent] : ([] as FileContent[]);
|
|
457
457
|
} else {
|
|
458
|
-
const subdirs = await
|
|
458
|
+
const subdirs = await readDirEntries(templatePath);
|
|
459
459
|
const fileContents = (
|
|
460
460
|
await Promise.all(
|
|
461
461
|
subdirs.map(async (subdir) => {
|
|
@@ -615,6 +615,9 @@ export class WorkspaceExecutor extends Executor {
|
|
|
615
615
|
if (type === "lib" || type === "pkg")
|
|
616
616
|
rootTsConfig.compilerOptions.paths[`@${name}`] = [`${type}s/${name}/index.ts`];
|
|
617
617
|
rootTsConfig.compilerOptions.paths[`@${name}/*`] = [`${type}s/${name}/*`];
|
|
618
|
+
rootTsConfig.compilerOptions.paths[`@${type}s/${name}/*`] = [`${type}s/${name}/*`];
|
|
619
|
+
if (type === "lib" || type === "pkg")
|
|
620
|
+
rootTsConfig.compilerOptions.paths[`@${type}s/${name}`] = [`${type}s/${name}/index.ts`];
|
|
618
621
|
if (rootTsConfig.references) {
|
|
619
622
|
if (!rootTsConfig.references.some((ref) => ref.path === `./${type}s/${name}/tsconfig.json`))
|
|
620
623
|
rootTsConfig.references.push({ path: `./${type}s/${name}/tsconfig.json` });
|
|
@@ -625,7 +628,7 @@ export class WorkspaceExecutor extends Executor {
|
|
|
625
628
|
async unsetTsPaths(type: "app" | "lib" | "pkg", name: string) {
|
|
626
629
|
const rootTsConfig = (await this.readJson("tsconfig.json")) as TsConfigJson;
|
|
627
630
|
const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter(
|
|
628
|
-
(key) => !key.startsWith(`@${name}`),
|
|
631
|
+
(key) => !key.startsWith(`@${name}`) && !key.startsWith(`@${type}s/${name}`),
|
|
629
632
|
);
|
|
630
633
|
rootTsConfig.compilerOptions.paths = Object.fromEntries(
|
|
631
634
|
filteredKeys.map((key) => [key, rootTsConfig.compilerOptions.paths?.[key] ?? []]),
|
|
@@ -17,6 +17,8 @@ export interface PackageEntry {
|
|
|
17
17
|
entryFile: string;
|
|
18
18
|
/** Absolute directory used as the base for subpath computation. Typically dirname(entryFile). */
|
|
19
19
|
pkgDir: string;
|
|
20
|
+
/** Preserve concrete file paths for package exports that do not support extensionless deep imports. */
|
|
21
|
+
preserveFilePath?: boolean;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface BarrelAnalyzerOptions {
|
|
@@ -162,6 +164,7 @@ export class BarrelAnalyzer {
|
|
|
162
164
|
#subpathFor(pkg: PackageEntry, absFile: string): string | null {
|
|
163
165
|
const rel = path.relative(pkg.pkgDir, absFile);
|
|
164
166
|
if (!rel || rel.startsWith("..") || path.isAbsolute(rel)) return null;
|
|
167
|
+
if (pkg.preserveFilePath) return `${pkg.pkgName}/${rel.split(path.sep).join("/")}`;
|
|
165
168
|
const noExt = stripKnownExt(rel);
|
|
166
169
|
|
|
167
170
|
const tail = collapseIndex(noExt);
|
|
@@ -19,7 +19,7 @@ export interface BarrelImportsPluginOptions {
|
|
|
19
19
|
|
|
20
20
|
export const createBarrelImportsPlugin = async (
|
|
21
21
|
app: App,
|
|
22
|
-
{ skipPath =
|
|
22
|
+
{ skipPath = defaultSkipPath, pipeAfter }: BarrelImportsPluginOptions = {},
|
|
23
23
|
): Promise<BunPlugin> => {
|
|
24
24
|
const akanConfig = await app.getConfig();
|
|
25
25
|
const barrels = [...new Set(akanConfig.barrelImports)].filter(Boolean);
|
|
@@ -31,40 +31,46 @@ export const createBarrelImportsPlugin = async (
|
|
|
31
31
|
name: "barrel-imports",
|
|
32
32
|
setup(build) {
|
|
33
33
|
|
|
34
|
-
build.onLoad(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
build.onLoad(
|
|
35
|
+
{
|
|
36
|
+
filter:
|
|
37
|
+
/^(?:(?!.*[\\/]node_modules[\\/]).*|.*[\\/]node_modules[\\/]akanjs[\\/].*)\.(tsx|ts|jsx|js)(\?v=\d+)?$/,
|
|
38
|
+
},
|
|
39
|
+
async (args) => {
|
|
40
|
+
const realPath = args.path.replace(/\?v=\d+$/, "");
|
|
41
|
+
const loader = loaderFor(realPath);
|
|
42
|
+
if (skipPath(realPath)) {
|
|
43
|
+
const raw = await Bun.file(realPath).text();
|
|
44
|
+
return { contents: raw, loader };
|
|
45
|
+
}
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
let source = await Bun.file(realPath).text();
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
const hasMacroAttr = MACRO_ATTR_RE.test(source);
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
if (!hasMacroAttr && barrels.length > 0) {
|
|
52
|
+
|
|
53
|
+
let maybe = false;
|
|
54
|
+
for (const b of barrels) {
|
|
55
|
+
if (source.includes(b)) {
|
|
56
|
+
maybe = true;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (maybe) {
|
|
61
|
+
const rewritten = await rewriteBarrelImports(source, barrels, analyzer);
|
|
62
|
+
if (rewritten !== null) source = rewritten;
|
|
53
63
|
}
|
|
54
64
|
}
|
|
55
|
-
if (maybe) {
|
|
56
|
-
const rewritten = await rewriteBarrelImports(source, barrels, analyzer);
|
|
57
|
-
if (rewritten !== null) source = rewritten;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
if (pipeAfter) {
|
|
67
|
+
const piped = await pipeAfter(source, { path: realPath });
|
|
68
|
+
if (piped !== null) source = piped;
|
|
69
|
+
}
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
return { contents: source, loader };
|
|
72
|
+
},
|
|
73
|
+
);
|
|
68
74
|
},
|
|
69
75
|
};
|
|
70
76
|
};
|
|
@@ -162,6 +168,10 @@ export const createTsconfigPackageResolver = async (
|
|
|
162
168
|
|
|
163
169
|
const CANDIDATE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
164
170
|
|
|
171
|
+
const NODE_MODULES_RE = /[\\/]node_modules[\\/]/;
|
|
172
|
+
const AKANJS_NODE_MODULE_RE = /[\\/]node_modules[\\/]akanjs[\\/]/;
|
|
173
|
+
const defaultSkipPath = (absPath: string) => NODE_MODULES_RE.test(absPath) && !AKANJS_NODE_MODULE_RE.test(absPath);
|
|
174
|
+
|
|
165
175
|
type ExportValue = string | string[] | { [condition: string]: ExportValue | undefined };
|
|
166
176
|
|
|
167
177
|
const resolveNodePackageExport = async (workspaceRoot: string, specifier: string): Promise<PackageEntry | null> => {
|
|
@@ -184,7 +194,7 @@ const resolveNodePackageExport = async (workspaceRoot: string, specifier: string
|
|
|
184
194
|
const entryFile = await resolveFileCandidate(path.resolve(pkgDir, rel));
|
|
185
195
|
if (!entryFile) return null;
|
|
186
196
|
const pkgEntryName = specifier;
|
|
187
|
-
return { pkgName: pkgEntryName, entryFile, pkgDir: path.dirname(entryFile) };
|
|
197
|
+
return { pkgName: pkgEntryName, entryFile, pkgDir: path.dirname(entryFile), preserveFilePath: true };
|
|
188
198
|
} catch {
|
|
189
199
|
return null;
|
|
190
200
|
}
|
package/package.json
CHANGED