@adbayb/stack 2.40.0-next-7baa8ed โ 2.40.0-next-314d883
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/bin/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import pkg from "../package.json" with { type: "json" };
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
void import(new URL(`../${package_.exports["."].default}`, import.meta.url));
|
|
5
|
+
void import(new URL(`../${pkg.exports["."].default}`, import.meta.url));
|
package/configs/oxlint/index.ts
CHANGED
|
@@ -15,8 +15,31 @@ export default defineConfig({
|
|
|
15
15
|
"unicorn",
|
|
16
16
|
"vitest",
|
|
17
17
|
],
|
|
18
|
+
// TODO: add jsPlugins for perfectionist and padding-line-between-statements + add React rules (such as set-state-in-effect) from React X https://github.com/oxc-project/oxc/issues/1022
|
|
18
19
|
categories: {
|
|
19
20
|
correctness: "error",
|
|
21
|
+
pedantic: "error",
|
|
22
|
+
perf: "error",
|
|
23
|
+
suspicious: "error",
|
|
24
|
+
nursery: "error",
|
|
25
|
+
},
|
|
26
|
+
rules: {
|
|
27
|
+
"no-undef": "off",
|
|
28
|
+
"prefer-readonly-parameter-types": "off",
|
|
29
|
+
"strict-boolean-expressions": "off",
|
|
30
|
+
"max-lines": "off",
|
|
31
|
+
"max-lines-per-function": "off",
|
|
32
|
+
"max-classes-per-file": "off",
|
|
33
|
+
"import/max-dependencies": "off",
|
|
34
|
+
"react/jsx-max-depth": "off",
|
|
35
|
+
"jsdoc/require-param-type": "off",
|
|
36
|
+
"jsdoc/require-property-type": "off",
|
|
37
|
+
"jsdoc/require-returns-type": "off",
|
|
38
|
+
"no-warning-comments": "off",
|
|
39
|
+
"array-callback-return": ["error", { allowImplicit: true }],
|
|
40
|
+
"typescript/consistent-return": "off",
|
|
41
|
+
"typescript/no-unsafe-type-assertion": "off",
|
|
42
|
+
// TODO: disable typescript/no-unsafe-type-assertion and check previous code to reinsert as assertion
|
|
20
43
|
},
|
|
21
44
|
options: {
|
|
22
45
|
denyWarnings: true,
|
package/dist/index.js
CHANGED
|
@@ -91,40 +91,42 @@ const setPackageManager = async () => {
|
|
|
91
91
|
*
|
|
92
92
|
* @see {@link https://github.com/nodejs/corepack/issues/613}
|
|
93
93
|
*/
|
|
94
|
-
|
|
94
|
+
await helpers.exec("pnx corepack enable");
|
|
95
95
|
};
|
|
96
|
-
|
|
96
|
+
async function getRequest(url, responseType) {
|
|
97
97
|
const response = await fetch(url);
|
|
98
98
|
if (!response.ok) throw createError("fetch", `Failed to fetch resources from ${url} (${JSON.stringify({
|
|
99
99
|
status: response.status,
|
|
100
100
|
statusText: response.statusText
|
|
101
101
|
})})`);
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
if (responseType === "text") return response.text();
|
|
103
|
+
return response.json();
|
|
104
|
+
}
|
|
105
|
+
const request = { get: getRequest };
|
|
104
106
|
const oxlint = (options) => async (files = []) => {
|
|
105
|
-
const
|
|
107
|
+
const args = [
|
|
106
108
|
...files,
|
|
107
109
|
"--disable-nested-config",
|
|
108
110
|
"--no-error-on-unmatched-pattern"
|
|
109
111
|
];
|
|
110
|
-
if (options.isFixMode)
|
|
112
|
+
if (options.isFixMode) args.push("--fix");
|
|
111
113
|
try {
|
|
112
|
-
return await helpers.exec(`oxlint ${
|
|
114
|
+
return await helpers.exec(`oxlint ${args.join(" ")}`);
|
|
113
115
|
} catch (error) {
|
|
114
|
-
throw createError("oxlint", error);
|
|
116
|
+
throw createError("oxlint", error instanceof Error ? error : new Error(String(error)));
|
|
115
117
|
}
|
|
116
118
|
};
|
|
117
119
|
const oxfmt = (options) => async (files = []) => {
|
|
118
|
-
const
|
|
120
|
+
const args = [
|
|
119
121
|
...files,
|
|
120
122
|
"--disable-nested-config",
|
|
121
123
|
"--no-error-on-unmatched-pattern",
|
|
122
124
|
options.isFixMode ? "--write" : "--check"
|
|
123
125
|
];
|
|
124
126
|
try {
|
|
125
|
-
return await helpers.exec(`oxfmt ${
|
|
127
|
+
return await helpers.exec(`oxfmt ${args.join(" ")}`);
|
|
126
128
|
} catch (error) {
|
|
127
|
-
throw createError("oxfmt", error);
|
|
129
|
+
throw createError("oxfmt", error instanceof Error ? error : new Error(String(error)));
|
|
128
130
|
}
|
|
129
131
|
};
|
|
130
132
|
const turbo = async (command, options = {}) => {
|
|
@@ -135,7 +137,7 @@ const turbo = async (command, options = {}) => {
|
|
|
135
137
|
hasLiveOutput
|
|
136
138
|
});
|
|
137
139
|
} catch (error) {
|
|
138
|
-
throw createError("turbo", error);
|
|
140
|
+
throw createError("turbo", error instanceof Error ? error : new Error(String(error)));
|
|
139
141
|
}
|
|
140
142
|
};
|
|
141
143
|
const logCheckableFiles = (files) => {
|
|
@@ -161,7 +163,7 @@ const changeset = async (command) => {
|
|
|
161
163
|
try {
|
|
162
164
|
return await helpers.exec(command, { hasLiveOutput: true });
|
|
163
165
|
} catch (error) {
|
|
164
|
-
throw createError("changeset", error);
|
|
166
|
+
throw createError("changeset", error instanceof Error ? error : new Error(String(error)));
|
|
165
167
|
}
|
|
166
168
|
};
|
|
167
169
|
|
|
@@ -186,7 +188,7 @@ const checkCommit = async () => {
|
|
|
186
188
|
try {
|
|
187
189
|
return await helpers.exec("commitlint --extends \"@commitlint/config-conventional\" --edit");
|
|
188
190
|
} catch (error) {
|
|
189
|
-
throw createError("commitlint", error);
|
|
191
|
+
throw createError("commitlint", error instanceof Error ? error : new Error(String(error)));
|
|
190
192
|
}
|
|
191
193
|
};
|
|
192
194
|
|
|
@@ -195,22 +197,22 @@ const checkCommit = async () => {
|
|
|
195
197
|
const checkDependency = async () => {
|
|
196
198
|
const stdout = await helpers.exec("pnpm recursive ls --json");
|
|
197
199
|
const checkDependencyVersionMismatch = createPackagesVersionMismatchChecker();
|
|
198
|
-
const packages = JSON.parse(stdout).map((
|
|
199
|
-
const packagePath = join(
|
|
200
|
-
assert(
|
|
200
|
+
const packages = JSON.parse(stdout).map((pkg) => {
|
|
201
|
+
const packagePath = join(pkg.path, "package.json");
|
|
202
|
+
assert(pkg.name, () => createPackageError(`\`${packagePath}\` must have a name field.`));
|
|
201
203
|
const packageContent = require(packagePath);
|
|
202
204
|
const peerDependencies = packageContent.peerDependencies ?? {};
|
|
203
205
|
const devDependencies = packageContent.devDependencies ?? {};
|
|
204
206
|
return {
|
|
205
207
|
dependencies: packageContent.dependencies ?? {},
|
|
206
208
|
devDependencies,
|
|
207
|
-
name:
|
|
209
|
+
name: pkg.name,
|
|
208
210
|
peerDependencies
|
|
209
211
|
};
|
|
210
212
|
});
|
|
211
|
-
for (const
|
|
212
|
-
checkDependencyVersionMismatch(
|
|
213
|
-
checkDependencyVersionRange(
|
|
213
|
+
for (const pkg of packages) {
|
|
214
|
+
checkDependencyVersionMismatch(pkg);
|
|
215
|
+
checkDependencyVersionRange(pkg);
|
|
214
216
|
}
|
|
215
217
|
};
|
|
216
218
|
const checkDependencyVersionRange = ({ dependencies, devDependencies, name, peerDependencies }) => {
|
|
@@ -219,7 +221,7 @@ const checkDependencyVersionRange = ({ dependencies, devDependencies, name, peer
|
|
|
219
221
|
consumedBy: name,
|
|
220
222
|
name: dependencyName
|
|
221
223
|
});
|
|
222
|
-
if (version !== "workspace:*" && !isExcluded(version) && !/^\d
|
|
224
|
+
if (version !== "workspace:*" && !isExcluded(version) && !/^\d/u.test(version)) throw createPackageError(`As a dev dependency, \`${dependencyName}\` version must be fixed (or set as "workspace:*" for local packages) to reduce accidental breaking change risks due to an implicit semver upgrade.`, {
|
|
223
225
|
consumedBy: name,
|
|
224
226
|
name: dependencyName
|
|
225
227
|
});
|
|
@@ -248,11 +250,11 @@ const checkDependencyVersionRange = ({ dependencies, devDependencies, name, peer
|
|
|
248
250
|
const createPackagesVersionMismatchChecker = () => {
|
|
249
251
|
const monorepoDependencies = /* @__PURE__ */ new Map();
|
|
250
252
|
const monorepoDevelopmentDependencies = /* @__PURE__ */ new Map();
|
|
251
|
-
const lint = (
|
|
252
|
-
const packageName =
|
|
253
|
+
const lint = (pkg, type) => {
|
|
254
|
+
const packageName = pkg.name;
|
|
253
255
|
const isDevelopment = type === "development";
|
|
254
256
|
const store = isDevelopment ? monorepoDevelopmentDependencies : monorepoDependencies;
|
|
255
|
-
const dependencies =
|
|
257
|
+
const dependencies = pkg[isDevelopment ? "devDependencies" : "dependencies"];
|
|
256
258
|
for (const [dependencyName, dependencyVersion] of Object.entries(dependencies)) {
|
|
257
259
|
if (!dependencyVersion) continue;
|
|
258
260
|
const storedVersion = store.get(dependencyName);
|
|
@@ -266,9 +268,9 @@ const createPackagesVersionMismatchChecker = () => {
|
|
|
266
268
|
});
|
|
267
269
|
}
|
|
268
270
|
};
|
|
269
|
-
return (
|
|
270
|
-
lint(
|
|
271
|
-
lint(
|
|
271
|
+
return (pkg) => {
|
|
272
|
+
lint(pkg, "development");
|
|
273
|
+
lint(pkg, "production");
|
|
272
274
|
};
|
|
273
275
|
};
|
|
274
276
|
const createPackageError = (message, context) => {
|
|
@@ -281,7 +283,7 @@ function assertVersion(version, { consumedBy, name }) {
|
|
|
281
283
|
}));
|
|
282
284
|
}
|
|
283
285
|
const isExcluded = (version) => {
|
|
284
|
-
const isPreReleaseVersion = /\d+\.\d+\.\d+-(alpha|beta|experimental|next|rc)
|
|
286
|
+
const isPreReleaseVersion = /\d+\.\d+\.\d+-(alpha|beta|experimental|next|rc).*/u.exec(version);
|
|
285
287
|
return version.startsWith("npm:") || isPreReleaseVersion;
|
|
286
288
|
};
|
|
287
289
|
const hasCaret = (version) => version.startsWith("^");
|
|
@@ -399,22 +401,24 @@ const createCleanCommand = (program) => {
|
|
|
399
401
|
};
|
|
400
402
|
const label$3 = (message) => `${message} ๐งน`;
|
|
401
403
|
const cleanFiles = async (files) => {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
404
|
+
await Promise.all(files.map(async (file) => {
|
|
405
|
+
await rm(file, {
|
|
406
|
+
force: true,
|
|
407
|
+
recursive: true
|
|
408
|
+
});
|
|
409
|
+
}));
|
|
406
410
|
};
|
|
407
411
|
const isDirectoryExistAndNotEmpty = (path) => {
|
|
408
412
|
return existsSync(path) && readdirSync(path).length > 0;
|
|
409
413
|
};
|
|
410
414
|
const retrieveIgnoredFiles = async () => {
|
|
411
|
-
return (await helpers.exec("git clean -fdXn")).split(/\n|\r\n/).filter((cleanOutput) => PRESERVE_FILES.every((excludedFile) => !cleanOutput.includes(excludedFile))).map((cleanOutput) => cleanOutput.split(" ").at(-1));
|
|
415
|
+
return (await helpers.exec("git clean -fdXn")).split(/\n|\r\n/u).filter((cleanOutput) => PRESERVE_FILES.every((excludedFile) => !cleanOutput.includes(excludedFile))).map((cleanOutput) => cleanOutput.split(" ").at(-1) ?? "").filter(Boolean);
|
|
412
416
|
};
|
|
413
417
|
const PRESERVE_FILES = ["node_modules"];
|
|
414
418
|
|
|
415
419
|
//#endregion
|
|
416
420
|
//#region package.json
|
|
417
|
-
var version = "2.40.0-next-
|
|
421
|
+
var version = "2.40.0-next-314d883";
|
|
418
422
|
|
|
419
423
|
//#endregion
|
|
420
424
|
//#region src/commands/create.ts
|
|
@@ -455,7 +459,7 @@ const createCreateCommand = (program) => {
|
|
|
455
459
|
}).task({
|
|
456
460
|
async handler({ inputDescription, inputName, inputTemplate, inputUrl }) {
|
|
457
461
|
if (!inputName) throw createError("stack create", "The project name is not optional. Make sure to provide a valid value (non-empty string).");
|
|
458
|
-
const { repoName, repoOwner } = (inputUrl.startsWith("git") ? /^git@.*:(?<repoOwner>.*)\/(?<repoName>.*)\.git$/ : /^https?:\/\/.*\/(?<repoOwner>.*)\/(?<repoName>.*)\.git$/).exec(inputUrl)?.groups ?? {};
|
|
462
|
+
const { repoName, repoOwner } = (inputUrl.startsWith("git") ? /^git@.*:(?<repoOwner>.*)\/(?<repoName>.*)\.git$/u : /^https?:\/\/.*\/(?<repoOwner>.*)\/(?<repoName>.*)\.git$/u).exec(inputUrl)?.groups ?? {};
|
|
459
463
|
if (!repoOwner || !repoName) throw createError("git", "The owner and repository name can not be extracted. Please make sure to follow either `/^git@.*:(?<repoOwner>.*)/(?<repoName>.*).git$/` or `/^https?://.*/(?<repoOwner>.*)/(?<repoName>.*).git$/` pattern.");
|
|
460
464
|
const nodeVersion = await request.get("https://resolve-node.vercel.app/lts", "text");
|
|
461
465
|
const { version: pnpmVersion } = await request.get("https://registry.npmjs.org/pnpm/latest", "json");
|
|
@@ -541,7 +545,7 @@ const createCreateCommand = (program) => {
|
|
|
541
545
|
await helpers.exec(`pnpm add ${localDevelopmentDependencies.join(" ")} --save-dev --filter ${projectName}`);
|
|
542
546
|
await helpers.exec("pnpm install");
|
|
543
547
|
} catch (error) {
|
|
544
|
-
throw createError("pnpm", error);
|
|
548
|
+
throw createError("pnpm", error instanceof Error ? error : new Error(String(error)));
|
|
545
549
|
}
|
|
546
550
|
},
|
|
547
551
|
label: label$2("Install dependencies")
|
|
@@ -566,7 +570,7 @@ const createCreateCommand = (program) => {
|
|
|
566
570
|
};
|
|
567
571
|
const label$2 = (message) => `${message} ๐จ`;
|
|
568
572
|
const slugify = (input) => {
|
|
569
|
-
return input.toLowerCase().replaceAll(/[^a-z0-9\s-]/
|
|
573
|
+
return input.toLowerCase().replaceAll(/[^a-z0-9\s-]/gu, "").trim().replaceAll(/\s+/gu, "-").replaceAll(/-+/gu, "-");
|
|
570
574
|
};
|
|
571
575
|
const toCapitalLetter = (input) => {
|
|
572
576
|
return input.charAt(0).toUpperCase() + input.slice(1);
|
|
@@ -586,7 +590,7 @@ const createTemplateEngine = async (workingPath, { projectName, templateModel, t
|
|
|
586
590
|
return {
|
|
587
591
|
async processContents() {
|
|
588
592
|
await Promise.all(templateEntries.filter(({ type }) => type === "content").map(async (entry) => {
|
|
589
|
-
|
|
593
|
+
await writeFile(entry.path, setTemplateVariables(entry, templateModel));
|
|
590
594
|
}));
|
|
591
595
|
},
|
|
592
596
|
async processPaths() {
|
|
@@ -621,7 +625,7 @@ const getTemplateEntries = async (path) => {
|
|
|
621
625
|
content: await readFile(entryPath, "utf8"),
|
|
622
626
|
type: "content"
|
|
623
627
|
}]).map(({ content, type }) => {
|
|
624
|
-
if (!hasTemplateVariable(content)) return
|
|
628
|
+
if (!hasTemplateVariable(content)) return;
|
|
625
629
|
return {
|
|
626
630
|
content,
|
|
627
631
|
path: entryPath,
|
|
@@ -635,7 +639,7 @@ const setTemplateVariables = (entry, model) => {
|
|
|
635
639
|
return model[dataModelKey] ?? match;
|
|
636
640
|
});
|
|
637
641
|
};
|
|
638
|
-
const TEMPLATE_VARIABLE_MATCHER =
|
|
642
|
+
const TEMPLATE_VARIABLE_MATCHER = /\{\{(.*?)\}\}/giu;
|
|
639
643
|
const hasTemplateVariable = (input) => {
|
|
640
644
|
/**
|
|
641
645
|
* TemplateVariableMatcher.test() is not used since the `RegExp` is stateful when the global is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adbayb/stack",
|
|
3
|
-
"version": "2.40.0-next-
|
|
3
|
+
"version": "2.40.0-next-314d883",
|
|
4
4
|
"description": "My opinionated JavaScript-based toolchain",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"development",
|
|
@@ -45,17 +45,17 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@changesets/changelog-github": "^0.7.0",
|
|
47
47
|
"@changesets/cli": "^2.31.0",
|
|
48
|
-
"@commitlint/cli": "^21.
|
|
49
|
-
"@commitlint/config-conventional": "^21.0
|
|
50
|
-
"oxfmt": "^0.
|
|
51
|
-
"oxlint": "^1.
|
|
48
|
+
"@commitlint/cli": "^21.2.1",
|
|
49
|
+
"@commitlint/config-conventional": "^21.2.0",
|
|
50
|
+
"oxfmt": "^0.58.0",
|
|
51
|
+
"oxlint": "^1.73.0",
|
|
52
52
|
"oxlint-tsgolint": "^0.24.0",
|
|
53
53
|
"termost": "^1.9.1",
|
|
54
|
-
"turbo": "^2.
|
|
54
|
+
"turbo": "^2.10.4",
|
|
55
55
|
"typescript": "^6.0.3"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@types/node": "24.13.
|
|
58
|
+
"@types/node": "24.13.3",
|
|
59
59
|
"quickbundle": "3.0.0"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|