Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Send the idempotency key as an Idempotency-Key header instead of a query parameter - #132

Open
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header
Open

Send the idempotency key as an Idempotency-Key header instead of a query parameter#132
eastagiletracker wants to merge 1 commit into
MethodFi:masterfrom
eastagiletracker:agile-board/forward-idempotency-key-header

Conversation

@eastagiletracker

Copy link
Copy Markdown

This PR proposes sending the idempotency key as an Idempotency-Key header instead of a query parameter on every resource create() that accepts one. We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/336. You can sign in with your GitHub ID to claim ownership of the project.

What's happening

Resource._create is declared as _create(data, params?, requestConfig = {}), and it already builds the Idempotency-Key header out of requestConfig.idempotency_key. Eleven public create() methods call it with only two arguments — super._create(opts, requestConfig) — so the request config lands in the params slot and requestConfig silently falls back to its {} default. The compiler cannot see it: Params defaults to {}, and IRequestConfig is structurally assignable to {}, so tsc accepts the call.

The effect is that the key each of those methods documents (@param requestConfig Idempotency key: { idempotency_key: string}) is serialized into the query string and no Idempotency-Key header is ever sent. payments.create is where that costs the most: a retried create looks like a brand new request to the API, so the retry can post a second payment. It also places the key in the request URL, where it lands in proxy and access logs.

Reproduced on master at d0aa5f6

consthttp=require('http');const{ Method }=require('method-node');constseen=[];constserver=http.createServer((req,res)=>{seen.push({url: req.url,headers: req.headers});res.setHeader('content-type','application/json');res.end(JSON.stringify({data: {id: 'pmt_123',status: 'pending'}}));});server.listen(0,'127.0.0.1',async()=>{constmethod=newMethod({apiKey: 'sk_test',env: 'dev',baseURL: `http://127.0.0.1:${server.address().port}`,});awaitmethod.payments.create({amount: 5000,source: 'acc_src',destination: 'acc_dst',description: 'Loan Pmt'},{idempotency_key: 'my-idem-key-123'},);console.log('request url :',seen[0].url);console.log('Idempotency-Key hdr :',seen[0].headers['idempotency-key']);server.close();});
request url : /payments?idempotency_key=my-idem-key-123
Idempotency-Key hdr : undefined

Affected today: accounts.create, entities.create, entities(id).subscriptions.create, entities(id).manualConnect.create, payments.create, reports.create, secrets.create, forwardingRequests.create, webhooks.create, teams.create and teams.publicKeys.create. entities(id).connect.create was already passing all three arguments and is correct as-is.

The change

Each of those eleven call sites now passes requestConfig in its own positional slot (super._create(opts, undefined, requestConfig)). No public method signature changes, Resource._create is untouched, and the only difference on the wire is the one that was documented all along: the key moves out of the query string and into the Idempotency-Key header. Running the same script above against this branch prints request url : /payments and Idempotency-Key hdr : my-idem-key-123.

How it was verified

test/resources/RequestConfig.tests.ts is new and wired into test/index.ts. It stands up a local HTTP server, points a client at it through the baseURL option, and asserts three things for each of the eleven methods: the key is sent as an Idempotency-Key header, it is absent from the query string, and no such header is sent when no request config is passed. It needs no API credentials, so it runs anywhere:

npx tsc -p tsconfig-test.json
NODE_ENV=TEST npx mocha --exit --timeout 20000 ./test-dist/test/resources/RequestConfig.tests.js

Against master's src those tests report 12 passing, 22 failing — the twelve that pass are the controls asserting no header when no request config is given, which is correct on both trees. With this change they report 34 passing. There is also a control for entities(id).connect.create, confirming it still sends its expand query parameters and the header, so the one already-correct caller does not move.

npx tsc -p tsconfig-test.json (your pretest) and npm run build are green before and after. npm run lint fails identically on both trees on a clean checkout, since .eslintrc.js references @typescript-eslint/eslint-plugin and it is not in devDependencies; that is untouched here. The credentialed suite needs TEST_CLIENT_KEY, which I do not have, so I could not run it — hence the new file being self-contained.

One merge note: #127 also adds a line to test/index.ts, so that file may want a trivial rebase depending on merge order.

How this was managed

This work was tracked on a board imported from this repository's own issues and pull requests — 131 stories in all. The story for this change is Idempotency key is sent as a query param instead of the Idempotency-Key header, on the board at https://eastagiletracker.com/projects/336.

board

If you'd rather not receive contributions like this, reply no-more-prs on this pull request and we won't open any further ones on your repositories.


Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@eastagiletracker