Skip to content

Commit 7773625

Browse files
kyleamazza-fqclaude
andcommitted
feat: add default fetch configuration and set Node 18+ requirement
## Changes - Service getters now provide default fetch configuration when no config is passed - Removed defensive error checking in favor of sensible defaults - Added Node.js 18+ engine requirement to package.json - Updated README to document Node.js 18+ requirement ## Benefits - Simpler code without defensive error checking - Services work "out of the box" without requiring provider or config - Aligns with modern JavaScript ecosystem standards (Node 18 is reasonable minimum) - Cleaner developer experience with automatic fetch fallback ## Default Behavior When no config is provided, service getters now default to: - Browser: `window.fetch.bind(window)` - Node.js 18+: `globalThis.fetch` This ensures services always have a working fetch implementation without requiring explicit configuration. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 371fe3a commit 7773625

File tree

4 files changed

+39
-28
lines changed

4 files changed

+39
-28
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
[Basketry generator](https://basketry.io) for generating React Query queryOptions and hooks. This generator can be coupled with any Basketry parser.
77

8+
## Requirements
9+
10+
- Node.js 18.0.0 or higher (for native fetch support)
11+
- React Query v5
12+
813
## Quick Start
914

1015
### Installation

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
},
3838
"homepage": "https://basketry.io/docs/components/@basketry/react-query",
3939
"funding": "https://github.com/sponsors/basketry",
40+
"engines": {
41+
"node": ">=18.0.0"
42+
},
4043
"devDependencies": {
4144
"@basketry/dotfiles": "^1.1.0",
4245
"@types/jest": "^27.4.0",

src/context-file.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,9 @@ export class ContextFile extends ModuleBuilder {
7575
// Add service getter function (v0.3.0)
7676
yield ``;
7777
yield `export const ${getterName} = (config?: ${contextPropsName}) => {`;
78-
yield ` const serviceConfig = config ?? getCurrentContext();`;
79-
yield ` if (!serviceConfig) {`;
80-
yield ` throw new Error('${getterName}: Configuration required. Either pass config parameter or wrap component in ${providerName}.');`;
81-
yield ` }`;
78+
yield ` const serviceConfig = config ?? getCurrentContext() ?? {`;
79+
yield ` fetch: typeof window !== 'undefined' ? window.fetch.bind(window) : globalThis.fetch`;
80+
yield ` };`;
8281
yield ` const ${localName}: ${this.types.type(
8382
interfaceName,
8483
)} = new ${this.client.fn(

src/snapshot/v1/hooks/context.tsx

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,13 @@ export const BasketryExampleProvider: FC<
7878
export const getAuthPermutationService = (
7979
config?: BasketryExampleContextProps,
8080
) => {
81-
const serviceConfig = config ?? getCurrentContext();
82-
if (!serviceConfig) {
83-
throw new Error(
84-
'getAuthPermutationService: Configuration required. Either pass config parameter or wrap component in BasketryExampleProvider.',
85-
);
86-
}
81+
const serviceConfig = config ??
82+
getCurrentContext() ?? {
83+
fetch:
84+
typeof window !== 'undefined'
85+
? window.fetch.bind(window)
86+
: globalThis.fetch,
87+
};
8788
const authPermutationService: AuthPermutationService =
8889
new HttpAuthPermutationService(
8990
serviceConfig.fetch ??
@@ -111,12 +112,13 @@ export const useAuthPermutationService = () => {
111112
};
112113

113114
export const getExhaustiveService = (config?: BasketryExampleContextProps) => {
114-
const serviceConfig = config ?? getCurrentContext();
115-
if (!serviceConfig) {
116-
throw new Error(
117-
'getExhaustiveService: Configuration required. Either pass config parameter or wrap component in BasketryExampleProvider.',
118-
);
119-
}
115+
const serviceConfig = config ??
116+
getCurrentContext() ?? {
117+
fetch:
118+
typeof window !== 'undefined'
119+
? window.fetch.bind(window)
120+
: globalThis.fetch,
121+
};
120122
const exhaustiveService: ExhaustiveService = new HttpExhaustiveService(
121123
serviceConfig.fetch ??
122124
(typeof window !== 'undefined'
@@ -142,12 +144,13 @@ export const useExhaustiveService = () => {
142144
};
143145

144146
export const getGizmoService = (config?: BasketryExampleContextProps) => {
145-
const serviceConfig = config ?? getCurrentContext();
146-
if (!serviceConfig) {
147-
throw new Error(
148-
'getGizmoService: Configuration required. Either pass config parameter or wrap component in BasketryExampleProvider.',
149-
);
150-
}
147+
const serviceConfig = config ??
148+
getCurrentContext() ?? {
149+
fetch:
150+
typeof window !== 'undefined'
151+
? window.fetch.bind(window)
152+
: globalThis.fetch,
153+
};
151154
const gizmoService: GizmoService = new HttpGizmoService(
152155
serviceConfig.fetch ??
153156
(typeof window !== 'undefined'
@@ -173,12 +176,13 @@ export const useGizmoService = () => {
173176
};
174177

175178
export const getWidgetService = (config?: BasketryExampleContextProps) => {
176-
const serviceConfig = config ?? getCurrentContext();
177-
if (!serviceConfig) {
178-
throw new Error(
179-
'getWidgetService: Configuration required. Either pass config parameter or wrap component in BasketryExampleProvider.',
180-
);
181-
}
179+
const serviceConfig = config ??
180+
getCurrentContext() ?? {
181+
fetch:
182+
typeof window !== 'undefined'
183+
? window.fetch.bind(window)
184+
: globalThis.fetch,
185+
};
182186
const widgetService: WidgetService = new HttpWidgetService(
183187
serviceConfig.fetch ??
184188
(typeof window !== 'undefined'

0 commit comments

Comments
 (0)