create-stitchkit 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,31 @@ step is overwritten by the next release.
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [0.6.2] — 2026-09-21
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **A scaffold installs the framework the manifest promises.** 0.6.1 rode in the
|
|
20
|
+
same release train as stitchkit 0.90.6 and therefore shipped a lockfile
|
|
21
|
+
resolving 0.90.5: a lockfile is written by an install, so it could not name a
|
|
22
|
+
version that train had not published yet. Every scaffold from 0.6.1 got a
|
|
23
|
+
framework one release behind the one its own range allowed. The template now
|
|
24
|
+
targets `^0.90.7` over a lockfile resolving 0.90.7, and the framework's release
|
|
25
|
+
machinery refuses that shape of train outright.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **The generated frontend takes its QueryClient from the framework.**
|
|
30
|
+
`lib/query-client.ts` now calls `createQueryClientFactory` from
|
|
31
|
+
`stitchkit/react` instead of restating it locally. The local copy spelled the
|
|
32
|
+
query retry as a plain `1`, which retries an unauthorized, forbidden or invalid
|
|
33
|
+
request exactly as eagerly as a network blip; the framework predicate retries
|
|
34
|
+
server failures and network faults and leaves the rest alone. Request-local
|
|
35
|
+
server identity, the browser singleton, pending dehydration and the
|
|
36
|
+
no-retry-for-mutations rule are unchanged in behaviour. This is the cutover
|
|
37
|
+
`UPGRADING.md` recorded under *Released migration: 0.6.1* — adopting it in a
|
|
38
|
+
project you already own remains optional.
|
|
39
|
+
|
|
15
40
|
## [0.6.1] — 2026-09-20
|
|
16
41
|
|
|
17
42
|
### Changed
|
package/package.json
CHANGED
package/template/bun.lock
CHANGED
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"zod": "4.6.5",
|
|
146
146
|
},
|
|
147
147
|
"catalog": {
|
|
148
|
-
"stitchkit": "^0.90.
|
|
148
|
+
"stitchkit": "^0.90.7",
|
|
149
149
|
},
|
|
150
150
|
"packages": {
|
|
151
151
|
"@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.87", "", { "dependencies": { "@ai-sdk/provider": "4.0.17", "@ai-sdk/provider-utils": "5.0.45", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6wJmX/D5OO7tvDJbtFdXdBuRt8AkCnW+FLK+W35UHe/tHgolAa4hclXtJcMSYnlTDy/t5DNRgdesVaoMXtwzow=="],
|
|
@@ -906,7 +906,7 @@
|
|
|
906
906
|
|
|
907
907
|
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
|
908
908
|
|
|
909
|
-
"ky": ["ky@2.0
|
|
909
|
+
"ky": ["ky@2.1.0", "", {}, "sha512-nIKwelw+7qVqKOlX4Eht6GXfEXlDHcdIjyLWV3s119kYt5s+70ayTnYS+0fRNmtgGRRAfqdeWQbh8YizqkS0ng=="],
|
|
910
910
|
|
|
911
911
|
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
|
912
912
|
|
|
@@ -1128,7 +1128,7 @@
|
|
|
1128
1128
|
|
|
1129
1129
|
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
|
|
1130
1130
|
|
|
1131
|
-
"stitchkit": ["stitchkit@0.90.
|
|
1131
|
+
"stitchkit": ["stitchkit@0.90.7", "", { "dependencies": { "ky": "^2.1.0" }, "peerDependencies": { "@modelcontextprotocol/ext-apps": "^1.7.2 || ^2.0.0", "@modelcontextprotocol/server": "^2.0.0", "@openrouter/ai-sdk-provider": "^3.1.0", "@opentelemetry/api": "^1.9.0", "@socket.io/bun-engine": "^0.1.2", "@socket.io/component-emitter": "^3.1.2", "@tanstack/react-query": ">=5", "@types/bun": "^1.4.2", "ai": "^7.0.107", "google-auth-library": "^11.1.0", "grammy": "^1.46.0", "maxmind": "^5.0.7", "react": ">=18", "react-query-kit": "^3.3.3", "socket.io": "^4.8.3", "socket.io-client": "^4.8.3", "srvx": "^0.12.5 || ^1.0.5", "zod": "^4.6.5" }, "optionalPeers": ["@modelcontextprotocol/ext-apps", "@modelcontextprotocol/server", "@openrouter/ai-sdk-provider", "@opentelemetry/api", "@socket.io/bun-engine", "@socket.io/component-emitter", "@tanstack/react-query", "@types/bun", "ai", "google-auth-library", "grammy", "maxmind", "react", "react-query-kit", "socket.io", "socket.io-client", "srvx"], "bin": { "stitchkit": "dist/upgrade-cli.js" } }, "sha512-My36iuzUc4FULJ26jIQK/czwY+uBy8MRh6AgbnvQNBIvo4fghuiINmN501uoJzeN7JM8v4J1C6fqjwA/XNxf/A=="],
|
|
1132
1132
|
|
|
1133
1133
|
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
|
|
1134
1134
|
|
package/template/package.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { ApiError } from 'stitchkit';
|
|
2
3
|
import { getQueryClient } from './query-client';
|
|
3
4
|
|
|
4
5
|
describe('query dehydration policy', () => {
|
|
@@ -20,9 +21,25 @@ describe('query dehydration policy', () => {
|
|
|
20
21
|
expect(shouldDehydrate(pending)).toBe(true);
|
|
21
22
|
});
|
|
22
23
|
|
|
23
|
-
test('retries a
|
|
24
|
+
test('retries a server failure once and never retries a mutation', () => {
|
|
25
|
+
// Asserted through the decision, not through the literal: the policy is a
|
|
26
|
+
// predicate now, and `retry === 1` would pass for a client that retries an
|
|
27
|
+
// unauthorized request too.
|
|
24
28
|
const defaults = getQueryClient().getDefaultOptions();
|
|
25
|
-
|
|
29
|
+
const retry = defaults.queries?.retry;
|
|
30
|
+
if (typeof retry !== 'function') throw new Error('query retry policy is required');
|
|
31
|
+
const serverFailure = new ApiError('INTERNAL_SERVER_ERROR', 500);
|
|
32
|
+
expect(retry(0, serverFailure)).toBe(true);
|
|
33
|
+
expect(retry(1, serverFailure)).toBe(false);
|
|
26
34
|
expect(defaults.mutations?.retry).toBe(false);
|
|
27
35
|
});
|
|
36
|
+
|
|
37
|
+
test('a request the user cannot repeat into success is not retried', () => {
|
|
38
|
+
const defaults = getQueryClient().getDefaultOptions();
|
|
39
|
+
const retry = defaults.queries?.retry;
|
|
40
|
+
if (typeof retry !== 'function') throw new Error('query retry policy is required');
|
|
41
|
+
for (const code of ['UNAUTHORIZED', 'FORBIDDEN', 'VALIDATION_ERROR']) {
|
|
42
|
+
expect(retry(0, new ApiError(code, 401))).toBe(false);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
28
45
|
});
|
|
@@ -1,36 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defaultShouldDehydrateQuery,
|
|
3
|
-
environmentManager,
|
|
4
|
-
QueryClient,
|
|
5
|
-
type QueryClientConfig,
|
|
6
|
-
} from '@tanstack/react-query';
|
|
7
1
|
import { cache } from 'react';
|
|
2
|
+
import { createQueryClientFactory } from 'stitchkit/react';
|
|
8
3
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
4
|
+
// One request-local server client and one browser singleton, both from the
|
|
5
|
+
// framework. The local construction this replaced was a second implementation
|
|
6
|
+
// of the same thing: it restated the dehydration policy and the mutation rule,
|
|
7
|
+
// and it spelled the query retry as a plain `1`, which retries an unauthorized
|
|
8
|
+
// or invalid request exactly as eagerly as a network blip. `apiErrorRetry` —
|
|
9
|
+
// the factory's default — retries what is worth retrying and nothing else.
|
|
10
|
+
// Project-specific cache configuration and mutation toasts belong in these
|
|
11
|
+
// options, never in a copy of the framework's retry predicate.
|
|
12
|
+
export const getQueryClient = createQueryClientFactory({
|
|
13
|
+
serverCache: cache,
|
|
14
|
+
queryClient: {
|
|
15
|
+
defaultOptions: { queries: { staleTime: 30_000 } },
|
|
22
16
|
},
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function createQueryClient(): QueryClient {
|
|
26
|
-
return new QueryClient(config);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const getServerQueryClient = cache(createQueryClient);
|
|
30
|
-
let browserQueryClient: QueryClient | undefined;
|
|
31
|
-
|
|
32
|
-
export function getQueryClient(): QueryClient {
|
|
33
|
-
if (environmentManager.isServer()) return getServerQueryClient();
|
|
34
|
-
browserQueryClient ??= createQueryClient();
|
|
35
|
-
return browserQueryClient;
|
|
36
|
-
}
|
|
17
|
+
});
|