@foss.global/codefeed 1.5.3 → 1.6.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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@foss.global/codefeed',
6
- version: '1.5.3',
7
- description: 'a module for creating feeds for code development'
6
+ version: '1.6.1',
7
+ description: 'The @foss.global/codefeed module is designed for generating feeds from Gitea repositories, enhancing development workflows by processing commit data and repository activities.'
8
8
  };
9
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGtEQUFrRDtDQUNoRSxDQUFBIn0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGlMQUFpTDtDQUMvTCxDQUFBIn0=
@@ -5,33 +5,27 @@ export declare class CodeFeed {
5
5
  private npmRegistry;
6
6
  private smartxmlInstance;
7
7
  private lastRunTimestamp;
8
+ private changelogContent;
8
9
  constructor(baseUrl: string, token?: string, lastRunTimestamp?: string);
9
10
  /**
10
- * Fetch all organizations from the Gitea instance.
11
+ * Load the changelog directly from the Gitea repository.
11
12
  */
12
- private fetchAllOrganizations;
13
+ private loadChangelogFromRepo;
13
14
  /**
14
- * Fetch organization-level activity RSS feed.
15
+ * Parse the changelog to find the entry for a given version.
16
+ * The changelog format is assumed as:
17
+ *
18
+ * # Changelog
19
+ *
20
+ * ## <date> - <version> - <description>
21
+ * <changes...>
15
22
  */
23
+ private getChangelogForVersion;
24
+ private fetchAllOrganizations;
16
25
  private fetchOrgRssFeed;
17
- /**
18
- * Check if the organization's RSS feed has any new activities since the last run.
19
- */
20
26
  private hasNewActivity;
21
- /**
22
- * Fetch all repositories accessible to the token/user.
23
- */
24
27
  private fetchAllRepositories;
25
- /**
26
- * Fetch all tags for a given repository.
27
- */
28
28
  private fetchTags;
29
- /**
30
- * Fetch commits from the last 24 hours for a repository.
31
- */
32
29
  private fetchRecentCommitsForRepo;
33
- /**
34
- * Fetch all commits by querying all organizations.
35
- */
36
- fetchAllCommitsFromInstance(): Promise<plugins.interfaces.CommitResult[]>;
30
+ fetchAllCommitsFromInstance(): Promise<plugins.interfaces.ICommitResult[]>;
37
31
  }
package/dist_ts/index.js CHANGED
@@ -9,8 +9,58 @@ export class CodeFeed {
9
9
  console.log('CodeFeed initialized with last run timestamp:', this.lastRunTimestamp);
10
10
  }
11
11
  /**
12
- * Fetch all organizations from the Gitea instance.
12
+ * Load the changelog directly from the Gitea repository.
13
13
  */
