@codefast/cli 0.3.16-canary.0 → 0.3.16-canary.2

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.
@@ -74,7 +74,7 @@ const MAX_STRIP_VARIANT_PASSES = 12;
74
74
  const EMPTY_CN_TV_BINDINGS = /* @__PURE__ */ new Set();
75
75
  /**
76
76
  * Bucket sort order — **render pipeline** (lower → earlier in `cn()` output).
77
- *
77
+ *
78
78
  * Matches README: Existence → Position → Layout → Sizing → Spacing → Shape → Background
79
79
  * → Shadow → Typography → Composite → Motion → Starting → Behavior → State → Selector,
80
80
  * then `other` and `arbitrary` as sort tails for unknown utilities and arbitrary properties.
@@ -129,7 +129,7 @@ const COMPATIBLE_BUCKET_SETS = [
129
129
  ];
130
130
  /**
131
131
  * Responsive / variant prefix — Tailwind v4 aware.
132
- *
132
+ *
133
133
  * v3: sm: md: … — v4: @sm:, @min-[600px]:, @[480px]:, named @md/sidebar:,
134
134
  * viewport md/sidebar:, min-[100px]: / max-[100px]:, …
135
135
  *
@@ -157,7 +157,7 @@ function inDataAttributeStem(token) {
157
157
  * Uses the **full variant stack** (every `:` segment outside `[…]`), not only the
158
158
  * outermost prefix, so `@md/foo:[&>*]:w-auto` and `@md/foo:has-[…]:mt-px` stay in
159
159
  * separate groups while `hover:opacity` still keys as `hover` + `opacity`…
160
- *
160
+ *
161
161
  * `data-[…]` / `aria-[…]` normalize the first segment via {@link dataAttributeStem} /
162
162
  * {@link ariaAttributeStem} (full token required for bracket capture).
163
163
  *
@@ -5,22 +5,22 @@ function resolvePackageScopedConfig(configMap, pkgMeta) {
5
5
  if (!configMap) return;
6
6
  return configMap[pkgMeta.packageName];
7
7
  }
8
- function groupFilesByModule(files) {
9
- const modules = /* @__PURE__ */ new Map();
10
- for (const file of files) {
11
- let ext;
8
+ function groupDistFilesByModule(relativeDistFiles) {
9
+ const distModulesByPath = /* @__PURE__ */ new Map();
10
+ for (const relativeDistFile of relativeDistFiles) {
11
+ let fileExt;
12
12
  let modulePath;
13
- const dtsExt = Array.from(VALID_DTS_EXTENSIONS).find((candidate) => file.endsWith(candidate));
14
- if (dtsExt) {
15
- ext = dtsExt;
16
- modulePath = file.slice(0, -dtsExt.length);
13
+ const declarationExt = Array.from(VALID_DTS_EXTENSIONS).find((candidate) => relativeDistFile.endsWith(candidate));
14
+ if (declarationExt) {
15
+ fileExt = declarationExt;
16
+ modulePath = relativeDistFile.slice(0, -declarationExt.length);
17
17
  } else {
18
- ext = nodePath.extname(file);
19
- if (!VALID_JS_EXTENSIONS.has(ext)) continue;
20
- modulePath = file.slice(0, -ext.length);
18
+ fileExt = nodePath.extname(relativeDistFile);
19
+ if (!VALID_JS_EXTENSIONS.has(fileExt)) continue;
20
+ modulePath = relativeDistFile.slice(0, -fileExt.length);
21
21
  }
22
22
  if (!nodePath.basename(modulePath)) continue;
23
- let distModule = modules.get(modulePath);
23
+ let distModule = distModulesByPath.get(modulePath);
24
24
  if (!distModule) {
25
25
  distModule = {
26
26
  path: modulePath,
@@ -31,21 +31,24 @@ function groupFilesByModule(files) {
31
31
  dts: null
32
32
  }
33
33
  };
34
- modules.set(modulePath, distModule);
34
+ distModulesByPath.set(modulePath, distModule);
35
35
  }
36
- if (ext === ".js") distModule.files.js = file;
37
- else if (ext === ".mjs") distModule.files.mjs = file;
38
- else if (ext === ".cjs") distModule.files.cjs = file;
39
- else if (VALID_DTS_EXTENSIONS.has(ext)) distModule.files.dts = file;
36
+ if (fileExt === ".js") distModule.files.js = relativeDistFile;
37
+ else if (fileExt === ".mjs") distModule.files.mjs = relativeDistFile;
38
+ else if (fileExt === ".cjs") distModule.files.cjs = relativeDistFile;
39
+ else if (VALID_DTS_EXTENSIONS.has(fileExt)) distModule.files.dts = relativeDistFile;
40
40
  }
41
- return modules;
41
+ return distModulesByPath;
42
42
  }
43
43
  function toExportPath(distPath) {
44
44
  if (distPath === "index") return ".";
45
45
  if (distPath.endsWith("/index")) return `./${distPath.slice(0, -6)}`;
46
46
  return `./${distPath}`;
47
47
  }
48
- const GROUP_ORDER = {
48
+ function isBundlerChunkPath(distPath) {
49
+ return distPath.split("/").includes("chunks");
50
+ }
51
+ const EXPORT_GROUP_ORDER = {
49
52
  components: 100,
50
53
  hooks: 200,
51
54
  primitives: 300,
@@ -56,16 +59,16 @@ const GROUP_ORDER = {
56
59
  script: 750,
57
60
  css: 900
58
61
  };
59
- function getExportGroup(exportPath, pathTransform) {
62
+ function getExportSortGroup(exportPath, pathTransform) {
60
63
  if (exportPath === ".") return [
61
64
  ".",
62
65
  "",
63
66
  0,
64
67
  0
65
68
  ];
66
- const cleanPath = exportPath.startsWith("./") ? exportPath.slice(2) : exportPath;
67
- if (cleanPath.endsWith("/*")) {
68
- const dirName = cleanPath.slice(0, -2);
69
+ const specifierPath = exportPath.startsWith("./") ? exportPath.slice(2) : exportPath;
70
+ if (specifierPath.endsWith("/*")) {
71
+ const dirName = specifierPath.slice(0, -2);
69
72
  return [
70
73
  dirName,
71
74
  "",
@@ -73,14 +76,14 @@ function getExportGroup(exportPath, pathTransform) {
73
76
  0
74
77
  ];
75
78
  }
76
- const parts = cleanPath.split("/");
79
+ const parts = specifierPath.split("/");
77
80
  if (parts.length === 1) {
78
81
  const name = parts[0];
79
82
  if (name === void 0) throw new Error("invariant: export path segment missing");
80
- if (name in GROUP_ORDER) return [
83
+ if (name in EXPORT_GROUP_ORDER) return [
81
84
  name,
82
85
  "",
83
- GROUP_ORDER[name] ?? 0,
86
+ EXPORT_GROUP_ORDER[name] ?? 0,
84
87
  0
85
88
  ];
86
89
  if (pathTransform) return [
@@ -100,7 +103,7 @@ function getExportGroup(exportPath, pathTransform) {
100
103
  return [
101
104
  group,
102
105
  parts.slice(1).join("/"),
103
- GROUP_ORDER[group] ?? 700,
106
+ EXPORT_GROUP_ORDER[group] ?? 700,
104
107
  1
105
108
  ];
106
109
  }
@@ -114,21 +117,21 @@ function createPathTransform(config, pkgMeta) {
114
117
  if (!removePrefix) return null;
115
118
  return (exportPath) => {
116
119
  if (!exportPath.startsWith(removePrefix)) return exportPath;
117
- const result = exportPath.slice(removePrefix.length);
118
- if (result && result !== "." && !result.startsWith("./")) return `./${result}`;
119
- return result;
120
+ const trimmedExportPath = exportPath.slice(removePrefix.length);
121
+ if (trimmedExportPath && trimmedExportPath !== "." && !trimmedExportPath.startsWith("./")) return `./${trimmedExportPath}`;
122
+ return trimmedExportPath;
120
123
  };
121
124
  }
122
- function getSortTuple(exportPath, pathTransform) {
123
- const [group, subpath, order, isIndex] = getExportGroup(exportPath, pathTransform);
125
+ function getExportSortKey(exportPath, pathTransform) {
126
+ const [groupName, subpath, groupOrder, indexRank] = getExportSortGroup(exportPath, pathTransform);
124
127
  return [
125
- order,
126
- group,
127
- isIndex,
128
+ groupOrder,
129
+ groupName,
130
+ indexRank,
128
131
  subpath
129
132
  ];
130
133
  }
131
- function compareTuples(left, right) {
134
+ function compareExportSortKeys(left, right) {
132
135
  if (left[0] !== right[0]) return left[0] - right[0];
133
136
  if (left[1] !== right[1]) return left[1] < right[1] ? -1 : 1;
134
137
  if (left[2] !== right[2]) return left[2] - right[2];
@@ -142,27 +145,27 @@ async function generateCssExports(fileSystemService, distDir, cssConfig) {
142
145
  const cssFiles = (await fileSystemService.listRelativeFilesRecursively(distDir)).filter((relativeDistPath) => relativeDistPath.endsWith(".css"));
143
146
  if (!cssFiles.length) return {};
144
147
  const cssExports = { ...cssConfig.customExports };
145
- const cssByDir = /* @__PURE__ */ new Map();
146
- const rootCss = [];
147
- for (const file of cssFiles) {
148
- const dirName = nodePath.dirname(file).split(nodePath.sep).join("/");
149
- if (dirName === ".") rootCss.push(file);
148
+ const cssFilesByDir = /* @__PURE__ */ new Map();
149
+ const rootCssFiles = [];
150
+ for (const cssFile of cssFiles) {
151
+ const dirName = nodePath.dirname(cssFile).split(nodePath.sep).join("/");
152
+ if (dirName === ".") rootCssFiles.push(cssFile);
150
153
  else {
151
- const arr = cssByDir.get(dirName) || [];
152
- arr.push(file);
153
- cssByDir.set(dirName, arr);
154
+ const dirCssFiles = cssFilesByDir.get(dirName) || [];
155
+ dirCssFiles.push(cssFile);
156
+ cssFilesByDir.set(dirName, dirCssFiles);
154
157
  }
155
158
  }
156
- for (const file of rootCss) {
157
- const exportPath = `./${file}`;
158
- if (!(exportPath in cssExports)) cssExports[exportPath] = `./dist/${file}`;
159
+ for (const cssFile of rootCssFiles) {
160
+ const exportPath = `./${cssFile}`;
161
+ if (!(exportPath in cssExports)) cssExports[exportPath] = `./dist/${cssFile}`;
159
162
  }
160
- for (const [dirName, dirFiles] of cssByDir.entries()) if (await fileSystemService.isDirectoryCssOnly(distDir, dirName) && !cssConfig.forceExportFiles) {
163
+ for (const [dirName, dirCssFiles] of cssFilesByDir.entries()) if (await fileSystemService.isDirectoryCssOnly(distDir, dirName) && !cssConfig.forceExportFiles) {
161
164
  const wildcardExport = `./${dirName}/*`;
162
165
  if (!(wildcardExport in cssExports)) cssExports[wildcardExport] = `./dist/${dirName}/*`;
163
- } else for (const file of dirFiles) {
164
- const exportPath = `./${file}`;
165
- if (!(exportPath in cssExports)) cssExports[exportPath] = `./dist/${file}`;
166
+ } else for (const cssFile of dirCssFiles) {
167
+ const exportPath = `./${cssFile}`;
168
+ if (!(exportPath in cssExports)) cssExports[exportPath] = `./dist/${cssFile}`;
166
169
  }
167
170
  return cssExports;
168
171
  }
@@ -172,53 +175,53 @@ async function generateCssExports(fileSystemService, distDir, cssConfig) {
172
175
  * @since 0.3.16-canary.0
173
176
  */
174
177
  async function generateExports(fileSystemService, distDir, pathTransform, cssConfig, customExports) {
175
- const files = await fileSystemService.listRelativeFilesRecursively(distDir);
176
- if (!files.length) return {
178
+ const relativeDistFiles = await fileSystemService.listRelativeFilesRecursively(distDir);
179
+ if (!relativeDistFiles.length) return {
177
180
  exports: { [PACKAGE_JSON_EXPORT]: PACKAGE_JSON_EXPORT },
178
181
  originalPathBySpecifier: { [PACKAGE_JSON_EXPORT]: PACKAGE_JSON_EXPORT },
179
182
  jsCount: 0,
180
183
  cssCount: 0
181
184
  };
182
- const modules = groupFilesByModule(files);
183
- const validModules = Array.from(modules.values()).filter((moduleEntry) => (moduleEntry.files.js || moduleEntry.files.mjs) && moduleEntry.files.dts);
184
- if (!validModules.length) return {
185
+ const distModulesByPath = groupDistFilesByModule(relativeDistFiles);
186
+ const exportableModules = Array.from(distModulesByPath.values()).filter((moduleEntry) => (moduleEntry.files.js || moduleEntry.files.mjs) && !isBundlerChunkPath(moduleEntry.path));
187
+ if (!exportableModules.length) return {
185
188
  exports: { [PACKAGE_JSON_EXPORT]: PACKAGE_JSON_EXPORT },
186
189
  originalPathBySpecifier: { [PACKAGE_JSON_EXPORT]: PACKAGE_JSON_EXPORT },
187
190
  jsCount: 0,
188
191
  cssCount: 0
189
192
  };
190
- const exportsObj = {};
193
+ const moduleExportsBySpecifier = {};
191
194
  const originalPathBySpecifier = {};
192
- for (const distModuleEntry of validModules) {
195
+ for (const distModuleEntry of exportableModules) {
193
196
  const originalExportPath = toExportPath(distModuleEntry.path);
194
197
  let exportPath = originalExportPath;
195
198
  if (pathTransform) exportPath = pathTransform(exportPath);
196
- const dtsFile = distModuleEntry.files.dts;
197
- if (dtsFile === void 0) throw new Error(`mirror exports: missing .d.ts for ${distModuleEntry.path}`);
198
- const entry = { types: `./dist/${dtsFile}` };
199
- if (distModuleEntry.files.mjs) entry.import = `./dist/${distModuleEntry.files.mjs}`;
200
- else if (distModuleEntry.files.js) entry.import = `./dist/${distModuleEntry.files.js}`;
201
- if (distModuleEntry.files.cjs) entry.require = `./dist/${distModuleEntry.files.cjs}`;
202
- exportsObj[exportPath] = entry;
199
+ const exportEntry = {};
200
+ const declarationFile = distModuleEntry.files.dts;
201
+ if (declarationFile) exportEntry.types = `./dist/${declarationFile}`;
202
+ if (distModuleEntry.files.mjs) exportEntry.import = `./dist/${distModuleEntry.files.mjs}`;
203
+ else if (distModuleEntry.files.js) exportEntry.import = `./dist/${distModuleEntry.files.js}`;
204
+ if (distModuleEntry.files.cjs) exportEntry.require = `./dist/${distModuleEntry.files.cjs}`;
205
+ moduleExportsBySpecifier[exportPath] = exportEntry;
203
206
  originalPathBySpecifier[exportPath] = originalExportPath;
204
207
  }
205
- let sortedKeys = Object.keys(exportsObj).sort((pathA, pathB) => compareTuples(getSortTuple(pathA, pathTransform), getSortTuple(pathB, pathTransform)));
208
+ let sortedSpecifiers = Object.keys(moduleExportsBySpecifier).sort((leftSpecifier, rightSpecifier) => compareExportSortKeys(getExportSortKey(leftSpecifier, pathTransform), getExportSortKey(rightSpecifier, pathTransform)));
206
209
  const sortedExports = {};
207
- for (const exportKey of sortedKeys) sortedExports[exportKey] = exportsObj[exportKey];
210
+ for (const exportKey of sortedSpecifiers) sortedExports[exportKey] = moduleExportsBySpecifier[exportKey];
208
211
  const cssExports = await generateCssExports(fileSystemService, distDir, cssConfig ?? { enabled: true });
209
212
  Object.assign(sortedExports, cssExports);
210
213
  for (const [specifier, mappedPath] of Object.entries(customExports || {})) if (specifier !== "./package.json") sortedExports[specifier] = mappedPath;
211
214
  for (const cssSpecifier of Object.keys(cssExports)) if (!(cssSpecifier in originalPathBySpecifier)) originalPathBySpecifier[cssSpecifier] = cssSpecifier;
212
215
  for (const customSpecifier of Object.keys(customExports || {})) if (customSpecifier !== "./package.json" && !(customSpecifier in originalPathBySpecifier)) originalPathBySpecifier[customSpecifier] = customSpecifier;
213
- sortedKeys = Object.keys(sortedExports).filter((exportKey) => exportKey !== PACKAGE_JSON_EXPORT).sort((pathA, pathB) => compareTuples(getSortTuple(pathA, pathTransform), getSortTuple(pathB, pathTransform)));
216
+ sortedSpecifiers = Object.keys(sortedExports).filter((exportKey) => exportKey !== PACKAGE_JSON_EXPORT).sort((leftSpecifier, rightSpecifier) => compareExportSortKeys(getExportSortKey(leftSpecifier, pathTransform), getExportSortKey(rightSpecifier, pathTransform)));
214
217
  const finalExports = {};
215
- for (const exportKey of sortedKeys) finalExports[exportKey] = sortedExports[exportKey];
218
+ for (const exportKey of sortedSpecifiers) finalExports[exportKey] = sortedExports[exportKey];
216
219
  finalExports[PACKAGE_JSON_EXPORT] = PACKAGE_JSON_EXPORT;
217
220
  originalPathBySpecifier[PACKAGE_JSON_EXPORT] = PACKAGE_JSON_EXPORT;
218
221
  return {
219
222
  exports: finalExports,
220
223
  originalPathBySpecifier,
221
- jsCount: Object.keys(exportsObj).length,
224
+ jsCount: Object.keys(moduleExportsBySpecifier).length,
222
225
  cssCount: Object.keys(cssExports).length
223
226
  };
224
227
  }
@@ -5,6 +5,7 @@ import ts from "typescript";
5
5
  * @since 0.3.16-canary.0
6
6
  */
7
7
  var TagSinceWriter = class {
8
+ fs;
8
9
  sinceDocumentationTag = "@since";
9
10
  constructor(fs) {
10
11
  this.fs = fs;
@@ -103,7 +104,7 @@ var TagSinceWriter = class {
103
104
  const hasNonEmptyAfter = lines.slice(lineIndex + 1).some((value) => value.length > 0);
104
105
  return hasNonEmptyBefore && hasNonEmptyAfter;
105
106
  });
106
- const replacement = `/**\n${normalizedBodyLines.length > 0 ? `${normalizedBodyLines.map((line) => `${baseIndent} * ${line}`).join("\n")}\n${baseIndent} *\n` : ""}${baseIndent} * ${this.sinceDocumentationTag} ${version}\n${baseIndent} */`;
107
+ const replacement = `/**\n${normalizedBodyLines.length > 0 ? `${normalizedBodyLines.map((line) => line.length > 0 ? `${baseIndent} * ${line}` : `${baseIndent} *`).join("\n")}\n${baseIndent} *\n` : ""}${baseIndent} * ${this.sinceDocumentationTag} ${version}\n${baseIndent} */`;
107
108
  return {
108
109
  start: existingComment.pos,
109
110
  end: existingComment.end,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codefast/cli",
3
- "version": "0.3.16-canary.0",
3
+ "version": "0.3.16-canary.2",
4
4
  "description": "Developer CLI for the Codefast monorepo (arrange, mirror, tag)",
5
5
  "keywords": [
6
6
  "cli",
@@ -52,20 +52,21 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "commander": "^14.0.3",
55
- "jiti": "^2.6.1",
55
+ "jiti": "^2.7.0",
56
56
  "picomatch": "^4.0.4",
57
57
  "typescript": "^6.0.3",
58
- "yaml": "^2.8.4",
58
+ "yaml": "^2.9.0",
59
59
  "zod": "^4.4.3"
60
60
  },
61
61
  "devDependencies": {
62
- "@types/node": "^25.6.0",
62
+ "@types/node": "^25.7.0",
63
63
  "@types/picomatch": "^4.0.3",
64
- "@typescript/native-preview": "7.0.0-dev.20260504.1",
65
- "@vitest/coverage-v8": "^4.1.5",
66
- "vite": "^8.0.10",
67
- "vitest": "^4.1.5",
68
- "@codefast/typescript-config": "0.3.16-canary.0"
64
+ "@typescript/native-preview": "7.0.0-dev.20260514.1",
65
+ "@vitest/coverage-v8": "^4.1.6",
66
+ "tsdown": "^0.22.0",
67
+ "vite": "^8.0.13",
68
+ "vitest": "^4.1.6",
69
+ "@codefast/typescript-config": "0.3.16-canary.2"
69
70
  },
70
71
  "engines": {
71
72
  "node": ">=22.0.0"
@@ -75,9 +76,11 @@
75
76
  "check-types": "tsgo --noEmit",
76
77
  "clean": "rm -rf dist",
77
78
  "test": "vitest run",
79
+ "test:coverage": "vitest run --coverage",
80
+ "test:e2e": "vitest run tests/e2e",
78
81
  "test:integration": "vitest run tests/integration",
82
+ "test:type": "vitest run tests/types",
79
83
  "test:unit": "vitest run tests/unit",
80
- "test:coverage": "vitest run --coverage",
81
84
  "test:watch": "vitest"
82
85
  }
83
86
  }