tegami 0.1.6 → 0.2.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.
@@ -1,109 +0,0 @@
1
- import { r as handlePluginError } from "./error-DNy8R5ue.js";
2
- import { n as jsonCodec, t as bumpTypeSchema } from "./schemas-CurBAaW5.js";
3
- import z$1 from "zod";
4
- import { dump } from "js-yaml";
5
- import { readFile } from "fs/promises";
6
- //#region src/changelog/shared.ts
7
- const changelogPackageConfigSchema = z$1.object({
8
- type: bumpTypeSchema.optional(),
9
- replay: z$1.array(z$1.string().min(1)).optional()
10
- });
11
- const changelogFrontmatterSchema = z$1.object({
12
- subject: z$1.string().optional(),
13
- packages: z$1.union([z$1.array(z$1.string()), z$1.record(z$1.string(), z$1.union([
14
- bumpTypeSchema,
15
- z$1.null(),
16
- changelogPackageConfigSchema
17
- ]))]).optional()
18
- });
19
- function renderChangelog(frontmatter, body) {
20
- return [
21
- "---",
22
- dump(frontmatter).trim(),
23
- "---",
24
- "",
25
- body.trim(),
26
- ""
27
- ].join("\n");
28
- }
29
- //#endregion
30
- //#region src/plans/store.ts
31
- const packagePlanStoreSchema = z$1.object({
32
- type: bumpTypeSchema.optional(),
33
- changelogIds: z$1.array(z$1.string()).optional(),
34
- bumpReasons: z$1.array(z$1.string()).optional(),
35
- npm: z$1.object({ distTag: z$1.string().optional() }).optional(),
36
- publish: z$1.boolean()
37
- });
38
- /** the persisted plan data for actual publishing */
39
- const planStoreSchema = jsonCodec(z$1.object({
40
- id: z$1.string(),
41
- createdAt: z$1.iso.datetime(),
42
- version: z$1.literal("0.0.0").default("0.0.0"),
43
- /** release note entries */
44
- changelogs: z$1.record(z$1.string(), z$1.object({
45
- filename: z$1.string(),
46
- content: z$1.string()
47
- })),
48
- /** package id -> package info */
49
- packages: z$1.record(z$1.string(), packagePlanStoreSchema)
50
- }));
51
- function createPlanStore(draft, context) {
52
- const store = {
53
- version: "0.0.0",
54
- id: `tegami-${Date.now().toString(36)}`,
55
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
56
- changelogs: {},
57
- packages: {}
58
- };
59
- for (const entry of draft.getChangelogs()) store.changelogs[entry.id] = {
60
- filename: entry.filename,
61
- content: entry.getRawContent()
62
- };
63
- for (const pkg of context.graph.getPackages()) {
64
- const plan = draft.getPackagePlan(pkg.id);
65
- if (plan) store.packages[pkg.id] = {
66
- publish: plan.publish ?? false,
67
- type: plan.type,
68
- npm: plan.npm,
69
- changelogIds: plan.changelogs?.map((entry) => entry.id),
70
- bumpReasons: plan.bumpReasons ? Array.from(plan.bumpReasons) : void 0
71
- };
72
- }
73
- return planStoreSchema.encode(store);
74
- }
75
- async function readPlanStore(context) {
76
- try {
77
- return planStoreSchema.decode(await readFile(context.planPath, "utf8"));
78
- } catch {}
79
- }
80
- //#endregion
81
- //#region src/plans/checks.ts
82
- async function publishPlanStatus(store, context) {
83
- async function defaultStatus() {
84
- try {
85
- await Promise.all(Object.entries(store.packages).map(async ([id, plan]) => {
86
- const pkg = context.graph.get(id);
87
- if (!pkg || !plan.publish) return;
88
- if (!await context.getRegistryClient(pkg).isPackagePublished(pkg)) throw "pending";
89
- }));
90
- return { state: "success" };
91
- } catch (err) {
92
- if (err === "pending") return { state: "pending" };
93
- throw err;
94
- }
95
- }
96
- let status = await defaultStatus();
97
- for (const plugin of context.plugins) {
98
- const resolved = await handlePluginError(plugin, "resolvePlanStatus", () => plugin.resolvePlanStatus?.call(context, status, { plan: store }));
99
- if (resolved) status = resolved;
100
- }
101
- return status;
102
- }
103
- async function assertPublishPlanFinished(context) {
104
- const store = await readPlanStore(context);
105
- if (!store) return;
106
- if ((await publishPlanStatus(store, context)).state === "pending") throw new Error(`Publish plan already exists at ${context.planPath} and is pending. Publish it before applying a new plan.`);
107
- }
108
- //#endregion
109
- export { changelogFrontmatterSchema as a, readPlanStore as i, publishPlanStatus as n, renderChangelog as o, createPlanStore as r, assertPublishPlanFinished as t };
@@ -1,282 +0,0 @@
1
- import { a as maxBump } from "./semver-C4vJ4SK8.js";
2
- import { r as handlePluginError } from "./error-DNy8R5ue.js";
3
- import { a as changelogFrontmatterSchema, n as publishPlanStatus } from "./checks-azjuIFt7.js";
4
- import { readFile, readdir } from "node:fs/promises";
5
- import { basename, join } from "node:path";
6
- import { dump, load } from "js-yaml";
7
- import { fromMarkdown } from "mdast-util-from-markdown";
8
- import { toMarkdown } from "mdast-util-to-markdown";
9
- //#region src/utils/frontmatter.ts
10
- /**
11
- * Inspired by https://github.com/jonschlinkert/gray-matter
12
- */
13
- const regex = /^---\r?\n(.+?)\r?\n---\r?\n?/s;
14
- /**
15
- * parse frontmatter, it supports only yaml format
16
- */
17
- function frontmatter(input) {
18
- const output = {
19
- matter: "",
20
- data: {},
21
- content: input
22
- };
23
- const match = regex.exec(input);
24
- if (!match) return output;
25
- output.matter = match[0];
26
- output.content = input.slice(match[0].length);
27
- output.data = load(match[1]) ?? {};
28
- return output;
29
- }
30
- //#endregion
31
- //#region src/changelog/parse.ts
32
- async function getChangelogFiles(context) {
33
- return (await readdir(context.changelogDir).catch(() => [])).filter((file) => file.endsWith(".md"));
34
- }
35
- async function readChangelogEntries(context) {
36
- const dir = context.changelogDir;
37
- const files = await getChangelogFiles(context);
38
- return (await Promise.all(files.map(async (file) => {
39
- const filePath = join(dir, file);
40
- const content = await readFile(filePath, "utf8");
41
- return parseChangelogFile(basename(filePath), content);
42
- }))).filter((v) => v !== void 0);
43
- }
44
- /** Parse one changelog markdown file into release entries. */
45
- function parseChangelogFile(filename, content) {
46
- const parsed = frontmatter(content);
47
- const { success, data } = changelogFrontmatterSchema.safeParse(parsed.data);
48
- if (!success || !data.packages) return;
49
- const tree = fromMarkdown(parsed.content);
50
- let headingBump;
51
- const packages = /* @__PURE__ */ new Map();
52
- const sections = [];
53
- for (const section of getHeadingSections(tree)) {
54
- const sectionBumpType = headingToBump(section.heading.depth);
55
- if (sectionBumpType) headingBump = headingBump ? maxBump(headingBump, sectionBumpType) : sectionBumpType;
56
- sections.push({
57
- depth: section.heading.depth,
58
- title: sectionToMarkdown(section.heading.children),
59
- content: sectionToMarkdown(section.children)
60
- });
61
- }
62
- if (sections.length === 0) return;
63
- if (Array.isArray(data.packages)) {
64
- if (!headingBump) return;
65
- for (const pkg of data.packages) packages.set(pkg, { type: headingBump });
66
- } else for (const [k, v] of Object.entries(data.packages)) {
67
- let config;
68
- if (typeof v === "string") config = { type: v };
69
- else if (v === null) config = { type: headingBump };
70
- else config = v;
71
- if (config.type || config.replay?.length) packages.set(k, config);
72
- }
73
- if (packages.size === 0) return;
74
- const entry = {
75
- id: filename,
76
- filename,
77
- subject: data.subject,
78
- packages,
79
- sections,
80
- _raw_body: parsed.content,
81
- getRawContent() {
82
- return [
83
- "---",
84
- dump({
85
- subject: this.subject,
86
- packages: Object.fromEntries(this.packages.entries())
87
- }).trim(),
88
- "---",
89
- "",
90
- entry._raw_body.trim(),
91
- ""
92
- ].join("\n");
93
- }
94
- };
95
- return entry;
96
- }
97
- function parseReplayCondition(condition) {
98
- if (condition.startsWith("exit prerelease:")) return {
99
- type: "on-exit-prerelease",
100
- name: condition.slice(16).trimStart()
101
- };
102
- const idx = condition.lastIndexOf("@");
103
- if (idx <= 0) return null;
104
- return {
105
- type: "on-version",
106
- name: condition.slice(0, idx),
107
- version: condition.slice(idx + 1)
108
- };
109
- }
110
- function getHeadingSections(tree) {
111
- const sections = [];
112
- let current;
113
- for (const child of tree.children) {
114
- if (child.type === "heading") {
115
- current = {
116
- heading: child,
117
- children: []
118
- };
119
- sections.push(current);
120
- continue;
121
- }
122
- current?.children.push(child);
123
- }
124
- return sections;
125
- }
126
- function sectionToMarkdown(children) {
127
- if (children.length === 0) return "";
128
- return toMarkdown({
129
- type: "root",
130
- children
131
- }, {
132
- bullet: "-",
133
- fence: "`"
134
- }).trim();
135
- }
136
- function headingToBump(depth) {
137
- switch (depth) {
138
- case 1: return "major";
139
- case 2: return "minor";
140
- case 3: return "patch";
141
- }
142
- }
143
- //#endregion
144
- //#region src/publish.ts
145
- async function resolvePublishTargets(context, store) {
146
- const targets = [];
147
- const preflightPromises = [];
148
- for (const [id, plan] of Object.entries(store.packages)) {
149
- if (!plan.publish) continue;
150
- const pkg = context.graph.get(id);
151
- if (!pkg) continue;
152
- targets.push(pkg.id);
153
- preflightPromises.push(context.getRegistryClient(pkg).publishPreflight?.(pkg, {
154
- store,
155
- packageStore: plan
156
- }));
157
- }
158
- const preflights = await Promise.all(preflightPromises);
159
- const children = /* @__PURE__ */ new Map();
160
- for (let i = 0; i < targets.length; i++) {
161
- const id = targets[i];
162
- children.set(id, preflights[i]?.wait);
163
- }
164
- const ordered = [];
165
- function scan(id, stack = /* @__PURE__ */ new Set()) {
166
- if (stack.has(id)) throw new Error(`circular reference of deps: ${[...stack, id].join(" -> ")}`);
167
- if (ordered.includes(id)) return;
168
- const deps = children.get(id);
169
- if (deps) {
170
- stack.add(id);
171
- for (const dep of deps) scan(dep, stack);
172
- stack.delete(id);
173
- }
174
- ordered.push(id);
175
- }
176
- for (const id of targets) scan(id);
177
- return ordered;
178
- }
179
- async function publishFromPlan(context, store, options) {
180
- const { dryRun = false } = options;
181
- const packages = [];
182
- if ((await publishPlanStatus(store, context)).state !== "pending") return { state: "skipped" };
183
- const orderedIds = await resolvePublishTargets(context, store);
184
- const parsedChangelogs = /* @__PURE__ */ new Map();
185
- for (const [id, entry] of Object.entries(store.changelogs)) {
186
- const parsed = parseChangelogFile(entry.filename, entry.content);
187
- if (!parsed) continue;
188
- parsedChangelogs.set(id, parsed);
189
- }
190
- for (const id of orderedIds) {
191
- const plan = store.packages[id];
192
- const pkg = context.graph.get(id);
193
- const registryClient = context.getRegistryClient(pkg);
194
- const changelogs = [];
195
- for (const id of plan.changelogIds ?? []) {
196
- const entry = parsedChangelogs.get(id);
197
- if (entry) changelogs.push(entry);
198
- }
199
- if (dryRun) {
200
- packages.push({
201
- id: pkg.id,
202
- name: pkg.name,
203
- version: pkg.version,
204
- npm: plan.npm,
205
- state: "success",
206
- changelogs
207
- });
208
- continue;
209
- }
210
- if (await registryClient.isPackagePublished(pkg)) {
211
- packages.push({
212
- id: pkg.id,
213
- name: pkg.name,
214
- version: pkg.version,
215
- npm: plan.npm,
216
- state: "success",
217
- changelogs
218
- });
219
- continue;
220
- }
221
- try {
222
- let result;
223
- for (const plugin of context.plugins) {
224
- const next = await handlePluginError(plugin, "willPublish", () => plugin.willPublish?.call(context, { pkg }));
225
- if (next !== void 0) {
226
- result = next;
227
- break;
228
- }
229
- }
230
- if (result === void 0) {
231
- await registryClient.publish(pkg, {
232
- packageStore: plan,
233
- store
234
- });
235
- result = {
236
- id: pkg.id,
237
- name: pkg.name,
238
- version: pkg.version,
239
- npm: plan.npm,
240
- state: "success",
241
- changelogs
242
- };
243
- }
244
- if (result === false) continue;
245
- for (const plugin of context.plugins) {
246
- const next = await handlePluginError(plugin, "afterPublish", () => plugin.afterPublish?.call(context, {
247
- pkg,
248
- result
249
- }));
250
- if (next) result = next;
251
- }
252
- packages.push(result);
253
- } catch (error) {
254
- packages.push({
255
- id: pkg.id,
256
- name: pkg.name,
257
- version: pkg.version,
258
- npm: plan.npm,
259
- changelogs,
260
- state: "failed",
261
- error: error instanceof Error ? error.message : String(error)
262
- });
263
- }
264
- }
265
- if (packages.length === 0) return { state: "skipped" };
266
- return {
267
- state: packages.some((pkg) => pkg.state === "failed") ? "failed" : "created",
268
- packages,
269
- _rawPlan: store
270
- };
271
- }
272
- function publishError(result, error) {
273
- result.state = "failed";
274
- if (result.state === "failed" && error) result.error = result.error ? `${result.error}\n${error}` : error;
275
- }
276
- function packagePublishError(result, packageResult, error) {
277
- result.state = "failed";
278
- packageResult.state = "failed";
279
- if (packageResult.state === "failed" && error) packageResult.error = packageResult.error ? `${packageResult.error}\n${error}` : error;
280
- }
281
- //#endregion
282
- export { readChangelogEntries as a, parseReplayCondition as i, publishError as n, publishFromPlan as r, packagePublishError as t };
@@ -1,42 +0,0 @@
1
- import { z } from "zod";
2
- //#region src/schemas.ts
3
- const stringRecordSchema = z.record(z.string(), z.string());
4
- const bumpTypeSchema = z.enum([
5
- "major",
6
- "minor",
7
- "patch"
8
- ]);
9
- const jsonCodec = (schema) => z.codec(z.string(), schema, {
10
- decode: (jsonString, ctx) => {
11
- try {
12
- return JSON.parse(jsonString);
13
- } catch (err) {
14
- ctx.issues.push({
15
- code: "invalid_format",
16
- format: "json",
17
- input: jsonString,
18
- message: err.message
19
- });
20
- return z.NEVER;
21
- }
22
- },
23
- encode: (value) => JSON.stringify(value)
24
- });
25
- const pnpmWorkspaceSchema = z.looseObject({ packages: z.array(z.string()).optional() });
26
- const packageManifestSchema = z.looseObject({
27
- name: z.string(),
28
- version: z.string().optional(),
29
- private: z.boolean().optional(),
30
- publishConfig: z.looseObject({
31
- access: z.enum(["public", "restricted"]).optional(),
32
- registry: z.string().optional(),
33
- tag: z.string().optional()
34
- }).optional(),
35
- workspaces: z.array(z.string()).optional(),
36
- dependencies: stringRecordSchema.optional(),
37
- devDependencies: stringRecordSchema.optional(),
38
- peerDependencies: stringRecordSchema.optional(),
39
- optionalDependencies: stringRecordSchema.optional()
40
- });
41
- //#endregion
42
- export { pnpmWorkspaceSchema as i, jsonCodec as n, packageManifestSchema as r, bumpTypeSchema as t };