14
+ async loadChangelogFromRepo(owner, repo) {
15
+ const url = `${this.baseUrl}/api/v1/repos/${owner}/${repo}/contents/changelog.md`;
16
+ const headers = {};
17
+ if (this.token) {
18
+ headers['Authorization'] = `token ${this.token}`;
19
+ }
20
+ const response = await fetch(url, { headers });
21
+ if (!response.ok) {
22
+ console.error(`Could not fetch CHANGELOG.md from ${owner}/${repo}: ${response.status} ${response.statusText}`);
23
+ this.changelogContent = '';
24
+ return;
25
+ }
26
+ const data = await response.json();
27
+ if (!data.content) {
28
+ console.warn(`No content field found in response for ${owner}/${repo}/changelog.md`);
29
+ this.changelogContent = '';
30
+ return;
31
+ }
32
+ const decodedContent = Buffer.from(data.content, 'base64').toString('utf8');
33
+ this.changelogContent = decodedContent;
34
+ }
35
+ /**
36
+ * Parse the changelog to find the entry for a given version.
37
+ * The changelog format is assumed as:
38
+ *
39
+ * # Changelog
40
+ *
41
+ * ## <date> - <version> - <description>
42
+ * <changes...>
43
+ */
44
+ getChangelogForVersion(version) {
45
+ if (!this.changelogContent) {
46
+ return undefined;
47
+ }
48
+ const lines = this.changelogContent.split('\n');
49
+ const versionHeaderIndex = lines.findIndex((line) => line.includes(`- ${version} -`));
50
+ if (versionHeaderIndex === -1) {
51
+ return undefined;
52
+ }
53
+ const changelogLines = [];
54
+ for (let i = versionHeaderIndex + 1; i < lines.length; i++) {
55
+ const line = lines[i];
56
+ // The next version header starts with `## `
57
+ if (line.startsWith('## ')) {
58
+ break;
59
+ }
60
+ changelogLines.push(line);
61
+ }
62
+ return changelogLines.join('\n').trim();
63
+ }
14
64
  async fetchAllOrganizations() {
15
65
  const url = `${this.baseUrl}/api/v1/orgs`;
16
66
  const response = await fetch(url, {
@@ -22,9 +72,6 @@ export class CodeFeed {
22
72
  const data = await response.json();
23
73
  return data.map((org) => org.username);
24
74
  }
25
- /**
26
- * Fetch organization-level activity RSS feed.
27
- */
28
75
  async fetchOrgRssFeed(optionsArg) {
29
76
  let rssUrl;
30
77
  if (optionsArg.orgName && !optionsArg.repoName) {
@@ -33,30 +80,24 @@ export class CodeFeed {
33
80
  else if (optionsArg.orgName && optionsArg.repoName) {
34
81
  rssUrl = `${this.baseUrl}/${optionsArg.orgName}/${optionsArg.repoName}.atom`;
35
82
  }
83
+ else {
84
+ throw new Error('Invalid arguments provided to fetchOrgRssFeed.');
85
+ }
36
86
  const response = await fetch(rssUrl);
37
87
  if (!response.ok) {
38
88
  throw new Error(`Failed to fetch RSS feed for organization ${optionsArg.orgName}/${optionsArg.repoName}: ${response.statusText}`);
39
89
  }
40
90
  const rssText = await response.text();
41
- // Parse the Atom feed using fast-xml-parser
42
91
  const rssData = this.smartxmlInstance.parseXmlToObject(rssText);
43
- // Return the <entry> elements from the feed
44
92
  return rssData.feed.entry || [];
45
93
  }
46
- /**
47
- * Check if the organization's RSS feed has any new activities since the last run.
48
- */
49
94
  async hasNewActivity(optionsArg) {
50
95
  const entries = await this.fetchOrgRssFeed(optionsArg);
51
- // Filter entries to find new activities since the last run
52
96
  return entries.some((entry) => {
53
97
  const updated = new Date(entry.updated);
54
98
  return updated > new Date(this.lastRunTimestamp);
55
99
  });
56
100
  }
57
- /**
58
- * Fetch all repositories accessible to the token/user.
59
- */
60
101
  async fetchAllRepositories() {
61
102
  let page = 1;
62
103
  const allRepos = [];
@@ -79,9 +120,6 @@ export class CodeFeed {
79
120
  }
80
121
  return allRepos;
81
122
  }
82
- /**
83
- * Fetch all tags for a given repository.
84
- */
85
123
  async fetchTags(owner, repo) {
86
124
  let page = 1;
87
125
  const tags = [];
@@ -111,9 +149,6 @@ export class CodeFeed {
111
149
  }
112
150
  return taggedCommitShas;
113
151
  }
114
- /**
115
- * Fetch commits from the last 24 hours for a repository.
116
- */
117
152
  async fetchRecentCommitsForRepo(owner, repo) {
118
153
  const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
119
154
  let page = 1;
@@ -146,9 +181,6 @@ export class CodeFeed {
146
181
  }
147
182
  return recentCommits;
148
183
  }
149
- /**
150
- * Fetch all commits by querying all organizations.
151
- */
152
184
  async fetchAllCommitsFromInstance() {
153
185
  const orgs = await this.fetchAllOrganizations();
154
186
  console.log(`Found ${orgs.length} organizations`);
@@ -191,6 +223,8 @@ export class CodeFeed {
191
223
  try {
192
224
  const taggedCommitShas = await this.fetchTags(org, repo);
193
225
  const commits = await this.fetchRecentCommitsForRepo(org, repo);
226
+ // Load the changelog from this repo.
227
+ await this.loadChangelogFromRepo(org, repo);
194
228
  const commitResults = commits.map((c) => {
195
229
  const commit = {
196
230
  baseUrl: this.baseUrl,
@@ -202,18 +236,24 @@ export class CodeFeed {
202
236
  commitMessage: c.commit.message,
203
237
  tagged: taggedCommitShas.has(c.sha),
204
238
  publishedOnNpm: false,
239
+ changelog: undefined
205
240
  };
206
241
  return commit;
207
242
  });
208
243
  if (commitResults.length > 0) {
209
244
  try {
210
245
  const packageInfo = await this.npmRegistry.getPackageInfo(`@${org}/${repo}`);
211
- for (const commit of commitResults.filter((c) => c.tagged)) {
246
+ for (const commitResult of commitResults.filter((c) => c.tagged)) {
247
+ const versionCandidate = commitResult.commitMessage.replace('\n', '').trim();
212
248
  const correspondingVersion = packageInfo.allVersions.find((versionArg) => {
213
- return versionArg.version === commit.commitMessage.replace('\n', '');
249
+ return versionArg.version === versionCandidate;
214
250
  });
215
251
  if (correspondingVersion) {
216
- commit.publishedOnNpm = true;
252
+ commitResult.publishedOnNpm = true;
253
+ const changelogEntry = this.getChangelogForVersion(versionCandidate);
254
+ if (changelogEntry) {
255
+ commitResult.changelog = changelogEntry;
256
+ }
217
257
  }
218
258
  }
219
259
  }
@@ -229,16 +269,18 @@ export class CodeFeed {
229
269
  }
230
270
  }
231
271
  console.log(`Processed ${allCommits.length} commits in total.`);
272
+ allCommits = allCommits.filter(commitArg => commitArg.tagged);
273
+ console.log(`Filtered to ${allCommits.length} commits with tagged statuses.`);
232
274
  for (const c of allCommits) {
233
275
  console.log(` ==========================================================================
234
276
  ${c.prettyAgoTime} ago:
235
277
  ${c.org}/${c.repo}
236
278
  ${c.commitMessage}
237
279
  Published on npm: ${c.publishedOnNpm}
280
+ ${c.changelog ? `Changelog:\n${c.changelog}\n` : ''}
238
281
  `);
239
282
  }
240
- allCommits = allCommits.filter(commitArg => commitArg.tagged);
241
283
  return allCommits;
242
284
  }
243
285
  }
244
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBR2pELE1BQU0sT0FBTyxRQUFRO0lBT25CLFlBQVksT0FBZSxFQUFFLEtBQWMsRUFBRSxnQkFBeUI7UUFKOUQsZ0JBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakQscUJBQWdCLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBSXpELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxnQkFBZ0IsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckcsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN0RixDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMscUJBQXFCO1FBQ2pDLE1BQU0sR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sY0FBYyxDQUFDO1FBQzFDLE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRTtZQUNoQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxhQUFhLEVBQUUsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtTQUNwRSxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsa0NBQWtDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFFRCxNQUFNLElBQUksR0FBMkIsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDM0QsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLGVBQWUsQ0FBQyxVQUc3QjtRQUNDLElBQUksTUFBYyxDQUFBO1FBQ2xCLElBQUksVUFBVSxDQUFDLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMvQyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxPQUFPLE9BQU8sQ0FBQztRQUN4RCxDQUFDO2FBQU0sSUFBSSxVQUFVLENBQUMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNyRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxPQUFPLElBQUksVUFBVSxDQUFDLFFBQVEsT0FBTyxDQUFDO1FBQy9FLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLFVBQVUsQ0FBQyxPQUFPLElBQUksVUFBVSxDQUFDLFFBQVEsS0FBSyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUNwSSxDQUFDO1FBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFdEMsNENBQTRDO1FBQzVDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVoRSw0Q0FBNEM7UUFDNUMsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7SUFDbEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLGNBQWMsQ0FBQyxVQUc1QjtRQUNDLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUV2RCwyREFBMkQ7UUFDM0QsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBVSxFQUFFLEVBQUU7WUFDakMsTUFBTSxPQUFPLEdBQUcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3hDLE9BQU8sT0FBTyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25ELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLG9CQUFvQjtRQUNoQyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7UUFDYixNQUFNLFFBQVEsR0FBb0MsRUFBRSxDQUFDO1FBRXJELE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLHNCQUFzQixDQUFDLENBQUM7WUFDM0QsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3BDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUU5QyxNQUFNLElBQUksR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFO2dCQUNqQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTthQUN0RSxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1lBQ3RFLENBQUM7WUFFRCxNQUFNLElBQUksR0FBMEMsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdEUsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUU1QixJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsRUFBRSxDQUFDO2dCQUMxQixNQUFNO1lBQ1IsQ0FBQztZQUNELElBQUksRUFBRSxDQUFDO1FBQ1QsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBYSxFQUFFLElBQVk7UUFDakQsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsTUFBTSxJQUFJLEdBQTZCLEVBQUUsQ0FBQztRQUUxQyxPQUFPLElBQUksRUFBRSxDQUFDO1lBQ1osTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxpQkFBaUIsS0FBSyxJQUFJLElBQUksT0FBTyxDQUFDLENBQUM7WUFDMUUsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3BDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUU5QyxNQUFNLElBQUksR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFO2dCQUNqQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTthQUN0RSxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsNEJBQTRCLEtBQUssSUFBSSxJQUFJLEtBQUssSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsVUFBVSxPQUFPLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUM3RyxNQUFNLElBQUksS0FBSyxDQUFDLDRCQUE0QixLQUFLLElBQUksSUFBSSxLQUFLLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1lBQ25GLENBQUM7WUFFRCxNQUFNLElBQUksR0FBNkIsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1lBRW5CLElBQUksSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLEVBQUUsQ0FBQztnQkFDckIsTUFBTTtZQUNSLENBQUM7WUFDRCxJQUFJLEVBQUUsQ0FBQztRQUNULENBQUM7UUFFRCxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDM0MsS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUM7Z0JBQ2xCLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxnQkFBZ0IsQ0FBQztJQUMxQixDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMseUJBQXlCLENBQUMsS0FBYSxFQUFFLElBQVk7UUFDakUsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDdEUsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsTUFBTSxhQUFhLEdBQWdDLEVBQUUsQ0FBQztRQUV0RCxPQUFPLElBQUksRUFBRSxDQUFDO1lBQ1osTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxpQkFBaUIsS0FBSyxJQUFJLElBQUksVUFBVSxDQUFDLENBQUM7WUFDN0UsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3BDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUU5QyxNQUFNLElBQUksR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFO2dCQUNqQyxPQUFPLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxlQUFlLEVBQUUsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTthQUN0RSxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEtBQUssSUFBSSxJQUFJLEtBQUssSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsVUFBVSxPQUFPLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUNoSCxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixLQUFLLElBQUksSUFBSSxLQUFLLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1lBQ3RGLENBQUM7WUFFRCxNQUFNLElBQUksR0FBZ0MsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDNUQsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUN0QixNQUFNO1lBQ1IsQ0FBQztZQUVELEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQzFCLE1BQU0sVUFBVSxHQUFHLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN2RCxJQUFJLFVBQVUsR0FBRyxrQkFBa0IsRUFBRSxDQUFDO29CQUNwQyxhQUFhLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUM3QixDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxhQUFhLENBQUM7Z0JBQ3ZCLENBQUM7WUFDSCxDQUFDO1lBRUQsSUFBSSxFQUFFLENBQUM7UUFDVCxDQUFDO1FBRUQsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLDJCQUEyQjtRQUN0QyxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxJQUFJLENBQUMsTUFBTSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ2xELElBQUksVUFBVSxHQUFzQyxFQUFFLENBQUM7UUFFdkQsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMzQixPQUFPLENBQUMsR0FBRyxDQUFDLHVDQUF1QyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBRTlELElBQUksQ0FBQztnQkFDSCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUM7b0JBQzVDLE9BQU87aUJBQ1IsQ0FBQyxDQUFDO2dCQUNILElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztvQkFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQ0FBcUMsT0FBTyxFQUFFLENBQUMsQ0FBQztvQkFDNUQsU0FBUztnQkFDWCxDQUFDO1lBQ0gsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsT0FBTyxHQUFHLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNyRixTQUFTO1lBQ1gsQ0FBQztZQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsMkNBQTJDLE9BQU8sOEJBQThCLENBQUMsQ0FBQztZQUU5RixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1lBQ2hELEtBQUssTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDckUsSUFBSSxDQUFDO29CQUNILE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQzt3QkFDNUMsT0FBTzt3QkFDUCxRQUFRLEVBQUUsQ0FBQyxDQUFDLElBQUk7cUJBQ2pCLENBQUMsQ0FBQztvQkFDSCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7d0JBQ2pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQW1DLE9BQU8sSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQzt3QkFDcEUsU0FBUztvQkFDWCxDQUFDO2dCQUNILENBQUM7Z0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztvQkFDZixPQUFPLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxPQUFPLElBQUksQ0FBQyxDQUFDLElBQUksR0FBRyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDN0YsU0FBUztnQkFDWCxDQUFDO2dCQUNELE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO2dCQUMxQixNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNwQixPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFFcEQsSUFBSSxDQUFDO29CQUNILE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFDekQsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMseUJBQXlCLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO29CQUVoRSxNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7d0JBQ3RDLE1BQU0sTUFBTSxHQUFvQzs0QkFDOUMsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPOzRCQUNyQixHQUFHOzRCQUNILElBQUk7NEJBQ0osU0FBUyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUk7NEJBQy9CLGFBQWEsRUFBRSxPQUFPLENBQUMsU0FBUyxDQUFDLHFDQUFxQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDOzRCQUNoSCxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUc7NEJBQ1gsYUFBYSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTzs0QkFDL0IsTUFBTSxFQUFFLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDOzRCQUNuQyxjQUFjLEVBQUUsS0FBSzt5QkFDdEIsQ0FBQTt3QkFDRCxPQUFPLE1BQU0sQ0FBQztvQkFDaEIsQ0FBQyxDQUFDLENBQUM7b0JBRUgsSUFBSSxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO3dCQUM3QixJQUFJLENBQUM7NEJBQ0gsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDOzRCQUM3RSxLQUFLLE1BQU0sTUFBTSxJQUFJLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO2dDQUMzRCxNQUFNLG9CQUFvQixHQUFHLFdBQVcsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7b0NBQ3ZFLE9BQU8sVUFBVSxDQUFDLE9BQU8sS0FBSyxNQUFNLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0NBQ3ZFLENBQUMsQ0FBQyxDQUFDO2dDQUNILElBQUksb0JBQW9CLEVBQUUsQ0FBQztvQ0FDekIsTUFBTSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUM7Z0NBQy9CLENBQUM7NEJBQ0gsQ0FBQzt3QkFDSCxDQUFDO3dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7NEJBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyxvQ0FBb0MsR0FBRyxJQUFJLElBQUksR0FBRyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQzt3QkFDbkYsQ0FBQztvQkFDSCxDQUFDO29CQUVELFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxhQUFhLENBQUMsQ0FBQztnQkFDcEMsQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxJQUFJLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDbkYsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLFVBQVUsQ0FBQyxNQUFNLG9CQUFvQixDQUFDLENBQUM7UUFDaEUsS0FBSyxNQUFNLENBQUMsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUMzQixPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ1YsQ0FBQyxDQUFDLGFBQWE7UUFDZixDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxJQUFJO1FBQ2YsQ0FBQyxDQUFDLGFBQWE7MEJBQ0csQ0FBQyxDQUFDLGNBQWM7S0FDckMsQ0FBQyxDQUFDO1FBQ0gsQ0FBQztRQUVELFVBQVUsR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTlELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7Q0FDRiJ9
286
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBRWpELE1BQU0sT0FBTyxRQUFRO0lBUW5CLFlBQVksT0FBZSxFQUFFLEtBQWMsRUFBRSxnQkFBeUI7UUFMOUQsZ0JBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakQscUJBQWdCLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBS3pELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxnQkFBZ0IsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDckcsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUN0RixDQUFDO0lBRUQ7O09BRUc7SUFDSyxLQUFLLENBQUMscUJBQXFCLENBQUMsS0FBYSxFQUFFLElBQVk7UUFDN0QsTUFBTSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxpQkFBaUIsS0FBSyxJQUFJLElBQUksd0JBQXdCLENBQUM7UUFDbEYsTUFBTSxPQUFPLEdBQTJCLEVBQUUsQ0FBQztRQUMzQyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxlQUFlLENBQUMsR0FBRyxTQUFTLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNuRCxDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMs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
@@ -1,30 +1,30 @@
1
- export interface RepositoryOwner {
1
+ export interface IRepositoryOwner {
2
2
  login: string;
3
3
  }
4
- export interface Repository {
5
- owner: RepositoryOwner;
4
+ export interface IRepository {
5
+ owner: IRepositoryOwner;
6
6
  name: string;
7
7
  }
8
- export interface CommitAuthor {
8
+ export interface ICommitAuthor {
9
9
  date: string;
10
10
  }
11
- export interface CommitDetail {
11
+ export interface ICommitDetail {
12
12
  message: string;
13
- author: CommitAuthor;
13
+ author: ICommitAuthor;
14
14
  }
15
- export interface Commit {
15
+ export interface ICommit {
16
16
  sha: string;
17
- commit: CommitDetail;
17
+ commit: ICommitDetail;
18
18
  }
19
- export interface Tag {
19
+ export interface ITag {
20
20
  commit?: {
21
21
  sha?: string;
22
22
  };
23
23
  }
24
- export interface RepoSearchResponse {
25
- data: Repository[];
24
+ export interface IRepoSearchResponse {
25
+ data: IRepository[];
26
26
  }
27
- export interface CommitResult {
27
+ export interface ICommitResult {
28
28
  baseUrl: string;
29
29
  org: string;
30
30
  repo: string;
@@ -34,4 +34,5 @@ export interface CommitResult {
34
34
  tagged: boolean;
35
35
  publishedOnNpm: boolean;
36
36
  prettyAgoTime: string;
37
+ changelog: string | undefined;
37
38
  }
package/npmextra.json CHANGED
@@ -5,10 +5,23 @@
5
5
  "githost": "code.foss.global",
6
6
  "gitscope": "foss.global",
7
7
  "gitrepo": "codefeed",
8
- "description": "a module for creating feeds for code development",
8
+ "description": "The @foss.global/codefeed module is designed for generating feeds from Gitea repositories, enhancing development workflows by processing commit data and repository activities.",
9
9
  "npmPackagename": "@foss.global/codefeed",
10
10
  "license": "MIT",
11
- "projectDomain": "foss.global"
11
+ "projectDomain": "foss.global",
12
+ "keywords": [
13
+ "codefeed",
14
+ "Gitea",
15
+ "commits",
16
+ "changelog",
17
+ "repository",
18
+ "development tools",
19
+ "npm",
20
+ "module",
21
+ "code analysis",
22
+ "activity feed",
23
+ "version control"
24
+ ]
12
25
  }
13
26
  },
14
27
  "npmci": {
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@foss.global/codefeed",
3
- "version": "1.5.3",
3
+ "version": "1.6.1",
4
4
  "private": false,
5
- "description": "a module for creating feeds for code development",
5
+ "description": "The @foss.global/codefeed module is designed for generating feeds from Gitea repositories, enhancing development workflows by processing commit data and repository activities.",
6
6
  "exports": {
7
7
  ".": "./dist_ts/index.js",
8
8
  "./interfaces": "./dist_ts/interfaces/index.js"
@@ -44,6 +44,19 @@
44
44
  "npmextra.json",
45
45
  "readme.md"
46
46
  ],
47
+ "keywords": [
48
+ "codefeed",
49
+ "Gitea",
50
+ "commits",
51
+ "changelog",
52
+ "repository",
53
+ "development tools",
54
+ "npm",
55
+ "module",
56
+ "code analysis",
57
+ "activity feed",
58
+ "version control"
59
+ ],
47
60
  "scripts": {
48
61
  "test": "(tstest test/ --web)",
49
62
  "build": "(tsbuild tsfolders --web --allowimplicitany)",
package/readme.md CHANGED
@@ -1,7 +1,130 @@
1
+ ```markdown
1
2
  # @foss.global/codefeed
2
3
 
3
- a module for creating feeds for code development
4
+ A module for creating feeds for code development.
4
5
 
5
- ## How to create the docs
6
+ ## Install
6
7
 
7
- To create docs run gitzone aidoc.
8
+ To install the `@foss.global/codefeed` package, you can run the following npm command in your project directory:
9
+
10
+ ```bash
11
+ npm install @foss.global/codefeed
12
+ ```
13
+
14
+ Ensure that you have a compatible version of Node.js installed and that your project is set up to support ECMAScript modules. The `@foss.global/codefeed` module uses ESM syntax.
15
+
16
+ ## Usage
17
+
18
+ The `@foss.global/codefeed` package is designed to help developers generate feeds for code developments, specifically targeting Gitea repositories. It fetches and processes commit data, changelogs, and repository activities for further analysis or visualization. Here, we'll delve into how you can utilize the different features of the `CodeFeed` class.
19
+
20
+ ### Setting Up CodeFeed
21
+
22
+ To get started, import the `CodeFeed` class from the module:
23
+
24
+ ```typescript
25
+ import { CodeFeed } from '@foss.global/codefeed';
26
+ ```
27
+
28
+ Then, create an instance of `CodeFeed`. You'll need the base URL of your Gitea instance and optionally an API token if your repositories require authentication:
29
+
30
+ ```typescript
31
+ const codeFeed = new CodeFeed('https://your-gitea-instance-url.com', 'your-api-token');
32
+ ```
33
+
34
+ The constructor can also accept a `lastRunTimestamp` which indicates the last time a sync was performed. If not provided, it defaults to 24 hours prior to the current time.
35
+
36
+ ### Fetching Commits
37
+
38
+ One of the core functionalities of CodeFeed is fetching commits from a Gitea instance. By calling `fetchAllCommitsFromInstance`, you can retrieve commits across multiple repositories:
39
+
40
+ ```typescript
41
+ (async () => {
42
+ try {
43
+ const commits = await codeFeed.fetchAllCommitsFromInstance();
44
+ console.log(commits);
45
+ } catch (error) {
46
+ console.error('An error occurred while fetching commits:', error);
47
+ }
48
+ })();
49
+ ```
50
+
51
+ This method scans all organizations and repositories, filters commits tagged within the last 24 hours, and enriches them with metadata like changelogs or npm publication status.
52
+
53
+ Each commit object in the resulting array conforms to the `ICommitResult` interface, containing details such as:
54
+ - `baseUrl`
55
+ - `org`
56
+ - `repo`
57
+ - `timestamp`
58
+ - `hash`
59
+ - `commitMessage`
60
+ - `tagged` (boolean)
61
+ - `publishedOnNpm` (boolean)
62
+ - `prettyAgoTime` (human-readable relative time)
63
+ - `changelog` (text from the `changelog.md` associated with a commit)
64
+
65
+ ### Understanding the Data Fetch Process
66
+
67
+ #### Fetching Organizations
68
+
69
+ The `fetchAllOrganizations` method collects all organizations within the Gitea instance:
70
+
71
+ ```typescript
72
+ const organizations = await codeFeed.fetchAllOrganizations();
73
+ console.log('Organizations:', organizations);
74
+ ```
75
+
76
+ This method interacts with the Gitea API to pull organization names, aiding further requests that require organization context.
77
+
78
+ #### Fetching Repositories
79
+
80
+ Repositories under these organizations can be retrieved using `fetchAllRepositories`:
81
+
82
+ ```typescript
83
+ const repositories = await codeFeed.fetchAllRepositories();
84
+ console.log('Repositories:', repositories);
85
+ ```
86
+
87
+ Here, filtering by organization can help narrow down the scope further when dealing with large instances.
88
+
89
+ #### Fetching Tags and Commits
90
+
91
+ To handle repository-specific details, use:
92
+
93
+ - `fetchTags(owner: string, repo: string)`: Appropriately handles paginated tag data within a repository.
94
+
95
+ - `fetchRecentCommitsForRepo(owner: string, repo: string)`: Gathers commit data specific to the past 24 hours for a given repository.
96
+
97
+ ```typescript
98
+ const tags = await codeFeed.fetchTags('orgName', 'repoName');
99
+ const recentCommits = await codeFeed.fetchRecentCommitsForRepo('orgName', 'repoName');
100
+
101
+ console.log('Tags:', tags);
102
+ console.log('Recent Commits:', recentCommits);
103
+ ```
104
+
105
+ ### Changelog Integration
106
+
107
+ Loading changelog content from a repository is integrated into the flow with `loadChangelogFromRepo`. This can be accessed when processing specific commits:
108
+
109
+ ```typescript
110
+ await codeFeed.loadChangelogFromRepo('org', 'repo');
111
+ const changelog = codeFeed.getChangelogForVersion('1.0.0');
112
+ console.log('Changelog for version 1.0.0:', changelog);
113
+ ```
114
+
115
+ ### Reacting to Repository Activity
116
+
117
+ The method `hasNewActivity` checks for recent changes within an organization or a repository. This is particularly useful for setting up alerting systems or continuous integration triggers:
118
+
119
+ ```typescript
120
+ const hasActivity = await codeFeed.hasNewActivity({ orgName: 'orgName', repoName: 'repoName' });
121
+ console.log('New activity detected:', hasActivity);
122
+ ```
123
+
124
+ ### Conclusion
125
+
126
+ The `@foss.global/codefeed` module provides robust capabilities for extracting and managing feed data related to code developments in Gitea environments. Through systematic setup and leveraging API-driven methods, it becomes a valuable tool for developers aiming to keep track of software progress and changes efficiently. The integration hooks like changelog and npm verification further enrich its utility, offering consolidated insights into each commit's journey from codebase to published package.
127
+
128
+ Explore integrating these capabilities into your development workflows to enhance tracking, deployment pipelines, or analytics systems within your projects. Remember to always handle API tokens securely and adhere to best practices when managing access to repository resources. Stay updated on any changes or enhancements to this module for further feature exposures or bug fixes. Happy coding!
129
+ ```
130
+ undefined
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@foss.global/codefeed',
6
- version: '1.5.3',
7
- description: 'a module for creating feeds for code development'
6
+ version: '1.6.1',
7
+ description: 'The @foss.global/codefeed module is designed for generating feeds from Gitea repositories, enhancing development workflows by processing commit data and repository activities.'
8
8
  }
package/ts/index.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as plugins from './codefeed.plugins.js';
2
2
 
3
-
4
3
  export class CodeFeed {
5
4
  private baseUrl: string;
6
5
  private token?: string;
7
6
  private npmRegistry = new plugins.smartnpm.NpmRegistry();
8
7
  private smartxmlInstance = new plugins.smartxml.SmartXml();
9
8
  private lastRunTimestamp: string;
9
+ private changelogContent: string;
10
10
 
11
11
  constructor(baseUrl: string, token?: string, lastRunTimestamp?: string) {
12
12
  this.baseUrl = baseUrl;
@@ -16,8 +16,66 @@ export class CodeFeed {
16
16
  }
17
17
 
18
18
  /**
19
- * Fetch all organizations from the Gitea instance.
19
+ * Load the changelog directly from the Gitea repository.
20
20
  */
21
+ private async loadChangelogFromRepo(owner: string, repo: string): Promise<void> {
22
+ const url = `${this.baseUrl}/api/v1/repos/${owner}/${repo}/contents/changelog.md`;
23
+ const headers: Record<string, string> = {};
24
+ if (this.token) {
25
+ headers['Authorization'] = `token ${this.token}`;
26
+ }
27
+
28
+ const response = await fetch(url, { headers });
29
+
30
+ if (!response.ok) {
31
+ console.error(`Could not fetch CHANGELOG.md from ${owner}/${repo}: ${response.status} ${response.statusText}`);
32
+ this.changelogContent = '';
33
+ return;
34
+ }
35
+
36
+ const data = await response.json();
37
+ if (!data.content) {
38
+ console.warn(`No content field found in response for ${owner}/${repo}/changelog.md`);
39
+ this.changelogContent = '';
40
+ return;
41
+ }
42
+
43
+ const decodedContent = Buffer.from(data.content, 'base64').toString('utf8');
44
+ this.changelogContent = decodedContent;
45
+ }
46
+
47
+ /**
48
+ * Parse the changelog to find the entry for a given version.
49
+ * The changelog format is assumed as:
50
+ *
51
+ * # Changelog
52
+ *
53
+ * ## <date> - <version> - <description>
54
+ * <changes...>
55
+ */
56
+ private getChangelogForVersion(version: string): string | undefined {
57
+ if (!this.changelogContent) {
58
+ return undefined;
59
+ }
60
+ const lines = this.changelogContent.split('\n');
61
+ const versionHeaderIndex = lines.findIndex((line) => line.includes(`- ${version} -`));
62
+ if (versionHeaderIndex === -1) {
63
+ return undefined;
64
+ }
65
+
66
+ const changelogLines: string[] = [];
67
+ for (let i = versionHeaderIndex + 1; i < lines.length; i++) {
68
+ const line = lines[i];
69
+ // The next version header starts with `## `
70
+ if (line.startsWith('## ')) {
71
+ break;
72
+ }
73
+ changelogLines.push(line);
74
+ }
75
+
76
+ return changelogLines.join('\n').trim();
77
+ }
78
+
21
79
  private async fetchAllOrganizations(): Promise<string[]> {
22
80
  const url = `${this.baseUrl}/api/v1/orgs`;
23
81
  const response = await fetch(url, {
@@ -32,18 +90,17 @@ export class CodeFeed {
32
90
  return data.map((org) => org.username);
33
91
  }
34
92
 
35
- /**
36
- * Fetch organization-level activity RSS feed.
37
- */
38
93
  private async fetchOrgRssFeed(optionsArg: {
39
94
  orgName: string,
40
95
  repoName?: string,
41
96
  }): Promise<any[]> {
42
- let rssUrl: string
97
+ let rssUrl: string;
43
98
  if (optionsArg.orgName && !optionsArg.repoName) {
44
99
  rssUrl = `${this.baseUrl}/${optionsArg.orgName}.atom`;
45
100
  } else if (optionsArg.orgName && optionsArg.repoName) {
46
101
  rssUrl = `${this.baseUrl}/${optionsArg.orgName}/${optionsArg.repoName}.atom`;
102
+ } else {
103
+ throw new Error('Invalid arguments provided to fetchOrgRssFeed.');
47
104
  }
48
105
 
49
106
  const response = await fetch(rssUrl);
@@ -52,36 +109,25 @@ export class CodeFeed {
52
109
  }
53
110
 
54
111
  const rssText = await response.text();
55
-
56
- // Parse the Atom feed using fast-xml-parser
57
112
  const rssData = this.smartxmlInstance.parseXmlToObject(rssText);
58
-
59
- // Return the <entry> elements from the feed
60
113
  return rssData.feed.entry || [];
61
114
  }
62
115
 
63
- /**
64
- * Check if the organization's RSS feed has any new activities since the last run.
65
- */
66
116
  private async hasNewActivity(optionsArg: {
67
117
  orgName: string,
68
118
  repoName?: string,
69
119
  }): Promise<boolean> {
70
120
  const entries = await this.fetchOrgRssFeed(optionsArg);
71
121
 
72
- // Filter entries to find new activities since the last run
73
122
  return entries.some((entry: any) => {
74
123
  const updated = new Date(entry.updated);
75
124
  return updated > new Date(this.lastRunTimestamp);
76
125
  });
77
126
  }
78
127
 
79
- /**
80
- * Fetch all repositories accessible to the token/user.
81
- */
82
- private async fetchAllRepositories(): Promise<plugins.interfaces.Repository[]> {
128
+ private async fetchAllRepositories(): Promise<plugins.interfaces.IRepository[]> {
83
129
  let page = 1;
84
- const allRepos: plugins.interfaces.Repository[] = [];
130
+ const allRepos: plugins.interfaces.IRepository[] = [];
85
131
 
86
132
  while (true) {
87
133
  const url = new URL(`${this.baseUrl}/api/v1/repos/search`);
@@ -96,7 +142,7 @@ export class CodeFeed {
96
142
  throw new Error(`Failed to fetch repositories: ${resp.statusText}`);
97
143
  }
98
144
 
99
- const data: plugins.interfaces.RepoSearchResponse = await resp.json();
145
+ const data: plugins.interfaces.IRepoSearchResponse = await resp.json();
100
146
  allRepos.push(...data.data);
101
147
 
102
148
  if (data.data.length < 50) {
@@ -108,12 +154,9 @@ export class CodeFeed {
108
154
  return allRepos;
109
155
  }
110
156
 
111
- /**
112
- * Fetch all tags for a given repository.
113
- */
114
157
  private async fetchTags(owner: string, repo: string): Promise<Set<string>> {
115
158
  let page = 1;
116
- const tags: plugins.interfaces.Tag[] = [];
159
+ const tags: plugins.interfaces.ITag[] = [];
117
160
 
118
161
  while (true) {
119
162
  const url = new URL(`${this.baseUrl}/api/v1/repos/${owner}/${repo}/tags`);
@@ -129,7 +172,7 @@ export class CodeFeed {
129
172
  throw new Error(`Failed to fetch tags for ${owner}/${repo}: ${resp.statusText}`);
130
173
  }
131
174
 
132
- const data: plugins.interfaces.Tag[] = await resp.json();
175
+ const data: plugins.interfaces.ITag[] = await resp.json();
133
176
  tags.push(...data);
134
177
 
135
178
  if (data.length < 50) {
@@ -148,13 +191,10 @@ export class CodeFeed {
148
191
  return taggedCommitShas;
149
192
  }
150
193
 
151
- /**
152
- * Fetch commits from the last 24 hours for a repository.
153
- */
154
- private async fetchRecentCommitsForRepo(owner: string, repo: string): Promise<plugins.interfaces.Commit[]> {
194
+ private async fetchRecentCommitsForRepo(owner: string, repo: string): Promise<plugins.interfaces.ICommit[]> {
155
195
  const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
156
196
  let page = 1;
157
- const recentCommits: plugins.interfaces.Commit[] = [];
197
+ const recentCommits: plugins.interfaces.ICommit[] = [];
158
198
 
159
199
  while (true) {
160
200
  const url = new URL(`${this.baseUrl}/api/v1/repos/${owner}/${repo}/commits`);
@@ -170,7 +210,7 @@ export class CodeFeed {
170
210
  throw new Error(`Failed to fetch commits for ${owner}/${repo}: ${resp.statusText}`);
171
211
  }
172
212
 
173
- const data: plugins.interfaces.Commit[] = await resp.json();
213
+ const data: plugins.interfaces.ICommit[] = await resp.json();
174
214
  if (data.length === 0) {
175
215
  break;
176
216
  }
@@ -190,13 +230,10 @@ export class CodeFeed {
190
230
  return recentCommits;
191
231
  }
192
232
 
193
- /**
194
- * Fetch all commits by querying all organizations.
195
- */
196
- public async fetchAllCommitsFromInstance(): Promise<plugins.interfaces.CommitResult[]> {
233
+ public async fetchAllCommitsFromInstance(): Promise<plugins.interfaces.ICommitResult[]> {
197
234
  const orgs = await this.fetchAllOrganizations();
198
235
  console.log(`Found ${orgs.length} organizations`);
199
- let allCommits: plugins.interfaces.CommitResult[] = [];
236
+ let allCommits: plugins.interfaces.ICommitResult[] = [];
200
237
 
201
238
  for (const orgName of orgs) {
202
239
  console.log(`Checking activity for organization: ${orgName}`);
@@ -209,7 +246,7 @@ export class CodeFeed {
209
246
  console.log(`No new activity for organization: ${orgName}`);
210
247
  continue;
211
248
  }
212
- } catch (error) {
249
+ } catch (error: any) {
213
250
  console.error(`Error fetching activity for organization ${orgName}:`, error.message);
214
251
  continue;
215
252
  }
@@ -227,10 +264,11 @@ export class CodeFeed {
227
264
  console.log(`No new activity for repository: ${orgName}/${r.name}`);
228
265
  continue;
229
266
  }
230
- } catch (error) {
267
+ } catch (error: any) {
231
268
  console.error(`Error fetching activity for repository ${orgName}/${r.name}:`, error.message);
232
269
  continue;
233
270
  }
271
+
234
272
  const org = r.owner.login;
235
273
  const repo = r.name;
236
274
  console.log(`Processing repository ${org}/${repo}`);
@@ -239,8 +277,11 @@ export class CodeFeed {
239
277
  const taggedCommitShas = await this.fetchTags(org, repo);
240
278
  const commits = await this.fetchRecentCommitsForRepo(org, repo);
241
279
 
280
+ // Load the changelog from this repo.
281
+ await this.loadChangelogFromRepo(org, repo);
282
+
242
283
  const commitResults = commits.map((c) => {
243
- const commit: plugins.interfaces.CommitResult = {
284
+ const commit: plugins.interfaces.ICommitResult = {
244
285
  baseUrl: this.baseUrl,
245
286
  org,
246
287
  repo,
@@ -250,45 +291,55 @@ export class CodeFeed {
250
291
  commitMessage: c.commit.message,
251
292
  tagged: taggedCommitShas.has(c.sha),
252
293
  publishedOnNpm: false,
253
- }
294
+ changelog: undefined
295
+ };
254
296
  return commit;
255
297
  });
256
298
 
257
299
  if (commitResults.length > 0) {
258
300
  try {
259
301
  const packageInfo = await this.npmRegistry.getPackageInfo(`@${org}/${repo}`);
260
- for (const commit of commitResults.filter((c) => c.tagged)) {
302
+ for (const commitResult of commitResults.filter((c) => c.tagged)) {
303
+ const versionCandidate = commitResult.commitMessage.replace('\n', '').trim();
261
304
  const correspondingVersion = packageInfo.allVersions.find((versionArg) => {
262
- return versionArg.version === commit.commitMessage.replace('\n', '');
305
+ return versionArg.version === versionCandidate;
263
306
  });
264
307
  if (correspondingVersion) {
265
- commit.publishedOnNpm = true;
308
+ commitResult.publishedOnNpm = true;
309
+ const changelogEntry = this.getChangelogForVersion(versionCandidate);
310
+ if (changelogEntry) {
311
+ commitResult.changelog = changelogEntry;
312
+ }
266
313
  }
267
314
  }
268
- } catch (error) {
315
+ } catch (error: any) {
269
316
  console.error(`Failed to fetch package info for ${org}/${repo}:`, error.message);
270
317
  }
271
318
  }
272
319
 
273
320
  allCommits.push(...commitResults);
274
- } catch (error) {
321
+ } catch (error: any) {
275
322
  console.error(`Skipping repository ${org}/${repo} due to error:`, error.message);
276
323
  }
277
324
  }
278
325
  }
279
326
 
280
327
  console.log(`Processed ${allCommits.length} commits in total.`);
328
+
329
+ allCommits = allCommits.filter(commitArg => commitArg.tagged);
330
+
331
+ console.log(`Filtered to ${allCommits.length} commits with tagged statuses.`);
332
+
281
333
  for (const c of allCommits) {
282
334
  console.log(` ==========================================================================
283
335
  ${c.prettyAgoTime} ago:
284
336
  ${c.org}/${c.repo}
285
337
  ${c.commitMessage}
286
338
  Published on npm: ${c.publishedOnNpm}
339
+ ${c.changelog ? `Changelog:\n${c.changelog}\n` : ''}
287
340
  `);
288
341
  }
289
342
 
290
- allCommits = allCommits.filter(commitArg => commitArg.tagged);
291
-
292
343
  return allCommits;
293
344
  }
294
345
  }
@@ -1,37 +1,37 @@
1
- export interface RepositoryOwner {
1
+ export interface IRepositoryOwner {
2
2
  login: string;
3
3
  }
4
4
 
5
- export interface Repository {
6
- owner: RepositoryOwner;
5
+ export interface IRepository {
6
+ owner: IRepositoryOwner;
7
7
  name: string;
8
8
  }
9
9
 
10
- export interface CommitAuthor {
10
+ export interface ICommitAuthor {
11
11
  date: string;
12
12
  }
13
13
 
14
- export interface CommitDetail {
14
+ export interface ICommitDetail {
15
15
  message: string;
16
- author: CommitAuthor;
16
+ author: ICommitAuthor;
17
17
  }
18
18
 
19
- export interface Commit {
19
+ export interface ICommit {
20
20
  sha: string;
21
- commit: CommitDetail;
21
+ commit: ICommitDetail;
22
22
  }
23
23
 
24
- export interface Tag {
24
+ export interface ITag {
25
25
  commit?: {
26
26
  sha?: string;
27
27
  };
28
28
  }
29
29
 
30
- export interface RepoSearchResponse {
31
- data: Repository[];
30
+ export interface IRepoSearchResponse {
31
+ data: IRepository[];
32
32
  }
33
33
 
34
- export interface CommitResult {
34
+ export interface ICommitResult {
35
35
  baseUrl: string;
36
36
  org: string;
37
37
  repo: string;
@@ -41,4 +41,5 @@ export interface CommitResult {
41
41
  tagged: boolean;
42
42
  publishedOnNpm: boolean;
43
43
  prettyAgoTime: string;
44
+ changelog: string | undefined;
44
45
  }