@oktis-works/plugin-runtime 0.5.10 → 0.7.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/dist/bootstrap.d.ts +86 -21
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +254 -42
- package/dist/bootstrap.js.map +1 -1
- package/dist/content-query.d.ts +29 -0
- package/dist/content-query.d.ts.map +1 -0
- package/dist/content-query.js +109 -0
- package/dist/content-query.js.map +1 -0
- package/dist/hook-registry.d.ts +21 -21
- package/dist/hook-registry.d.ts.map +1 -1
- package/dist/hook-registry.js +26 -26
- package/dist/hook-registry.js.map +1 -1
- package/dist/http.d.ts +49 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +313 -0
- package/dist/http.js.map +1 -0
- package/dist/i18n.d.ts +16 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +73 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loader.js +3 -3
- package/dist/loader.js.map +1 -1
- package/dist/manifest.d.ts +11 -6
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +227 -17
- package/dist/manifest.js.map +1 -1
- package/dist/plugin-api.d.ts +191 -38
- package/dist/plugin-api.d.ts.map +1 -1
- package/dist/plugin-api.js +572 -10
- package/dist/plugin-api.js.map +1 -1
- package/dist/plugin-migrations.d.ts +15 -0
- package/dist/plugin-migrations.d.ts.map +1 -0
- package/dist/plugin-migrations.js +68 -0
- package/dist/plugin-migrations.js.map +1 -0
- package/dist/sandbox.d.ts +13 -11
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +11 -9
- package/dist/sandbox.js.map +1 -1
- package/dist/style-isolation.d.ts +3 -3
- package/dist/style-isolation.js +6 -6
- package/dist/style-isolation.js.map +1 -1
- package/package.json +7 -6
package/dist/http.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Agent } from 'undici';
|
|
2
|
+
import { type PluginHttpApi } from '@oktis-works/plugin-sdk';
|
|
3
|
+
export declare const DEFAULT_TIMEOUT_MS = 10000;
|
|
4
|
+
export declare const MAX_TIMEOUT_MS = 60000;
|
|
5
|
+
export declare const DEFAULT_MAX_BYTES: number;
|
|
6
|
+
export declare const MAX_REDIRECTS = 3;
|
|
7
|
+
export interface ResolvedAddress {
|
|
8
|
+
address: string;
|
|
9
|
+
family: number;
|
|
10
|
+
}
|
|
11
|
+
/** Erro de api.http com flag de retentativa. */
|
|
12
|
+
export declare class HttpError extends Error {
|
|
13
|
+
readonly retriable: boolean;
|
|
14
|
+
constructor(message: string, retriable: boolean);
|
|
15
|
+
}
|
|
16
|
+
/** Is the IPv4 publicly routable? Fail-closed on any special/reserved range. */
|
|
17
|
+
export declare function isPublicIpv4(ip: string): boolean;
|
|
18
|
+
/** Is the IPv6 publicly routable? Fail-closed: only 2000::/3 (global unicast). */
|
|
19
|
+
export declare function isPublicIpv6(ip: string): boolean;
|
|
20
|
+
/** Any non-public IP in the list → false. */
|
|
21
|
+
export declare function isPublicIp(ip: string): boolean;
|
|
22
|
+
/** Picks the first public address (for pinning). Throws when none. */
|
|
23
|
+
export declare function selectPublicAddresses(addresses: ResolvedAddress[]): ResolvedAddress;
|
|
24
|
+
/**
|
|
25
|
+
* Manifest allowlist: exact entry or `*.suffix.com` (subdomains — the apex
|
|
26
|
+
* needs its own entry). Empty/absent list = any host (advertising is still
|
|
27
|
+
* guaranteed by IP validation).
|
|
28
|
+
*/
|
|
29
|
+
export declare function isAllowedHost(hostname: string, allowHosts?: string[]): boolean;
|
|
30
|
+
type Resolver = (hostname: string) => Promise<ResolvedAddress[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Lookup "puro" usado pelo undici Agent: resolve E valida no MESMO passo —
|
|
33
|
+
* the returned IP is exactly what the connection uses (real pinning, no
|
|
34
|
+
* de rebinding).
|
|
35
|
+
*/
|
|
36
|
+
export declare function createSafeLookup(resolve?: Resolver): (hostname: string, _options: unknown, callback: (err: NodeJS.ErrnoException | null, address?: string | never, family?: number) => void) => void;
|
|
37
|
+
/** Dispatcher compartilhado com lookup validado (pinning). */
|
|
38
|
+
export declare function getSafeAgent(): Agent;
|
|
39
|
+
/** Validates a target before touching the network (scheme + allowlist + public DNS). */
|
|
40
|
+
export declare function validateTargetUrl(rawUrl: string, allowHosts?: string[]): Promise<URL>;
|
|
41
|
+
export interface HttpApiConfig {
|
|
42
|
+
/** Allowlist estrita do manifesto (httpPolicy.allowHosts). */
|
|
43
|
+
allowHosts?: string[];
|
|
44
|
+
/** Permission gate (http:outbound) — injected by the PluginAPI factory. */
|
|
45
|
+
requirePermission: (permission: string) => void;
|
|
46
|
+
}
|
|
47
|
+
export declare function createHttpApi(config: HttpApiConfig): PluginHttpApi;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAe,KAAK,aAAa,EAAmD,MAAM,yBAAyB,CAAC;AAE3H,eAAO,MAAM,kBAAkB,QAAS,CAAC;AACzC,eAAO,MAAM,cAAc,QAAS,CAAC;AACrC,eAAO,MAAM,iBAAiB,QAAkB,CAAC;AACjD,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,gDAAgD;AAChD,qBAAa,SAAU,SAAQ,KAAK;IAGhC,QAAQ,CAAC,SAAS,EAAE,OAAO;gBAD3B,OAAO,EAAE,MAAM,EACN,SAAS,EAAE,OAAO;CAK9B;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAoBhD;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAkBhD;AAED,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,eAAe,CASnF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAY9E;AAED,KAAK,QAAQ,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;AAQjE;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,QAA0B,cAEtD,MAAM,YACN,OAAO,YACP,CAAC,GAAG,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,KAC/F,IAAI,CAeR;AAID,8DAA8D;AAC9D,wBAAgB,YAAY,IAAI,KAAK,CAUpC;AAED,wFAAwF;AACxF,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAmC3F;AAwGD,MAAM,WAAW,aAAa;IAC5B,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,2EAA2E;IAC3E,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAyClE"}
|
package/dist/http.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
// @oktis-works/plugin-runtime - api.http: cliente HTTP externo anti-SSRF
|
|
2
|
+
//
|
|
3
|
+
// Item 4 do plugin-parity-plan (+ Item 16 egress isolation). Camadas:
|
|
4
|
+
//
|
|
5
|
+
// 1. allowlist `httpPolicy.allowHosts` do manifesto (quando declarada);
|
|
6
|
+
// 2. apenas scheme http/https;
|
|
7
|
+
// 3. DNS pre-validation per HOP — EVERY resolved IP must be
|
|
8
|
+
// public (blocks RFC1918, loopback, link-local 169.254.169.254 =
|
|
9
|
+
// metadata de cloud, CGNAT, multicast, ULA/link-local IPv6);
|
|
10
|
+
// 4. DNS pinning: o dispatcher (undici Agent) conecta exatamente no IP
|
|
11
|
+
// validado (elimina a janela de DNS rebinding entre lookup e connect);
|
|
12
|
+
// 5. `manual` redirects with re-validation on every hop (max 3);
|
|
13
|
+
// 6. timeout por tentativa e teto de corpo;
|
|
14
|
+
// 7. retries only on network errors/5xx (GET/HEAD by default).
|
|
15
|
+
//
|
|
16
|
+
// Fail-closed: DNS that fails or resolves to a non-public IP NEVER lets the
|
|
17
|
+
// request through, even if the runtime fetch ignored the dispatcher (Bun).
|
|
18
|
+
import { promises as dnsPromises } from 'node:dns';
|
|
19
|
+
import { Agent } from 'undici';
|
|
20
|
+
import { PERMISSIONS } from '@oktis-works/plugin-sdk';
|
|
21
|
+
export const DEFAULT_TIMEOUT_MS = 10_000;
|
|
22
|
+
export const MAX_TIMEOUT_MS = 60_000;
|
|
23
|
+
export const DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
|
|
24
|
+
export const MAX_REDIRECTS = 3;
|
|
25
|
+
/** Erro de api.http com flag de retentativa. */
|
|
26
|
+
export class HttpError extends Error {
|
|
27
|
+
retriable;
|
|
28
|
+
constructor(message, retriable) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.retriable = retriable;
|
|
31
|
+
this.name = 'HttpError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Is the IPv4 publicly routable? Fail-closed on any special/reserved range. */
|
|
35
|
+
export function isPublicIpv4(ip) {
|
|
36
|
+
const parts = ip.split('.');
|
|
37
|
+
if (parts.length !== 4)
|
|
38
|
+
return false;
|
|
39
|
+
const octets = parts.map((part) => Number(part));
|
|
40
|
+
if (octets.some((octet) => !Number.isInteger(octet) || octet < 0 || octet > 255))
|
|
41
|
+
return false;
|
|
42
|
+
const a = octets[0] ?? 0;
|
|
43
|
+
const b = octets[1] ?? 0;
|
|
44
|
+
const c = octets[2] ?? 0;
|
|
45
|
+
if (a === 0)
|
|
46
|
+
return false; // 0.0.0.0/8 "este host"
|
|
47
|
+
if (a === 10)
|
|
48
|
+
return false; // RFC1918
|
|
49
|
+
if (a === 127)
|
|
50
|
+
return false; // loopback
|
|
51
|
+
if (a === 169 && b === 254)
|
|
52
|
+
return false; // link-local = metadata cloud (169.254.169.254)
|
|
53
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
54
|
+
return false; // RFC1918
|
|
55
|
+
if (a === 192 && b === 168)
|
|
56
|
+
return false; // RFC1918
|
|
57
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
58
|
+
return false; // CGNAT RFC6598
|
|
59
|
+
if (a === 192 && b === 0 && c === 0)
|
|
60
|
+
return false; // RFC6890 IETF
|
|
61
|
+
if (a === 198 && (b === 18 || b === 19))
|
|
62
|
+
return false; // benchmark RFC2544
|
|
63
|
+
if (a >= 224)
|
|
64
|
+
return false; // multicast (224/4) + broadcast/reservado (240/4)
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
/** Is the IPv6 publicly routable? Fail-closed: only 2000::/3 (global unicast). */
|
|
68
|
+
export function isPublicIpv6(ip) {
|
|
69
|
+
const bare = (ip.split('%')[0] ?? '').toLowerCase();
|
|
70
|
+
if (bare === '::' || bare === '::1')
|
|
71
|
+
return false;
|
|
72
|
+
// IPv4-mapped ::ffff:a.b.c.d → aplica as regras de IPv4
|
|
73
|
+
const mapped = /^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/.exec(bare);
|
|
74
|
+
if (mapped?.[1])
|
|
75
|
+
return isPublicIpv4(mapped[1]);
|
|
76
|
+
// leading '::' compression outside mapped → special/deprecated → blocked
|
|
77
|
+
if (bare.startsWith('::'))
|
|
78
|
+
return false;
|
|
79
|
+
const firstBlock = bare.split(':')[0] ?? '';
|
|
80
|
+
if (firstBlock.includes('.'))
|
|
81
|
+
return false; // v4-suffix not handled above
|
|
82
|
+
const hextet = Number.parseInt(firstBlock, 16);
|
|
83
|
+
if (Number.isNaN(hextet))
|
|
84
|
+
return false;
|
|
85
|
+
// 2000::/3 = the only assigned global unicast block
|
|
86
|
+
return hextet >= 0x2000 && hextet <= 0x3fff;
|
|
87
|
+
}
|
|
88
|
+
/** Any non-public IP in the list → false. */
|
|
89
|
+
export function isPublicIp(ip) {
|
|
90
|
+
return ip.includes(':') ? isPublicIpv6(ip) : isPublicIpv4(ip);
|
|
91
|
+
}
|
|
92
|
+
/** Picks the first public address (for pinning). Throws when none. */
|
|
93
|
+
export function selectPublicAddresses(addresses) {
|
|
94
|
+
const safe = addresses.find((entry) => isPublicIp(entry.address));
|
|
95
|
+
if (!safe) {
|
|
96
|
+
throw new HttpError(`host resolves only to non-public address(es): ${addresses.map((entry) => entry.address).join(', ')}`, false);
|
|
97
|
+
}
|
|
98
|
+
return safe;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Manifest allowlist: exact entry or `*.suffix.com` (subdomains — the apex
|
|
102
|
+
* needs its own entry). Empty/absent list = any host (advertising is still
|
|
103
|
+
* guaranteed by IP validation).
|
|
104
|
+
*/
|
|
105
|
+
export function isAllowedHost(hostname, allowHosts) {
|
|
106
|
+
if (!allowHosts || allowHosts.length === 0)
|
|
107
|
+
return true;
|
|
108
|
+
const host = hostname.toLowerCase().replace(/^\[|\]$/g, '');
|
|
109
|
+
return allowHosts.some((entry) => {
|
|
110
|
+
const pattern = entry.trim().toLowerCase();
|
|
111
|
+
if (!pattern)
|
|
112
|
+
return false;
|
|
113
|
+
if (pattern.startsWith('*.')) {
|
|
114
|
+
const suffix = pattern.slice(1); // ".sufixo.com"
|
|
115
|
+
return host.endsWith(suffix) && host.length > suffix.length;
|
|
116
|
+
}
|
|
117
|
+
return host === pattern;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
const defaultResolver = async (hostname) => {
|
|
121
|
+
const bare = hostname.replace(/^\[|\]$/g, '');
|
|
122
|
+
const addresses = await dnsPromises.lookup(bare, { all: true, verbatim: true });
|
|
123
|
+
return addresses.map((entry) => ({ address: entry.address, family: entry.family }));
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Lookup "puro" usado pelo undici Agent: resolve E valida no MESMO passo —
|
|
127
|
+
* the returned IP is exactly what the connection uses (real pinning, no
|
|
128
|
+
* de rebinding).
|
|
129
|
+
*/
|
|
130
|
+
export function createSafeLookup(resolve = defaultResolver) {
|
|
131
|
+
return (hostname, _options, callback) => {
|
|
132
|
+
resolve(hostname).then((addresses) => {
|
|
133
|
+
try {
|
|
134
|
+
const safe = selectPublicAddresses(addresses);
|
|
135
|
+
callback(null, safe.address, safe.family);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
callback(error);
|
|
139
|
+
}
|
|
140
|
+
}, (error) => {
|
|
141
|
+
callback(error);
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
let sharedAgent = null;
|
|
146
|
+
/** Dispatcher compartilhado com lookup validado (pinning). */
|
|
147
|
+
export function getSafeAgent() {
|
|
148
|
+
if (!sharedAgent) {
|
|
149
|
+
sharedAgent = new Agent({
|
|
150
|
+
connect: {
|
|
151
|
+
// Signature compatible with net.LookupFunction via a structural cast
|
|
152
|
+
lookup: createSafeLookup(),
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return sharedAgent;
|
|
157
|
+
}
|
|
158
|
+
/** Validates a target before touching the network (scheme + allowlist + public DNS). */
|
|
159
|
+
export async function validateTargetUrl(rawUrl, allowHosts) {
|
|
160
|
+
let url;
|
|
161
|
+
try {
|
|
162
|
+
url = new URL(rawUrl);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
throw new HttpError(`invalid URL: ${rawUrl}`, false);
|
|
166
|
+
}
|
|
167
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
168
|
+
throw new HttpError(`scheme not allowed: ${url.protocol}`, false);
|
|
169
|
+
}
|
|
170
|
+
if (!isAllowedHost(url.hostname, allowHosts)) {
|
|
171
|
+
throw new HttpError(`host "${url.hostname}" is not in httpPolicy.allowHosts`, false);
|
|
172
|
+
}
|
|
173
|
+
let addresses;
|
|
174
|
+
try {
|
|
175
|
+
addresses = await defaultResolver(url.hostname);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
throw new HttpError(`DNS resolution failed for ${url.hostname}: ${error instanceof Error ? error.message : String(error)}`, false);
|
|
179
|
+
}
|
|
180
|
+
if (addresses.length === 0) {
|
|
181
|
+
throw new HttpError(`no addresses for ${url.hostname}`, false);
|
|
182
|
+
}
|
|
183
|
+
// EVERY IP must be public (round-robin with one private IP is also blocked)
|
|
184
|
+
const unsafe = addresses.filter((entry) => !isPublicIp(entry.address));
|
|
185
|
+
if (unsafe.length > 0) {
|
|
186
|
+
throw new HttpError(`host ${url.hostname} resolves to non-public address(es): ${unsafe.map((entry) => entry.address).join(', ')}`, false);
|
|
187
|
+
}
|
|
188
|
+
return url;
|
|
189
|
+
}
|
|
190
|
+
async function readBodyCapped(response, maxBytes) {
|
|
191
|
+
if (!response.body)
|
|
192
|
+
return '';
|
|
193
|
+
const reader = response.body.getReader();
|
|
194
|
+
const chunks = [];
|
|
195
|
+
let total = 0;
|
|
196
|
+
try {
|
|
197
|
+
for (;;) {
|
|
198
|
+
const { done, value } = await reader.read();
|
|
199
|
+
if (done)
|
|
200
|
+
break;
|
|
201
|
+
if (value) {
|
|
202
|
+
total += value.byteLength;
|
|
203
|
+
if (total > maxBytes) {
|
|
204
|
+
await reader.cancel().catch(() => undefined);
|
|
205
|
+
throw new HttpError(`response body exceeds limit of ${maxBytes} bytes`, false);
|
|
206
|
+
}
|
|
207
|
+
chunks.push(value);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
reader.releaseLock();
|
|
213
|
+
}
|
|
214
|
+
const merged = Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)));
|
|
215
|
+
return merged.toString('utf8');
|
|
216
|
+
}
|
|
217
|
+
async function readResponse(response, maxBytes) {
|
|
218
|
+
const body = await readBodyCapped(response, maxBytes);
|
|
219
|
+
const headers = {};
|
|
220
|
+
response.headers.forEach((value, key) => {
|
|
221
|
+
headers[key.toLowerCase()] = value;
|
|
222
|
+
});
|
|
223
|
+
return {
|
|
224
|
+
status: response.status,
|
|
225
|
+
ok: response.ok,
|
|
226
|
+
headers,
|
|
227
|
+
body,
|
|
228
|
+
json() {
|
|
229
|
+
return JSON.parse(body);
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/** Executa a cadeia de redirects (cada hop revalidado) — 1 tentativa. */
|
|
234
|
+
async function runRedirects(rawUrl, allowHosts, config) {
|
|
235
|
+
let currentUrl = rawUrl;
|
|
236
|
+
let method = config.method;
|
|
237
|
+
let body = config.body;
|
|
238
|
+
for (let hop = 0; hop <= MAX_REDIRECTS; hop += 1) {
|
|
239
|
+
const target = await validateTargetUrl(currentUrl, allowHosts);
|
|
240
|
+
const fetchInit = {
|
|
241
|
+
method,
|
|
242
|
+
headers: config.headers,
|
|
243
|
+
body: method === 'GET' || method === 'HEAD' ? undefined : body,
|
|
244
|
+
redirect: 'manual',
|
|
245
|
+
signal: AbortSignal.timeout(config.timeoutMs),
|
|
246
|
+
// Node/undici: conecta no IP validado (pinning). Runtimes que ignoram
|
|
247
|
+
// `dispatcher` (Bun) remain protected by the pre-validation above.
|
|
248
|
+
dispatcher: getSafeAgent(),
|
|
249
|
+
};
|
|
250
|
+
const response = await fetch(target.toString(), fetchInit);
|
|
251
|
+
if (response.status >= 300 && response.status < 400) {
|
|
252
|
+
const location = response.headers.get('location');
|
|
253
|
+
if (!location)
|
|
254
|
+
return readResponse(response, config.maxBytes);
|
|
255
|
+
if (hop === MAX_REDIRECTS) {
|
|
256
|
+
throw new HttpError(`too many redirects (max ${MAX_REDIRECTS})`, false);
|
|
257
|
+
}
|
|
258
|
+
// Libera o corpo do redirect sem consumir
|
|
259
|
+
await response.body?.cancel().catch(() => undefined);
|
|
260
|
+
currentUrl = new URL(location, target).toString();
|
|
261
|
+
if (response.status === 303 ||
|
|
262
|
+
((response.status === 301 || response.status === 302) && method === 'POST')) {
|
|
263
|
+
method = 'GET';
|
|
264
|
+
body = undefined;
|
|
265
|
+
}
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
268
|
+
return readResponse(response, config.maxBytes);
|
|
269
|
+
}
|
|
270
|
+
throw new HttpError(`too many redirects (max ${MAX_REDIRECTS})`, false);
|
|
271
|
+
}
|
|
272
|
+
export function createHttpApi(config) {
|
|
273
|
+
async function request(rawUrl, options = {}) {
|
|
274
|
+
config.requirePermission(PERMISSIONS.HTTP_OUTBOUND);
|
|
275
|
+
const method = (options.method ?? 'GET').toUpperCase();
|
|
276
|
+
const timeoutMs = Math.min(Math.max(options.timeoutMs ?? DEFAULT_TIMEOUT_MS, 1), MAX_TIMEOUT_MS);
|
|
277
|
+
const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
|
|
278
|
+
const retries = options.retries ?? (method === 'GET' || method === 'HEAD' ? 2 : 0);
|
|
279
|
+
const attemptConfig = {
|
|
280
|
+
method,
|
|
281
|
+
headers: options.headers,
|
|
282
|
+
body: options.body,
|
|
283
|
+
timeoutMs,
|
|
284
|
+
maxBytes,
|
|
285
|
+
};
|
|
286
|
+
let lastError;
|
|
287
|
+
for (let attempt = 0; attempt <= retries; attempt += 1) {
|
|
288
|
+
try {
|
|
289
|
+
const response = await runRedirects(rawUrl, config.allowHosts, attemptConfig);
|
|
290
|
+
if (response.status >= 500 && attempt < retries) {
|
|
291
|
+
lastError = new HttpError(`upstream ${response.status}`, true);
|
|
292
|
+
await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt));
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
return response;
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
lastError = error;
|
|
299
|
+
const retriable = error instanceof HttpError ? error.retriable : true; // rede/timeout
|
|
300
|
+
if (!retriable || attempt >= retries)
|
|
301
|
+
break;
|
|
302
|
+
await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
request,
|
|
309
|
+
get: (url, options) => request(url, { ...options, method: 'GET' }),
|
|
310
|
+
post: (url, body, options) => request(url, { ...options, method: 'POST', body }),
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PluginManifest, PluginI18nApi } from '@oktis-works/plugin-sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Fallback chain for a locale: `pt-BR` → [`pt-BR`, `pt`, `en`];
|
|
4
|
+
* `en` → [`en`]; `fr` → [`fr`, `en`]. Duplicates removed.
|
|
5
|
+
*/
|
|
6
|
+
export declare function i18nFallbackChain(locale: string): string[];
|
|
7
|
+
/** Replaces `{token}` placeholders with stringified params (missing → kept). */
|
|
8
|
+
export declare function i18nInterpolate(template: string, params?: Record<string, unknown>): string;
|
|
9
|
+
/**
|
|
10
|
+
* Loads manifest `locales[]` JSON files (flat key/value) into the plugin's
|
|
11
|
+
* i18n store. The filename defines the locale (`locales/pt-BR.json` →
|
|
12
|
+
* `pt-BR`). Malformed/out-of-tree files are skipped — never breaks boot.
|
|
13
|
+
* Returns the number of successfully loaded files.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadPluginLocales(pluginDir: string, manifest: PluginManifest, i18n: PluginI18nApi): Promise<number>;
|
|
16
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7E;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAU1D;AAED,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAM1F;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// @oktis-works/plugin-runtime - Plugin i18n helpers (Item 9 do plugin-parity-plan)
|
|
2
|
+
//
|
|
3
|
+
// Server-side translations for plugins:
|
|
4
|
+
// - `api.i18n.load(locale, bundle)` merges flat { key: string } bundles;
|
|
5
|
+
// - `api.i18n.translate(key, params?, locale?)` resolves through the
|
|
6
|
+
// fallback chain (requested locale → base language → 'en' → key) with
|
|
7
|
+
// {param} interpolation;
|
|
8
|
+
// - manifest `locales[]` JSON files (flat key/value) are loaded at boot.
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
/**
|
|
12
|
+
* Fallback chain for a locale: `pt-BR` → [`pt-BR`, `pt`, `en`];
|
|
13
|
+
* `en` → [`en`]; `fr` → [`fr`, `en`]. Duplicates removed.
|
|
14
|
+
*/
|
|
15
|
+
export function i18nFallbackChain(locale) {
|
|
16
|
+
const chain = [];
|
|
17
|
+
const push = (value) => {
|
|
18
|
+
if (value && !chain.includes(value))
|
|
19
|
+
chain.push(value);
|
|
20
|
+
};
|
|
21
|
+
push(locale);
|
|
22
|
+
const base = locale.split('-')[0];
|
|
23
|
+
if (base)
|
|
24
|
+
push(base);
|
|
25
|
+
push('en');
|
|
26
|
+
return chain;
|
|
27
|
+
}
|
|
28
|
+
/** Replaces `{token}` placeholders with stringified params (missing → kept). */
|
|
29
|
+
export function i18nInterpolate(template, params) {
|
|
30
|
+
if (!params || typeof params !== 'object')
|
|
31
|
+
return template;
|
|
32
|
+
return template.replace(/\{([a-zA-Z0-9_]+)\}/g, (match, token) => {
|
|
33
|
+
const value = params[token];
|
|
34
|
+
return value === undefined || value === null ? match : String(value);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Loads manifest `locales[]` JSON files (flat key/value) into the plugin's
|
|
39
|
+
* i18n store. The filename defines the locale (`locales/pt-BR.json` →
|
|
40
|
+
* `pt-BR`). Malformed/out-of-tree files are skipped — never breaks boot.
|
|
41
|
+
* Returns the number of successfully loaded files.
|
|
42
|
+
*/
|
|
43
|
+
export async function loadPluginLocales(pluginDir, manifest, i18n) {
|
|
44
|
+
const files = manifest.locales;
|
|
45
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
46
|
+
return 0;
|
|
47
|
+
let loaded = 0;
|
|
48
|
+
for (const relative of files) {
|
|
49
|
+
if (typeof relative !== 'string' || relative.includes('..') || relative.startsWith('/'))
|
|
50
|
+
continue;
|
|
51
|
+
try {
|
|
52
|
+
const raw = await readFile(join(pluginDir, relative), 'utf8');
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
55
|
+
continue;
|
|
56
|
+
const locale = relative.replace(/\.json$/, '').split('/').pop() ?? '';
|
|
57
|
+
if (!locale)
|
|
58
|
+
continue;
|
|
59
|
+
const bundle = {};
|
|
60
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
61
|
+
if (typeof value === 'string')
|
|
62
|
+
bundle[key] = value;
|
|
63
|
+
}
|
|
64
|
+
i18n.load(locale, bundle);
|
|
65
|
+
loaded += 1;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// malformed locale file — skip (translation falls back to the key)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return loaded;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=i18n.js.map
|
package/dist/i18n.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,9 @@ export { readPluginManifest, normalizePluginManifest } from './manifest.js';
|
|
|
6
6
|
export type { ManifestSource, ReadManifestResult } from './manifest.js';
|
|
7
7
|
export { HookRegistry, HookRegistryStore, getHookRegistry, getHookRegistryStore, setHookRegistry, setHookRegistryStore, setHookTenantResolver, getCurrentHookTenantId, } from './hook-registry.js';
|
|
8
8
|
export type { AddHookOptions, AuditLogEntry, HookCallback } from './hook-registry.js';
|
|
9
|
-
export { bootstrapPlugins, resetLoadedPlugins, listLoadedScopes, unloadScope, unloadTenant, getLoadedPluginRoutes } from './bootstrap.js';
|
|
9
|
+
export { bootstrapPlugins, resetLoadedPlugins, listLoadedScopes, unloadScope, unloadTenant, getLoadedPluginRoutes, getLoadedPluginJobHandlers } from './bootstrap.js';
|
|
10
10
|
export type { BootstrapPluginsOptions, BootstrapPluginsSql, PluginBootstrapResult, } from './bootstrap.js';
|
|
11
11
|
export { createPluginApi, type PluginAPI, type PluginContext, type RouteDefinition, type TenantInfo, type UserInfo, type PluginApiDependencies, type PluginApiInternal, } from './plugin-api.js';
|
|
12
|
+
export type { PluginFieldTypeManifest } from '@oktis-works/plugin-sdk';
|
|
12
13
|
export { scopePluginCss, getPluginScopeAttribute, wrapWithPluginScope, lintPluginCss, } from './style-isolation.js';
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC5E,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AACtK,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,eAAe,EACf,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,GACd,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { PluginSandbox } from './sandbox.js';
|
|
|
2
2
|
export { PluginLoader } from './loader.js';
|
|
3
3
|
export { readPluginManifest, normalizePluginManifest } from './manifest.js';
|
|
4
4
|
export { HookRegistry, HookRegistryStore, getHookRegistry, getHookRegistryStore, setHookRegistry, setHookRegistryStore, setHookTenantResolver, getCurrentHookTenantId, } from './hook-registry.js';
|
|
5
|
-
export { bootstrapPlugins, resetLoadedPlugins, listLoadedScopes, unloadScope, unloadTenant, getLoadedPluginRoutes } from './bootstrap.js';
|
|
5
|
+
export { bootstrapPlugins, resetLoadedPlugins, listLoadedScopes, unloadScope, unloadTenant, getLoadedPluginRoutes, getLoadedPluginJobHandlers } from './bootstrap.js';
|
|
6
6
|
export { createPluginApi, } from './plugin-api.js';
|
|
7
7
|
export { scopePluginCss, getPluginScopeAttribute, wrapWithPluginScope, lintPluginCss, } from './style-isolation.js';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE5E,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE5E,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAMtK,OAAO,EACL,eAAe,GAQhB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,GACd,MAAM,sBAAsB,CAAC"}
|
package/dist/loader.js
CHANGED
|
@@ -23,10 +23,10 @@ export class PluginLoader {
|
|
|
23
23
|
return plugins;
|
|
24
24
|
}
|
|
25
25
|
async loadPlugin(manifest, pluginPath) {
|
|
26
|
-
// RULE-semver-compatibility:
|
|
26
|
+
// RULE-semver-compatibility: the compatibility.okcms range must satisfy the CMS version
|
|
27
27
|
const compat = manifest.compatibility?.okcms;
|
|
28
28
|
if (typeof compat === 'string' && validRange(compat) && !satisfies(CMS_VERSION, compat)) {
|
|
29
|
-
throw new Error(`Plugin "${manifest.name}"
|
|
29
|
+
throw new Error(`Plugin "${manifest.name}" requires OkCMS ${compat}, but the current version is ${CMS_VERSION}`);
|
|
30
30
|
}
|
|
31
31
|
const entryPath = resolve(join(pluginPath, manifest.main));
|
|
32
32
|
if (!entryPath.startsWith(this.pluginsDir)) {
|
|
@@ -109,7 +109,7 @@ export class PluginLoader {
|
|
|
109
109
|
return result.length > 0 ? result : [0];
|
|
110
110
|
}
|
|
111
111
|
async loadManifest(pluginPath) {
|
|
112
|
-
//
|
|
112
|
+
// Single source (WP6): the canonical `manifest.json` wins over `package.json` (npm).
|
|
113
113
|
// Antes a ordem era inversa — um plugin com ambos os arquivos era lido de
|
|
114
114
|
// um jeito no loader e de outro no sync/CLI.
|
|
115
115
|
const { manifest } = await readPluginManifest(pluginPath);
|
package/dist/loader.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAOnD,MAAM,OAAO,YAAY;IACf,UAAU,CAAS;IAE3B,YAAY,UAAkB;QAC5B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,SAAS;YACnC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YACrD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;YACrD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAwB,EAAE,UAAkB;QAC3D,
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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"}
|
package/dist/manifest.d.ts
CHANGED
|
@@ -3,22 +3,27 @@ export type ManifestSource = 'manifest.json' | 'package.json';
|
|
|
3
3
|
export interface ReadManifestResult {
|
|
4
4
|
manifest: PluginManifest | null;
|
|
5
5
|
source: ManifestSource | null;
|
|
6
|
-
/**
|
|
6
|
+
/** Found issues (the rejection reason when `manifest` is null). */
|
|
7
7
|
issues: string[];
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Valida os campos do schema v2 (tudo opcional — um manifesto v1 continua
|
|
11
|
+
* valid). Returns the found issues; empty = valid.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateManifestV2(merged: Record<string, unknown>): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Reads a plugin directory's manifest with a single precedence rule.
|
|
11
16
|
*
|
|
12
|
-
* @param dir
|
|
17
|
+
* @param dir the plugin directory
|
|
13
18
|
* @param options.strict exige `main` e valida `type === 'plugin'` quando
|
|
14
|
-
*
|
|
19
|
+
* declared (used by sync/install/CLI)
|
|
15
20
|
*/
|
|
16
21
|
export declare function readPluginManifest(dir: string, options?: {
|
|
17
22
|
strict?: boolean;
|
|
18
23
|
}): Promise<ReadManifestResult>;
|
|
19
24
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
25
|
+
* Normalizes the manifest for database storage (keeps only known fields,
|
|
26
|
+
* preserving the author's legitimate extra fields).
|
|
22
27
|
*/
|
|
23
28
|
export declare function normalizePluginManifest(manifest: PluginManifest): Record<string, unknown>;
|
|
24
29
|
//# sourceMappingURL=manifest.d.ts.map
|
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAG9D,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,cAAc,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,mEAAmE;IACnE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAUD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAmM5E;AAYD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,OAAO,CAAC,kBAAkB,CAAC,CAiD7B;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzF"}
|