stripe-node
stripe-node copied to clipboard
`_prepResources()` and `ResourceNamespace` iterate all properties, but don't check `hasOwnProperty`
trafficstars
Describe the bug
Hi there, when including the scope-extensions-js package in my project, Stripe errors out with the following on startup:
<project>/node_modules/scope-extensions-js/dist/index.js:2
return block(this);
^
TypeError: block is not a function
at new Object.let (<project>/node_modules/scope-extensions-js/dist/index.js:2:12)
at new ResourceNamespace (<project>/node_modules/stripe/cjs/ResourceNamespace.js:9:26)
at new <anonymous> (<project>/node_modules/stripe/cjs/ResourceNamespace.js:15:16)
at Stripe._prepResources (<project>/node_modules/stripe/cjs/stripe.core.js:321:65)
at new Stripe (<project>/node_modules/stripe/cjs/stripe.core.js:99:14)
at Object.<anonymous> (<project>/src/services/stripeService.ts:17:16)
at Module._compile (node:internal/modules/cjs/loader:1369:14)
at Module.m._compile (<project>/node_modules/ts-node/src/index.ts:1618:23)
at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
at Object.require.extensions.<computed> [as .ts] (<project>/node_modules/ts-node/src/index.ts:1621:12)
This is a ts-node project, but not sure if that's important.
The issues appears to be these couple loops, which iterate resources, but pick up unexpected things on the prototype chain:
// stripe.core.js, line 318
_prepResources() {
for (const name in resources) {
if (resources.hasOwnProperty(name)) {
// @ts-ignore
this[(0, utils_js_1.pascalToCamelCase)(name)] = new resources[name](this);
}
}
},
// ResourceNamescape.js, line 6
function ResourceNamespace(stripe, resources) {
for (const name in resources) {
const camelCaseName = name[0].toLowerCase() + name.substring(1);
const resource = new resources[name](stripe);
this[camelCaseName] = resource;
}
}
I believe that we want an Object.hasOwnProperty() check inside those loops, to avoid this issue.
Here is a patch file (using patch-package) that fixes the issue for me:
diff --git a/node_modules/stripe/cjs/ResourceNamespace.js b/node_modules/stripe/cjs/ResourceNamespace.js
index 25c6cf3..20d2431 100644
--- a/node_modules/stripe/cjs/ResourceNamespace.js
+++ b/node_modules/stripe/cjs/ResourceNamespace.js
@@ -5,9 +5,11 @@ exports.resourceNamespace = void 0;
// It also works recursively, so you could do i.e. `stripe.billing.invoicing.pay`.
function ResourceNamespace(stripe, resources) {
for (const name in resources) {
- const camelCaseName = name[0].toLowerCase() + name.substring(1);
- const resource = new resources[name](stripe);
- this[camelCaseName] = resource;
+ if (resources.hasOwnProperty(name)) {
+ const camelCaseName = name[0].toLowerCase() + name.substring(1);
+ const resource = new resources[name](stripe);
+ this[camelCaseName] = resource;
+ }
}
}
function resourceNamespace(namespace, resources) {
diff --git a/node_modules/stripe/cjs/stripe.core.js b/node_modules/stripe/cjs/stripe.core.js
index 4baa951..aff9860 100644
--- a/node_modules/stripe/cjs/stripe.core.js
+++ b/node_modules/stripe/cjs/stripe.core.js
@@ -317,8 +317,10 @@ function createStripe(platformFunctions, requestSender = defaultRequestSenderFac
*/
_prepResources() {
for (const name in resources) {
- // @ts-ignore
- this[(0, utils_js_1.pascalToCamelCase)(name)] = new resources[name](this);
+ if (resources.hasOwnProperty(name)) {
+ // @ts-ignore
+ this[(0, utils_js_1.pascalToCamelCase)(name)] = new resources[name](this);
+ }
}
},
/**
To Reproduce
Use the following package.json:
{
"name": "test",
"version": "1.0.0",
"main": "index.ts",
"scripts": {
"start": "ts-node ./index.ts"
},
"dependencies": {
"scope-extensions-js": "^1.1.0",
"stripe": "^15.12.0",
"ts-node": "^10.9.2",
"typescript": "^5.5.2"
}
}
And index.ts:
import 'scope-extensions-js';
import Stripe from 'stripe';
const stripe = new Stripe('abc123', {
apiVersion: '2024-04-10',
typescript: true,
});
console.log('Done!');
Run yarn && yarn start (or the npm equivalent). See error.
❯ yarn start 11:27:51 AM, Jun 21
yarn run v1.22.22
$ ts-node ./index.ts
<project>/node_modules/scope-extensions-js/dist/index.js:2
return block(this);
^
TypeError: block is not a function
at new Object.let (<project>/node_modules/scope-extensions-js/dist/index.js:2:12)
at new ResourceNamespace (<project>/node_modules/stripe/cjs/ResourceNamespace.js:9:26)
at new <anonymous> (<project>/node_modules/stripe/cjs/ResourceNamespace.js:15:16)
at Stripe._prepResources (<project>/node_modules/stripe/cjs/stripe.core.js:321:65)
at new Stripe (<project>/node_modules/stripe/cjs/stripe.core.js:99:14)
at Object.<anonymous> (/<project>/index.ts:4:16)
at Module._compile (node:internal/modules/cjs/loader:1369:14)
at Module.m._compile (<project>/node_modules/ts-node/src/index.ts:1618:23)
at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
at Object.require.extensions.<computed> [as .ts] (<project>/node_modules/ts-node/src/index.ts:1621:12)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Expected behavior
Project should startup without error.
Code snippets
No response
OS
MacOS Sonoma 14.5
Node version
v20.12.1
Library version
v15.12.0
API version
2024-04-10
Additional context
No response