@capgo/capacitor-pretty-toast 8.1.14 → 8.1.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-pretty-toast",
3
- "version": "8.1.14",
3
+ "version": "8.1.16",
4
4
  "description": "Native-first pretty toast notifications for Capacitor and the web",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -55,7 +55,8 @@
55
55
  "prepublishOnly": "bun run build",
56
56
  "check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs",
57
57
  "example:install": "cd example-app && bun install --frozen-lockfile",
58
- "example:build": "bun run build && cd example-app && bun install --frozen-lockfile && bun run build"
58
+ "example:build": "bun run build && cd example-app && bun install --frozen-lockfile && bun run build",
59
+ "changelog:ai": "node scripts/generate-ai-changelog.mjs"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@capacitor/android": "^8.0.0",
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Generate a release changelog with Cloudflare Workers AI in CI.
4
+ * Invoked from build.yml on tag releases via `bun run changelog:ai`.
5
+ */
6
+
7
+ import { execFileSync } from 'node:child_process';
8
+ import { appendFileSync } from 'node:fs';
9
+
10
+ const DEFAULT_MODEL = '@cf/moonshotai/kimi-k2.7-code';
11
+
12
+ function parseArgs(argv) {
13
+ const args = { fromTag: process.env.FROM_TAG, toTag: process.env.TO_TAG };
14
+ for (let i = 0; i < argv.length; i++) {
15
+ if (argv[i] === '--from-tag') args.fromTag = argv[++i];
16
+ if (argv[i] === '--to-tag') args.toTag = argv[++i];
17
+ if (argv[i] === '--model') args.model = argv[++i];
18
+ }
19
+ return args;
20
+ }
21
+
22
+ function git(args) {
23
+ return execFileSync('/usr/bin/git', args, { encoding: 'utf8' }).trim();
24
+ }
25
+
26
+ function resolveTags({ fromTag, toTag }) {
27
+ const currentTag =
28
+ toTag ??
29
+ (process.env.GITHUB_REF?.startsWith('refs/tags/') ? process.env.GITHUB_REF.replace('refs/tags/', '') : null);
30
+
31
+ if (!currentTag) {
32
+ throw new Error('Missing target tag. Set GITHUB_REF to refs/tags/<tag> or pass --to-tag.');
33
+ }
34
+
35
+ const previousTag = fromTag ?? git(['describe', '--tags', '--abbrev=0', `${currentTag}^`]);
36
+ return { previousTag, currentTag };
37
+ }
38
+
39
+ function buildPrompt(previousTag, currentTag) {
40
+ const commits = git(['log', `${previousTag}..${currentTag}`, '--pretty=format:%s']);
41
+ const diffLines = git(['diff', '--stat', `${previousTag}..${currentTag}`]).split('\n');
42
+ const diffStat = diffLines.at(-1)?.trim() ?? '';
43
+
44
+ return `You are a technical writer creating a changelog for a software project.
45
+
46
+ There are changes in the git repository between two points:
47
+ - From tag: ${previousTag}
48
+ - To tag: ${currentTag}
49
+ - Commits:
50
+ ${commits || '(none)'}
51
+ - Diff summary: ${diffStat || '(no file changes)'}
52
+
53
+ ## Instructions:
54
+ 1. **Categorize changes** using standard changelog categories:
55
+ - **Added**: New features
56
+ - **Changed**: Changes in existing functionality
57
+ - **Deprecated**: Soon-to-be removed features
58
+ - **Removed**: Removed features
59
+ - **Fixed**: Bug fixes
60
+ - **Security**: Security improvements
61
+
62
+ 2. **Write clear, user-focused descriptions** that explain:
63
+ - What changed from a user's perspective
64
+ - Why it matters
65
+ - Any breaking changes or migration notes
66
+
67
+ 3. **Use consistent formatting**:
68
+ - Each item should be a concise bullet point
69
+ - Start with an action verb when possible
70
+ - Group related changes together
71
+
72
+ 4. **Focus on semantic meaning** rather than technical implementation details
73
+
74
+ Output ONLY the changelog content in markdown format. Do NOT include any explanatory text, metadata, introductory phrases like "Based on the git analysis" or "Here's the changelog", or concluding remarks. Start IMMEDIATELY with the changelog categories and items (e.g., "## Added"). Do not include version numbers or dates. Do not preface your response with any text whatsoever.`;
75
+ }
76
+
77
+ async function generateChangelog(prompt, model) {
78
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
79
+ const apiToken = process.env.CLOUDFLARE_API_TOKEN;
80
+
81
+ if (!accountId || !apiToken) {
82
+ throw new Error('CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN are required.');
83
+ }
84
+
85
+ const url = `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/run/${model}`;
86
+ const response = await fetch(url, {
87
+ method: 'POST',
88
+ headers: {
89
+ Authorization: `Bearer ${apiToken}`,
90
+ 'Content-Type': 'application/json',
91
+ },
92
+ body: JSON.stringify({
93
+ messages: [{ role: 'user', content: prompt }],
94
+ }),
95
+ });
96
+
97
+ const payload = await response.json();
98
+ if (!response.ok || !payload.success) {
99
+ throw new Error(`Cloudflare AI request failed with status ${response.status}`);
100
+ }
101
+
102
+ const content = payload.result?.choices?.[0]?.message?.content ?? payload.result?.response;
103
+ if (!content || typeof content !== 'string') {
104
+ throw new Error('Cloudflare AI returned an empty changelog response');
105
+ }
106
+
107
+ return content.trim();
108
+ }
109
+
110
+ function writeGithubOutput({ result, fromTag, toTag }) {
111
+ const outputFile = process.env.GITHUB_OUTPUT;
112
+ if (!outputFile) return;
113
+
114
+ const delimiter = `changelog_${Date.now()}`;
115
+ appendFileSync(outputFile, `result<<${delimiter}\n${result}\n${delimiter}\n`);
116
+ appendFileSync(outputFile, `from_tag=${fromTag}\n`);
117
+ appendFileSync(outputFile, `to_tag=${toTag}\n`);
118
+ }
119
+
120
+ const args = parseArgs(process.argv.slice(2));
121
+ const model = args.model ?? process.env.CLOUDFLARE_AI_MODEL ?? DEFAULT_MODEL;
122
+ const { previousTag, currentTag } = resolveTags(args);
123
+ const prompt = buildPrompt(previousTag, currentTag);
124
+
125
+ console.error(`Generating changelog with ${model}`);
126
+ console.error(`Range: ${previousTag}..${currentTag}`);
127
+
128
+ try {
129
+ const result = await generateChangelog(prompt, model);
130
+ writeGithubOutput({ result, fromTag: previousTag, toTag: currentTag });
131
+ } catch (error) {
132
+ const message = error instanceof Error ? error.message : 'Unknown error';
133
+ console.error(`Changelog generation failed: ${message}`);
134
+ process.exit(1);
135
+ }