Skip to content

Commit 0b8b336

Browse files
authored
Merge pull request rmosolgo#4305 from rmosolgo/js-header-option-fix
JS: fix header handling, add changeset-version option
2 parents add7046 + 3f4f74c commit 0b8b336

7 files changed

Lines changed: 45 additions & 7 deletions

File tree

guides/javascript_client/sync.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ option | description
5353
`--header={key}:{value}` | Add a header to the outgoing HTTP request (may be repeated)
5454
`--add-typename` | Add `__typename` to all selection sets (for use with Apollo Client)
5555
`--verbose` | Output some debug information
56+
`--changeset-version` | Set a {% internal_link "Changeset Version", "/changesets/installation#controller-setup" %} when syncing these queries
5657

5758
You can see these and a few others with `graphql-ruby-client sync --help`.
5859

javascript_client/src/__tests__/cliTest.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ describe("CLI", () => {
1212
})
1313

1414
it("runs with some options", () => {
15-
var buffer = childProcess.execSync("node ./cli.js sync --client=something --header=Abcd:efgh --header=\"Abc: 123 45\" --mode=file --path=\"**/doc1.graphql\"", {stdio: "pipe"})
15+
var buffer = childProcess.execSync("node ./cli.js sync --client=something --header=Abcd:efgh --header=\"Abc: 123 45\" --changeset-version=2023-01-01 --mode=file --path=\"**/doc1.graphql\"", {stdio: "pipe"})
16+
var response = buffer.toString().replace(/\033\[[0-9;]*m/g, "")
17+
expect(response).toEqual("No URL; Generating artifacts without syncing them\nGenerating client module in src/OperationStoreClient.js...\n✓ Done!\n")
18+
})
19+
20+
it("runs with just one header", () => {
21+
var buffer = childProcess.execSync("node ./cli.js sync --client=something --header=Ab-cd:ef-gh --mode=file --path=\"**/doc1.graphql\"", {stdio: "pipe"})
1622
var response = buffer.toString().replace(/\033\[[0-9;]*m/g, "")
1723
expect(response).toEqual("No URL; Generating artifacts without syncing them\nGenerating client module in src/OperationStoreClient.js...\n✓ Done!\n")
1824
})

javascript_client/src/__tests__/syncTest.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,18 @@ describe("sync operations", () => {
5353
headers: {
5454
"X-Something-Special": "🎂",
5555
},
56+
changesetVersion: "2023-05-05",
5657
quiet: true,
57-
send: (_sendPayload: object, options: { url: string, headers: {[key: string]: string} }) => {
58+
send: (_sendPayload: object, options: { url: string, headers: {[key: string]: string}, changesetVersion: string }) => {
5859
url = options.url
5960
Object.keys(options.headers).forEach((h) => {
6061
url += "?" + h + "=" + options.headers[h]
6162
})
63+
url += "&changesetVersion=" + options.changesetVersion
6264
},
6365
}
6466
return sync(options).then(function() {
65-
expect(url).toEqual("bogus?X-Something-Special=🎂")
67+
expect(url).toEqual("bogus?X-Something-Special=🎂&changesetVersion=2023-05-05")
6668
})
6769
})
6870
})

