@luanxdd/meowgallery 0.0.0-stage → 0.2.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/README.md +112 -2
- package/dist/client.d.ts +14 -0
- package/dist/client.js +181 -0
- package/dist/client.js.map +1 -0
- package/dist/error.d.ts +12 -0
- package/dist/error.js +15 -0
- package/dist/error.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +6 -0
- package/dist/node.js +37 -0
- package/dist/node.js.map +1 -0
- package/dist/types.d.ts +56 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +49 -4
package/README.md
CHANGED
|
@@ -1,3 +1,113 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MeowGallery SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript 7.0.2, ESM, Node.js 22+ e navegadores modernos com Fetch e AbortSignal. Sem dependências de produção.
|
|
4
|
+
|
|
5
|
+
## Instalar
|
|
6
|
+
|
|
7
|
+
O pacote ainda não foi publicado. Instale o arquivo incluído nesta entrega:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install ./meowgallery-sdk-0.2.0.tgz
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Obter uma publicação
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { MeowGallery } from "@meowgallery/sdk";
|
|
17
|
+
|
|
18
|
+
const gallery = new MeowGallery({
|
|
19
|
+
baseUrl: "https://gallery.seudominio.com",
|
|
20
|
+
token: process.env.MEOWGALLERY_KEY!,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const post = await gallery.capture("https://www.instagram.com/p/CODIGO_REAL/");
|
|
24
|
+
|
|
25
|
+
console.log(post.author.name);
|
|
26
|
+
console.log(post.caption);
|
|
27
|
+
|
|
28
|
+
for (const item of post.items) {
|
|
29
|
+
console.log(item.kind, item.width, item.height, item.delivery.expiresAt);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`items` preserva a ordem do carrossel. `audio` contém a faixa de posts de fotos do TikTok quando disponível. Cada mídia tem um link próprio. URLs de origem e cookies não são retornados.
|
|
34
|
+
|
|
35
|
+
## Baixar no consumidor Node
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { saveMedia } from "@meowgallery/sdk/node";
|
|
39
|
+
|
|
40
|
+
const item = post.items[0];
|
|
41
|
+
|
|
42
|
+
if (item) {
|
|
43
|
+
await saveMedia(gallery, item, "./publicacao.bin");
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A gravação acontece no consumidor. A API apenas repassa o stream. O helper limita bytes, remove arquivos parciais e não sobrescreve arquivos existentes. Escolha a extensão conforme o tipo real da mídia; `.bin` não altera o conteúdo.
|
|
48
|
+
|
|
49
|
+
Para encaminhar ao seu framework sem salvar:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const response = await gallery.download(post.items[0]!);
|
|
53
|
+
const stream = response.body;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Consuma ou cancele o stream. Um intervalo pode ser solicitado com `gallery.download(item, { range: "bytes=0-1023" })`. A chave da API não é enviada no download: o próprio link é uma credencial temporária.
|
|
57
|
+
|
|
58
|
+
## Fotos e áudio
|
|
59
|
+
|
|
60
|
+
Carrosséis preservam a ordem em `post.items`. Quando disponível, `post.audio`
|
|
61
|
+
contém a faixa separada, com seu próprio link temporário.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
if (post.audio) {
|
|
65
|
+
await saveMedia(gallery, post.audio, "./audio.m4a");
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Confira `mimeType` para escolher a extensão. A SDK não converte fotos em vídeo
|
|
70
|
+
e não depende de FFmpeg. Na versão 0.2.0 foram removidos `createMotion`,
|
|
71
|
+
`MotionOptions` e o campo `composition`.
|
|
72
|
+
|
|
73
|
+
## OAuth
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const gallery = new MeowGallery({
|
|
77
|
+
baseUrl: "https://gallery.seudominio.com",
|
|
78
|
+
token: async () => auth.getAccessToken(),
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`auth` representa o SDK do seu provedor de identidade, responsável por login, PKCE e renovação. A função é chamada antes de cada operação autenticada. Não coloque chaves de bot ou Owner no código público do site.
|
|
83
|
+
|
|
84
|
+
## Cancelamento e erros
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { MeowGalleryError } from "@meowgallery/sdk";
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const post = await gallery.capture(url, {
|
|
91
|
+
signal: AbortSignal.timeout(30_000),
|
|
92
|
+
});
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error instanceof MeowGalleryError) {
|
|
95
|
+
console.error(error.code, error.message, error.requestId);
|
|
96
|
+
} else {
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
O erro contém `code`, `status`, `requestId` e `retryAfter`. POSTs não são repetidos automaticamente, para não duplicar emissões de links e consumo de cota. Ao expirar, solicite a publicação novamente. Se a origem expirar antes do link, use `gallery.capture(url, { refresh: true })` para ignorar o cache.
|
|
103
|
+
|
|
104
|
+
## Desenvolvimento
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm ci
|
|
108
|
+
npm run check
|
|
109
|
+
npm test
|
|
110
|
+
npm pack
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Os aliases internos estão declarados em `package.json#imports`; o consumidor não precisa configurar `tsconfig.paths`. A entrada `/node` não deve entrar em bundles de navegador.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Capture, CreatedCredential, Credential, CredentialInput, Media, MeowGalleryOptions, RequestOptions } from "#types";
|
|
2
|
+
export declare class MeowGallery {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(options: MeowGalleryOptions);
|
|
5
|
+
capture(url: string, options?: RequestOptions & {
|
|
6
|
+
readonly refresh?: boolean;
|
|
7
|
+
}): Promise<Capture>;
|
|
8
|
+
createCredential(input: CredentialInput, options?: RequestOptions): Promise<CreatedCredential>;
|
|
9
|
+
listCredentials(options?: RequestOptions): Promise<Credential[]>;
|
|
10
|
+
revokeCredential(id: string, options?: RequestOptions): Promise<void>;
|
|
11
|
+
download(media: Media, options?: RequestOptions & {
|
|
12
|
+
readonly range?: string;
|
|
13
|
+
}): Promise<Response>;
|
|
14
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { MeowGalleryError } from "#error";
|
|
2
|
+
export class MeowGallery {
|
|
3
|
+
#origin;
|
|
4
|
+
#token;
|
|
5
|
+
#fetch;
|
|
6
|
+
#timeout;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
const url = new URL(options.baseUrl);
|
|
9
|
+
const local = ["localhost", "127.0.0.1"].includes(url.hostname);
|
|
10
|
+
if ((url.protocol !== "https:" &&
|
|
11
|
+
!(options.allowLocalHttp && local && url.protocol === "http:")) ||
|
|
12
|
+
url.username ||
|
|
13
|
+
url.password ||
|
|
14
|
+
url.pathname !== "/" ||
|
|
15
|
+
url.search ||
|
|
16
|
+
url.hash) {
|
|
17
|
+
throw new TypeError("baseUrl deve ser uma origem HTTPS válida.");
|
|
18
|
+
}
|
|
19
|
+
this.#origin = url.origin;
|
|
20
|
+
this.#token = options.token;
|
|
21
|
+
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
22
|
+
this.#timeout = options.timeoutMs ?? 35_000;
|
|
23
|
+
if (!Number.isSafeInteger(this.#timeout) ||
|
|
24
|
+
this.#timeout < 1 ||
|
|
25
|
+
this.#timeout > 300_000) {
|
|
26
|
+
throw new TypeError("timeoutMs deve estar entre 1 e 300000.");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
capture(url, options = {}) {
|
|
30
|
+
return this.#request("POST", "/v1/captures", options.refresh ? { url, refresh: true } : { url }, options);
|
|
31
|
+
}
|
|
32
|
+
createCredential(input, options = {}) {
|
|
33
|
+
return this.#request("POST", "/v1/credentials", input, options);
|
|
34
|
+
}
|
|
35
|
+
listCredentials(options = {}) {
|
|
36
|
+
return this.#request("GET", "/v1/credentials", undefined, options);
|
|
37
|
+
}
|
|
38
|
+
revokeCredential(id, options = {}) {
|
|
39
|
+
if (!/^[0-9a-f-]{36}$/i.test(id)) {
|
|
40
|
+
throw new TypeError("Identificador de credencial inválido.");
|
|
41
|
+
}
|
|
42
|
+
return this.#request("DELETE", `/v1/credentials/${id}`, undefined, options);
|
|
43
|
+
}
|
|
44
|
+
async download(media, options = {}) {
|
|
45
|
+
const url = new URL(media.delivery.url);
|
|
46
|
+
if (url.origin !== this.#origin ||
|
|
47
|
+
!/^\/v1\/delivery\/[A-Za-z0-9_-]+$/.test(url.pathname) ||
|
|
48
|
+
url.username ||
|
|
49
|
+
url.password ||
|
|
50
|
+
url.search ||
|
|
51
|
+
url.hash) {
|
|
52
|
+
throw new TypeError("O link de entrega não pertence a esta MeowGallery.");
|
|
53
|
+
}
|
|
54
|
+
const expires = Date.parse(media.delivery.expiresAt);
|
|
55
|
+
if (!Number.isFinite(expires) || expires <= Date.now()) {
|
|
56
|
+
throw new MeowGalleryError("O link expirou. Solicite a publicação novamente.", { code: "delivery_expired", status: 410 });
|
|
57
|
+
}
|
|
58
|
+
const headers = new Headers();
|
|
59
|
+
if (options.range) {
|
|
60
|
+
headers.set("Range", options.range);
|
|
61
|
+
}
|
|
62
|
+
const response = await this.#send(url.href, {
|
|
63
|
+
headers,
|
|
64
|
+
signal: this.#signal(options.signal, 300_000),
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
throw await this.#failure(response);
|
|
68
|
+
}
|
|
69
|
+
return response;
|
|
70
|
+
}
|
|
71
|
+
async #request(method, path, body, options) {
|
|
72
|
+
const token = typeof this.#token === "function" ? await this.#token() : this.#token;
|
|
73
|
+
if (!token || /[\r\n]/.test(token)) {
|
|
74
|
+
throw new TypeError("Token de autenticação inválido.");
|
|
75
|
+
}
|
|
76
|
+
const headers = new Headers({
|
|
77
|
+
Accept: "application/json",
|
|
78
|
+
Authorization: `Bearer ${token}`,
|
|
79
|
+
});
|
|
80
|
+
const init = {
|
|
81
|
+
method,
|
|
82
|
+
headers,
|
|
83
|
+
signal: this.#signal(options.signal, this.#timeout),
|
|
84
|
+
};
|
|
85
|
+
if (body !== undefined) {
|
|
86
|
+
headers.set("Content-Type", "application/json");
|
|
87
|
+
init.body = JSON.stringify(body);
|
|
88
|
+
}
|
|
89
|
+
const response = await this.#send(`${this.#origin}${path}`, init);
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
throw await this.#failure(response);
|
|
92
|
+
}
|
|
93
|
+
if (response.status === 204) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
const envelope = await this.#json(response);
|
|
97
|
+
if (!envelope || typeof envelope !== "object" || !("data" in envelope)) {
|
|
98
|
+
throw new MeowGalleryError("Resposta inesperada do serviço.", {
|
|
99
|
+
code: "invalid_response",
|
|
100
|
+
status: response.status,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return envelope.data;
|
|
104
|
+
}
|
|
105
|
+
#signal(signal, timeout) {
|
|
106
|
+
const deadline = AbortSignal.timeout(timeout);
|
|
107
|
+
return signal ? AbortSignal.any([signal, deadline]) : deadline;
|
|
108
|
+
}
|
|
109
|
+
async #send(url, init) {
|
|
110
|
+
try {
|
|
111
|
+
return await this.#fetch(url, {
|
|
112
|
+
...init,
|
|
113
|
+
redirect: "error",
|
|
114
|
+
credentials: "omit",
|
|
115
|
+
cache: "no-store",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
throw new MeowGalleryError(init.signal?.aborted
|
|
120
|
+
? "Solicitação cancelada ou expirada."
|
|
121
|
+
: "Não foi possível conectar à MeowGallery.", { code: init.signal?.aborted ? "request_aborted" : "network_error" });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async #failure(response) {
|
|
125
|
+
const body = (await this.#json(response).catch(() => null));
|
|
126
|
+
const retryHeader = response.headers.get("retry-after");
|
|
127
|
+
const retry = retryHeader === null ? NaN : Number(retryHeader);
|
|
128
|
+
return new MeowGalleryError(typeof body?.error?.message === "string"
|
|
129
|
+
? body.error.message
|
|
130
|
+
: "A solicitação não foi concluída.", {
|
|
131
|
+
code: typeof body?.error?.code === "string"
|
|
132
|
+
? body.error.code
|
|
133
|
+
: "http_error",
|
|
134
|
+
status: response.status,
|
|
135
|
+
requestId: response.headers.get("x-request-id"),
|
|
136
|
+
retryAfter: Number.isFinite(retry) && retry >= 0 ? retry : null,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
async #json(response) {
|
|
140
|
+
const reader = response.body?.getReader();
|
|
141
|
+
if (!reader) {
|
|
142
|
+
throw new MeowGalleryError("Resposta vazia do serviço.", {
|
|
143
|
+
code: "invalid_response",
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const chunks = [];
|
|
147
|
+
let size = 0;
|
|
148
|
+
try {
|
|
149
|
+
for (;;) {
|
|
150
|
+
const { done, value } = await reader.read();
|
|
151
|
+
if (done) {
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
size += value.byteLength;
|
|
155
|
+
if (size > 1_048_576) {
|
|
156
|
+
await reader.cancel();
|
|
157
|
+
throw new Error("Response limit exceeded");
|
|
158
|
+
}
|
|
159
|
+
chunks.push(value);
|
|
160
|
+
}
|
|
161
|
+
const joined = new Uint8Array(size);
|
|
162
|
+
let offset = 0;
|
|
163
|
+
for (const chunk of chunks) {
|
|
164
|
+
joined.set(chunk, offset);
|
|
165
|
+
offset += chunk.byteLength;
|
|
166
|
+
}
|
|
167
|
+
return JSON.parse(new TextDecoder().decode(joined));
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
throw new MeowGalleryError("Resposta inválida ou interrompida do serviço.", {
|
|
171
|
+
code: "invalid_response",
|
|
172
|
+
status: response.status,
|
|
173
|
+
requestId: response.headers.get("x-request-id"),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
reader.releaseLock();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class MeowGalleryError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly requestId: string | null;
|
|
5
|
+
readonly retryAfter: number | null;
|
|
6
|
+
constructor(message: string, details: {
|
|
7
|
+
code: string;
|
|
8
|
+
status?: number;
|
|
9
|
+
requestId?: string | null;
|
|
10
|
+
retryAfter?: number | null;
|
|
11
|
+
});
|
|
12
|
+
}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class MeowGalleryError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
requestId;
|
|
5
|
+
retryAfter;
|
|
6
|
+
constructor(message, details) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "MeowGalleryError";
|
|
9
|
+
this.code = details.code;
|
|
10
|
+
this.status = details.status ?? 0;
|
|
11
|
+
this.requestId = details.requestId ?? null;
|
|
12
|
+
this.retryAfter = details.retryAfter ?? null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAS;IACb,MAAM,CAAS;IACf,SAAS,CAAgB;IACzB,UAAU,CAAgB;IAEnC,YACE,OAAe,EACf,OAKC;QAED,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC/C,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC"}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MeowGallery } from "#client";
|
|
2
|
+
import type { Media, RequestOptions } from "#types";
|
|
3
|
+
export interface SaveOptions extends RequestOptions {
|
|
4
|
+
readonly maxBytes?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function saveMedia(client: MeowGallery, media: Media, destination: string, options?: SaveOptions): Promise<string>;
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createWriteStream } from "node:fs";
|
|
2
|
+
import { link, mkdtemp, rm } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { Readable, Transform } from "node:stream";
|
|
5
|
+
import { pipeline } from "node:stream/promises";
|
|
6
|
+
export async function saveMedia(client, media, destination, options = {}) {
|
|
7
|
+
const target = resolve(destination);
|
|
8
|
+
const directory = await mkdtemp(join(dirname(target), ".meowgallery-"));
|
|
9
|
+
const temporary = join(directory, "media");
|
|
10
|
+
const limit = options.maxBytes ?? 256 * 1024 * 1024;
|
|
11
|
+
if (!Number.isSafeInteger(limit) || limit <= 0) {
|
|
12
|
+
await rm(directory, { recursive: true, force: true });
|
|
13
|
+
throw new TypeError("maxBytes deve ser um inteiro positivo.");
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const response = await client.download(media, options);
|
|
17
|
+
if (!response.body) {
|
|
18
|
+
throw new Error("O serviço retornou uma mídia vazia.");
|
|
19
|
+
}
|
|
20
|
+
let total = 0;
|
|
21
|
+
const bounded = new Transform({
|
|
22
|
+
transform(chunk, _encoding, callback) {
|
|
23
|
+
total += chunk.length;
|
|
24
|
+
callback(total > limit
|
|
25
|
+
? new Error("A mídia excede o limite de tamanho.")
|
|
26
|
+
: null, chunk);
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
await pipeline(Readable.fromWeb(response.body), bounded, createWriteStream(temporary, { flags: "wx", mode: 0o600 }), { signal: options.signal });
|
|
30
|
+
await link(temporary, target);
|
|
31
|
+
return target;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
await rm(directory, { recursive: true, force: true });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAShD,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAmB,EACnB,KAAY,EACZ,WAAmB,EACnB,OAAO,GAAgB,EAAE;IAEzB,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC;YAC5B,SAAS,CAAC,KAAa,EAAE,SAAS,EAAE,QAAQ;gBAC1C,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC;gBACtB,QAAQ,CACN,KAAK,GAAG,KAAK;oBACX,CAAC,CAAC,IAAI,KAAK,CAAC,qCAAqC,CAAC;oBAClD,CAAC,CAAC,IAAI,EACR,KAAK,CACN,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;QAEH,MAAM,QAAQ,CACZ,QAAQ,CAAC,OAAO,CACd,QAAQ,CAAC,IAA4D,CACtE,EACD,OAAO,EACP,iBAAiB,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAC1D,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAC3B,CAAC;QACF,MAAM,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC9B,OAAO,MAAM,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export type Scope = "captures:read" | "delivery:read" | "sources:authenticated";
|
|
2
|
+
export interface Media {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly kind: "image" | "video" | "audio";
|
|
5
|
+
readonly mimeType: string;
|
|
6
|
+
readonly width: number | null;
|
|
7
|
+
readonly height: number | null;
|
|
8
|
+
readonly quality: {
|
|
9
|
+
readonly selection: "best_available";
|
|
10
|
+
readonly hd: boolean | null;
|
|
11
|
+
readonly verified: boolean;
|
|
12
|
+
};
|
|
13
|
+
readonly delivery: {
|
|
14
|
+
readonly url: string;
|
|
15
|
+
readonly expiresAt: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface Capture {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly platform: "instagram" | "tiktok";
|
|
21
|
+
readonly caption: string;
|
|
22
|
+
readonly author: {
|
|
23
|
+
readonly username: string;
|
|
24
|
+
readonly name: string;
|
|
25
|
+
};
|
|
26
|
+
readonly items: readonly Media[];
|
|
27
|
+
readonly audio: Media | null;
|
|
28
|
+
}
|
|
29
|
+
export interface CredentialInput {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly scopes: readonly Scope[];
|
|
32
|
+
readonly requestsPerMinute: number;
|
|
33
|
+
readonly subject?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface Credential {
|
|
36
|
+
readonly id: string;
|
|
37
|
+
readonly name: string;
|
|
38
|
+
readonly scopes: readonly Scope[];
|
|
39
|
+
readonly requestsPerMinute: number;
|
|
40
|
+
readonly isAdmin: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface CreatedCredential extends Omit<CredentialInput, "subject"> {
|
|
43
|
+
readonly id: string;
|
|
44
|
+
readonly key: string | null;
|
|
45
|
+
readonly subject: string | null;
|
|
46
|
+
}
|
|
47
|
+
export interface RequestOptions {
|
|
48
|
+
readonly signal?: AbortSignal;
|
|
49
|
+
}
|
|
50
|
+
export interface MeowGalleryOptions {
|
|
51
|
+
readonly baseUrl: string;
|
|
52
|
+
readonly token: string | (() => string | Promise<string>);
|
|
53
|
+
readonly timeoutMs?: number;
|
|
54
|
+
readonly allowLocalHttp?: boolean;
|
|
55
|
+
readonly fetch?: typeof fetch;
|
|
56
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luanxdd/meowgallery",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Uma interface simples para capturar e entregar mídias com MeowGallery.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./node": {
|
|
20
|
+
"types": "./dist/node.d.ts",
|
|
21
|
+
"import": "./dist/node.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"imports": {
|
|
25
|
+
"#types": {
|
|
26
|
+
"types": "./dist/types.d.ts",
|
|
27
|
+
"default": "./dist/types.js"
|
|
28
|
+
},
|
|
29
|
+
"#error": {
|
|
30
|
+
"types": "./dist/error.d.ts",
|
|
31
|
+
"default": "./dist/error.js"
|
|
32
|
+
},
|
|
33
|
+
"#client": {
|
|
34
|
+
"types": "./dist/client.d.ts",
|
|
35
|
+
"default": "./dist/client.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc -p tsconfig.json",
|
|
40
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
41
|
+
"test": "npm run build && node --test test/*.test.mjs",
|
|
42
|
+
"prepack": "npm run build"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "^24.0.0",
|
|
46
|
+
"typescript": "7.0.2"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
}
|
|
51
|
+
}
|