@apicity/meta 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +356 -0
- package/dist/src/example.d.ts +8 -0
- package/dist/src/example.d.ts.map +1 -0
- package/dist/src/example.js +94 -0
- package/dist/src/example.js.map +1 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/meta.d.ts +3 -0
- package/dist/src/meta.d.ts.map +1 -0
- package/dist/src/meta.js +104 -0
- package/dist/src/meta.js.map +1 -0
- package/dist/src/types.d.ts +55 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +14 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/zod.d.ts +79 -0
- package/dist/src/zod.d.ts.map +1 -0
- package/dist/src/zod.js +59 -0
- package/dist/src/zod.js.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Justin Tanner
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# @apicity/meta
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@apicity/meta)
|
|
4
|
+
[](package.json)
|
|
5
|
+
[](tsconfig.json)
|
|
6
|
+
|
|
7
|
+
Instagram Graph API provider for posting reels via the public-URL flow (graph.instagram.com).
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @apicity/meta
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @apicity/meta
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { meta as createMeta } from "@apicity/meta";
|
|
21
|
+
|
|
22
|
+
const meta = createMeta({ apiKey: process.env.META_API_KEY! });
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
Instagram requires a **long-lived (60-day) user access token** from the
|
|
28
|
+
Instagram Login OAuth flow. The token is bound to a specific Instagram
|
|
29
|
+
Business or Creator account; personal accounts have no programmatic
|
|
30
|
+
publishing access.
|
|
31
|
+
|
|
32
|
+
### 1. Configure your Meta App
|
|
33
|
+
|
|
34
|
+
Open [developers.facebook.com](https://developers.facebook.com), create a
|
|
35
|
+
new app (type: **Business**), then add the **Instagram** product.
|
|
36
|
+
Choose **API setup with Instagram login** and configure:
|
|
37
|
+
|
|
38
|
+
- Valid OAuth Redirect URI: `http://127.0.0.1:8765/callback`
|
|
39
|
+
- Permissions: `instagram_business_basic` + `instagram_business_content_publish`
|
|
40
|
+
- Save the **Instagram App ID** and **Instagram App Secret**
|
|
41
|
+
|
|
42
|
+
### 2. Verify Instagram account type
|
|
43
|
+
|
|
44
|
+
The Instagram account you're publishing to must be **Business** or
|
|
45
|
+
**Creator** (not Personal). Switch in the Instagram mobile app under
|
|
46
|
+
Settings → Account type and tools. No Facebook Page link is required
|
|
47
|
+
for the Instagram Login flow.
|
|
48
|
+
|
|
49
|
+
### 3. Mint a long-lived access token
|
|
50
|
+
|
|
51
|
+
Save the script below as `mint-ig-token.mjs` and run it:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
IG_CLIENT_ID=<your-instagram-app-id> \
|
|
55
|
+
IG_CLIENT_SECRET=<your-instagram-app-secret> \
|
|
56
|
+
node mint-ig-token.mjs
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
It prints an authorize URL — open it, click **Allow**, and the helper
|
|
60
|
+
captures the redirect on `127.0.0.1:8765`, exchanges the code for a
|
|
61
|
+
short-lived token, then upgrades it to a long-lived (60-day) token and
|
|
62
|
+
prints `{ access_token, user_id, expires_in }`. Save both `access_token`
|
|
63
|
+
and `user_id` — you need both to call the API.
|
|
64
|
+
|
|
65
|
+
<details>
|
|
66
|
+
<summary><code>mint-ig-token.mjs</code> — zero-dep OAuth 2.0 helper</summary>
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import http from "node:http";
|
|
70
|
+
import crypto from "node:crypto";
|
|
71
|
+
|
|
72
|
+
const CLIENT_ID = process.env.IG_CLIENT_ID;
|
|
73
|
+
const CLIENT_SECRET = process.env.IG_CLIENT_SECRET;
|
|
74
|
+
const REDIRECT = "http://127.0.0.1:8765/callback";
|
|
75
|
+
const SCOPES = [
|
|
76
|
+
"instagram_business_basic",
|
|
77
|
+
"instagram_business_content_publish",
|
|
78
|
+
].join(",");
|
|
79
|
+
|
|
80
|
+
if (!CLIENT_ID || !CLIENT_SECRET) {
|
|
81
|
+
console.error("Set IG_CLIENT_ID and IG_CLIENT_SECRET");
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const state = crypto.randomBytes(16).toString("hex");
|
|
86
|
+
const authURL = new URL("https://www.instagram.com/oauth/authorize");
|
|
87
|
+
authURL.searchParams.set("client_id", CLIENT_ID);
|
|
88
|
+
authURL.searchParams.set("redirect_uri", REDIRECT);
|
|
89
|
+
authURL.searchParams.set("response_type", "code");
|
|
90
|
+
authURL.searchParams.set("scope", SCOPES);
|
|
91
|
+
authURL.searchParams.set("state", state);
|
|
92
|
+
|
|
93
|
+
console.log("Open this URL and click Allow:\n" + authURL.toString());
|
|
94
|
+
|
|
95
|
+
const server = http.createServer(async (req, res) => {
|
|
96
|
+
const url = new URL(req.url, REDIRECT);
|
|
97
|
+
if (!url.pathname.startsWith("/callback")) {
|
|
98
|
+
res.writeHead(404).end();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const code = url.searchParams.get("code");
|
|
102
|
+
if (!code || url.searchParams.get("state") !== state) {
|
|
103
|
+
res.writeHead(400).end("bad state");
|
|
104
|
+
server.close();
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 1. short-lived
|
|
109
|
+
const shortRes = await fetch(
|
|
110
|
+
"https://api.instagram.com/oauth/access_token",
|
|
111
|
+
{
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
114
|
+
body: new URLSearchParams({
|
|
115
|
+
client_id: CLIENT_ID,
|
|
116
|
+
client_secret: CLIENT_SECRET,
|
|
117
|
+
grant_type: "authorization_code",
|
|
118
|
+
redirect_uri: REDIRECT,
|
|
119
|
+
code,
|
|
120
|
+
}),
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
const short = await shortRes.json();
|
|
124
|
+
|
|
125
|
+
// 2. long-lived (60-day)
|
|
126
|
+
const longURL = new URL("https://graph.instagram.com/access_token");
|
|
127
|
+
longURL.searchParams.set("grant_type", "ig_exchange_token");
|
|
128
|
+
longURL.searchParams.set("client_secret", CLIENT_SECRET);
|
|
129
|
+
longURL.searchParams.set("access_token", short.access_token);
|
|
130
|
+
const longRes = await fetch(longURL);
|
|
131
|
+
const long = await longRes.json();
|
|
132
|
+
|
|
133
|
+
console.log(JSON.stringify({
|
|
134
|
+
access_token: long.access_token,
|
|
135
|
+
expires_in: long.expires_in,
|
|
136
|
+
user_id: short.user_id,
|
|
137
|
+
}, null, 2));
|
|
138
|
+
res.writeHead(200).end("Authorized — check your terminal.");
|
|
139
|
+
server.close();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
server.listen(8765, "127.0.0.1");
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
</details>
|
|
146
|
+
|
|
147
|
+
### 4. Use the token
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { meta as createMeta } from "@apicity/meta";
|
|
151
|
+
|
|
152
|
+
const meta = createIg({ accessToken: process.env.IG_ACCESS_TOKEN });
|
|
153
|
+
const igUserId = process.env.IG_USER_ID;
|
|
154
|
+
|
|
155
|
+
// Public-URL flow: host the mp4 somewhere (e.g. via @apicity/free-media-upload) and
|
|
156
|
+
// pass its URL. Meta GETs the video and processes it asynchronously.
|
|
157
|
+
const container = await ig.post.v25.media(igUserId, {
|
|
158
|
+
media_type: "REELS",
|
|
159
|
+
video_url: "https://example.com/clip.mp4",
|
|
160
|
+
caption: "hello from @apicity/meta",
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Poll until the container is ready.
|
|
164
|
+
let status = "IN_PROGRESS";
|
|
165
|
+
while (status === "IN_PROGRESS") {
|
|
166
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
167
|
+
const s = await ig.get.v25.container(container.id, {
|
|
168
|
+
fields: "status_code,status",
|
|
169
|
+
});
|
|
170
|
+
status = s.status_code ?? "FINISHED";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Publish.
|
|
174
|
+
const post = await ig.post.v25.mediaPublish(igUserId, {
|
|
175
|
+
creation_id: container.id,
|
|
176
|
+
});
|
|
177
|
+
console.log(post.id);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Real-world example: publish a Reel via the public-URL flow
|
|
181
|
+
|
|
182
|
+
Instagram's Graph API doesn't take video bytes directly — Meta needs a
|
|
183
|
+
publicly reachable URL it can `GET` and transcode asynchronously. The
|
|
184
|
+
snippet below chains `@apicity/free-media-upload` (catbox public hosting, free + zero
|
|
185
|
+
auth) into `@apicity/meta` to land an `mp4` on disk as a published Reel,
|
|
186
|
+
mirroring
|
|
187
|
+
[`tests/integration/ig-post-video.test.ts`](../../../tests/integration/ig-post-video.test.ts)
|
|
188
|
+
step-for-step. The catbox upload replays against
|
|
189
|
+
[`tests/recordings/free_2578706139/`](../../../tests/recordings/free_2578706139/);
|
|
190
|
+
the IG calls land in `tests/recordings/ig_*/post-video_*/recording.har`
|
|
191
|
+
once a Business/Creator account's `IG_ACCESS_TOKEN` is recorded.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { readFileSync } from "node:fs";
|
|
195
|
+
import { meta as createMeta } from "@apicity/meta";
|
|
196
|
+
import { freeMediaUpload as createFreeMediaUpload } from "@apicity/free-media-upload";
|
|
197
|
+
|
|
198
|
+
const meta = createIg({ accessToken: process.env.IG_ACCESS_TOKEN! });
|
|
199
|
+
const igUserId = process.env.IG_USER_ID!; // 17-digit numeric, e.g. "17841471234567890"
|
|
200
|
+
|
|
201
|
+
// 1. Host the mp4 publicly. catbox.moe is auth-free and persistent —
|
|
202
|
+
// Meta's transcode worker will fetch this URL once during step 2,
|
|
203
|
+
// so any host that returns the bytes within ~30s works (S3 presigned
|
|
204
|
+
// URL, R2, your own CDN). @apicity/free-media-upload wraps the multipart upload
|
|
205
|
+
// and returns the resolved file URL as a string.
|
|
206
|
+
const bytes = readFileSync("./jump.mp4");
|
|
207
|
+
const blob = new Blob([bytes], { type: "video/mp4" });
|
|
208
|
+
|
|
209
|
+
const freeMediaUpload = createFree({});
|
|
210
|
+
const videoUrl = await free.catbox.upload({
|
|
211
|
+
file: blob,
|
|
212
|
+
filename: "jump.mp4",
|
|
213
|
+
});
|
|
214
|
+
console.log(videoUrl);
|
|
215
|
+
// → "https://files.catbox.moe/nn9sei.mp4"
|
|
216
|
+
// catbox returns a permanent public URL of the form
|
|
217
|
+
// `https://files.catbox.moe/<6char>.<ext>` — that's what Meta will GET.
|
|
218
|
+
|
|
219
|
+
// 2. Create a media container. For Reels you must pass `media_type:
|
|
220
|
+
// "REELS"` (NOT "VIDEO" — that's the legacy IGTV path Meta
|
|
221
|
+
// deprecated in 2024). The container is a server-side handle: Meta
|
|
222
|
+
// queues the transcode against `video_url` and returns its id
|
|
223
|
+
// immediately. Containers expire 24h after creation if you don't
|
|
224
|
+
// publish them.
|
|
225
|
+
const container = await ig.post.v25.media(igUserId, {
|
|
226
|
+
media_type: "REELS",
|
|
227
|
+
video_url: videoUrl,
|
|
228
|
+
caption: "jump #reels",
|
|
229
|
+
});
|
|
230
|
+
console.log(container.id);
|
|
231
|
+
// → "17889012345678901" (17-digit container id)
|
|
232
|
+
|
|
233
|
+
// 3. Poll the container's status_code until it leaves IN_PROGRESS.
|
|
234
|
+
// The state machine is IN_PROGRESS → FINISHED on success;
|
|
235
|
+
// FINISHED is the only state media_publish accepts. ERROR and
|
|
236
|
+
// EXPIRED are terminal failure states; PUBLISHED is what you'll
|
|
237
|
+
// see if you re-poll AFTER calling media_publish. The `fields`
|
|
238
|
+
// query param is required — by default the GET only returns `id`.
|
|
239
|
+
let statusCode: string = "IN_PROGRESS";
|
|
240
|
+
while (statusCode === "IN_PROGRESS") {
|
|
241
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
242
|
+
const s = await ig.get.v25.container(container.id, {
|
|
243
|
+
fields: "status_code,status",
|
|
244
|
+
});
|
|
245
|
+
statusCode = s.status_code ?? "FINISHED";
|
|
246
|
+
if (statusCode === "ERROR" || statusCode === "EXPIRED") {
|
|
247
|
+
throw new Error(`container ${container.id} ${statusCode}: ${s.status}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
// statusCode → "FINISHED"
|
|
251
|
+
// s.status → "Finished: Media is ready to be published."
|
|
252
|
+
|
|
253
|
+
// 4. Publish. media_publish takes the container id (NOT the media url)
|
|
254
|
+
// and returns the new post's id — that's the permanent ig_id you'd
|
|
255
|
+
// use to construct an https://www.instagram.com/reel/<shortcode>/
|
|
256
|
+
// URL or to query insights later via Graph API.
|
|
257
|
+
const post = await ig.post.v25.mediaPublish(igUserId, {
|
|
258
|
+
creation_id: container.id,
|
|
259
|
+
});
|
|
260
|
+
console.log(post.id);
|
|
261
|
+
// → "17912345678901234" (17-digit post id, distinct from container id)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Notes**
|
|
265
|
+
|
|
266
|
+
- Meta requires a **Business** or **Creator** Instagram account plus a
|
|
267
|
+
Meta App approved for `instagram_business_content_publish`. Personal
|
|
268
|
+
accounts get `190` ("Invalid OAuth access token") even with a
|
|
269
|
+
syntactically valid token.
|
|
270
|
+
- `video_url` must be reachable from Meta's IPs and serve `Content-Type:
|
|
271
|
+
video/mp4`. Common gotchas: presigned S3 URLs that expire before the
|
|
272
|
+
transcoder pulls, hosts that require a `User-Agent`, and CDNs that
|
|
273
|
+
redirect to a different origin. catbox.moe sidesteps all three.
|
|
274
|
+
- The Reel itself must satisfy Meta's Reel constraints — 9:16 aspect,
|
|
275
|
+
3–90s duration, ≤ 1GB, H.264 video, AAC audio. Mismatches surface as
|
|
276
|
+
`status_code: "ERROR"` during the poll, with the human-readable
|
|
277
|
+
reason in `status` (e.g. `"Error: The video is too short."`).
|
|
278
|
+
- Containers and posts use **distinct** 17-digit ids. The container id
|
|
279
|
+
is throwaway — you only need it for the GET poll and the subsequent
|
|
280
|
+
`media_publish` `creation_id`. The post id is permanent and survives
|
|
281
|
+
user deletion of the post.
|
|
282
|
+
- Errors throw `MetaError` with `status` (HTTP code), `body` (the parsed
|
|
283
|
+
Meta error envelope), and an optional `code`. Meta's two error shapes
|
|
284
|
+
— `error.error_user_msg` for user-facing validation and `error.message`
|
|
285
|
+
for everything else — are both surfaced in `MetaError.message`, so a
|
|
286
|
+
single `try/catch` reads naturally.
|
|
287
|
+
|
|
288
|
+
## API Reference
|
|
289
|
+
|
|
290
|
+
3 endpoints across 3 groups. Each method mirrors an upstream URL path.
|
|
291
|
+
|
|
292
|
+
### container
|
|
293
|
+
|
|
294
|
+
<details>
|
|
295
|
+
<summary><code>GET</code> <b><code>meta.v25.container</code></b></summary>
|
|
296
|
+
|
|
297
|
+
<code>GET https://graph.instagram.com/v25.0/{containerId}{query}</code>
|
|
298
|
+
|
|
299
|
+
[Upstream docs ↗](https://developers.facebook.com/docs/instagram-platform/reference/ig-container/)
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
const res = await meta.v25.container({ /* ... */ });
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Source: [`packages/provider/meta/src/meta.ts`](src/meta.ts)
|
|
306
|
+
|
|
307
|
+
</details>
|
|
308
|
+
|
|
309
|
+
### media
|
|
310
|
+
|
|
311
|
+
<details>
|
|
312
|
+
<summary><code>POST</code> <b><code>meta.v25.media</code></b></summary>
|
|
313
|
+
|
|
314
|
+
<code>POST https://graph.instagram.com/v25.0/{igUserId}/media</code>
|
|
315
|
+
|
|
316
|
+
[Upstream docs ↗](https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media/)
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
const res = await meta.v25.media({ /* ... */ });
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Source: [`packages/provider/meta/src/meta.ts`](src/meta.ts)
|
|
323
|
+
|
|
324
|
+
</details>
|
|
325
|
+
|
|
326
|
+
### mediaPublish
|
|
327
|
+
|
|
328
|
+
<details>
|
|
329
|
+
<summary><code>POST</code> <b><code>meta.v25.mediaPublish</code></b></summary>
|
|
330
|
+
|
|
331
|
+
<code>POST https://graph.instagram.com/v25.0/{igUserId}/media_publish</code>
|
|
332
|
+
|
|
333
|
+
[Upstream docs ↗](https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media_publish/)
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
const res = await meta.v25.mediaPublish({ /* ... */ });
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Source: [`packages/provider/meta/src/meta.ts`](src/meta.ts)
|
|
340
|
+
|
|
341
|
+
</details>
|
|
342
|
+
|
|
343
|
+
## Middleware
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
import { meta as createMeta, withRetry } from "@apicity/meta";
|
|
347
|
+
|
|
348
|
+
const meta = createMeta({ apiKey: process.env.META_API_KEY! });
|
|
349
|
+
const models = withRetry(meta.get.v1.models, { retries: 3 });
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Part of the [apicity](https://github.com/justintanner/apicity) monorepo.
|
|
353
|
+
|
|
354
|
+
## License
|
|
355
|
+
|
|
356
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../../src/example.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,QAAA,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAS7C,CAAC;AAEF,eAAe,QAAQ,CAAC;AAOxB,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CA6ChD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Auto-generated by `pnpm run gen:examples` — do not edit by hand.
|
|
2
|
+
// Source: tests/recordings/<provider>_*/<test>_*/recording.har
|
|
3
|
+
//
|
|
4
|
+
// Each entry is the green-path payload for one endpoint, mined from a real
|
|
5
|
+
// integration-test recording. `attachExamples` walks the provider tree and
|
|
6
|
+
// hangs the matching entry off each endpoint function as `.example`.
|
|
7
|
+
const EXAMPLES = {
|
|
8
|
+
"POST v25.media": {
|
|
9
|
+
"source": "meta/media-create",
|
|
10
|
+
"payload": {
|
|
11
|
+
"media_type": "REELS",
|
|
12
|
+
"video_url": "https://files.catbox.moe/example-reel.mp4",
|
|
13
|
+
"caption": "hello from @apicity/meta"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export default EXAMPLES;
|
|
18
|
+
// Walks each "<METHOD> <dotPath>" key onto the provider's tree. Tries the
|
|
19
|
+
// standard `provider.<method>.<dotPath>` shape first, then a few fallbacks
|
|
20
|
+
// to cover providers with non-standard layouts (fal's `.run.` namespace,
|
|
21
|
+
// kie's sub-providers, `free`'s flat root). Returns the same provider for
|
|
22
|
+
// drop-in use as `return attachExamples({ ... });`.
|
|
23
|
+
export function attachExamples(provider) {
|
|
24
|
+
const root = provider;
|
|
25
|
+
const HTTP_KEYS = new Set(["post", "get", "put", "delete", "patch", "head"]);
|
|
26
|
+
for (const [key, example] of Object.entries(EXAMPLES)) {
|
|
27
|
+
const sp = key.indexOf(" ");
|
|
28
|
+
if (sp < 0)
|
|
29
|
+
continue;
|
|
30
|
+
const method = key.slice(0, sp).toLowerCase();
|
|
31
|
+
const segs = key.slice(sp + 1).split(".");
|
|
32
|
+
const candidates = [
|
|
33
|
+
root[method],
|
|
34
|
+
root[method]?.run,
|
|
35
|
+
root,
|
|
36
|
+
];
|
|
37
|
+
if (segs.length > 1) {
|
|
38
|
+
const sub = root[segs[0]];
|
|
39
|
+
if (sub && typeof sub === "object") {
|
|
40
|
+
const subMethod = sub[method];
|
|
41
|
+
if (subMethod)
|
|
42
|
+
candidates.push({ __nested: subMethod, __segs: segs.slice(1) });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let attached = false;
|
|
46
|
+
for (const c of candidates) {
|
|
47
|
+
const fn = walkToFn(c, segs);
|
|
48
|
+
if (fn) {
|
|
49
|
+
Object.assign(fn, { example });
|
|
50
|
+
attached = true;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (attached)
|
|
55
|
+
continue;
|
|
56
|
+
for (const k of Object.keys(root)) {
|
|
57
|
+
if (HTTP_KEYS.has(k))
|
|
58
|
+
continue;
|
|
59
|
+
if (!segs.includes(k))
|
|
60
|
+
continue;
|
|
61
|
+
const sub = root[k];
|
|
62
|
+
if (!sub || typeof sub !== "object")
|
|
63
|
+
continue;
|
|
64
|
+
const subMethod = sub[method];
|
|
65
|
+
if (!subMethod)
|
|
66
|
+
continue;
|
|
67
|
+
const fn = walkToFn(subMethod, segs);
|
|
68
|
+
if (fn) {
|
|
69
|
+
Object.assign(fn, { example });
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return provider;
|
|
75
|
+
}
|
|
76
|
+
function walkToFn(start, segs) {
|
|
77
|
+
if (start && typeof start === "object" && "__nested" in start) {
|
|
78
|
+
const wrapper = start;
|
|
79
|
+
return walkToFn(wrapper.__nested, wrapper.__segs);
|
|
80
|
+
}
|
|
81
|
+
let cur = start;
|
|
82
|
+
for (const seg of segs) {
|
|
83
|
+
if (cur === null || cur === undefined)
|
|
84
|
+
return null;
|
|
85
|
+
const t = typeof cur;
|
|
86
|
+
if (t !== "object" && t !== "function")
|
|
87
|
+
return null;
|
|
88
|
+
cur = cur[seg];
|
|
89
|
+
}
|
|
90
|
+
return typeof cur === "function"
|
|
91
|
+
? cur
|
|
92
|
+
: null;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.js","sourceRoot":"","sources":["../../src/example.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { meta } from "./meta";
|
|
2
|
+
export { MetaError } from "./types";
|
|
3
|
+
export type { MetaOptions, MetaMediaCreateRequest, MetaMediaCreateResponse, MetaMediaCreateMethod, MetaContainerStatusCode, MetaContainerStatusQuery, MetaContainerStatusResponse, MetaContainerStatusMethod, MetaMediaPublishRequest, MetaMediaPublishResponse, MetaMediaPublishMethod, MetaPostV25Namespace, MetaPostNamespace, MetaGetV25Namespace, MetaGetNamespace, MetaProvider, } from "./types";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,YAAY,EACV,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EACxB,2BAA2B,EAC3B,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,GACb,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/meta.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAOX,YAAY,EAEb,MAAM,SAAS,CAAC;AAOjB,wBAAgB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CAiKpD"}
|
package/dist/src/meta.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { MetaError, } from "./types.js";
|
|
2
|
+
import { MetaMediaCreateRequestSchema, MetaMediaPublishRequestSchema, } from "./zod.js";
|
|
3
|
+
import { attachExamples } from "./example.js";
|
|
4
|
+
export function meta(opts) {
|
|
5
|
+
const baseURL = opts.baseURL ?? "https://graph.instagram.com";
|
|
6
|
+
const doFetch = opts.fetch ?? fetch;
|
|
7
|
+
const timeout = opts.timeout ?? 30000;
|
|
8
|
+
function attachAbortHandler(signal, controller) {
|
|
9
|
+
if (signal.aborted) {
|
|
10
|
+
controller.abort();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
14
|
+
}
|
|
15
|
+
// Meta Graph API errors come as `{ error: { message, type, code, ... } }`
|
|
16
|
+
// for the legacy shape, with a top-level `error_user_msg` available on
|
|
17
|
+
// some validation failures. Surface whichever the server sent so the
|
|
18
|
+
// caller sees the actual reason rather than a generic "IG API error: 400".
|
|
19
|
+
function formatErrorMessage(status, body) {
|
|
20
|
+
if (typeof body === "object" && body !== null) {
|
|
21
|
+
const b = body;
|
|
22
|
+
if (b.error?.error_user_msg)
|
|
23
|
+
return `IG API error ${status}: ${b.error.error_user_msg}`;
|
|
24
|
+
if (b.error?.message)
|
|
25
|
+
return `IG API error ${status}: ${b.error.message}`;
|
|
26
|
+
}
|
|
27
|
+
return `IG API error: ${status}`;
|
|
28
|
+
}
|
|
29
|
+
async function makeJsonRequest(method, path, body, signal) {
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
32
|
+
if (signal) {
|
|
33
|
+
attachAbortHandler(signal, controller);
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const headers = {
|
|
37
|
+
Authorization: `Bearer ${opts.accessToken}`,
|
|
38
|
+
};
|
|
39
|
+
const init = {
|
|
40
|
+
method,
|
|
41
|
+
headers,
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
};
|
|
44
|
+
if (body !== undefined) {
|
|
45
|
+
headers["Content-Type"] = "application/json";
|
|
46
|
+
init.body = JSON.stringify(body);
|
|
47
|
+
}
|
|
48
|
+
const res = await doFetch(`${baseURL}${path}`, init);
|
|
49
|
+
clearTimeout(timeoutId);
|
|
50
|
+
if (!res.ok) {
|
|
51
|
+
let resBody = null;
|
|
52
|
+
try {
|
|
53
|
+
resBody = await res.json();
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// ignore parse errors
|
|
57
|
+
}
|
|
58
|
+
throw new MetaError(formatErrorMessage(res.status, resBody), res.status, resBody);
|
|
59
|
+
}
|
|
60
|
+
return (await res.json());
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
clearTimeout(timeoutId);
|
|
64
|
+
if (error instanceof MetaError)
|
|
65
|
+
throw error;
|
|
66
|
+
throw new MetaError(`IG request failed: ${error}`, 500);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// sig-ok: numeric URL segments (`/v25.0/`) become identifier-safe (`v25`)
|
|
70
|
+
// POST https://graph.instagram.com/v25.0/{igUserId}/media
|
|
71
|
+
// Docs: https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media/
|
|
72
|
+
const mediaCreate = Object.assign(async (igUserId, req, signal) => {
|
|
73
|
+
return makeJsonRequest("POST", `/v25.0/${encodeURIComponent(igUserId)}/media`, req, signal);
|
|
74
|
+
}, { schema: MetaMediaCreateRequestSchema });
|
|
75
|
+
// sig-ok: numeric URL segments (`/v25.0/`) become identifier-safe (`v25`)
|
|
76
|
+
// GET https://graph.instagram.com/v25.0/{containerId}{query}
|
|
77
|
+
// Docs: https://developers.facebook.com/docs/instagram-platform/reference/ig-container/
|
|
78
|
+
async function containerStatus(containerId, params, signal) {
|
|
79
|
+
const query = params?.fields
|
|
80
|
+
? `?fields=${encodeURIComponent(params.fields)}`
|
|
81
|
+
: "";
|
|
82
|
+
return makeJsonRequest("GET", `/v25.0/${encodeURIComponent(containerId)}${query}`, undefined, signal);
|
|
83
|
+
}
|
|
84
|
+
// sig-ok: numeric URL segments (`/v25.0/`) become identifier-safe (`v25`)
|
|
85
|
+
// POST https://graph.instagram.com/v25.0/{igUserId}/media_publish
|
|
86
|
+
// Docs: https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/media_publish/
|
|
87
|
+
const mediaPublish = Object.assign(async (igUserId, req, signal) => {
|
|
88
|
+
return makeJsonRequest("POST", `/v25.0/${encodeURIComponent(igUserId)}/media_publish`, req, signal);
|
|
89
|
+
}, { schema: MetaMediaPublishRequestSchema });
|
|
90
|
+
return attachExamples({
|
|
91
|
+
post: {
|
|
92
|
+
v25: {
|
|
93
|
+
media: mediaCreate,
|
|
94
|
+
mediaPublish,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
get: {
|
|
98
|
+
v25: {
|
|
99
|
+
container: containerStatus,
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/meta.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { MetaMediaCreateRequest, MetaMediaPublishRequest } from "./zod";
|
|
3
|
+
export type { MetaOptions, MetaMediaCreateRequest, MetaMediaPublishRequest, } from "./zod";
|
|
4
|
+
export declare class MetaError extends Error {
|
|
5
|
+
readonly status: number;
|
|
6
|
+
readonly body: unknown;
|
|
7
|
+
readonly code?: string;
|
|
8
|
+
constructor(message: string, status: number, body?: unknown, code?: string);
|
|
9
|
+
}
|
|
10
|
+
export interface MetaMediaCreateResponse {
|
|
11
|
+
id: string;
|
|
12
|
+
}
|
|
13
|
+
export type MetaContainerStatusCode = "EXPIRED" | "ERROR" | "FINISHED" | "IN_PROGRESS" | "PUBLISHED";
|
|
14
|
+
export interface MetaContainerStatusResponse {
|
|
15
|
+
id: string;
|
|
16
|
+
status_code?: MetaContainerStatusCode;
|
|
17
|
+
status?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface MetaContainerStatusQuery {
|
|
20
|
+
/** Comma-separated field list. Default returns only `id`; pass
|
|
21
|
+
* `"status_code,status"` to read processing state. */
|
|
22
|
+
fields?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface MetaMediaCreateMethod {
|
|
25
|
+
(igUserId: string, req: MetaMediaCreateRequest, signal?: AbortSignal): Promise<MetaMediaCreateResponse>;
|
|
26
|
+
schema: z.ZodType<MetaMediaCreateRequest>;
|
|
27
|
+
}
|
|
28
|
+
export interface MetaContainerStatusMethod {
|
|
29
|
+
(containerId: string, query?: MetaContainerStatusQuery, signal?: AbortSignal): Promise<MetaContainerStatusResponse>;
|
|
30
|
+
}
|
|
31
|
+
export interface MetaMediaPublishResponse {
|
|
32
|
+
id: string;
|
|
33
|
+
}
|
|
34
|
+
export interface MetaMediaPublishMethod {
|
|
35
|
+
(igUserId: string, req: MetaMediaPublishRequest, signal?: AbortSignal): Promise<MetaMediaPublishResponse>;
|
|
36
|
+
schema: z.ZodType<MetaMediaPublishRequest>;
|
|
37
|
+
}
|
|
38
|
+
export interface MetaPostV25Namespace {
|
|
39
|
+
media: MetaMediaCreateMethod;
|
|
40
|
+
mediaPublish: MetaMediaPublishMethod;
|
|
41
|
+
}
|
|
42
|
+
export interface MetaPostNamespace {
|
|
43
|
+
v25: MetaPostV25Namespace;
|
|
44
|
+
}
|
|
45
|
+
export interface MetaGetV25Namespace {
|
|
46
|
+
container: MetaContainerStatusMethod;
|
|
47
|
+
}
|
|
48
|
+
export interface MetaGetNamespace {
|
|
49
|
+
v25: MetaGetV25Namespace;
|
|
50
|
+
}
|
|
51
|
+
export interface MetaProvider {
|
|
52
|
+
post: MetaPostNamespace;
|
|
53
|
+
get: MetaGetNamespace;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,OAAO,CAAC;AAE7E,YAAY,EACV,WAAW,EACX,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,OAAO,CAAC;AAIf,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM;CAO3E;AAMD,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,uBAAuB,GAC/B,SAAS,GACT,OAAO,GACP,UAAU,GACV,aAAa,GACb,WAAW,CAAC;AAKhB,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC;2DACuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAID,MAAM,WAAW,qBAAqB;IACpC,CACE,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,sBAAsB,EAC3B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,yBAAyB;IACxC,CACE,WAAW,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,wBAAwB,EAChC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,2BAA2B,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,sBAAsB;IACrC,CACE,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,uBAAuB,EAC5B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACrC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC5C;AAID,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,YAAY,EAAE,sBAAsB,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,oBAAoB,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,yBAAyB,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,mBAAmB,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,gBAAgB,CAAC;CACvB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// -- Error -------------------------------------------------------------------
|
|
2
|
+
export class MetaError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
body;
|
|
5
|
+
code;
|
|
6
|
+
constructor(message, status, body, code) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "MetaError";
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.body = body ?? null;
|
|
11
|
+
this.code = code;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AASA,+EAA+E;AAE/E,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,MAAM,CAAS;IACf,IAAI,CAAU;IACd,IAAI,CAAU;IAEvB,YAAY,OAAe,EAAE,MAAc,EAAE,IAAc,EAAE,IAAa;QACxE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const MetaOptionsSchema: z.ZodObject<{
|
|
3
|
+
accessToken: z.ZodString;
|
|
4
|
+
baseURL: z.ZodOptional<z.ZodString>;
|
|
5
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
fetch: z.ZodOptional<z.ZodType<typeof fetch, z.ZodTypeDef, typeof fetch>>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
accessToken: string;
|
|
9
|
+
baseURL?: string | undefined;
|
|
10
|
+
timeout?: number | undefined;
|
|
11
|
+
fetch?: typeof fetch | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
accessToken: string;
|
|
14
|
+
baseURL?: string | undefined;
|
|
15
|
+
timeout?: number | undefined;
|
|
16
|
+
fetch?: typeof fetch | undefined;
|
|
17
|
+
}>;
|
|
18
|
+
export type MetaOptions = z.infer<typeof MetaOptionsSchema>;
|
|
19
|
+
export declare const MetaMediaCreateRequestSchema: z.ZodObject<{
|
|
20
|
+
media_type: z.ZodEnum<["REELS", "VIDEO", "IMAGE", "CAROUSEL"]>;
|
|
21
|
+
video_url: z.ZodOptional<z.ZodString>;
|
|
22
|
+
image_url: z.ZodOptional<z.ZodString>;
|
|
23
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
24
|
+
thumb_offset: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
share_to_feed: z.ZodOptional<z.ZodBoolean>;
|
|
26
|
+
location_id: z.ZodOptional<z.ZodString>;
|
|
27
|
+
user_tags: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
28
|
+
username: z.ZodString;
|
|
29
|
+
x: z.ZodOptional<z.ZodNumber>;
|
|
30
|
+
y: z.ZodOptional<z.ZodNumber>;
|
|
31
|
+
}, "strip", z.ZodTypeAny, {
|
|
32
|
+
username: string;
|
|
33
|
+
x?: number | undefined;
|
|
34
|
+
y?: number | undefined;
|
|
35
|
+
}, {
|
|
36
|
+
username: string;
|
|
37
|
+
x?: number | undefined;
|
|
38
|
+
y?: number | undefined;
|
|
39
|
+
}>, "many">>;
|
|
40
|
+
collaborators: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
41
|
+
}, "strip", z.ZodTypeAny, {
|
|
42
|
+
media_type: "REELS" | "VIDEO" | "IMAGE" | "CAROUSEL";
|
|
43
|
+
video_url?: string | undefined;
|
|
44
|
+
image_url?: string | undefined;
|
|
45
|
+
caption?: string | undefined;
|
|
46
|
+
thumb_offset?: number | undefined;
|
|
47
|
+
share_to_feed?: boolean | undefined;
|
|
48
|
+
location_id?: string | undefined;
|
|
49
|
+
user_tags?: {
|
|
50
|
+
username: string;
|
|
51
|
+
x?: number | undefined;
|
|
52
|
+
y?: number | undefined;
|
|
53
|
+
}[] | undefined;
|
|
54
|
+
collaborators?: string[] | undefined;
|
|
55
|
+
}, {
|
|
56
|
+
media_type: "REELS" | "VIDEO" | "IMAGE" | "CAROUSEL";
|
|
57
|
+
video_url?: string | undefined;
|
|
58
|
+
image_url?: string | undefined;
|
|
59
|
+
caption?: string | undefined;
|
|
60
|
+
thumb_offset?: number | undefined;
|
|
61
|
+
share_to_feed?: boolean | undefined;
|
|
62
|
+
location_id?: string | undefined;
|
|
63
|
+
user_tags?: {
|
|
64
|
+
username: string;
|
|
65
|
+
x?: number | undefined;
|
|
66
|
+
y?: number | undefined;
|
|
67
|
+
}[] | undefined;
|
|
68
|
+
collaborators?: string[] | undefined;
|
|
69
|
+
}>;
|
|
70
|
+
export type MetaMediaCreateRequest = z.infer<typeof MetaMediaCreateRequestSchema>;
|
|
71
|
+
export declare const MetaMediaPublishRequestSchema: z.ZodObject<{
|
|
72
|
+
creation_id: z.ZodString;
|
|
73
|
+
}, "strip", z.ZodTypeAny, {
|
|
74
|
+
creation_id: string;
|
|
75
|
+
}, {
|
|
76
|
+
creation_id: string;
|
|
77
|
+
}>;
|
|
78
|
+
export type MetaMediaPublishRequest = z.infer<typeof MetaMediaPublishRequestSchema>;
|
|
79
|
+
//# sourceMappingURL=zod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AA8B5D,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUvC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAC1C,OAAO,4BAA4B,CACpC,CAAC;AASF,eAAO,MAAM,6BAA6B;;;;;;EAExC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC"}
|
package/dist/src/zod.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Provider options
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Instagram Graph API requires a long-lived user access token from the
|
|
6
|
+
// Instagram Login OAuth flow (instagram_business_basic +
|
|
7
|
+
// instagram_business_content_publish scopes). The caller obtains the token
|
|
8
|
+
// externally and supplies it here; this package does not implement the OAuth
|
|
9
|
+
// dance. Tokens last 60 days and are refreshable for another 60 each time.
|
|
10
|
+
export const MetaOptionsSchema = z.object({
|
|
11
|
+
accessToken: z.string().min(1),
|
|
12
|
+
baseURL: z.string().optional(),
|
|
13
|
+
timeout: z.number().optional(),
|
|
14
|
+
fetch: z.custom().optional(),
|
|
15
|
+
});
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Shared building blocks
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Instagram object IDs are numeric strings. The Graph API uses 64-bit ints
|
|
20
|
+
// over the wire as decimal strings to avoid JS precision loss. Cap at 19
|
|
21
|
+
// digits (max int64).
|
|
22
|
+
const MetaIdStringSchema = z.string().regex(/^[0-9]{1,19}$/);
|
|
23
|
+
const MetaUserTagSchema = z.object({
|
|
24
|
+
username: z.string().min(1),
|
|
25
|
+
x: z.number().min(0).max(1).optional(),
|
|
26
|
+
y: z.number().min(0).max(1).optional(),
|
|
27
|
+
});
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// POST /v25.0/{ig-user-id}/media
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// `media_type` drives which url field is required. Carousel items reference
|
|
32
|
+
// their parent container via `is_carousel_item: true`, but full carousel
|
|
33
|
+
// support is out of scope for this first cut — REELS / VIDEO / IMAGE only.
|
|
34
|
+
const MetaMediaTypeSchema = z.enum(["REELS", "VIDEO", "IMAGE", "CAROUSEL"]);
|
|
35
|
+
// Server-side validation enforces that REELS / VIDEO require `video_url`,
|
|
36
|
+
// IMAGE requires `image_url`, etc. Mirror the docs at the SDK layer with
|
|
37
|
+
// simple optionality so error messages come back from the API verbatim
|
|
38
|
+
// instead of being pre-empted by an over-zealous local schema.
|
|
39
|
+
export const MetaMediaCreateRequestSchema = z.object({
|
|
40
|
+
media_type: MetaMediaTypeSchema,
|
|
41
|
+
video_url: z.string().url().optional(),
|
|
42
|
+
image_url: z.string().url().optional(),
|
|
43
|
+
caption: z.string().max(2200).optional(),
|
|
44
|
+
thumb_offset: z.number().int().min(0).optional(),
|
|
45
|
+
share_to_feed: z.boolean().optional(),
|
|
46
|
+
location_id: MetaIdStringSchema.optional(),
|
|
47
|
+
user_tags: z.array(MetaUserTagSchema).max(20).optional(),
|
|
48
|
+
collaborators: z.array(z.string().min(1)).max(3).optional(),
|
|
49
|
+
});
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// POST /v25.0/{ig-user-id}/media_publish
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// `creation_id` is the container ID returned from /media — must reach
|
|
54
|
+
// status_code === "FINISHED" before this endpoint will accept it (server
|
|
55
|
+
// returns 400 otherwise).
|
|
56
|
+
export const MetaMediaPublishRequestSchema = z.object({
|
|
57
|
+
creation_id: MetaIdStringSchema,
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=zod.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod.js","sourceRoot":"","sources":["../../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,uEAAuE;AACvE,yDAAyD;AACzD,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAgB,CAAC,QAAQ,EAAE;CAC3C,CAAC,CAAC;AAIH,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,2EAA2E;AAC3E,yEAAyE;AACzE,sBAAsB;AACtB,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAE7D,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACtC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E,4EAA4E;AAC5E,yEAAyE;AACzE,2EAA2E;AAC3E,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AAE5E,0EAA0E;AAC1E,yEAAyE;AACzE,uEAAuE;AACvE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,UAAU,EAAE,mBAAmB;IAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACtC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACtC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;IACxC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAChD,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,WAAW,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IACxD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC,CAAC;AAMH,8EAA8E;AAC9E,yCAAyC;AACzC,8EAA8E;AAE9E,sEAAsE;AACtE,yEAAyE;AACzE,0BAA0B;AAC1B,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,WAAW,EAAE,kBAAkB;CAChC,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apicity/meta",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Instagram Graph API provider for posting reels via the public-URL flow (graph.instagram.com).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/justintanner/apicity.git",
|
|
9
|
+
"directory": "provider/meta"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/src/index.js",
|
|
16
|
+
"types": "dist/src/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./dist/src/index.js",
|
|
20
|
+
"types": "./dist/src/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./zod": {
|
|
23
|
+
"import": "./dist/src/zod.js",
|
|
24
|
+
"types": "./dist/src/zod.d.ts"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"zod": "^3.24.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependenciesMeta": {
|
|
31
|
+
"zod": {
|
|
32
|
+
"optional": true
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"sideEffects": false,
|
|
41
|
+
"keywords": [
|
|
42
|
+
"instagram",
|
|
43
|
+
"ig",
|
|
44
|
+
"meta",
|
|
45
|
+
"social",
|
|
46
|
+
"reels",
|
|
47
|
+
"post",
|
|
48
|
+
"media-publish",
|
|
49
|
+
"apicity"
|
|
50
|
+
],
|
|
51
|
+
"author": "Justin Tanner",
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=18.0.0"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/justintanner/apicity#readme",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/justintanner/apicity/issues"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "tsc -p tsconfig.json && node scripts/dist.mjs"
|
|
61
|
+
}
|
|
62
|
+
}
|