javascript_client/src/cli.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ optional arguments:
3434
- otherwise, "project"
3535
--header=<header>:<value> Add a header to the outgoing HTTP request
3636
(may be repeated)
37+
--changeset-version=<version> Populates \`context[:changeset_version]\` for this sync (for the GraphQL-Enterprise "Changesets" feature)
3738
--add-typename Automatically adds the "__typename" field to your queries
3839
--quiet Suppress status logging
3940
--verbose Print debug output
@@ -47,10 +48,15 @@ optional arguments:
4748
} else {
4849
var parsedHeaders: {[key: string]: string} = {}
4950
if (argv.header) {
50-
argv.header.forEach((h: string) => {
51-
var headerParts = h.split(":")
51+
if (typeof(argv.header) === "string") {
52+
var headerParts = argv.header.split(":")
5253
parsedHeaders[headerParts[0]] = headerParts[1]
53-
})
54+
} else {
55+
argv.header.forEach((h: string) => {
56+
var headerParts = h.split(":")
57+
parsedHeaders[headerParts[0]] = headerParts[1]
58+
})
59+
}
5460
}
5561
var result = sync({
5662
path: argv.path,
@@ -67,6 +73,7 @@ optional arguments:
6773
addTypename: argv["add-typename"],
6874
quiet: argv.hasOwnProperty("quiet"),
6975
verbose: argv.hasOwnProperty("verbose"),
76+
changesetVersion: argv["changset-version"],
7077
})
7178

7279
result.then(function() {

javascript_client/src/sync/__tests__/sendPayloadTest.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,21 @@ describe("Posting GraphQL to OperationStore Endpoint", () => {
4444
})
4545
})
4646

47+
it("Sends headers and changeset version", () => {
48+
var mock = nock("http://example.com", {
49+
reqheaders: {
50+
thing: "Stuff",
51+
"Changeset-Version": "2023-01-01",
52+
}
53+
})
54+
.post("/stored_operations/sync")
55+
.reply(200, { result: "ok" })
56+
57+
return sendPayload("payload", { url: "http://example.com/stored_operations/sync", headers: { thing: "Stuff" }, changesetVersion: "2023-01-01" }).then(function(_response) {
58+
expect(mock.isDone()).toEqual(true)
59+
})
60+
})
61+
4762
it("Adds an hmac-sha256 header if key is present", () => {
4863
var payload = { "payload": [1,2,3] }
4964
var key = "2f26b770ded2a04279bc4bf824ca54ac"

javascript_client/src/sync/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ interface SyncOptions {
2121
verbose?: boolean,
2222
quiet?: boolean,
2323
addTypename?: boolean,
24+
changesetVersion?: string,
2425
headers?: {[key: string]: string},
2526
}
2627
/**
@@ -42,6 +43,7 @@ interface SyncOptions {
4243
* @param {Function} options.hash - A custom hash function for query strings with the signature `options.hash(string) => digest` (Default is `md5(string) => digest`)
4344
* @param {Boolean} options.verbose - If true, log debug output
4445
* @param {Object<String, String>} options.headers - If present, extra headers to add to the HTTP request
46+
* @param {String} options.changesetVersion - If present, sent to populate `context[:changeset_version]` on the server
4547
* @return {Promise} Rejects with an Error or String if something goes wrong. Resolves with the operation payload if successful.
4648
*/
4749
function sync(options: SyncOptions) {
@@ -147,6 +149,7 @@ function sync(options: SyncOptions) {
147149
secret: encryptionKey,
148150
verbose: verbose,
149151
headers: options.headers,
152+
changesetVersion: options.changesetVersion,
150153
}
151154
var sendPromise = Promise.resolve(sendFunc(payload, sendOpts))
152155
return sendPromise.then(function(response) {

javascript_client/src/sync/sendPayload.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ interface SendPayloadOptions {
88
secret?: string,
99
client?: string,
1010
verbose?: boolean,
11-
headers?: [string],
11+
headers?: { [key: string]: string },
12+
changesetVersion?: string,
1213
}
1314
/**
1415
* Use HTTP POST to send this payload to the endpoint.
@@ -41,6 +42,9 @@ function sendPayload(payload: any, options: SendPayloadOptions) {
4142
'Content-Length': Buffer.byteLength(postData).toString()
4243
}
4344

45+
if (options.changesetVersion) {
46+
defaultHeaders["Changeset-Version"] = options.changesetVersion
47+
}
4448
var allHeaders = Object.assign({}, options.headers, defaultHeaders)
4549

4650
var httpOptions = {

0 commit comments

Comments
 (0)