create-stitchkit 0.6.7 → 0.6.9
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 +28 -0
- package/dist/cli.js +7 -7
- package/package.json +3 -3
- package/template/bun.lock +2 -2
- package/template/e2e/starter.spec.ts +2 -1
- package/template/package.json +2 -2
- package/template/packages/frontend/src/features/board/board-panel.tsx +10 -1
- package/templates/agent/package.json +1 -1
- package/templates/telegram-bot/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,34 @@ step is overwritten by the next release.
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [0.6.9] — 2026-09-29
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Generated projects track Stitchkit `^0.100.3`, which adds Telegram screens,
|
|
20
|
+
message markup, webhook ownership and durable update intake, and keyboard
|
|
21
|
+
layers for React.
|
|
22
|
+
- Generated projects pin `packageManager: bun@1.4.2`, the current Bun, in the
|
|
23
|
+
full-stack, agent and Telegram-bot templates.
|
|
24
|
+
|
|
25
|
+
## [0.6.8] — 2026-09-28
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Generated projects track Stitchkit `^0.100.1`. The catalog stayed on
|
|
30
|
+
`^0.96.1` while 0.97.0–0.100.1 shipped, and on 0.x a caret never crosses a
|
|
31
|
+
minor, so a new project started four minors behind. The generated code needs
|
|
32
|
+
no change; what a project that grows past the new defaults must know — the
|
|
33
|
+
finite watch capacities of 0.100.0 among them — is in Stitchkit's
|
|
34
|
+
`docs/guide/upgrading.md`.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- The board keeps a note typed before the page hydrated. The text reached the
|
|
39
|
+
input but not React's state, so Post stayed disabled over a filled field — a
|
|
40
|
+
slow browser's end-to-end run timed out on it, and a person typing early saw
|
|
41
|
+
the same.
|
|
42
|
+
|
|
15
43
|
## [0.6.7] — 2026-09-24
|
|
16
44
|
|
|
17
45
|
### Fixed
|
package/dist/cli.js
CHANGED
|
@@ -197,8 +197,8 @@ function createApplicationIdentity(destination, displayName) {
|
|
|
197
197
|
}
|
|
198
198
|
});
|
|
199
199
|
}
|
|
200
|
-
function withIdentity(
|
|
201
|
-
const copied = parseProjectDeclaration(
|
|
200
|
+
function withIdentity(declaration, identity) {
|
|
201
|
+
const copied = parseProjectDeclaration(declaration);
|
|
202
202
|
return parseProjectDeclaration({ ...copied, identity });
|
|
203
203
|
}
|
|
204
204
|
|
|
@@ -425,13 +425,13 @@ async function scaffoldProject(templateDirectory, destination, options = {}) {
|
|
|
425
425
|
await rm(join(resolvedDestination, "bun.lock"), { force: true });
|
|
426
426
|
}
|
|
427
427
|
const declarationPath = join(resolvedDestination, "project.json");
|
|
428
|
-
const
|
|
429
|
-
await writeFile(declarationPath, `${JSON.stringify(
|
|
428
|
+
const declaration = withIdentity(JSON.parse(await readFile(declarationPath, "utf8")), identity);
|
|
429
|
+
await writeFile(declarationPath, `${JSON.stringify(declaration, undefined, 2)}
|
|
430
430
|
`);
|
|
431
431
|
if (options.identityModule !== false) {
|
|
432
432
|
const identityPath = join(resolvedDestination, APP_IDENTITY_PATH);
|
|
433
433
|
await mkdir(dirname(identityPath), { recursive: true });
|
|
434
|
-
await writeFile(identityPath, renderAppIdentityModule(
|
|
434
|
+
await writeFile(identityPath, renderAppIdentityModule(declaration.identity));
|
|
435
435
|
}
|
|
436
436
|
const manifestPath = join(resolvedDestination, "package.json");
|
|
437
437
|
const manifest = RootManifestSchema.parse(JSON.parse(await readFile(manifestPath, "utf8")));
|
|
@@ -548,10 +548,10 @@ if (import.meta.main) {
|
|
|
548
548
|
}
|
|
549
549
|
async function roleAddresses(destination) {
|
|
550
550
|
try {
|
|
551
|
-
const
|
|
551
|
+
const declaration = parseProjectDeclaration(JSON.parse(await readFile2(join2(destination, "project.json"), "utf8")));
|
|
552
552
|
const environment = readEnvironmentExample(await readFile2(join2(destination, ".env.example"), "utf8"));
|
|
553
553
|
const host = environment.BIND_HOST ?? "127.0.0.1";
|
|
554
|
-
return
|
|
554
|
+
return declaration.roles.flatMap((role) => {
|
|
555
555
|
const port = role.listener && environment[role.listener.portVariable];
|
|
556
556
|
if (!role.listener || !port)
|
|
557
557
|
return [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-stitchkit",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "Create a production-shaped Stitchkit application",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Max Listov <maxlistov@gmail.com>",
|
|
@@ -84,11 +84,11 @@
|
|
|
84
84
|
"@types/react": "^19.3.0",
|
|
85
85
|
"ai": "^7.0.111",
|
|
86
86
|
"react": "^19.3.0",
|
|
87
|
-
"stitchkit": "0.
|
|
87
|
+
"stitchkit": "0.100.3",
|
|
88
88
|
"typescript": "^7.0.2"
|
|
89
89
|
},
|
|
90
90
|
"engines": {
|
|
91
91
|
"bun": ">=1.2.0"
|
|
92
92
|
},
|
|
93
|
-
"packageManager": "bun@1.
|
|
93
|
+
"packageManager": "bun@1.4.2"
|
|
94
94
|
}
|
package/template/bun.lock
CHANGED
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"zod": "4.6.5",
|
|
146
146
|
},
|
|
147
147
|
"catalog": {
|
|
148
|
-
"stitchkit": "^0.
|
|
148
|
+
"stitchkit": "^0.100.3",
|
|
149
149
|
},
|
|
150
150
|
"packages": {
|
|
151
151
|
"@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.89", "", { "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-n0Q88UUASYQBGK3Ogs9pCe8h3ZXeTHFSuGOLBJAyH73MVGNKUv9w8EJX2f340WUF3eDWWOV305gO7YBpSCPblA=="],
|
|
@@ -1128,7 +1128,7 @@
|
|
|
1128
1128
|
|
|
1129
1129
|
"std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
|
|
1130
1130
|
|
|
1131
|
-
"stitchkit": ["stitchkit@0.
|
|
1131
|
+
"stitchkit": ["stitchkit@0.100.3", "", { "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/entrypoints/bin/upgrade-cli.js" } }, "sha512-FEfMOfEuGe8dn+e4YWN1CK7Q41ZsuPw39YNSz6xMFplhQc6WL8MMIIOvSkEF6eBVPQw7Wo1DGx12df/B/baH5A=="],
|
|
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
|
|
|
@@ -45,7 +45,8 @@ test('a note posted in one tab reaches another through the web origin and the so
|
|
|
45
45
|
const writer = await browser.newPage();
|
|
46
46
|
const reader = await browser.newPage();
|
|
47
47
|
await Promise.all([writer.goto('/en'), reader.goto('/en')]);
|
|
48
|
-
|
|
48
|
+
// Browser projects share the backend and can post in the same millisecond.
|
|
49
|
+
const note = `note ${crypto.randomUUID()}`;
|
|
49
50
|
await writer.getByRole('textbox', { name: 'Note' }).fill(note);
|
|
50
51
|
await writer.getByRole('button', { name: 'Post' }).click();
|
|
51
52
|
await expect(writer.getByText(note)).toBeVisible();
|
package/template/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"packages/*"
|
|
8
8
|
],
|
|
9
9
|
"catalog": {
|
|
10
|
-
"stitchkit": "^0.
|
|
10
|
+
"stitchkit": "^0.100.3"
|
|
11
11
|
},
|
|
12
12
|
"overrides": {
|
|
13
13
|
"@playwright/test": "1.63.0",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"bun": ">=1.2.0",
|
|
65
65
|
"node": ">=22"
|
|
66
66
|
},
|
|
67
|
-
"packageManager": "bun@1.
|
|
67
|
+
"packageManager": "bun@1.4.2"
|
|
68
68
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import type { Board } from '@app/shared';
|
|
4
|
-
import { useEffect, useState } from 'react';
|
|
4
|
+
import { useEffect, useRef, useState } from 'react';
|
|
5
5
|
import type { WatchStateFrame } from 'stitchkit/live';
|
|
6
6
|
import {
|
|
7
7
|
Button,
|
|
@@ -27,6 +27,14 @@ export function BoardPanel({ realtimeOrigin }: { realtimeOrigin?: string }) {
|
|
|
27
27
|
const [state, setState] = useState<WatchStateFrame>();
|
|
28
28
|
const [draft, setDraft] = useState('');
|
|
29
29
|
const [posting, setPosting] = useState(false);
|
|
30
|
+
const draftInput = useRef<HTMLInputElement>(null);
|
|
31
|
+
|
|
32
|
+
// Text typed before hydration is in the input but not in state, which would
|
|
33
|
+
// leave Post disabled over a filled field. Take it once, on mount.
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
const typed = draftInput.current?.value;
|
|
36
|
+
if (typed) setDraft(typed);
|
|
37
|
+
}, []);
|
|
30
38
|
|
|
31
39
|
useEffect(() => {
|
|
32
40
|
const watch = watchBoard(setBoard, setState, realtimeOrigin);
|
|
@@ -60,6 +68,7 @@ export function BoardPanel({ realtimeOrigin }: { realtimeOrigin?: string }) {
|
|
|
60
68
|
maxLength={140}
|
|
61
69
|
onChange={(event) => setDraft(event.target.value)}
|
|
62
70
|
placeholder='Say something, then open a second tab'
|
|
71
|
+
ref={draftInput}
|
|
63
72
|
value={draft}
|
|
64
73
|
/>
|
|
65
74
|
<Button disabled={posting || draft.trim().length === 0} type='submit'>
|