@fluxfiles/node 0.1.14 → 0.1.16

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/index.d.mts CHANGED
@@ -104,6 +104,15 @@ interface BaseTokenOptions {
104
104
  autoOptimize?: boolean;
105
105
  /** WebP quality for optimization, 40–95. `0`/omitted = inherit the server default (82). */
106
106
  optimizeQuality?: number;
107
+ /** Target format for optimization: `'webp'` (default) or `'avif'` (falls back to
108
+ * WebP when the server build lacks AVIF). */
109
+ optimizeFormat?: 'webp' | 'avif';
110
+ /** Keep the original file when optimizing (default false = replace in place). */
111
+ optimizeKeepOriginal?: boolean;
112
+ /** Skip optimizing a file larger than this many MB (0/omitted = no limit). */
113
+ optimizeMaxMb?: number;
114
+ /** Ghostscript preset for PDF optimization. Default `'ebook'`. */
115
+ pdfLevel?: 'screen' | 'ebook' | 'printer' | 'prepress' | 'default';
107
116
  /** How an upload whose NAME collides with an existing different file is handled
108
117
  * (content dedup is separate, by hash): `'rename'` keep both `<name>-1.<ext>`
109
118
  * (default), `'overwrite'` replace in place, `'reject'` 409 for the host to prompt. */
@@ -111,6 +120,21 @@ interface BaseTokenOptions {
111
120
  /** Show dotfiles (.env, .gitignore, …) in listings + search. Default **false** —
112
121
  * dotfiles are hidden, matching Finder / cPanel / Nextcloud. */
113
122
  showHidden?: boolean;
123
+ /** Refuse byte-for-byte duplicate uploads (SHA-256). Default **false** — an
124
+ * identical re-upload is kept as a copy (like Finder / Drive / Dropbox); set true
125
+ * to save storage by blocking duplicates. */
126
+ dedupeUploads?: boolean;
127
+ /** Edition preset that defaults a tier's claims (`pro`/`agency`/`enterprise`).
128
+ * DX sugar — explicit claim options still win, and the license gates the code. */
129
+ edition?: 'free' | 'pro' | 'agency' | 'enterprise';
130
+ /** Paid-module claims (3-layer gate: code installed + licensed + this claim).
131
+ * All default off; inert unless the module is installed & licensed on the server. */
132
+ allowShare?: boolean;
133
+ allowAiVision?: boolean;
134
+ allowOcr?: boolean;
135
+ allowVirusScan?: boolean;
136
+ allowBackup?: boolean;
137
+ allowC2pa?: boolean;
114
138
  /** Allow downloading a multi-file/-folder selection as a zip (POST /api/fm/zip). Default true. */
115
139
  allowZip?: boolean;
116
140
  /** Allow extracting a zip in place (POST /api/fm/extract). Default true. */
package/dist/index.d.ts CHANGED
@@ -104,6 +104,15 @@ interface BaseTokenOptions {
104
104
  autoOptimize?: boolean;
105
105
  /** WebP quality for optimization, 40–95. `0`/omitted = inherit the server default (82). */
106
106
  optimizeQuality?: number;
107
+ /** Target format for optimization: `'webp'` (default) or `'avif'` (falls back to
108
+ * WebP when the server build lacks AVIF). */
109
+ optimizeFormat?: 'webp' | 'avif';
110
+ /** Keep the original file when optimizing (default false = replace in place). */
111
+ optimizeKeepOriginal?: boolean;
112
+ /** Skip optimizing a file larger than this many MB (0/omitted = no limit). */
113
+ optimizeMaxMb?: number;
114
+ /** Ghostscript preset for PDF optimization. Default `'ebook'`. */
115
+ pdfLevel?: 'screen' | 'ebook' | 'printer' | 'prepress' | 'default';
107
116
  /** How an upload whose NAME collides with an existing different file is handled
108
117
  * (content dedup is separate, by hash): `'rename'` keep both `<name>-1.<ext>`
109
118
  * (default), `'overwrite'` replace in place, `'reject'` 409 for the host to prompt. */
@@ -111,6 +120,21 @@ interface BaseTokenOptions {
111
120
  /** Show dotfiles (.env, .gitignore, …) in listings + search. Default **false** —
112
121
  * dotfiles are hidden, matching Finder / cPanel / Nextcloud. */
113
122
  showHidden?: boolean;
123
+ /** Refuse byte-for-byte duplicate uploads (SHA-256). Default **false** — an
124
+ * identical re-upload is kept as a copy (like Finder / Drive / Dropbox); set true
125
+ * to save storage by blocking duplicates. */
126
+ dedupeUploads?: boolean;
127
+ /** Edition preset that defaults a tier's claims (`pro`/`agency`/`enterprise`).
128
+ * DX sugar — explicit claim options still win, and the license gates the code. */
129
+ edition?: 'free' | 'pro' | 'agency' | 'enterprise';
130
+ /** Paid-module claims (3-layer gate: code installed + licensed + this claim).
131
+ * All default off; inert unless the module is installed & licensed on the server. */
132
+ allowShare?: boolean;
133
+ allowAiVision?: boolean;
134
+ allowOcr?: boolean;
135
+ allowVirusScan?: boolean;
136
+ allowBackup?: boolean;
137
+ allowC2pa?: boolean;
114
138
  /** Allow downloading a multi-file/-folder selection as a zip (POST /api/fm/zip). Default true. */
115
139
  allowZip?: boolean;
116
140
  /** Allow extracting a zip in place (POST /api/fm/extract). Default true. */
package/dist/index.js CHANGED
@@ -136,7 +136,16 @@ function sanitizeVariants(v) {
136
136
  }
137
137
  return Object.keys(out).length ? out : null;
138
138
  }
139
+ var EDITION_PRESETS = {
140
+ pro: { allow_optimize: true, allow_share: true },
141
+ agency: { allow_optimize: true, allow_share: true },
142
+ enterprise: { allow_optimize: true, allow_share: true, allow_virus_scan: true }
143
+ };
139
144
  function applyTenantOverrides(payload, opts) {
145
+ const preset = opts.edition ? EDITION_PRESETS[String(opts.edition).toLowerCase()] : void 0;
146
+ if (preset) {
147
+ for (const [k, v] of Object.entries(preset)) if (!(k in payload)) payload[k] = v;
148
+ }
140
149
  if (opts.aiAutoTag !== void 0) payload.ai_auto_tag = !!opts.aiAutoTag;
141
150
  if (opts.rateRead && opts.rateRead > 0) payload.rate_read = Math.trunc(opts.rateRead);
142
151
  if (opts.rateWrite && opts.rateWrite > 0) payload.rate_write = Math.trunc(opts.rateWrite);
@@ -163,12 +172,25 @@ function applyTenantOverrides(payload, opts) {
163
172
  if (opts.allowChmod !== void 0) payload.allow_chmod = !!opts.allowChmod;
164
173
  if (opts.allowCodeEdit !== void 0) payload.allow_code_edit = !!opts.allowCodeEdit;
165
174
  if (opts.allowOptimize !== void 0) payload.allow_optimize = !!opts.allowOptimize;
175
+ if (opts.allowShare !== void 0) payload.allow_share = !!opts.allowShare;
176
+ if (opts.allowAiVision !== void 0) payload.allow_ai_vision = !!opts.allowAiVision;
177
+ if (opts.allowOcr !== void 0) payload.allow_ocr = !!opts.allowOcr;
178
+ if (opts.allowVirusScan !== void 0) payload.allow_virus_scan = !!opts.allowVirusScan;
179
+ if (opts.allowBackup !== void 0) payload.allow_backup = !!opts.allowBackup;
180
+ if (opts.allowC2pa !== void 0) payload.allow_c2pa = !!opts.allowC2pa;
166
181
  if (opts.autoOptimize !== void 0) payload.auto_optimize = !!opts.autoOptimize;
167
182
  if (opts.optimizeQuality && opts.optimizeQuality > 0) payload.optimize_quality = Math.trunc(opts.optimizeQuality);
183
+ if (opts.optimizeFormat === "avif") payload.optimize_format = "avif";
184
+ if (opts.optimizeKeepOriginal !== void 0) payload.optimize_keep_original = !!opts.optimizeKeepOriginal;
185
+ if (opts.optimizeMaxMb && opts.optimizeMaxMb > 0) payload.optimize_max_mb = Math.trunc(opts.optimizeMaxMb);
186
+ if (opts.pdfLevel && ["screen", "ebook", "printer", "prepress", "default"].includes(opts.pdfLevel)) {
187
+ payload.pdf_level = opts.pdfLevel;
188
+ }
168
189
  if (opts.uploadCollision && ["rename", "overwrite", "reject"].includes(opts.uploadCollision)) {
169
190
  payload.upload_collision = opts.uploadCollision;
170
191
  }
171
192
  if (opts.showHidden !== void 0) payload.show_hidden = !!opts.showHidden;
193
+ if (opts.dedupeUploads !== void 0) payload.dedupe_uploads = !!opts.dedupeUploads;
172
194
  if (opts.allowZip !== void 0) payload.allow_zip = !!opts.allowZip;
173
195
  if (opts.allowExtract !== void 0) payload.allow_extract = !!opts.allowExtract;
174
196
  if (opts.zipMaxMb && opts.zipMaxMb > 0) payload.zip_max_mb = Math.trunc(opts.zipMaxMb);
package/dist/index.mjs CHANGED
@@ -114,7 +114,16 @@ function sanitizeVariants(v) {
114
114
  }
115
115
  return Object.keys(out).length ? out : null;
116
116
  }
117
+ var EDITION_PRESETS = {
118
+ pro: { allow_optimize: true, allow_share: true },
119
+ agency: { allow_optimize: true, allow_share: true },
120
+ enterprise: { allow_optimize: true, allow_share: true, allow_virus_scan: true }
121
+ };
117
122
  function applyTenantOverrides(payload, opts) {
123
+ const preset = opts.edition ? EDITION_PRESETS[String(opts.edition).toLowerCase()] : void 0;
124
+ if (preset) {
125
+ for (const [k, v] of Object.entries(preset)) if (!(k in payload)) payload[k] = v;
126
+ }
118
127
  if (opts.aiAutoTag !== void 0) payload.ai_auto_tag = !!opts.aiAutoTag;
119
128
  if (opts.rateRead && opts.rateRead > 0) payload.rate_read = Math.trunc(opts.rateRead);
120
129
  if (opts.rateWrite && opts.rateWrite > 0) payload.rate_write = Math.trunc(opts.rateWrite);
@@ -141,12 +150,25 @@ function applyTenantOverrides(payload, opts) {
141
150
  if (opts.allowChmod !== void 0) payload.allow_chmod = !!opts.allowChmod;
142
151
  if (opts.allowCodeEdit !== void 0) payload.allow_code_edit = !!opts.allowCodeEdit;
143
152
  if (opts.allowOptimize !== void 0) payload.allow_optimize = !!opts.allowOptimize;
153
+ if (opts.allowShare !== void 0) payload.allow_share = !!opts.allowShare;
154
+ if (opts.allowAiVision !== void 0) payload.allow_ai_vision = !!opts.allowAiVision;
155
+ if (opts.allowOcr !== void 0) payload.allow_ocr = !!opts.allowOcr;
156
+ if (opts.allowVirusScan !== void 0) payload.allow_virus_scan = !!opts.allowVirusScan;
157
+ if (opts.allowBackup !== void 0) payload.allow_backup = !!opts.allowBackup;
158
+ if (opts.allowC2pa !== void 0) payload.allow_c2pa = !!opts.allowC2pa;
144
159
  if (opts.autoOptimize !== void 0) payload.auto_optimize = !!opts.autoOptimize;
145
160
  if (opts.optimizeQuality && opts.optimizeQuality > 0) payload.optimize_quality = Math.trunc(opts.optimizeQuality);
161
+ if (opts.optimizeFormat === "avif") payload.optimize_format = "avif";
162
+ if (opts.optimizeKeepOriginal !== void 0) payload.optimize_keep_original = !!opts.optimizeKeepOriginal;
163
+ if (opts.optimizeMaxMb && opts.optimizeMaxMb > 0) payload.optimize_max_mb = Math.trunc(opts.optimizeMaxMb);
164
+ if (opts.pdfLevel && ["screen", "ebook", "printer", "prepress", "default"].includes(opts.pdfLevel)) {
165
+ payload.pdf_level = opts.pdfLevel;
166
+ }
146
167
  if (opts.uploadCollision && ["rename", "overwrite", "reject"].includes(opts.uploadCollision)) {
147
168
  payload.upload_collision = opts.uploadCollision;
148
169
  }
149
170
  if (opts.showHidden !== void 0) payload.show_hidden = !!opts.showHidden;
171
+ if (opts.dedupeUploads !== void 0) payload.dedupe_uploads = !!opts.dedupeUploads;
150
172
  if (opts.allowZip !== void 0) payload.allow_zip = !!opts.allowZip;
151
173
  if (opts.allowExtract !== void 0) payload.allow_extract = !!opts.allowExtract;
152
174
  if (opts.zipMaxMb && opts.zipMaxMb > 0) payload.zip_max_mb = Math.trunc(opts.zipMaxMb);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluxfiles/node",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Server-side Node/TypeScript SDK for minting FluxFiles JWTs (plain + BYOB), byte-compatible with the PHP core",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
package/src/token.ts CHANGED
@@ -97,8 +97,17 @@ function sanitizeVariants(v: BaseTokenOptions['variants']): Record<string, numbe
97
97
  return Object.keys(out).length ? out : null;
98
98
  }
99
99
 
100
+ /** Edition preset (DX sugar): default a tier's claims; explicit opts below win. */
101
+ const EDITION_PRESETS: Record<string, Record<string, boolean>> = {
102
+ pro: { allow_optimize: true, allow_share: true },
103
+ agency: { allow_optimize: true, allow_share: true },
104
+ enterprise: { allow_optimize: true, allow_share: true, allow_virus_scan: true },
105
+ };
106
+
100
107
  /** Copy the optional per-tenant override claims into a payload when set. */
101
108
  function applyTenantOverrides(payload: Record<string, unknown>, opts: BaseTokenOptions): void {
109
+ const preset = opts.edition ? EDITION_PRESETS[String(opts.edition).toLowerCase()] : undefined;
110
+ if (preset) for (const [k, v] of Object.entries(preset)) if (!(k in payload)) payload[k] = v;
102
111
  if (opts.aiAutoTag !== undefined) payload.ai_auto_tag = !!opts.aiAutoTag;
103
112
  if (opts.rateRead && opts.rateRead > 0) payload.rate_read = Math.trunc(opts.rateRead);
104
113
  if (opts.rateWrite && opts.rateWrite > 0) payload.rate_write = Math.trunc(opts.rateWrite);
@@ -133,12 +142,26 @@ function applyTenantOverrides(payload: Record<string, unknown>, opts: BaseTokenO
133
142
  if (opts.allowChmod !== undefined) payload.allow_chmod = !!opts.allowChmod;
134
143
  if (opts.allowCodeEdit !== undefined) payload.allow_code_edit = !!opts.allowCodeEdit;
135
144
  if (opts.allowOptimize !== undefined) payload.allow_optimize = !!opts.allowOptimize;
145
+ // Other paid-module claims (inert unless the module is installed + licensed).
146
+ if (opts.allowShare !== undefined) payload.allow_share = !!opts.allowShare;
147
+ if (opts.allowAiVision !== undefined) payload.allow_ai_vision = !!opts.allowAiVision;
148
+ if (opts.allowOcr !== undefined) payload.allow_ocr = !!opts.allowOcr;
149
+ if (opts.allowVirusScan !== undefined) payload.allow_virus_scan = !!opts.allowVirusScan;
150
+ if (opts.allowBackup !== undefined) payload.allow_backup = !!opts.allowBackup;
151
+ if (opts.allowC2pa !== undefined) payload.allow_c2pa = !!opts.allowC2pa;
136
152
  if (opts.autoOptimize !== undefined) payload.auto_optimize = !!opts.autoOptimize;
137
153
  if (opts.optimizeQuality && opts.optimizeQuality > 0) payload.optimize_quality = Math.trunc(opts.optimizeQuality);
154
+ if (opts.optimizeFormat === 'avif') payload.optimize_format = 'avif';
155
+ if (opts.optimizeKeepOriginal !== undefined) payload.optimize_keep_original = !!opts.optimizeKeepOriginal;
156
+ if (opts.optimizeMaxMb && opts.optimizeMaxMb > 0) payload.optimize_max_mb = Math.trunc(opts.optimizeMaxMb);
157
+ if (opts.pdfLevel && ['screen', 'ebook', 'printer', 'prepress', 'default'].includes(opts.pdfLevel)) {
158
+ payload.pdf_level = opts.pdfLevel;
159
+ }
138
160
  if (opts.uploadCollision && ['rename', 'overwrite', 'reject'].includes(opts.uploadCollision)) {
139
161
  payload.upload_collision = opts.uploadCollision;
140
162
  }
141
163
  if (opts.showHidden !== undefined) payload.show_hidden = !!opts.showHidden;
164
+ if (opts.dedupeUploads !== undefined) payload.dedupe_uploads = !!opts.dedupeUploads;
142
165
  if (opts.allowZip !== undefined) payload.allow_zip = !!opts.allowZip;
143
166
  if (opts.allowExtract !== undefined) payload.allow_extract = !!opts.allowExtract;
144
167
  if (opts.zipMaxMb && opts.zipMaxMb > 0) payload.zip_max_mb = Math.trunc(opts.zipMaxMb);
package/src/types.ts CHANGED
@@ -108,6 +108,15 @@ export interface BaseTokenOptions {
108
108
  autoOptimize?: boolean;
109
109
  /** WebP quality for optimization, 40–95. `0`/omitted = inherit the server default (82). */
110
110
  optimizeQuality?: number;
111
+ /** Target format for optimization: `'webp'` (default) or `'avif'` (falls back to
112
+ * WebP when the server build lacks AVIF). */
113
+ optimizeFormat?: 'webp' | 'avif';
114
+ /** Keep the original file when optimizing (default false = replace in place). */
115
+ optimizeKeepOriginal?: boolean;
116
+ /** Skip optimizing a file larger than this many MB (0/omitted = no limit). */
117
+ optimizeMaxMb?: number;
118
+ /** Ghostscript preset for PDF optimization. Default `'ebook'`. */
119
+ pdfLevel?: 'screen' | 'ebook' | 'printer' | 'prepress' | 'default';
111
120
  /** How an upload whose NAME collides with an existing different file is handled
112
121
  * (content dedup is separate, by hash): `'rename'` keep both `<name>-1.<ext>`
113
122
  * (default), `'overwrite'` replace in place, `'reject'` 409 for the host to prompt. */
@@ -115,6 +124,21 @@ export interface BaseTokenOptions {
115
124
  /** Show dotfiles (.env, .gitignore, …) in listings + search. Default **false** —
116
125
  * dotfiles are hidden, matching Finder / cPanel / Nextcloud. */
117
126
  showHidden?: boolean;
127
+ /** Refuse byte-for-byte duplicate uploads (SHA-256). Default **false** — an
128
+ * identical re-upload is kept as a copy (like Finder / Drive / Dropbox); set true
129
+ * to save storage by blocking duplicates. */
130
+ dedupeUploads?: boolean;
131
+ /** Edition preset that defaults a tier's claims (`pro`/`agency`/`enterprise`).
132
+ * DX sugar — explicit claim options still win, and the license gates the code. */
133
+ edition?: 'free' | 'pro' | 'agency' | 'enterprise';
134
+ /** Paid-module claims (3-layer gate: code installed + licensed + this claim).
135
+ * All default off; inert unless the module is installed & licensed on the server. */
136
+ allowShare?: boolean;
137
+ allowAiVision?: boolean;
138
+ allowOcr?: boolean;
139
+ allowVirusScan?: boolean;
140
+ allowBackup?: boolean;
141
+ allowC2pa?: boolean;
118
142
  /** Allow downloading a multi-file/-folder selection as a zip (POST /api/fm/zip). Default true. */
119
143
  allowZip?: boolean;
120
144
  /** Allow extracting a zip in place (POST /api/fm/extract). Default true. */