routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025-PRESENT Anthony Fu <https://github.com/antfu>
|
||||
Copyright (c) 2025-PRESENT 三咲智子 Kevin Deng <https://github.com/sxzz>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { Document, ToStringOptions } from "yaml";
|
||||
|
||||
//#region src/index.d.ts
|
||||
interface PnpmWorkspaceYamlSchema {
|
||||
packages?: string[];
|
||||
overrides?: Record<string, string>;
|
||||
catalog?: Record<string, string>;
|
||||
catalogs?: Record<string, Record<string, string>>;
|
||||
}
|
||||
interface PnpmWorkspaceYaml {
|
||||
getDocument: () => Document.Parsed;
|
||||
setContent: (content: string) => void;
|
||||
hasChanged: () => boolean;
|
||||
toJSON: () => PnpmWorkspaceYamlSchema;
|
||||
toString: (options?: ToStringOptions) => string;
|
||||
setPath: (path: string[], value: any) => void;
|
||||
/**
|
||||
* Set a package to catalog
|
||||
*/
|
||||
setPackage: (catalog: 'default' | (string & {}), packageName: string, specifier: string) => void;
|
||||
/**
|
||||
* Set a package to catalog only when the version matches, otherwise create a conflicts catalog
|
||||
*/
|
||||
setPackageNoConflicts: (catalog: 'default' | (string & {}), packageName: string, specifier: string) => void;
|
||||
/**
|
||||
* Get all catalogs for a package
|
||||
*/
|
||||
getPackageCatalogs: (packageName: string) => string[];
|
||||
/**
|
||||
* Check if the specifier has conflicts with the existing specifier in the catalog
|
||||
*/
|
||||
hasSpecifierConflicts: (catalog: 'default' | (string & {}), packageName: string, specifier: string) => {
|
||||
conflicts: boolean;
|
||||
newCatalogName: string;
|
||||
existingSpecifier?: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Parse pnpm workspace yaml content, and return an object to modify the content
|
||||
* while preserving the comments, anchor, and alias.
|
||||
*/
|
||||
declare function parsePnpmWorkspaceYaml(content: string): PnpmWorkspaceYaml;
|
||||
//#endregion
|
||||
export { PnpmWorkspaceYaml, PnpmWorkspaceYamlSchema, parsePnpmWorkspaceYaml };
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
import { Pair, isAlias, parseDocument, visit } from "yaml";
|
||||
|
||||
//#region src/index.ts
|
||||
/**
|
||||
* Parse pnpm workspace yaml content, and return an object to modify the content
|
||||
* while preserving the comments, anchor, and alias.
|
||||
*/
|
||||
function parsePnpmWorkspaceYaml(content) {
|
||||
let document = parseDocument(content);
|
||||
let hasChanged = false;
|
||||
function setContent(newContent) {
|
||||
content = newContent;
|
||||
document = parseDocument(content);
|
||||
hasChanged = false;
|
||||
}
|
||||
function setPath(path, value) {
|
||||
let map = path.length === 1 ? document.contents : document.getIn(path.slice(0, -1));
|
||||
if (!map) {
|
||||
map = document.createNode({});
|
||||
document.setIn(path.slice(0, -1), map);
|
||||
}
|
||||
const key = path[path.length - 1];
|
||||
let pair = map.items.find((i) => typeof i.key === "string" ? i.key === key : i.key.value === key);
|
||||
const keys = map.items.map((i) => typeof i.key === "string" ? i.key : String(i.key.value));
|
||||
if (!pair) {
|
||||
let index = 0;
|
||||
for (; index < keys.length; index++) if (keys[index].localeCompare(key) > 0) break;
|
||||
pair = new Pair(key, value);
|
||||
map.items.splice(index, 0, pair);
|
||||
hasChanged = true;
|
||||
} else if (isAlias(pair.value)) {
|
||||
const alias = findAnchor(document, pair.value);
|
||||
if (alias) {
|
||||
if (alias.value !== value) {
|
||||
alias.value = value;
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
} else if (!pair.value || typeof pair.value === "string") {
|
||||
if (pair.value !== value) {
|
||||
pair.value = value;
|
||||
hasChanged = true;
|
||||
}
|
||||
} else if (pair.value.value !== value) {
|
||||
pair.value.value = value;
|
||||
hasChanged = true;
|
||||
}
|
||||
}
|
||||
function hasSpecifierConflicts(catalogName, packageName, specifier) {
|
||||
const data = document.toJSON() || {};
|
||||
const existingSpecifier = catalogName === "default" ? data.catalog?.[packageName] : data.catalogs?.[catalogName]?.[packageName];
|
||||
if (existingSpecifier === specifier) return {
|
||||
conflicts: false,
|
||||
newCatalogName: catalogName,
|
||||
existingSpecifier
|
||||
};
|
||||
if (existingSpecifier) {
|
||||
const versionSuffix = normalizeCatalogName(specifier);
|
||||
return {
|
||||
conflicts: true,
|
||||
existingSpecifier,
|
||||
newCatalogName: catalogName === "default" ? `conflicts_${packageName}_${versionSuffix}` : `conflicts_${catalogName}_${versionSuffix}`
|
||||
};
|
||||
}
|
||||
return {
|
||||
conflicts: false,
|
||||
newCatalogName: catalogName
|
||||
};
|
||||
}
|
||||
function setPackageNoConflicts(catalogName, packageName, specifier) {
|
||||
const { newCatalogName } = hasSpecifierConflicts(catalogName, packageName, specifier);
|
||||
setPackage(newCatalogName, packageName, specifier);
|
||||
}
|
||||
function setPackage(catalogName, packageName, specifier) {
|
||||
const useCatalogsDefault = document.toJSON()?.catalogs?.default !== void 0;
|
||||
if (catalogName === "default" && !useCatalogsDefault) setPath(["catalog", packageName], specifier);
|
||||
else setPath([
|
||||
"catalogs",
|
||||
catalogName,
|
||||
packageName
|
||||
], specifier);
|
||||
}
|
||||
function getPackageCatalogs(packageName) {
|
||||
const catalogs = [];
|
||||
const data = document.toJSON() || {};
|
||||
if (data.catalogs) {
|
||||
for (const catalog of Object.keys(data.catalogs)) if (data.catalogs[catalog]?.[packageName]) catalogs.push(catalog);
|
||||
}
|
||||
if (data.catalog) {
|
||||
if (data.catalog[packageName]) catalogs.push("default");
|
||||
}
|
||||
return catalogs;
|
||||
}
|
||||
return {
|
||||
getDocument() {
|
||||
return document;
|
||||
},
|
||||
setContent,
|
||||
hasChanged: () => hasChanged,
|
||||
toJSON: () => document.toJSON(),
|
||||
toString: (options) => {
|
||||
const singleQuote = content.split("'").length >= content.split("\"").length;
|
||||
return document.toString({
|
||||
singleQuote,
|
||||
...options
|
||||
});
|
||||
},
|
||||
setPath,
|
||||
setPackage,
|
||||
setPackageNoConflicts,
|
||||
getPackageCatalogs,
|
||||
hasSpecifierConflicts
|
||||
};
|
||||
}
|
||||
function findAnchor(doc, alias) {
|
||||
let anchor;
|
||||
visit(doc, { Scalar: (_key, scalar, _path) => {
|
||||
if (scalar.anchor === alias.source && typeof scalar.value === "string") anchor = scalar;
|
||||
} });
|
||||
return anchor;
|
||||
}
|
||||
function normalizeCatalogName(name) {
|
||||
return name.replace(/\^/g, "h").replace(/~/g, "t").replace(/\./g, "_").replace(/</g, "l").replace(/>/g, "g").replace(/=/g, "e").replace(/\*/g, "s").replace(/@/g, "a").replace(/\|/g, "p").replace(/&/g, "n").replace(/-/g, "m").replace(/\+/g, "u").replace(/\s/g, "_");
|
||||
}
|
||||
|
||||
//#endregion
|
||||
export { parsePnpmWorkspaceYaml };
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "pnpm-workspace-yaml",
|
||||
"type": "module",
|
||||
"version": "1.6.0",
|
||||
"description": "Utilities for managing pnpm-workspace.yaml",
|
||||
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "三咲智子 Kevin Deng",
|
||||
"email": "sxzz@sxzz.moe"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/antfu"
|
||||
},
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
}
|
||||
],
|
||||
"homepage": "https://github.com/antfu/pnpm-workspace-utils#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/antfu/pnpm-workspace-utils.git",
|
||||
"directory": "packages/pnpm-workspace-yaml"
|
||||
},
|
||||
"bugs": "https://github.com/antfu/pnpm-workspace-utils/issues",
|
||||
"keywords": [
|
||||
"pnpm"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": "./dist/index.mjs",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"types": "./dist/index.d.mts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"yaml": "^2.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "tsx src/index.ts"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user