Skip to content

Commit 1eca0bc

Browse files
Merge pull request #58 from alvinashcraft/alvinashcraft/main-dew-drop-site-upd
Update for new dew without az fn
2 parents ffac5e2 + c716bd4 commit 1eca0bc

6 files changed

Lines changed: 35 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to the "Dev Feed Curator" extension will be documented in th
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [3.11.0] - 2026-06-08
8+
9+
### Fixed
10+
11+
- Replaced the removed Azure Functions `v1/posts` API (`https://alvinashcraft.com/v1/posts?limit=20`) with the new static Blazor Static Web App feed endpoint (`https://alvinashcraft.com/feeds/index-recent.json`) in both the latest Dew Drop date fallback (`rssProvider.ts`) and the latest Dew Drop number fallback (`exportManager.ts`). Updated response parsing from `data.items[]` to `data.posts[]` to match the new JSON shape
12+
713
## [3.10.5] - 2026-06-03
814

915
### Fixed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "%displayName%",
44
"description": "%description%",
55
"icon": "images/rssBlogIcon.png",
6-
"version": "3.10.5",
6+
"version": "3.11.0",
77
"publisher": "alvinashcraft",
88
"repository": {
99
"type": "git",

src/exportManager.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,9 @@ export class ExportManager {
281281
}
282282

283283
/**
284-
* Fallback: query the read-only Morning Dew v1 API for the latest Dew Drop
285-
* post number. Only invoked when the configured WordPress blog URL points
286-
* at alvinashcraft.com.
284+
* Fallback: query the read-only Morning Dew feeds endpoint for the latest
285+
* Dew Drop post number. Only invoked when the configured WordPress blog
286+
* URL points at alvinashcraft.com.
287287
*/
288288
private async tryGetLatestDewDropNumberFromApi(): Promise<number | null> {
289289
const config = vscode.workspace.getConfiguration('rssBlogCategorizer');
@@ -292,9 +292,9 @@ export class ExportManager {
292292
}
293293

294294
try {
295-
console.log('Falling back to Morning Dew v1 API for latest Dew Drop number...');
296-
const data = await fetchJson('https://alvinashcraft.com/v1/posts?limit=20');
297-
const items: Array<{ title?: string }> = Array.isArray(data?.items) ? data.items : [];
295+
console.log('Falling back to Morning Dew feeds endpoint for latest Dew Drop number...');
296+
const data = await fetchJson('https://alvinashcraft.com/feeds/index-recent.json');
297+
const items: Array<{ title?: string }> = Array.isArray(data?.posts) ? data.posts : [];
298298
for (const item of items) {
299299
const title = item.title || '';
300300
if (!title.toLowerCase().includes('dew drop')) {
@@ -303,14 +303,14 @@ export class ExportManager {
303303
const match = title.match(/#(\d+)\)/);
304304
if (match) {
305305
const postNumber = parseInt(match[1], 10);
306-
console.log(`✓ Latest Dew Drop post found via API: "${title}" (number: ${postNumber})`);
306+
console.log(`✓ Latest Dew Drop post found via feeds endpoint: "${title}" (number: ${postNumber})`);
307307
return postNumber;
308308
}
309309
}
310-
console.warn('Morning Dew API returned no Dew Drop posts with parseable numbers');
310+
console.warn('Morning Dew feeds endpoint returned no Dew Drop posts with parseable numbers');
311311
return null;
312312
} catch (error) {
313-
console.error('Error fetching latest Dew Drop number from API:', error);
313+
console.error('Error fetching latest Dew Drop number from feeds endpoint:', error);
314314
return null;
315315
}
316316
}

src/rssProvider.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ interface AuthorMappingsConfig {
9898
}
9999

100100
/**
101-
* Minimal JSON GET helper used by the Morning Dew v1 API fallback path lives
101+
* Minimal JSON GET helper used by the Morning Dew feeds fallback path lives
102102
* in `./utils/http` to be shared with `exportManager.ts`.
103103
*/
104104

@@ -167,13 +167,13 @@ export class RSSBlogProvider implements vscode.TreeDataProvider<any> {
167167
console.log('Available post titles:', posts.slice(0, 5).map(p => `"${p.title}"`).join(', '));
168168
}
169169

170-
// Fallback: query the read-only Morning Dew API when the configured
171-
// WordPress blog URL points at alvinashcraft.com.
170+
// Fallback: query the read-only Morning Dew feeds endpoint when the
171+
// configured WordPress blog URL points at alvinashcraft.com.
172172
if (this.isAlvinAshcraftBlogConfigured()) {
173-
console.log('Falling back to Morning Dew v1 API for latest Dew Drop date...');
173+
console.log('Falling back to Morning Dew feeds endpoint for latest Dew Drop date...');
174174
const apiPost = await this.fetchLatestDewDropFromApi();
175175
if (apiPost?.date && !isNaN(apiPost.date.getTime())) {
176-
console.log(`✅ Latest Dew Drop post found via API: "${apiPost.title}" from ${apiPost.date.toISOString()}`);
176+
console.log(`✅ Latest Dew Drop post found via feeds endpoint: "${apiPost.title}" from ${apiPost.date.toISOString()}`);
177177
return apiPost.date;
178178
}
179179
}
@@ -192,20 +192,20 @@ export class RSSBlogProvider implements vscode.TreeDataProvider<any> {
192192

193193
private async fetchLatestDewDropFromApi(): Promise<{ title: string; date: Date; number: number | null } | null> {
194194
try {
195-
const json = await fetchJson('https://alvinashcraft.com/v1/posts?limit=20');
196-
if (!json || !Array.isArray(json.items)) {
197-
console.log('Morning Dew API returned no items');
195+
const json = await fetchJson('https://alvinashcraft.com/feeds/index-recent.json');
196+
if (!json || !Array.isArray(json.posts)) {
197+
console.log('Morning Dew feeds endpoint returned no posts');
198198
return null;
199199
}
200200

201-
const items = json.items as Array<{ title?: string; date?: string }>;
201+
const items = json.posts as Array<{ title?: string; date?: string }>;
202202
const dewDrop = items.find(item => {
203203
const t = (item.title || '').toLowerCase();
204204
return t.startsWith('dew d');
205205
});
206206

207207
if (!dewDrop || !dewDrop.title || !dewDrop.date) {
208-
console.log('Morning Dew API returned no Dew Drop posts in first 20 items');
208+
console.log('Morning Dew feeds endpoint returned no Dew Drop posts in the returned posts list');
209209
return null;
210210
}
211211

@@ -217,7 +217,7 @@ export class RSSBlogProvider implements vscode.TreeDataProvider<any> {
217217
number: numberMatch ? parseInt(numberMatch[1], 10) : null
218218
};
219219
} catch (error) {
220-
console.error('Error fetching latest Dew Drop from Morning Dew API:', error);
220+
console.error('Error fetching latest Dew Drop from Morning Dew feeds endpoint:', error);
221221
return null;
222222
}
223223
}

src/test/unit/rssProvider.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ describe('RSSBlogProvider', () => {
372372
expect(posts.find(p => p.title.includes('Future Post Should Be Included'))).to.exist;
373373
});
374374

375-
it('should fall back to Morning Dew v1 API when RSS has no Dew Drop posts and blog is alvinashcraft.com', async () => {
375+
it('should fall back to the Morning Dew feeds endpoint when RSS has no Dew Drop posts and blog is alvinashcraft.com', async () => {
376376
const apiDate = new Date('2026-05-29T10:56:41Z');
377377

378378
const configWithBlog = new MockConfiguration({
@@ -397,7 +397,7 @@ describe('RSSBlogProvider', () => {
397397
</rss>`;
398398

399399
const apiPayload = JSON.stringify({
400-
items: [
400+
posts: [
401401
{
402402
title: 'Dew Drop - May 29, 2026 (#4679)',
403403
date: apiDate.toISOString(),
@@ -424,7 +424,7 @@ describe('RSSBlogProvider', () => {
424424

425425
let apiHit = false;
426426
httpsGetStub.callsFake((url: string, options: any, callback: any) => {
427-
if (url.includes('/v1/posts')) {
427+
if (url.includes('/feeds/index-recent.json')) {
428428
apiHit = true;
429429
callback(apiResponse);
430430
} else if (url.includes('alvinashcraft.com')) {
@@ -435,10 +435,10 @@ describe('RSSBlogProvider', () => {
435435

436436
await provider.refresh();
437437

438-
expect(apiHit, 'expected Morning Dew v1 API to be queried as fallback').to.be.true;
438+
expect(apiHit, 'expected Morning Dew feeds endpoint to be queried as fallback').to.be.true;
439439
});
440440

441-
it('should NOT call Morning Dew v1 API when blog URL is not alvinashcraft.com', async () => {
441+
it('should NOT call the Morning Dew feeds endpoint when blog URL is not alvinashcraft.com', async () => {
442442
const configWithOtherBlog = new MockConfiguration({
443443
feedUrl: 'https://example.com/feed.xml',
444444
recordCount: 100,
@@ -469,7 +469,7 @@ describe('RSSBlogProvider', () => {
469469

470470
let apiHit = false;
471471
httpsGetStub.callsFake((url: string, options: any, callback: any) => {
472-
if (url.includes('/v1/posts')) {
472+
if (url.includes('/feeds/index-recent.json')) {
473473
apiHit = true;
474474
}
475475
callback(rssResponse);
@@ -478,7 +478,7 @@ describe('RSSBlogProvider', () => {
478478

479479
await provider.refresh();
480480

481-
expect(apiHit, 'API should not be queried when blog URL is not alvinashcraft.com').to.be.false;
481+
expect(apiHit, 'feeds endpoint should not be queried when blog URL is not alvinashcraft.com').to.be.false;
482482
});
483483
});
484484

src/utils/http.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as https from 'https';
22

33
/**
4-
* Minimal JSON GET helper used by the Morning Dew v1 API fallback paths.
4+
* Minimal JSON GET helper used by the Morning Dew feeds fallback paths.
55
* Kept dependency-free to avoid pulling in a new module for one-off calls.
66
*/
77
export function fetchJson(url: string, timeoutMs: number = 10000): Promise<any> {

0 commit comments

Comments
 (0)