@zuplo/cli 7.9.17 → 7.9.19
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/source/ai-gateway/catalog.json +170 -1
- package/dist/source/ai-gateway/planner.test.js +49 -1
- package/dist/source/ai-gateway/planner.test.js.map +1 -1
- package/node_modules/@posthog/core/dist/error-tracking/chunk-ids.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/error-tracking/chunk-ids.js +36 -22
- package/node_modules/@posthog/core/dist/error-tracking/chunk-ids.mjs +36 -22
- package/node_modules/@posthog/core/dist/error-tracking/release.d.ts +3 -5
- package/node_modules/@posthog/core/dist/error-tracking/release.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/error-tracking/release.js +4 -0
- package/node_modules/@posthog/core/dist/error-tracking/release.mjs +4 -0
- package/node_modules/@posthog/core/dist/featureFlagUtils.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/featureFlagUtils.js +1 -2
- package/node_modules/@posthog/core/dist/featureFlagUtils.mjs +1 -2
- package/node_modules/@posthog/core/package.json +2 -2
- package/node_modules/@posthog/core/src/error-tracking/chunk-ids.spec.ts +77 -0
- package/node_modules/@posthog/core/src/error-tracking/chunk-ids.ts +50 -25
- package/node_modules/@posthog/core/src/error-tracking/release.spec.ts +34 -0
- package/node_modules/@posthog/core/src/error-tracking/release.ts +10 -5
- package/node_modules/@posthog/core/src/featureFlagUtils.ts +0 -2
- package/node_modules/@zuplo/core/customer.cli.minified.js +1 -1
- package/node_modules/@zuplo/core/index.minified.js +1 -1
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/{chunk-UJ56MYSD.js → chunk-6YPRGG62.js} +108 -107
- package/node_modules/@zuplo/runtime/out/esm/chunk-6YPRGG62.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/types/index.d.ts +122 -10
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/node_modules/content-disposition/README.md +105 -35
- package/node_modules/content-disposition/dist/index.d.ts +72 -0
- package/node_modules/content-disposition/dist/index.js +388 -0
- package/node_modules/content-disposition/dist/index.js.map +1 -0
- package/node_modules/content-disposition/package.json +31 -19
- package/node_modules/express/Readme.md +15 -9
- package/node_modules/express/lib/application.js +2 -2
- package/node_modules/express/lib/request.js +32 -19
- package/node_modules/express/lib/response.js +27 -30
- package/node_modules/express/node_modules/content-type/LICENSE +22 -0
- package/node_modules/express/node_modules/content-type/README.md +71 -0
- package/node_modules/express/node_modules/content-type/dist/index.d.ts +46 -0
- package/node_modules/express/node_modules/content-type/dist/index.js +176 -0
- package/node_modules/express/node_modules/content-type/dist/index.js.map +1 -0
- package/node_modules/express/node_modules/content-type/package.json +52 -0
- package/node_modules/express/package.json +10 -10
- package/package.json +11 -11
- package/node_modules/@zuplo/runtime/out/esm/chunk-UJ56MYSD.js.map +0 -1
- package/node_modules/content-disposition/index.js +0 -536
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-UJ56MYSD.js.LEGAL.txt → chunk-6YPRGG62.js.LEGAL.txt} +0 -0
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
* DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*--------------------------------------------------------------------------------------------*/
|
|
24
24
|
|
|
25
|
-
import{E as p,J as c,M as u}from"../chunk-
|
|
25
|
+
import{E as p,J as c,M as u}from"../chunk-6YPRGG62.js";import"../chunk-VTO3F6DK.js";import{a as d}from"../chunk-QGAJTUPE.js";import"../chunk-A3QGJZO7.js";import"../chunk-YJ2BHVUH.js";import{aa as i}from"../chunk-PBDT4FDO.js";import{a as o}from"../chunk-TYV53J3B.js";function w(l={request:new Request("https://api.example.com")}){let e=[];function t(s){e.push(Promise.resolve(s))}return o(t,"waitUntil"),{context:new a({event:{waitUntil:t},route:l.route,originalRequest:l.request}),invokeResponse:o(async()=>{await Promise.all(e)},"invokeResponse")}}o(w,"createMockContext");var g={path:"/",methods:["GET"],handler:{module:{},export:"default"},raw:o(()=>({}),"raw")},a=class extends EventTarget{static{o(this,"MockZuploContext")}#e;#t;contextId;requestId;log;route;custom;incomingRequestProperties;parentContext;analyticsContext;constructor({event:e,route:t=g,parentContext:n,originalRequest:r}){super(),this.requestId=crypto.randomUUID(),this.contextId=crypto.randomUUID(),this.log={info:i.console.info,log:i.console.log,debug:i.console.debug,warn:i.console.warn,error:i.console.error,setLogProperties:o(()=>{},"setLogProperties")},this.custom={},this.route=t,this.incomingRequestProperties={ip:"203.0.113.7",asn:1234,asOrganization:"ORGANIZATION",city:"Seattle",region:"Washington",regionCode:"WA",colo:"SEA",continent:"NA",country:"US",postalCode:"98004",metroCode:"SEA",latitude:void 0,longitude:void 0,timezone:void 0,httpProtocol:void 0,clientCert:void 0,clientMtlsVerificationStatus:void 0,clientMtlsVerificationReason:void 0,clientCertFingerprintSha256:void 0,clientCertNotBefore:void 0,clientCertNotAfter:void 0,clientCertIssuerDn:void 0,clientCertSubjectDn:void 0},this.parentContext=n,this.#e=e,this.#t=r,this.analyticsContext=new c(this.requestId)}waitUntil(e){this.#e.waitUntil(e)}invokeInboundPolicy(e,t){throw new Error("Not implemented")}invokeOutboundPolicy(e,t,n){throw new Error("Not implemented")}invokeRoute(e,t){throw new Error("Not implemented")}addResponseSendingHook(e){throw new Error("Not implemented")}addResponseSendingFinalHook(e){throw new Error("Not implemented")}addPreRequestHandler(e,t){let n;try{n=u.getContextExtensions(this)}catch{n=u.initialize(this,new d(this.#t??new Request("https://api.example.com")))}n.preRequestPhase??="active",p(this,n,e,t)}get preRequestHandlers(){let e;try{e=u.getContextExtensions(this)}catch{return[]}return(e.preRequestState?.entries??[]).map(t=>({policyName:t.policyName,name:t.name}))}addEventListener(e,t,n){let r=o(s=>{try{typeof t=="function"?t(s):t.handleEvent(s)}catch(m){throw this.log.error(`Error invoking event ${e}. See following logs for details.`),m}},"wrapped");super.addEventListener(e,r,n)}};export{a as MockZuploContext,w as createMockContext};
|
|
26
26
|
//# sourceMappingURL=index.js.map
|
|
@@ -540,6 +540,61 @@ export declare const AIGatewayInternalOnlyInboundPolicy: typeof InternalOnlyInbo
|
|
|
540
540
|
export declare type AIGatewayInternalOnlyInboundPolicyOptions =
|
|
541
541
|
InternalOnlyInboundPolicyOptions;
|
|
542
542
|
|
|
543
|
+
/**
|
|
544
|
+
* Spreads AI requests across a list of models. The policy cycles through the
|
|
545
|
+
* list, or keeps requests that share a key, such as a user or a conversation,
|
|
546
|
+
* on the same model. Most requests also get a retry model from the list. A
|
|
547
|
+
* request moves there when the chosen model stays rate limited. Chat
|
|
548
|
+
* completions and embeddings requests also move there when the model returns a
|
|
549
|
+
* server error, can't be reached, or times out.
|
|
550
|
+
*
|
|
551
|
+
* The policy picks the model for every request it handles and ignores the
|
|
552
|
+
* request's own `model`, so the list also limits which models clients can
|
|
553
|
+
* reach. An earlier policy's model selection is never overwritten.
|
|
554
|
+
*
|
|
555
|
+
* @title Model Load Balancing
|
|
556
|
+
* @product ai-gateway
|
|
557
|
+
* @requiresAI
|
|
558
|
+
* @param request - The ZuploRequest
|
|
559
|
+
* @param context - The ZuploContext
|
|
560
|
+
* @param options - The policy options set in policies.json
|
|
561
|
+
* @param policyName - The name of the policy as set in policies.json
|
|
562
|
+
* @returns The request with model routing stored in context, or a refusal
|
|
563
|
+
* @example
|
|
564
|
+
* ```json
|
|
565
|
+
* {
|
|
566
|
+
* "strategy": "round-robin",
|
|
567
|
+
* "models": {
|
|
568
|
+
* "completions": [
|
|
569
|
+
* "azure-eastus/gpt-5",
|
|
570
|
+
* "azure-westus/gpt-5",
|
|
571
|
+
* "openai/gpt-5"
|
|
572
|
+
* ]
|
|
573
|
+
* }
|
|
574
|
+
* }
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
export declare class AIGatewayLoadBalancingInboundPolicy extends InboundPolicy<AIGatewayLoadBalancingInboundPolicyOptions> {
|
|
578
|
+
#private;
|
|
579
|
+
static readonly policyType = "ai-gateway-load-balancing";
|
|
580
|
+
handler(
|
|
581
|
+
request: ZuploRequest,
|
|
582
|
+
context: ZuploContext
|
|
583
|
+
): Promise<ZuploRequest | Response>;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Options for spreading AI Gateway requests across a list of models.
|
|
588
|
+
* @public
|
|
589
|
+
*/
|
|
590
|
+
export declare interface AIGatewayLoadBalancingInboundPolicyOptions {
|
|
591
|
+
strategy?: Strategy;
|
|
592
|
+
stickyBy?: StickyBy;
|
|
593
|
+
expression?: Expression;
|
|
594
|
+
models: Models;
|
|
595
|
+
fallbackTimeoutSeconds?: FallbackTimeoutSeconds_2;
|
|
596
|
+
}
|
|
597
|
+
|
|
543
598
|
/* Excluded from this release type: AIGatewayMeterIncrements */
|
|
544
599
|
|
|
545
600
|
/**
|
|
@@ -721,7 +776,7 @@ export { AIGatewayModelFilteringInboundPolicy as AIGatewayModelFilteringV2Inboun
|
|
|
721
776
|
* @public
|
|
722
777
|
*/
|
|
723
778
|
declare interface AIGatewayModelFilteringInboundPolicyOptions {
|
|
724
|
-
models:
|
|
779
|
+
models: Models_2;
|
|
725
780
|
}
|
|
726
781
|
export { AIGatewayModelFilteringInboundPolicyOptions };
|
|
727
782
|
export { AIGatewayModelFilteringInboundPolicyOptions as AIGatewayModelFilteringV2InboundPolicyOptions };
|
|
@@ -799,7 +854,7 @@ export declare class AIGatewayModelOverrideInboundPolicy extends InboundPolicy<A
|
|
|
799
854
|
* @public
|
|
800
855
|
*/
|
|
801
856
|
export declare interface AIGatewayModelOverrideInboundPolicyOptions {
|
|
802
|
-
models:
|
|
857
|
+
models: Models_3;
|
|
803
858
|
}
|
|
804
859
|
|
|
805
860
|
/**
|
|
@@ -1608,13 +1663,13 @@ export declare interface AkamaiFirewallForAiOutboundPolicyOptions {
|
|
|
1608
1663
|
* @minItems 1
|
|
1609
1664
|
* @public
|
|
1610
1665
|
*/
|
|
1611
|
-
declare type AllowedModels = [
|
|
1666
|
+
declare type AllowedModels = [ProviderAndModel_2, ...ProviderAndModel_2[]];
|
|
1612
1667
|
|
|
1613
1668
|
/**
|
|
1614
1669
|
* @minItems 1
|
|
1615
1670
|
* @public
|
|
1616
1671
|
*/
|
|
1617
|
-
declare type AllowedModels1 = [
|
|
1672
|
+
declare type AllowedModels1 = [ProviderAndModel_2, ...ProviderAndModel_2[]];
|
|
1618
1673
|
|
|
1619
1674
|
/**
|
|
1620
1675
|
* Amberflo is a usage metering and billing service. This policy allows
|
|
@@ -3203,13 +3258,13 @@ declare interface BatchDispatcherOptions {
|
|
|
3203
3258
|
* @minItems 1
|
|
3204
3259
|
* @public
|
|
3205
3260
|
*/
|
|
3206
|
-
declare type BlockedModels = [
|
|
3261
|
+
declare type BlockedModels = [ProviderAndModel_2, ...ProviderAndModel_2[]];
|
|
3207
3262
|
|
|
3208
3263
|
/**
|
|
3209
3264
|
* @minItems 1
|
|
3210
3265
|
* @public
|
|
3211
3266
|
*/
|
|
3212
|
-
declare type BlockedModels1 = [
|
|
3267
|
+
declare type BlockedModels1 = [ProviderAndModel_2, ...ProviderAndModel_2[]];
|
|
3213
3268
|
|
|
3214
3269
|
/**
|
|
3215
3270
|
* The brownout policy allows performing scheduled downtime on your API
|
|
@@ -4179,11 +4234,20 @@ declare interface CompletionsFallbacks {
|
|
|
4179
4234
|
quotaFallback?: QuotaFallbackModel;
|
|
4180
4235
|
}
|
|
4181
4236
|
|
|
4237
|
+
/**
|
|
4238
|
+
* Models for chat completions, Responses, Messages, and System One requests, as `providerName/model`. From 1 through 32 models, each listed once. Provider names aren't case-sensitive, so `openai/gpt-5` and `OpenAI/gpt-5` are the same model. Write each model ID exactly as your provider spells it.
|
|
4239
|
+
*
|
|
4240
|
+
* @minItems 1
|
|
4241
|
+
* @maxItems 32
|
|
4242
|
+
* @public
|
|
4243
|
+
*/
|
|
4244
|
+
declare type CompletionsModels = [ProviderAndModel, ...ProviderAndModel[]];
|
|
4245
|
+
|
|
4182
4246
|
/**
|
|
4183
4247
|
* Rules for chat completions, Responses, and Anthropic Messages requests.
|
|
4184
4248
|
* @public
|
|
4185
4249
|
*/
|
|
4186
|
-
declare type
|
|
4250
|
+
declare type CompletionsModels_2 =
|
|
4187
4251
|
| {
|
|
4188
4252
|
allowList: AllowedModels;
|
|
4189
4253
|
}
|
|
@@ -5321,11 +5385,20 @@ declare interface EmbeddingsFallbacks {
|
|
|
5321
5385
|
quotaFallback?: QuotaFallbackModel;
|
|
5322
5386
|
}
|
|
5323
5387
|
|
|
5388
|
+
/**
|
|
5389
|
+
* Models for embeddings requests, as `providerName/model`. From 1 through 32 models, each listed once. Provider names aren't case-sensitive. Write each model ID exactly as your provider spells it. Every entry must be the same embedding model, such as one model on several accounts.
|
|
5390
|
+
*
|
|
5391
|
+
* @minItems 1
|
|
5392
|
+
* @maxItems 32
|
|
5393
|
+
* @public
|
|
5394
|
+
*/
|
|
5395
|
+
declare type EmbeddingsModels = [ProviderAndModel, ...ProviderAndModel[]];
|
|
5396
|
+
|
|
5324
5397
|
/**
|
|
5325
5398
|
* Rules for embedding requests.
|
|
5326
5399
|
* @public
|
|
5327
5400
|
*/
|
|
5328
|
-
declare type
|
|
5401
|
+
declare type EmbeddingsModels_2 =
|
|
5329
5402
|
| {
|
|
5330
5403
|
allowList: AllowedModels1;
|
|
5331
5404
|
}
|
|
@@ -5429,6 +5502,12 @@ declare type EventType = (typeof EventType)[keyof typeof EventType];
|
|
|
5429
5502
|
*/
|
|
5430
5503
|
declare type Execution = "sequential" | "parallel";
|
|
5431
5504
|
|
|
5505
|
+
/**
|
|
5506
|
+
* The value to key on, written like a {@link https://zuplo.com/docs/policies/ai-gateway-metering-inbound#budget-expressions|Metering budget expression}, such as `request.headers.get("x-end-user-id")`. Required when `stickyBy` is `expression`, and not allowed otherwise.
|
|
5507
|
+
* @public
|
|
5508
|
+
*/
|
|
5509
|
+
declare type Expression = string;
|
|
5510
|
+
|
|
5432
5511
|
/**
|
|
5433
5512
|
* Best-effort flatten of ALL human/assistant text in a request OR response body,
|
|
5434
5513
|
* across every shape — the one sanctioned cross-shape helper. Intended for
|
|
@@ -5492,6 +5571,12 @@ declare interface FallbackModels {
|
|
|
5492
5571
|
*/
|
|
5493
5572
|
declare type FallbackTimeoutSeconds = number;
|
|
5494
5573
|
|
|
5574
|
+
/**
|
|
5575
|
+
* How long to wait for a model to start responding before retrying the request on another model. Applies to chat completions and embeddings. The timeout ends when the response starts, so it doesn't cut off a long streaming response. A response that doesn't stream starts only when it's complete, so the timeout covers the whole response. From 1 through 300.
|
|
5576
|
+
* @public
|
|
5577
|
+
*/
|
|
5578
|
+
declare type FallbackTimeoutSeconds_2 = number;
|
|
5579
|
+
|
|
5495
5580
|
declare interface FetchOptions<T> {
|
|
5496
5581
|
method?: HttpMethod_2;
|
|
5497
5582
|
data?: T;
|
|
@@ -10681,7 +10766,7 @@ declare interface ModelConfiguration {
|
|
|
10681
10766
|
}
|
|
10682
10767
|
|
|
10683
10768
|
/**
|
|
10684
|
-
*
|
|
10769
|
+
* The models to spread requests across, by request type. Set at least one list.
|
|
10685
10770
|
* @public
|
|
10686
10771
|
*/
|
|
10687
10772
|
declare interface Models {
|
|
@@ -10690,10 +10775,19 @@ declare interface Models {
|
|
|
10690
10775
|
}
|
|
10691
10776
|
|
|
10692
10777
|
/**
|
|
10693
|
-
*
|
|
10778
|
+
* Model filtering rules grouped by AI Gateway capability.
|
|
10694
10779
|
* @public
|
|
10695
10780
|
*/
|
|
10696
10781
|
declare interface Models_2 {
|
|
10782
|
+
completions?: CompletionsModels_2;
|
|
10783
|
+
embeddings?: EmbeddingsModels_2;
|
|
10784
|
+
}
|
|
10785
|
+
|
|
10786
|
+
/**
|
|
10787
|
+
* Override rules grouped by AI Gateway capability.
|
|
10788
|
+
* @public
|
|
10789
|
+
*/
|
|
10790
|
+
declare interface Models_3 {
|
|
10697
10791
|
completions?: CompletionsOverride;
|
|
10698
10792
|
embeddings?: EmbeddingsOverride;
|
|
10699
10793
|
}
|
|
@@ -12686,6 +12780,12 @@ export declare interface PropelAuthJwtInboundPolicyOptions {
|
|
|
12686
12780
|
*/
|
|
12687
12781
|
declare type ProviderAndModel = string;
|
|
12688
12782
|
|
|
12783
|
+
/**
|
|
12784
|
+
* A model reference in providerName/model form, split on the first slash.
|
|
12785
|
+
* @public
|
|
12786
|
+
*/
|
|
12787
|
+
declare type ProviderAndModel_2 = string;
|
|
12788
|
+
|
|
12689
12789
|
/**
|
|
12690
12790
|
* Extracts a query parameter and sets it as a header in the request.
|
|
12691
12791
|
*
|
|
@@ -14445,6 +14545,18 @@ declare interface StartsWithRule {
|
|
|
14445
14545
|
startsWith: string;
|
|
14446
14546
|
}
|
|
14447
14547
|
|
|
14548
|
+
/**
|
|
14549
|
+
* The key that `sticky` uses. `user` uses the authenticated caller, `request.user.sub`. `conversation` uses the conversation's system prompt and its first user message with text. `expression` uses the value that `expression` selects. Required when `strategy` is `sticky`, and not allowed with `round-robin`.
|
|
14550
|
+
* @public
|
|
14551
|
+
*/
|
|
14552
|
+
declare type StickyBy = "user" | "conversation" | "expression";
|
|
14553
|
+
|
|
14554
|
+
/**
|
|
14555
|
+
* How the policy picks a model for each request. `round-robin` cycles through the list in order. `sticky` sends every request with the same key to the same model.
|
|
14556
|
+
* @public
|
|
14557
|
+
*/
|
|
14558
|
+
declare type Strategy = "round-robin" | "sticky";
|
|
14559
|
+
|
|
14448
14560
|
/**
|
|
14449
14561
|
* Configuration for accumulating and validating streaming responses.
|
|
14450
14562
|
* @public
|
|
@@ -17,17 +17,17 @@ $ npm install content-disposition
|
|
|
17
17
|
## API
|
|
18
18
|
|
|
19
19
|
```js
|
|
20
|
-
|
|
20
|
+
import { create, parse, format } from 'content-disposition';
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### create(filename, options)
|
|
24
24
|
|
|
25
25
|
Create an attachment `Content-Disposition` header value using the given file name,
|
|
26
26
|
if supplied. The `filename` is optional and if no file name is desired, but you
|
|
27
27
|
want to specify `options`, set `filename` to `undefined`.
|
|
28
28
|
|
|
29
29
|
```js
|
|
30
|
-
res.setHeader('Content-Disposition',
|
|
30
|
+
res.setHeader('Content-Disposition', create('∫ maths.pdf'));
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
**note** HTTP headers are of the ISO-8859-1 character set. If you are writing this
|
|
@@ -40,73 +40,139 @@ the `'binary'` encoding in Node.js.
|
|
|
40
40
|
|
|
41
41
|
##### fallback
|
|
42
42
|
|
|
43
|
-
If the `filename` option is outside
|
|
43
|
+
If the `filename` option is outside US-ASCII, then the file name is actually
|
|
44
44
|
stored in a supplemental field for clients that support Unicode file names and
|
|
45
|
-
a
|
|
45
|
+
a US-ASCII version of the file name is automatically generated.
|
|
46
46
|
|
|
47
|
-
This specifies the
|
|
47
|
+
This specifies the US-ASCII file name to override the automatic generation or
|
|
48
48
|
disables the generation all together, defaults to `true`.
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
- A string will specify the US-ASCII file name to use in place of automatic
|
|
51
|
+
generation.
|
|
52
|
+
- `false` will disable including a US-ASCII file name and only include the
|
|
53
|
+
Unicode version (unless the file name is already US-ASCII).
|
|
54
|
+
- `true` will enable automatic generation if the file name is outside US-ASCII.
|
|
55
55
|
|
|
56
|
-
If the `filename` option is
|
|
56
|
+
If the `filename` option is US-ASCII and this option is specified and has a
|
|
57
57
|
different value, then the `filename` option is encoded in the extended field
|
|
58
|
-
and this set as the fallback field, even though they are both
|
|
58
|
+
and this set as the fallback field, even though they are both US-ASCII.
|
|
59
59
|
|
|
60
60
|
##### type
|
|
61
61
|
|
|
62
62
|
Specifies the disposition type, defaults to `"attachment"`. This can also be
|
|
63
63
|
`"inline"`, or any other value (all values except inline are treated like
|
|
64
64
|
`attachment`, but can convey additional information if both parties agree to
|
|
65
|
-
it).
|
|
65
|
+
it).
|
|
66
66
|
|
|
67
|
-
###
|
|
67
|
+
### parse(string, options)
|
|
68
68
|
|
|
69
69
|
```js
|
|
70
|
-
const disposition =
|
|
70
|
+
const disposition = parse(
|
|
71
|
+
'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt',
|
|
72
|
+
);
|
|
71
73
|
```
|
|
72
74
|
|
|
73
75
|
Parse a `Content-Disposition` header string. This automatically handles extended
|
|
74
76
|
("Unicode") parameters by decoding them and providing them under the standard
|
|
75
|
-
parameter name. This will return an object with the following properties
|
|
76
|
-
are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt'`):
|
|
77
|
+
parameter name. This will return an object with the following properties:
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
- `type`: The disposition type (always lower case). Example: `'attachment'`
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
- `parameters`: An object of the parameters in the disposition (name of parameter
|
|
82
|
+
always lower case and extended versions replace non-extended versions). Example:
|
|
83
|
+
`{filename: "€ rates.txt"}`
|
|
84
|
+
|
|
85
|
+
#### Options
|
|
86
|
+
|
|
87
|
+
##### multipart
|
|
88
|
+
|
|
89
|
+
Parse parameters using browser `multipart/form-data` behavior.
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
parse('form-data; name="file"; filename="the %22plans%22.pdf"', {
|
|
93
|
+
multipart: true,
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
##### extended
|
|
98
|
+
|
|
99
|
+
Parse RFC 5987 extended header parameters automatically when decoding
|
|
100
|
+
parameters, defaults to `true`.
|
|
101
|
+
|
|
102
|
+
### format(obj, options)
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const disposition = format({
|
|
106
|
+
type: 'attachment',
|
|
107
|
+
parameters: {
|
|
108
|
+
filename: '€ rates.txt',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Formats an object to a `Content-Disposition` header string. This automatically
|
|
114
|
+
handles extended ("Unicode") parameters and returns a string. Example:
|
|
115
|
+
`'attachment; filename*=UTF-8''%E2%82%AC%20rates.txt'`
|
|
116
|
+
|
|
117
|
+
#### Options
|
|
118
|
+
|
|
119
|
+
##### multipart
|
|
120
|
+
|
|
121
|
+
Format parameters using browser `multipart/form-data` behavior. This quotes
|
|
122
|
+
parameter values, escapes `"` as `%22`, and writes Unicode values directly
|
|
123
|
+
instead of using extended parameters.
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
format(
|
|
127
|
+
{
|
|
128
|
+
type: 'form-data',
|
|
129
|
+
parameters: { name: 'file', filename: '€ rates.txt' },
|
|
130
|
+
},
|
|
131
|
+
{ multipart: true },
|
|
132
|
+
);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
##### extended
|
|
136
|
+
|
|
137
|
+
Encode Unicode parameter values using RFC 5987 extended header parameters,
|
|
138
|
+
e.g. `filename*=`, defaults to `true`.
|
|
83
139
|
|
|
84
140
|
## Examples
|
|
85
141
|
|
|
86
142
|
### Send a file for download
|
|
87
143
|
|
|
88
144
|
```js
|
|
89
|
-
const contentDisposition = require('content-disposition')
|
|
90
|
-
const fs = require('fs')
|
|
91
|
-
const http = require('http')
|
|
92
|
-
const onFinished = require('on-finished')
|
|
145
|
+
const contentDisposition = require('content-disposition');
|
|
146
|
+
const fs = require('fs');
|
|
147
|
+
const http = require('http');
|
|
148
|
+
const onFinished = require('on-finished');
|
|
93
149
|
|
|
94
|
-
const filePath = '/path/to/public/plans.pdf'
|
|
150
|
+
const filePath = '/path/to/public/plans.pdf';
|
|
95
151
|
|
|
96
|
-
http.createServer(function onRequest
|
|
152
|
+
http.createServer(function onRequest(req, res) {
|
|
97
153
|
// set headers
|
|
98
|
-
res.setHeader('Content-Type', 'application/pdf')
|
|
99
|
-
res.setHeader('Content-Disposition', contentDisposition(filePath))
|
|
154
|
+
res.setHeader('Content-Type', 'application/pdf');
|
|
155
|
+
res.setHeader('Content-Disposition', contentDisposition(filePath));
|
|
100
156
|
|
|
101
157
|
// send file
|
|
102
|
-
const stream = fs.createReadStream(filePath)
|
|
103
|
-
stream.pipe(res)
|
|
158
|
+
const stream = fs.createReadStream(filePath);
|
|
159
|
+
stream.pipe(res);
|
|
104
160
|
onFinished(res, function () {
|
|
105
|
-
stream.destroy()
|
|
106
|
-
})
|
|
107
|
-
})
|
|
161
|
+
stream.destroy();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
108
164
|
```
|
|
109
165
|
|
|
166
|
+
## Local demo
|
|
167
|
+
|
|
168
|
+
Run the upload inspector locally:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
npm run demo
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Then open `http://127.0.0.1:3000` in your browser. The demo lets you upload files, inspect the multipart upload part headers sent by the browser, and compare them with the download `Content-Disposition` header generated by this package.
|
|
175
|
+
|
|
110
176
|
## Testing
|
|
111
177
|
|
|
112
178
|
```sh
|
|
@@ -118,11 +184,15 @@ $ npm test
|
|
|
118
184
|
- [RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1][rfc-2616]
|
|
119
185
|
- [RFC 5987: Character Set and Language Encoding for Hypertext Transfer Protocol (HTTP) Header Field Parameters][rfc-5987]
|
|
120
186
|
- [RFC 6266: Use of the Content-Disposition Header Field in the Hypertext Transfer Protocol (HTTP)][rfc-6266]
|
|
187
|
+
- [RFC 8187: Indicating Character Encoding and Language for HTTP Header Field Parameters][rfc-8187]
|
|
188
|
+
- [HTML Living Standard: Multipart form data][html-form]
|
|
121
189
|
- [Test Cases for HTTP Content-Disposition header field (RFC 6266) and the Encodings defined in RFCs 2047, 2231 and 5987][tc-2231]
|
|
122
190
|
|
|
123
191
|
[rfc-2616]: https://datatracker.ietf.org/doc/html/rfc2616
|
|
124
192
|
[rfc-5987]: https://datatracker.ietf.org/doc/html/rfc5987
|
|
125
193
|
[rfc-6266]: https://datatracker.ietf.org/doc/html/rfc6266
|
|
194
|
+
[rfc-8187]: https://datatracker.ietf.org/doc/html/rfc8187
|
|
195
|
+
[html-form]: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#multipart-form-data
|
|
126
196
|
[tc-2231]: http://greenbytes.de/tech/tc2231/
|
|
127
197
|
|
|
128
198
|
## License
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* content-disposition
|
|
3
|
+
* Copyright(c) 2014-2017 Douglas Christopher Wilson
|
|
4
|
+
* MIT Licensed
|
|
5
|
+
*/
|
|
6
|
+
export interface ContentDisposition {
|
|
7
|
+
/**
|
|
8
|
+
* Content-Disposition type, such as "attachment" or "inline"
|
|
9
|
+
*/
|
|
10
|
+
type: string;
|
|
11
|
+
/**
|
|
12
|
+
* Content-Disposition parameters, such as "filename"
|
|
13
|
+
*/
|
|
14
|
+
parameters: Record<string, string>;
|
|
15
|
+
}
|
|
16
|
+
export interface CreateOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Content-Disposition type, defaults to "attachment"
|
|
19
|
+
* @default "attachment"
|
|
20
|
+
*/
|
|
21
|
+
type?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Fallback filename for non-US-ASCII strings. If true, a fallback will be generated by replacing non-US-ASCII characters with "?". If false, no fallback will be generated.
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
26
|
+
fallback?: string | boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create an attachment Content-Disposition header.
|
|
30
|
+
*/
|
|
31
|
+
export declare function create(filename?: string, options?: CreateOptions): string;
|
|
32
|
+
export interface ParseOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Whether to decode RFC 8187 encoded parameters.
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
extended?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Parse parameters as sent by browsers in `multipart/form-data`.
|
|
40
|
+
* @default false
|
|
41
|
+
*/
|
|
42
|
+
multipart?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse Content-Disposition header string.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parse(header: string, options?: ParseOptions): ContentDisposition;
|
|
48
|
+
/**
|
|
49
|
+
* Decode a RFC 8187 field value (gracefully).
|
|
50
|
+
*/
|
|
51
|
+
export declare function decodeExtended(str: string): string | undefined;
|
|
52
|
+
export interface FormatOptions {
|
|
53
|
+
/**
|
|
54
|
+
* Whether to use extended parameter encoding for non-ISO-8859-1 strings.
|
|
55
|
+
* If false, an error will be thrown when formatting such strings.
|
|
56
|
+
* @default true
|
|
57
|
+
*/
|
|
58
|
+
extended?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Format parameters as sent by browsers in `multipart/form-data`.
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
multipart?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Format object to Content-Disposition header.
|
|
67
|
+
*/
|
|
68
|
+
export declare function format(obj: Partial<ContentDisposition>, options?: FormatOptions): string;
|
|
69
|
+
/**
|
|
70
|
+
* Encode a Unicode string for HTTP (RFC 8187).
|
|
71
|
+
*/
|
|
72
|
+
export declare function encodeExtended(str: string): string;
|