@tallyrelease/plugins 0.5.0 → 0.6.0-beta.12
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/dist/dart/plugin.d.ts +1 -3
- package/dist/dart/plugin.js +99 -32
- package/package.json +2 -2
package/dist/dart/plugin.d.ts
CHANGED
package/dist/dart/plugin.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import { defaultUnitId, definePlugin
|
|
1
|
+
import { defaultUnitId, definePlugin } from "@tallyrelease/core";
|
|
2
2
|
import { parse as parseYaml } from "yaml";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { edgeBetween, unitsByPackage } from "../_kit/edges.js";
|
|
5
5
|
import { joinRoot, rootOf } from "../_kit/paths.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
buildOffset: z.number().int().nonnegative().optional(),
|
|
9
|
-
});
|
|
6
|
+
import { BUILD, NUMBERS, PRERELEASE } from "../_kit/semver.js";
|
|
7
|
+
const optionsSchema = z.strictObject({});
|
|
10
8
|
const PUBSPEC = "pubspec.yaml";
|
|
9
|
+
const MELOS = "melos.yaml";
|
|
11
10
|
const DEP_FIELDS = [
|
|
12
11
|
"dependencies",
|
|
13
12
|
"dev_dependencies",
|
|
14
13
|
"dependency_overrides",
|
|
15
14
|
];
|
|
15
|
+
const VERSION = `${NUMBERS}${PRERELEASE}${BUILD}`;
|
|
16
|
+
const EXACT = new RegExp(`^${VERSION}$`);
|
|
17
|
+
/** An exact `name: version` entry; the groups are the indent, name, colon, quote and trailing text. */
|
|
18
|
+
const PIN_LINE = new RegExp(`^([ \\t]+)([\\w.-]+)(:[ \\t]*)(["']?)${VERSION}\\4(?=\\s|$)(.*)$`);
|
|
16
19
|
/** The top-level `version:` line; group 3 is the value without quotes. */
|
|
17
20
|
const VERSION_LINE = /^(version:[ \t]*)(["']?)([^\s"'#]+)\2/m;
|
|
18
21
|
const record = (value) => typeof value === "object" && value !== null
|
|
@@ -34,49 +37,95 @@ const readPubspec = (ctx, root) => {
|
|
|
34
37
|
};
|
|
35
38
|
/** Directories whose pubspecs are never units. */
|
|
36
39
|
const SKIPPED = new Set(["build", "example"]);
|
|
37
|
-
/**
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
/** A root pubspec that only anchors a pub workspace or melos setup, without its own version. */
|
|
41
|
+
const isWorkspaceRoot = (ctx) => {
|
|
42
|
+
const pubspec = readPubspec(ctx, ".");
|
|
43
|
+
return (pubspec !== undefined &&
|
|
44
|
+
pubspec["version"] === undefined &&
|
|
45
|
+
(pubspec["workspace"] !== undefined || ctx.fs.exists(MELOS)));
|
|
46
|
+
};
|
|
47
|
+
/** Roots of every `pubspec.yaml`, skipping dot, `build` and `example` directories and a workspace root. */
|
|
48
|
+
const pubspecRoots = (ctx) => {
|
|
49
|
+
const skipRoot = isWorkspaceRoot(ctx);
|
|
50
|
+
return ctx.fs
|
|
51
|
+
.glob([PUBSPEC, `**/${PUBSPEC}`])
|
|
52
|
+
.filter((p) => p
|
|
53
|
+
.split("/")
|
|
54
|
+
.slice(0, -1)
|
|
55
|
+
.every((s) => !s.startsWith(".") && !SKIPPED.has(s)))
|
|
56
|
+
.map((p) => (p === PUBSPEC ? "." : rootOf(p, PUBSPEC)))
|
|
57
|
+
.filter((root) => !(skipRoot && root === "."));
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Whether a dependency entry makes the dependent ship the dependency's code:
|
|
61
|
+
* `path:` maps and exact versions under `dependencies`. Undefined when the
|
|
62
|
+
* entry is no link to a unit.
|
|
63
|
+
*/
|
|
64
|
+
const pinnedLink = (field, spec) => {
|
|
65
|
+
if (spec === null) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (typeof spec === "string") {
|
|
69
|
+
return field === "dependencies" && EXACT.test(spec);
|
|
70
|
+
}
|
|
71
|
+
return typeof record(spec)["path"] === "string"
|
|
72
|
+
? field === "dependencies"
|
|
73
|
+
: undefined;
|
|
74
|
+
};
|
|
75
|
+
/** Sets the exact version entries under top-level `dependencies:` that name a released package. */
|
|
76
|
+
const rewritePins = (content, released) => {
|
|
77
|
+
let inDeps = false;
|
|
78
|
+
let indent;
|
|
79
|
+
return content.replace(/^.*$/gm, (line) => {
|
|
80
|
+
if (/^dependencies:\s*(#.*)?$/.test(line)) {
|
|
81
|
+
inDeps = true;
|
|
82
|
+
indent = undefined;
|
|
83
|
+
return line;
|
|
84
|
+
}
|
|
85
|
+
if (!inDeps || /^\s*(#.*)?$/.test(line)) {
|
|
86
|
+
return line;
|
|
87
|
+
}
|
|
88
|
+
if (!/^\s/.test(line)) {
|
|
89
|
+
inDeps = false;
|
|
90
|
+
return line;
|
|
91
|
+
}
|
|
92
|
+
const [, lead = "", name = "", colon = "", quote = "", rest = ""] = PIN_LINE.exec(line) ?? [];
|
|
93
|
+
const version = released.get(name);
|
|
94
|
+
indent ??= /^[ \t]*/.exec(line)?.[0];
|
|
95
|
+
if (version === undefined || lead !== indent) {
|
|
96
|
+
return line;
|
|
97
|
+
}
|
|
98
|
+
return `${lead}${name}${colon}${quote}${version}${quote}${rest}`;
|
|
99
|
+
});
|
|
100
|
+
};
|
|
49
101
|
export const dartPlugin = definePlugin({
|
|
50
102
|
apiVersion: 1,
|
|
51
103
|
name: "dart",
|
|
52
104
|
options: optionsSchema,
|
|
53
|
-
schemes: { flutter },
|
|
54
105
|
discover: (ctx) => pubspecRoots(ctx).map((root) => {
|
|
55
106
|
const pubspec = readPubspec(ctx, root) ?? {};
|
|
56
107
|
const packageName = pubspec["name"];
|
|
57
|
-
const { buildOffset } = ctx.options;
|
|
58
108
|
return {
|
|
59
109
|
id: defaultUnitId(root, ctx.repo.name),
|
|
60
110
|
root,
|
|
61
111
|
version: "file",
|
|
62
|
-
|
|
63
|
-
meta: {
|
|
64
|
-
...(typeof packageName === "string" && { packageName }),
|
|
65
|
-
...(buildOffset !== undefined && { buildOffset }),
|
|
66
|
-
},
|
|
112
|
+
meta: typeof packageName === "string" ? { packageName } : {},
|
|
67
113
|
};
|
|
68
114
|
}),
|
|
69
115
|
edges: (ctx, units) => {
|
|
70
|
-
const byName = unitsByPackage(units, "dart")
|
|
116
|
+
const byName = unitsByPackage(units, "dart", (name, prior, unit) => {
|
|
117
|
+
ctx.log.warn(`package "${name}" is declared by "${prior.root}" and "${unit.root}"; using "${unit.root}"`);
|
|
118
|
+
});
|
|
71
119
|
const edges = [];
|
|
72
120
|
for (const to of byName.values()) {
|
|
73
121
|
const pubspec = readPubspec(ctx, to.root) ?? {};
|
|
74
122
|
for (const field of DEP_FIELDS) {
|
|
75
123
|
for (const [name, spec] of Object.entries(record(pubspec[field]))) {
|
|
76
|
-
|
|
124
|
+
const pinned = pinnedLink(field, spec);
|
|
125
|
+
if (pinned !== undefined) {
|
|
77
126
|
edges.push(...edgeBetween(byName.get(name), to, {
|
|
78
127
|
reason: `${field}: ${name}`,
|
|
79
|
-
pinned
|
|
128
|
+
pinned,
|
|
80
129
|
}));
|
|
81
130
|
}
|
|
82
131
|
}
|
|
@@ -88,11 +137,29 @@ export const dartPlugin = definePlugin({
|
|
|
88
137
|
{
|
|
89
138
|
path: joinRoot(unit.root, PUBSPEC),
|
|
90
139
|
read: (content) => VERSION_LINE.exec(content)?.[3],
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
140
|
+
write: (content, next, { units, versions }) => {
|
|
141
|
+
const released = new Map();
|
|
142
|
+
for (const u of units) {
|
|
143
|
+
const name = u.meta["dart"]?.["packageName"];
|
|
144
|
+
const version = versions.get(u.id);
|
|
145
|
+
if (typeof name === "string" && version !== undefined) {
|
|
146
|
+
released.set(name, version);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// A pubspec without a version line gets one after `name:`.
|
|
150
|
+
const versioned = VERSION_LINE.test(content)
|
|
151
|
+
? content.replace(VERSION_LINE, (_, key, quote) => `${key}${quote}${next}${quote}`)
|
|
152
|
+
: content.replace(/^name:.*$/m, (line) => `${line}${content.includes("\r\n") ? "\r\n" : "\n"}version: ${next}`);
|
|
153
|
+
return rewritePins(versioned, released);
|
|
154
|
+
},
|
|
95
155
|
},
|
|
96
156
|
],
|
|
97
|
-
inputs: () => ({
|
|
157
|
+
inputs: (ctx) => ({
|
|
158
|
+
global: [
|
|
159
|
+
"pubspec.lock",
|
|
160
|
+
MELOS,
|
|
161
|
+
"analysis_options.yaml",
|
|
162
|
+
...(isWorkspaceRoot(ctx) ? [PUBSPEC] : []),
|
|
163
|
+
],
|
|
164
|
+
}),
|
|
98
165
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tallyrelease/plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-beta.12",
|
|
4
4
|
"description": "Built-in ecosystem plugins of tallyrelease",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"prettier": "@abinnovision/prettier-config",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@tallyrelease/core": "^0.
|
|
44
|
+
"@tallyrelease/core": "^0.6.0-beta.12",
|
|
45
45
|
"yaml": "^2.9.1",
|
|
46
46
|
"zod": "^4.6.7"
|
|
47
47
|
},
|