@giveitsmaller/sdk 0.4.0 → 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/_audit.js +67 -0
- package/dist/builder.d.ts +406 -0
- package/dist/builder.js +706 -0
- package/dist/client.d.ts +96 -2
- package/dist/client.js +968 -33
- package/dist/credentials.d.ts +61 -0
- package/dist/credentials.js +200 -0
- package/dist/ergonomic/preset_resolver.d.ts +75 -0
- package/dist/ergonomic/preset_resolver.js +568 -0
- package/dist/ergonomic/presets/_translate.d.ts +11 -0
- package/dist/ergonomic/presets/_translate.js +35 -0
- package/dist/ergonomic/presets/audio_compress.d.ts +16 -0
- package/dist/ergonomic/presets/audio_compress.js +45 -0
- package/dist/ergonomic/presets/document_epub_compress.d.ts +14 -0
- package/dist/ergonomic/presets/document_epub_compress.js +34 -0
- package/dist/ergonomic/presets/document_odf_compress.d.ts +14 -0
- package/dist/ergonomic/presets/document_odf_compress.js +34 -0
- package/dist/ergonomic/presets/document_office_compress.d.ts +16 -0
- package/dist/ergonomic/presets/document_office_compress.js +40 -0
- package/dist/ergonomic/presets/document_pdf_compress.d.ts +14 -0
- package/dist/ergonomic/presets/document_pdf_compress.js +35 -0
- package/dist/ergonomic/presets/image_compress.d.ts +43 -0
- package/dist/ergonomic/presets/image_compress.js +95 -0
- package/dist/ergonomic/presets/index.d.ts +77 -0
- package/dist/ergonomic/presets/index.js +216 -0
- package/dist/ergonomic/presets/video_compress.d.ts +30 -0
- package/dist/ergonomic/presets/video_compress.js +83 -0
- package/dist/errors.d.ts +251 -1
- package/dist/errors.js +268 -0
- package/dist/generated/sdk_spec/enums.d.ts +195 -0
- package/dist/generated/sdk_spec/enums.js +127 -0
- package/dist/generated/sdk_spec/errors.d.ts +16 -0
- package/dist/generated/sdk_spec/errors.js +473 -0
- package/dist/generated/sdk_spec/index.d.ts +4 -0
- package/dist/generated/sdk_spec/index.js +7 -0
- package/dist/generated/sdk_spec/presets.d.ts +6 -0
- package/dist/generated/sdk_spec/presets.js +157 -0
- package/dist/generated/sdk_spec/version.d.ts +3 -0
- package/dist/generated/sdk_spec/version.js +6 -0
- package/dist/gisl.d.ts +112 -0
- package/dist/gisl.js +266 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.js +33 -3
- package/dist/merge.d.ts +142 -0
- package/dist/merge.js +411 -0
- package/dist/sse.d.ts +20 -1
- package/dist/sse.js +62 -3
- package/dist/types.d.ts +144 -14
- package/dist/types.js +18 -0
- package/package.json +2 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential + endpoint resolution for the ergonomic-layer `gisl.create()`
|
|
3
|
+
* factory. Implements an AWS-style short-circuiting chain:
|
|
4
|
+
* API key: explicit arg → `GISL_API_KEY` env → `~/.gisl/credentials` profile
|
|
5
|
+
* Endpoint: explicit arg → `GISL_ENVIRONMENT` / `GISL_BASE_URL` env → prod default
|
|
6
|
+
*
|
|
7
|
+
* Sources are tried in order; the first hit wins. Malformed profile files
|
|
8
|
+
* surface as `GislConfigError` naming the offending profile (NEVER the value
|
|
9
|
+
* — credential values must not appear in error messages).
|
|
10
|
+
*
|
|
11
|
+
* Browser-safe: profile-file lookups dynamic-import `node:fs/promises` only
|
|
12
|
+
* when a profile path is requested AND a Node runtime is detected; missing
|
|
13
|
+
* fs in the browser yields the typed
|
|
14
|
+
* `GislConfigError('profile_unavailable_in_runtime')`.
|
|
15
|
+
*/
|
|
16
|
+
export declare const GISL_API_KEY_ENV = "GISL_API_KEY";
|
|
17
|
+
export declare const GISL_BASE_URL_ENV = "GISL_BASE_URL";
|
|
18
|
+
export declare const GISL_ENVIRONMENT_ENV = "GISL_ENVIRONMENT";
|
|
19
|
+
/**
|
|
20
|
+
* Named environments → base URLs. Kept colocated with the resolver so the
|
|
21
|
+
* mapping table doesn't leak into `gisl.ts`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const ENVIRONMENT_ENDPOINTS: {
|
|
24
|
+
readonly prod: "https://api.giveitsmaller.com";
|
|
25
|
+
readonly staging: "https://api.staging.giveitsmaller.com";
|
|
26
|
+
};
|
|
27
|
+
export type Environment = keyof typeof ENVIRONMENT_ENDPOINTS;
|
|
28
|
+
export declare const DEFAULT_ENDPOINT: "https://api.giveitsmaller.com";
|
|
29
|
+
export interface ResolveCredentialsOptions {
|
|
30
|
+
/** Explicit API key — highest precedence. */
|
|
31
|
+
readonly apiKey?: string;
|
|
32
|
+
/** Profile name from `~/.gisl/credentials`. Default: `'default'`. */
|
|
33
|
+
readonly profile?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Cookie-mode flag. When `true`, the caller is authenticating via
|
|
36
|
+
* session cookie (browser SPA flow) and a missing apiKey is NOT a
|
|
37
|
+
* configuration error — `resolveApiKey` returns `null` without
|
|
38
|
+
* throwing, and the ergonomic-layer factory accepts it.
|
|
39
|
+
*/
|
|
40
|
+
readonly useSessionCookie?: boolean;
|
|
41
|
+
/** Override the profile-file path (testing). */
|
|
42
|
+
readonly profilePath?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ResolveEndpointOptions {
|
|
45
|
+
readonly baseUrl?: string;
|
|
46
|
+
readonly environment?: Environment;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve the API key via the credential chain. Returns the resolved key,
|
|
50
|
+
* or `null` if no source produced one. The ergonomic-layer factory is
|
|
51
|
+
* responsible for deciding whether `null` is an error (default: yes, throw
|
|
52
|
+
* `GislMissingCredentialsError`) or acceptable (anonymous / cookie-mode).
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveApiKey(opts?: ResolveCredentialsOptions): Promise<string | null>;
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the base URL. Explicit `baseUrl` wins; otherwise an explicit
|
|
57
|
+
* `environment` name; otherwise the `GISL_BASE_URL` / `GISL_ENVIRONMENT`
|
|
58
|
+
* env vars; otherwise the prod default. Never throws — the chain always
|
|
59
|
+
* resolves to a usable URL.
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveEndpoint(opts?: ResolveEndpointOptions): string;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential + endpoint resolution for the ergonomic-layer `gisl.create()`
|
|
3
|
+
* factory. Implements an AWS-style short-circuiting chain:
|
|
4
|
+
* API key: explicit arg → `GISL_API_KEY` env → `~/.gisl/credentials` profile
|
|
5
|
+
* Endpoint: explicit arg → `GISL_ENVIRONMENT` / `GISL_BASE_URL` env → prod default
|
|
6
|
+
*
|
|
7
|
+
* Sources are tried in order; the first hit wins. Malformed profile files
|
|
8
|
+
* surface as `GislConfigError` naming the offending profile (NEVER the value
|
|
9
|
+
* — credential values must not appear in error messages).
|
|
10
|
+
*
|
|
11
|
+
* Browser-safe: profile-file lookups dynamic-import `node:fs/promises` only
|
|
12
|
+
* when a profile path is requested AND a Node runtime is detected; missing
|
|
13
|
+
* fs in the browser yields the typed
|
|
14
|
+
* `GislConfigError('profile_unavailable_in_runtime')`.
|
|
15
|
+
*/
|
|
16
|
+
import { GislConfigError } from './errors.js';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Environment constants
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
export const GISL_API_KEY_ENV = 'GISL_API_KEY';
|
|
21
|
+
export const GISL_BASE_URL_ENV = 'GISL_BASE_URL';
|
|
22
|
+
export const GISL_ENVIRONMENT_ENV = 'GISL_ENVIRONMENT';
|
|
23
|
+
/**
|
|
24
|
+
* Named environments → base URLs. Kept colocated with the resolver so the
|
|
25
|
+
* mapping table doesn't leak into `gisl.ts`.
|
|
26
|
+
*/
|
|
27
|
+
export const ENVIRONMENT_ENDPOINTS = {
|
|
28
|
+
prod: 'https://api.giveitsmaller.com',
|
|
29
|
+
staging: 'https://api.staging.giveitsmaller.com',
|
|
30
|
+
};
|
|
31
|
+
export const DEFAULT_ENDPOINT = ENVIRONMENT_ENDPOINTS.prod;
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Public resolvers
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the API key via the credential chain. Returns the resolved key,
|
|
37
|
+
* or `null` if no source produced one. The ergonomic-layer factory is
|
|
38
|
+
* responsible for deciding whether `null` is an error (default: yes, throw
|
|
39
|
+
* `GislMissingCredentialsError`) or acceptable (anonymous / cookie-mode).
|
|
40
|
+
*/
|
|
41
|
+
export async function resolveApiKey(opts = {}) {
|
|
42
|
+
// 1. Explicit wins.
|
|
43
|
+
if (typeof opts.apiKey === 'string' && opts.apiKey.length > 0) {
|
|
44
|
+
return opts.apiKey;
|
|
45
|
+
}
|
|
46
|
+
// 2. Environment variable.
|
|
47
|
+
const envKey = readEnv(GISL_API_KEY_ENV);
|
|
48
|
+
if (envKey !== null && envKey.length > 0) {
|
|
49
|
+
return envKey;
|
|
50
|
+
}
|
|
51
|
+
// 3. Shared-config profile (`~/.gisl/credentials`). Skipped silently
|
|
52
|
+
// when running in a non-Node runtime (browser, edge) — the resolver
|
|
53
|
+
// returns `null` and the caller decides whether that's fatal.
|
|
54
|
+
if (!isNodeRuntime()) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const profileName = opts.profile ?? 'default';
|
|
58
|
+
const profilePath = opts.profilePath ?? defaultProfilePath();
|
|
59
|
+
if (profilePath === null) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const profileEntries = await readProfile(profilePath, profileName);
|
|
63
|
+
if (profileEntries === null) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const profileKey = profileEntries.api_key;
|
|
67
|
+
if (typeof profileKey === 'string' && profileKey.length > 0) {
|
|
68
|
+
return profileKey;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve the base URL. Explicit `baseUrl` wins; otherwise an explicit
|
|
74
|
+
* `environment` name; otherwise the `GISL_BASE_URL` / `GISL_ENVIRONMENT`
|
|
75
|
+
* env vars; otherwise the prod default. Never throws — the chain always
|
|
76
|
+
* resolves to a usable URL.
|
|
77
|
+
*/
|
|
78
|
+
export function resolveEndpoint(opts = {}) {
|
|
79
|
+
if (typeof opts.baseUrl === 'string' && opts.baseUrl.length > 0) {
|
|
80
|
+
return opts.baseUrl;
|
|
81
|
+
}
|
|
82
|
+
if (typeof opts.environment === 'string') {
|
|
83
|
+
const explicitEnv = ENVIRONMENT_ENDPOINTS[opts.environment];
|
|
84
|
+
if (explicitEnv !== undefined) {
|
|
85
|
+
return explicitEnv;
|
|
86
|
+
}
|
|
87
|
+
// Codex r2 medium 23a17c1dbf75 — fail-closed on an unknown explicit
|
|
88
|
+
// environment name. A typo or JS-side caller previously silently fell
|
|
89
|
+
// through to env-var / prod default, which can mis-route a staging-
|
|
90
|
+
// intended request to production. The env-var path still allows
|
|
91
|
+
// unknown values to fall through (low-impact since it's an env config,
|
|
92
|
+
// not a code-level arg).
|
|
93
|
+
throw new GislConfigError(`Unknown environment '${opts.environment}'. Valid values: ${Object.keys(ENVIRONMENT_ENDPOINTS).join(', ')}.`);
|
|
94
|
+
}
|
|
95
|
+
const envBaseUrl = readEnv(GISL_BASE_URL_ENV);
|
|
96
|
+
if (envBaseUrl !== null && envBaseUrl.length > 0) {
|
|
97
|
+
return envBaseUrl;
|
|
98
|
+
}
|
|
99
|
+
const envEnvironment = readEnv(GISL_ENVIRONMENT_ENV);
|
|
100
|
+
if (envEnvironment !== null) {
|
|
101
|
+
const envMapped = ENVIRONMENT_ENDPOINTS[envEnvironment];
|
|
102
|
+
if (envMapped !== undefined) {
|
|
103
|
+
return envMapped;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return DEFAULT_ENDPOINT;
|
|
107
|
+
}
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// Internals
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
function isNodeRuntime() {
|
|
112
|
+
return (typeof process !== 'undefined' &&
|
|
113
|
+
process.versions !== undefined &&
|
|
114
|
+
typeof process.versions.node === 'string');
|
|
115
|
+
}
|
|
116
|
+
function readEnv(name) {
|
|
117
|
+
if (!isNodeRuntime()) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
const value = process.env[name];
|
|
121
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
122
|
+
}
|
|
123
|
+
function defaultProfilePath() {
|
|
124
|
+
const homeDir = readEnv('HOME') ?? readEnv('USERPROFILE');
|
|
125
|
+
if (homeDir === null) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
// Use forward-slash join — Node accepts it on every platform.
|
|
129
|
+
return `${homeDir}/.gisl/credentials`;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Read a single profile section from an INI-format credentials file.
|
|
133
|
+
* Returns `null` when the file does not exist; throws `GislConfigError`
|
|
134
|
+
* when the file exists but is malformed or the requested profile is
|
|
135
|
+
* absent. Never includes credential VALUES in error messages.
|
|
136
|
+
*/
|
|
137
|
+
async function readProfile(path, profileName) {
|
|
138
|
+
let raw;
|
|
139
|
+
try {
|
|
140
|
+
// Lazy import keeps `node:fs` out of browser bundles.
|
|
141
|
+
const fs = await import('node:fs/promises');
|
|
142
|
+
raw = await fs.readFile(path, 'utf8');
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
// ENOENT → no file = no credentials from this source (not an error).
|
|
146
|
+
const code = err.code;
|
|
147
|
+
if (code === 'ENOENT' || code === 'ENOTDIR') {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
throw new GislConfigError(`Failed to read shared credentials file at ${path}: ${code ?? 'unknown error'}`);
|
|
151
|
+
}
|
|
152
|
+
const parsed = parseIni(raw, path);
|
|
153
|
+
const entries = parsed[profileName];
|
|
154
|
+
if (entries === undefined) {
|
|
155
|
+
throw new GislConfigError(`Profile '${profileName}' not found in shared credentials file at ${path}`);
|
|
156
|
+
}
|
|
157
|
+
return entries;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Minimal INI parser sufficient for AWS-style credentials files: section
|
|
161
|
+
* headers `[name]`, `key = value` lines, `#` and `;` comments. Whitespace
|
|
162
|
+
* around `=` is trimmed. No nested sections, no interpolation, no quoting.
|
|
163
|
+
* Throws `GislConfigError` on malformed lines, naming only the LINE NUMBER
|
|
164
|
+
* and PROFILE — never the value.
|
|
165
|
+
*/
|
|
166
|
+
function parseIni(raw, sourcePath) {
|
|
167
|
+
const sections = {};
|
|
168
|
+
let currentSection = null;
|
|
169
|
+
const lines = raw.split(/\r?\n/);
|
|
170
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
171
|
+
const line = lines[i].trim();
|
|
172
|
+
if (line === '' || line.startsWith('#') || line.startsWith(';')) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (line.startsWith('[') && line.endsWith(']')) {
|
|
176
|
+
currentSection = line.slice(1, -1).trim();
|
|
177
|
+
if (currentSection === '') {
|
|
178
|
+
throw new GislConfigError(`Empty section header at line ${i + 1} in ${sourcePath}`);
|
|
179
|
+
}
|
|
180
|
+
if (sections[currentSection] === undefined) {
|
|
181
|
+
sections[currentSection] = {};
|
|
182
|
+
}
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (currentSection === null) {
|
|
186
|
+
throw new GislConfigError(`Key-value line at line ${i + 1} in ${sourcePath} is outside any section header`);
|
|
187
|
+
}
|
|
188
|
+
const eqIndex = line.indexOf('=');
|
|
189
|
+
if (eqIndex === -1) {
|
|
190
|
+
throw new GislConfigError(`Malformed line ${i + 1} in ${sourcePath} (expected key=value)`);
|
|
191
|
+
}
|
|
192
|
+
const key = line.slice(0, eqIndex).trim();
|
|
193
|
+
if (key === '') {
|
|
194
|
+
throw new GislConfigError(`Empty key at line ${i + 1} in ${sourcePath}`);
|
|
195
|
+
}
|
|
196
|
+
const value = line.slice(eqIndex + 1).trim();
|
|
197
|
+
sections[currentSection][key] = value;
|
|
198
|
+
}
|
|
199
|
+
return sections;
|
|
200
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ResolvedOptions } from '../builder.js';
|
|
2
|
+
import type { OptimizeFor } from '../generated/sdk_spec/enums.js';
|
|
3
|
+
import { type PresetDefaults, type PresetMedia, type PresetOp } from './presets/index.js';
|
|
4
|
+
/** Bumped on any change to a `*PresetOptions.shippedDefaultsFor(...)` cell value. */
|
|
5
|
+
export declare const PRESET_VERSION = "1.0";
|
|
6
|
+
/**
|
|
7
|
+
* Inputs to {@link resolveCompressOptions}. `media` selects which leaf
|
|
8
|
+
* DTO drives sdkDefault + clientDefault lookups + invalid-combo
|
|
9
|
+
* validations. `op` is currently always `'compress'`; future ops will
|
|
10
|
+
* extend the union.
|
|
11
|
+
*/
|
|
12
|
+
export interface ResolveCompressOptionsInput {
|
|
13
|
+
readonly media: PresetMedia;
|
|
14
|
+
readonly op: PresetOp;
|
|
15
|
+
/** Defaults registered via `gisl.create({ presetDefaults: ... })`. */
|
|
16
|
+
readonly presetDefaults?: PresetDefaults;
|
|
17
|
+
/**
|
|
18
|
+
* Scoped defaults attached via `client.withPresetDefaults(...)` (T4c —
|
|
19
|
+
* `ULAlOP6j`). Layered between `presetDefaults` and `presetOverrides`
|
|
20
|
+
* in the resolver chain. The derived client closes over this
|
|
21
|
+
* reference; `undefined` for clients that never went through a
|
|
22
|
+
* `withPresetDefaults` call.
|
|
23
|
+
*/
|
|
24
|
+
readonly scopedPresetDefaults?: PresetDefaults;
|
|
25
|
+
/** Per-call `presetOverrides` argument from the operation builder. */
|
|
26
|
+
readonly presetOverrides?: Readonly<Record<string, unknown>>;
|
|
27
|
+
/**
|
|
28
|
+
* `optimize` selects the preset level. When unset, NO shipped
|
|
29
|
+
* defaults apply (resolver layer 1 contributes nothing); the
|
|
30
|
+
* resulting `resolvedOptions.preset` is `null`.
|
|
31
|
+
*/
|
|
32
|
+
readonly optimize?: OptimizeFor;
|
|
33
|
+
/**
|
|
34
|
+
* Explicit per-call knobs the caller passed alongside `optimize` —
|
|
35
|
+
* e.g. `{ autoOrient: true }`. These are the highest-precedence
|
|
36
|
+
* layer.
|
|
37
|
+
*/
|
|
38
|
+
readonly explicitOptions: Readonly<Record<string, unknown>>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Output of {@link resolveCompressOptions}. `wireOptions` is the
|
|
42
|
+
* snake_case payload ready for the operation argument; `resolvedOptions`
|
|
43
|
+
* is the introspection projection surfaced on `Result.resolvedOptions`.
|
|
44
|
+
*/
|
|
45
|
+
export interface ResolveCompressOptionsOutput {
|
|
46
|
+
readonly wireOptions: Record<string, unknown>;
|
|
47
|
+
readonly resolvedOptions: ResolvedOptions;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse a `targetSize` value into a positive integer byte count.
|
|
51
|
+
*
|
|
52
|
+
* - Integer input passes through after non-negative + finite checks.
|
|
53
|
+
* - String input must match `<number><unit?>` with unit in
|
|
54
|
+
* `B|KB|MB|GB|TB` (case-insensitive). Multipliers are BINARY
|
|
55
|
+
* (1 KB = 1024). Decimal fractions allowed in the magnitude
|
|
56
|
+
* (`'1.5GB'` → `1.5 * 2^30` rounded down to integer bytes).
|
|
57
|
+
*
|
|
58
|
+
* Throws {@link GislConfigError} with `reason: 'invalid_target_size'`
|
|
59
|
+
* on any other input — including negative numbers, infinities, missing
|
|
60
|
+
* magnitude, unknown unit, or zero magnitude.
|
|
61
|
+
*
|
|
62
|
+
* @internal — exported for unit tests.
|
|
63
|
+
*/
|
|
64
|
+
export declare function _parseTargetSize(value: unknown): number;
|
|
65
|
+
/**
|
|
66
|
+
* Resolve the wire payload + introspection projection for a compress
|
|
67
|
+
* operation call. Throws {@link GislConfigError} before any network
|
|
68
|
+
* round-trip when the merged options violate a documented constraint.
|
|
69
|
+
*
|
|
70
|
+
* Layers are applied in fixed order:
|
|
71
|
+
* SDK shipped → client default → scoped (T4c) → callPresetOverride → explicit.
|
|
72
|
+
*
|
|
73
|
+
* `optimize` unset ⇒ layer 1 contributes nothing; `resolvedOptions.preset = null`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveCompressOptions(input: ResolveCompressOptionsInput): ResolveCompressOptionsOutput;
|