-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add header input type to support multi headers #8
Changes from 13 commits
2b6f56b
95712de
d85eb10
458fa78
c9419cb
6986f72
c6bda20
adfc8e4
aac34e3
77383b0
64df60d
ec61f99
ff6f4e0
b89812d
ef2a7b0
02f5a5e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
export type SforceMru = { | ||
updateMru: boolean; | ||
}; | ||
export type PackageVersion = { | ||
package: string; | ||
version: string; | ||
}; | ||
|
||
export type GenericHeader = { | ||
header: string; | ||
value: string; | ||
}; | ||
|
||
export type RequestHeadersInput = { | ||
'Sforce-Auto-Assign'?: boolean; | ||
'Sforce-Mru'?: SforceMru; | ||
'x-sfdc-packageversion'?: PackageVersion; | ||
'If-Modified-Since'?: Date; | ||
'If-Unmodified-Since'?: Date; | ||
'If-Match'?: string[]; | ||
'If-None-Match'?: string[]; | ||
'Generic-Header'?: GenericHeader; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is If so, it seems like you would want to potentially support multiple values. It might also be easier to just allow a
|
||
}; | ||
|
||
export const ConditionalRequestHeaders: (keyof RequestHeadersInput)[] = [ | ||
'If-Match', | ||
'If-None-Match', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've never actually used these
Does it really only work with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From the document here, Etag is used for http caching. I guess that’s the reason why it’s said only work with Account. I test with a a case project, and |
||
'If-Modified-Since', | ||
'If-Unmodified-Since', | ||
]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,11 +10,10 @@ import { | |
import { Rest } from './rest'; | ||
import { getSFieldProps, SalesforceFieldType, SFieldProperties } from './sObjectDecorators'; | ||
import { SObject } from './sObject'; | ||
import { CompositeError, StandardRestError } from './errors'; | ||
import { CompositeError, ConditionalError, StandardRestError } from './errors'; | ||
import { FieldProps } from '..'; | ||
import { CalendarDate, calendarToString, getCalendarDate } from '../utils/calendarDate'; | ||
import { AxiosRequestHeaders, AxiosResponse } from 'axios'; | ||
import { STATUS_CODES } from 'http'; | ||
import { RequestHeadersInput, ConditionalRequestHeaders, SforceMru, PackageVersion, GenericHeader } from './restHeader'; | ||
|
||
export interface DMLResponse { | ||
id: string; | ||
|
@@ -229,27 +228,29 @@ export abstract class RestObject extends SObject { | |
* @returns {Promise<void>} | ||
* @memberof RestObject | ||
*/ | ||
public async update(opts?: { | ||
refresh?: boolean; | ||
sendAllFields?: boolean; | ||
ifModifiedSince?: Date; | ||
ifUnmodifiedSince?: Date; | ||
}): Promise<this> { | ||
public async update(opts?: { refresh?: boolean; sendAllFields?: boolean; headers?: RequestHeadersInput[] }): Promise<this> { | ||
opts = opts || {}; | ||
if (this.id == null) { | ||
throw new Error('Must have Id to update!'); | ||
} | ||
if (opts.refresh === true) { | ||
return this.updateComposite(opts.sendAllFields); | ||
} else { | ||
const headers = {}; | ||
if (opts.ifModifiedSince) headers['If-Modified-Since'] = opts.ifModifiedSince.toUTCString() | ||
if (opts.ifUnmodifiedSince) headers['If-Unmodified-Since'] = opts.ifUnmodifiedSince.toUTCString() | ||
const headerOutput = this.setHeader(opts.headers); | ||
const response = await this._client.request.patch( | ||
`${this.attributes.url}/${this.id}`, | ||
this.toJson({ dmlMode: opts.sendAllFields ? 'update' : 'update_modified_only' }), | ||
{ headers } | ||
{ headers: headerOutput } | ||
); | ||
|
||
// Check if it contains Conditional Request Headers and deal with errors | ||
const containsConditionalHeader = Object.keys(opts.headers).some((key) => | ||
ConditionalRequestHeaders.includes(key as keyof RequestHeadersInput) | ||
); | ||
if (containsConditionalHeader && (response.status === 304 || response.status === 412)) { | ||
throw new ConditionalError('Conditions not met'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might want to include the header keys in the exception |
||
} | ||
|
||
this._modified.clear(); | ||
} | ||
return this; | ||
|
@@ -497,4 +498,38 @@ export abstract class RestObject extends SObject { | |
throw e; | ||
} | ||
} | ||
|
||
private setHeader(headersInput: RequestHeadersInput[]) { | ||
const headers = {}; | ||
for (const header of headersInput) { | ||
for (const [name, value] of Object.entries(header)) { | ||
switch (name) { | ||
case 'Sforce-Auto-Assign': | ||
headers[name] = value.toString(); | ||
break; | ||
case 'If-Match': | ||
case 'If-None-Match': | ||
headers[name] = `"${(value as string[]).join('", "')}"`; | ||
break; | ||
case 'If-Modified-Since': | ||
case 'If-Unmodified-Since': | ||
headers[name] = (value as Date).toUTCString(); | ||
break; | ||
case 'Sforce-Mru': | ||
headers[name] = `updateMru=${(value as SforceMru).updateMru}`; | ||
break; | ||
case 'x-sfdc-packageversion': | ||
const packageDetail = value as PackageVersion; | ||
headers[`x-sfdc-packageversion-${packageDetail.package}`] = packageDetail.version; | ||
break; | ||
case 'Generic-Header': | ||
default: | ||
const defaultValue = value as GenericHeader; | ||
headers[defaultValue.header] = defaultValue.value; | ||
break; | ||
} | ||
} | ||
} | ||
return headers; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a breaking change? Should we increment the major version?