naystack 1.9.0 → 1.9.2
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/README.md +8 -1
- package/dist/socials/index.cjs.js +6 -1
- package/dist/socials/index.esm.js +6 -1
- package/dist/socials/instagram/adapter.cjs.js +6 -1
- package/dist/socials/instagram/adapter.esm.js +6 -1
- package/dist/socials/provider.d.mts +4 -2
- package/dist/socials/provider.d.ts +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -713,7 +713,8 @@ constant so the generalized pieces pick it up for free.
|
|
|
713
713
|
A provider is a plain object with no per-instance state — import the constant, no
|
|
714
714
|
construction. Capability is method presence: a platform that can't refresh tokens
|
|
715
715
|
omits `refresh`, one with no content-listing API omits `fetchMedia`, and callers
|
|
716
|
-
narrow with a plain `if`.
|
|
716
|
+
narrow with a plain `if`. Platform *knowledge* is not a capability, so it is
|
|
717
|
+
always there: `platform` and `profileURL(username)` are required of every adapter.
|
|
717
718
|
|
|
718
719
|
```typescript
|
|
719
720
|
import { InstagramProvider } from "naystack/socials";
|
|
@@ -723,6 +724,12 @@ const profile = await InstagramProvider.fetchProfile(accessToken);
|
|
|
723
724
|
|
|
724
725
|
const posts = await InstagramProvider.fetchMedia?.(accessToken, { limit: 6 });
|
|
725
726
|
// [{ kind: "video", permalink: "…", likes: 812, comments: null, … }]
|
|
727
|
+
// null instead means the request failed — an account with nothing posted
|
|
728
|
+
// returns []. Cache the empty, retry the null.
|
|
729
|
+
|
|
730
|
+
InstagramProvider.profileURL(profile.username);
|
|
731
|
+
// "https://instagram.com/…" — so a stored account row links out without the
|
|
732
|
+
// consumer keeping its own per-platform URL table
|
|
726
733
|
```
|
|
727
734
|
|
|
728
735
|
Every metric on a `SocialPost` is `number | null`, and `null` always means *the
|
|
@@ -444,6 +444,7 @@ var InstagramProvider = {
|
|
|
444
444
|
};
|
|
445
445
|
}
|
|
446
446
|
},
|
|
447
|
+
profileURL: (username) => `https://instagram.com/${username}`,
|
|
447
448
|
fetchProfile: async (accessToken) => {
|
|
448
449
|
const user = await getInstagramUser(
|
|
449
450
|
accessToken,
|
|
@@ -470,7 +471,11 @@ var InstagramProvider = {
|
|
|
470
471
|
MEDIA_FIELDS,
|
|
471
472
|
options?.limit
|
|
472
473
|
);
|
|
473
|
-
if (!result?.data)
|
|
474
|
+
if (!Array.isArray(result?.data)) {
|
|
475
|
+
if (result?.error)
|
|
476
|
+
console.error("[naystack] Instagram media:", result.error.message);
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
474
479
|
return result.data.map(toPost);
|
|
475
480
|
}
|
|
476
481
|
};
|
|
@@ -388,6 +388,7 @@ var InstagramProvider = {
|
|
|
388
388
|
};
|
|
389
389
|
}
|
|
390
390
|
},
|
|
391
|
+
profileURL: (username) => `https://instagram.com/${username}`,
|
|
391
392
|
fetchProfile: async (accessToken) => {
|
|
392
393
|
const user = await getInstagramUser(
|
|
393
394
|
accessToken,
|
|
@@ -414,7 +415,11 @@ var InstagramProvider = {
|
|
|
414
415
|
MEDIA_FIELDS,
|
|
415
416
|
options?.limit
|
|
416
417
|
);
|
|
417
|
-
if (!result?.data)
|
|
418
|
+
if (!Array.isArray(result?.data)) {
|
|
419
|
+
if (result?.error)
|
|
420
|
+
console.error("[naystack] Instagram media:", result.error.message);
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
418
423
|
return result.data.map(toPost);
|
|
419
424
|
}
|
|
420
425
|
};
|
|
@@ -239,6 +239,7 @@ var InstagramProvider = {
|
|
|
239
239
|
};
|
|
240
240
|
}
|
|
241
241
|
},
|
|
242
|
+
profileURL: (username) => `https://instagram.com/${username}`,
|
|
242
243
|
fetchProfile: async (accessToken) => {
|
|
243
244
|
const user = await getInstagramUser(
|
|
244
245
|
accessToken,
|
|
@@ -265,7 +266,11 @@ var InstagramProvider = {
|
|
|
265
266
|
MEDIA_FIELDS,
|
|
266
267
|
options?.limit
|
|
267
268
|
);
|
|
268
|
-
if (!result?.data)
|
|
269
|
+
if (!Array.isArray(result?.data)) {
|
|
270
|
+
if (result?.error)
|
|
271
|
+
console.error("[naystack] Instagram media:", result.error.message);
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
269
274
|
return result.data.map(toPost);
|
|
270
275
|
}
|
|
271
276
|
};
|
|
@@ -213,6 +213,7 @@ var InstagramProvider = {
|
|
|
213
213
|
};
|
|
214
214
|
}
|
|
215
215
|
},
|
|
216
|
+
profileURL: (username) => `https://instagram.com/${username}`,
|
|
216
217
|
fetchProfile: async (accessToken) => {
|
|
217
218
|
const user = await getInstagramUser(
|
|
218
219
|
accessToken,
|
|
@@ -239,7 +240,11 @@ var InstagramProvider = {
|
|
|
239
240
|
MEDIA_FIELDS,
|
|
240
241
|
options?.limit
|
|
241
242
|
);
|
|
242
|
-
if (!result?.data)
|
|
243
|
+
if (!Array.isArray(result?.data)) {
|
|
244
|
+
if (result?.error)
|
|
245
|
+
console.error("[naystack] Instagram media:", result.error.message);
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
243
248
|
return result.data.map(toPost);
|
|
244
249
|
}
|
|
245
250
|
};
|
|
@@ -15,7 +15,8 @@ import { SocialPlatform, SocialTokens, SocialProfile, SocialPost } from './types
|
|
|
15
15
|
* @property auth.authorizationURL - `state` comes back on the callback; `redirectURI` must match what the platform has registered.
|
|
16
16
|
* @property auth.exchangeCode - Trades the callback `code` for tokens. `platformUserId` is `null` on platforms whose token response carries no id (Google); the route then takes it from `fetchProfile`.
|
|
17
17
|
* @property auth.refresh - Omitted by platforms whose tokens don't expire or can't be refreshed.
|
|
18
|
-
* @property fetchMedia - Omitted by platforms with no content-listing API.
|
|
18
|
+
* @property fetchMedia - Omitted by platforms with no content-listing API. Resolves to `null` when the request failed and `[]` when the account genuinely has no content — a caller that caches results must not treat an outage as an empty grid.
|
|
19
|
+
* @property profileURL - Public profile link for a handle. Platform knowledge, not a capability, so every adapter has one.
|
|
19
20
|
*
|
|
20
21
|
* @example
|
|
21
22
|
* ```ts
|
|
@@ -44,9 +45,10 @@ type SocialProvider = {
|
|
|
44
45
|
refresh?: (tokens: SocialTokens) => Promise<SocialTokens | null>;
|
|
45
46
|
};
|
|
46
47
|
fetchProfile: (accessToken: string) => Promise<SocialProfile | null>;
|
|
48
|
+
profileURL: (username: string) => string;
|
|
47
49
|
fetchMedia?: (accessToken: string, options?: {
|
|
48
50
|
limit?: number;
|
|
49
|
-
}) => Promise<SocialPost[]>;
|
|
51
|
+
}) => Promise<SocialPost[] | null>;
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
export type { SocialProvider };
|
|
@@ -15,7 +15,8 @@ import { SocialPlatform, SocialTokens, SocialProfile, SocialPost } from './types
|
|
|
15
15
|
* @property auth.authorizationURL - `state` comes back on the callback; `redirectURI` must match what the platform has registered.
|
|
16
16
|
* @property auth.exchangeCode - Trades the callback `code` for tokens. `platformUserId` is `null` on platforms whose token response carries no id (Google); the route then takes it from `fetchProfile`.
|
|
17
17
|
* @property auth.refresh - Omitted by platforms whose tokens don't expire or can't be refreshed.
|
|
18
|
-
* @property fetchMedia - Omitted by platforms with no content-listing API.
|
|
18
|
+
* @property fetchMedia - Omitted by platforms with no content-listing API. Resolves to `null` when the request failed and `[]` when the account genuinely has no content — a caller that caches results must not treat an outage as an empty grid.
|
|
19
|
+
* @property profileURL - Public profile link for a handle. Platform knowledge, not a capability, so every adapter has one.
|
|
19
20
|
*
|
|
20
21
|
* @example
|
|
21
22
|
* ```ts
|
|
@@ -44,9 +45,10 @@ type SocialProvider = {
|
|
|
44
45
|
refresh?: (tokens: SocialTokens) => Promise<SocialTokens | null>;
|
|
45
46
|
};
|
|
46
47
|
fetchProfile: (accessToken: string) => Promise<SocialProfile | null>;
|
|
48
|
+
profileURL: (username: string) => string;
|
|
47
49
|
fetchMedia?: (accessToken: string, options?: {
|
|
48
50
|
limit?: number;
|
|
49
|
-
}) => Promise<SocialPost[]>;
|
|
51
|
+
}) => Promise<SocialPost[] | null>;
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
export type { SocialProvider };
|