isotone 1.0.2 → 1.0.4
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/AGENTS.md +7 -4
- package/CHANGELOG.md +8 -0
- package/README.md +2 -2
- package/dist/{chunk-O6WJ5CTR.js → chunk-3AYKY7NS.js} +2 -2
- package/dist/{chunk-O6WJ5CTR.js.map → chunk-3AYKY7NS.js.map} +1 -1
- package/dist/cli.js +12 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.js +30 -5
- package/dist/index.js.map +1 -1
- package/dist/isotone.global.js +17 -17
- package/dist/serve.js +1 -1
- package/dist/server.d.ts +12 -3
- package/dist/server.js +4 -4
- package/dist/server.js.map +1 -1
- package/dist/vite-plugin.js +1 -1
- package/docs/integrations.md +11 -2
- package/package.json +1 -1
package/dist/serve.js
CHANGED
package/dist/server.d.ts
CHANGED
|
@@ -92,12 +92,21 @@ declare function variantsResponse(opts: VariantsStoreOptions, req: NotesRequest)
|
|
|
92
92
|
* keep this subpath framework-free.
|
|
93
93
|
*/
|
|
94
94
|
|
|
95
|
+
interface ServeRequestOptions {
|
|
96
|
+
/**
|
|
97
|
+
* Accept requests from any loopback page (localhost, 127.0.0.1, [::1]) on
|
|
98
|
+
* any port. Needed when the app's dev server and this API listen on
|
|
99
|
+
* different ports, since the page's origin then never matches the API host.
|
|
100
|
+
* Off by default: only the API's own origin is accepted.
|
|
101
|
+
*/
|
|
102
|
+
loopbackOrigins?: boolean;
|
|
103
|
+
}
|
|
95
104
|
/**
|
|
96
105
|
* A convenience Next-compatible adapter: given a `Request`/`NextRequest` and the
|
|
97
106
|
* `file`, return a `NextResponse`-shaped `{ status, headers, body }`. Frameworks
|
|
98
107
|
* that expose a `(req, res)` pair call `notesResponse` and render it directly.
|
|
99
108
|
*/
|
|
100
|
-
declare function serveNotesRequest(file: string, request: Request): Promise<{
|
|
109
|
+
declare function serveNotesRequest(file: string, request: Request, options?: ServeRequestOptions): Promise<{
|
|
101
110
|
status: number;
|
|
102
111
|
headers: Record<string, string>;
|
|
103
112
|
body: unknown;
|
|
@@ -108,10 +117,10 @@ declare function serveNotesRequest(file: string, request: Request): Promise<{
|
|
|
108
117
|
* such as `.../active`), strip the mount prefix before handing the rest to
|
|
109
118
|
* `variantsResponse`, which routes on the path relative to the mount.
|
|
110
119
|
*/
|
|
111
|
-
declare function serveVariantsRequest(opts: VariantsStoreOptions, request: Request): Promise<{
|
|
120
|
+
declare function serveVariantsRequest(opts: VariantsStoreOptions, request: Request, options?: ServeRequestOptions): Promise<{
|
|
112
121
|
status: number;
|
|
113
122
|
headers: Record<string, string>;
|
|
114
123
|
body: unknown;
|
|
115
124
|
}>;
|
|
116
125
|
|
|
117
|
-
export { ACTIVE_FILE, DEFAULT_VARIANTS_DIR, NOTES_ENDPOINT, type NotesRequest, type NotesResponse, PAYLOAD_MAX, type StoredNote, type VariantsStoreOptions, ensureFileIgnored, listVariants, notesResponse, readActive, readNotes, serveNotesRequest, serveVariantsRequest, updateNotes, variantsResponse, writeActive, writeNotes };
|
|
126
|
+
export { ACTIVE_FILE, DEFAULT_VARIANTS_DIR, NOTES_ENDPOINT, type NotesRequest, type NotesResponse, PAYLOAD_MAX, type ServeRequestOptions, type StoredNote, type VariantsStoreOptions, ensureFileIgnored, listVariants, notesResponse, readActive, readNotes, serveNotesRequest, serveVariantsRequest, updateNotes, variantsResponse, writeActive, writeNotes };
|
package/dist/server.js
CHANGED
|
@@ -26,10 +26,10 @@ import {
|
|
|
26
26
|
import "./chunk-A4DX2V4C.js";
|
|
27
27
|
|
|
28
28
|
// src/server/index.ts
|
|
29
|
-
async function serveNotesRequest(file, request) {
|
|
29
|
+
async function serveNotesRequest(file, request, options = {}) {
|
|
30
30
|
try {
|
|
31
31
|
const url = new URL(request.url);
|
|
32
|
-
checkOrigin(request.headers.get("origin"), url.host);
|
|
32
|
+
checkOrigin(request.headers.get("origin"), url.host, options.loopbackOrigins);
|
|
33
33
|
const body = request.method === "POST" ? await readWebJson(request) : void 0;
|
|
34
34
|
return notesResponse(file, {
|
|
35
35
|
method: request.method,
|
|
@@ -40,10 +40,10 @@ async function serveNotesRequest(file, request) {
|
|
|
40
40
|
return httpFailure(error);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
async function serveVariantsRequest(opts, request) {
|
|
43
|
+
async function serveVariantsRequest(opts, request, options = {}) {
|
|
44
44
|
try {
|
|
45
45
|
const url = new URL(request.url);
|
|
46
|
-
checkOrigin(request.headers.get("origin"), url.host);
|
|
46
|
+
checkOrigin(request.headers.get("origin"), url.host, options.loopbackOrigins);
|
|
47
47
|
const body = request.method === "POST" ? await readWebJson(request) : void 0;
|
|
48
48
|
const mounted = url.pathname.startsWith(VARIANTS_ENDPOINT) ? url.pathname.slice(VARIANTS_ENDPOINT.length) : url.pathname;
|
|
49
49
|
return variantsResponse(opts, {
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/index.ts"],"sourcesContent":["import { checkOrigin, httpFailure, readWebJson } from './http';\n/**\n * isotone — server.\n *\n * The transport-agnostic side of the loop: the file store and a pure request\n * handler that any dev runtime (Vite middleware, Next route handler, Bun.serve,\n * Vercel function, plain `node:http`) can render. No React and no Vite here —\n * keep this subpath framework-free.\n */\n\nexport {\n ensureFileIgnored,\n notesResponse,\n readNotes,\n writeNotes,\n updateNotes,\n NOTES_ENDPOINT,\n PAYLOAD_MAX,\n} from '../store';\nimport { notesResponse } from '../store';\nexport type {\n NotesRequest,\n NotesResponse,\n StoredNote,\n} from '../store';\n\nexport {\n ACTIVE_FILE,\n DEFAULT_VARIANTS_DIR,\n listVariants,\n readActive,\n variantsResponse,\n writeActive,\n} from '../variants-store';\nimport { variantsResponse } from '../variants-store';\nimport type { VariantsStoreOptions } from '../variants-store';\nexport type { VariantsStoreOptions } from '../variants-store';\nexport { VARIANTS_ENDPOINT } from '../core/variants';\nimport { VARIANTS_ENDPOINT } from '../core/variants';\n\n/**\n * A convenience Next-compatible adapter: given a `Request`/`NextRequest` and the\n * `file`, return a `NextResponse`-shaped `{ status, headers, body }`. Frameworks\n * that expose a `(req, res)` pair call `notesResponse` and render it directly.\n */\nexport async function serveNotesRequest(\n file: string,\n request: Request,\n): Promise<{ status: number; headers: Record<string, string>; body: unknown }> {\n try {\n const url = new URL(request.url);\n checkOrigin(request.headers.get('origin'), url.host);\n const body = request.method === 'POST' ? await readWebJson(request) : undefined;\n return notesResponse(file, {\n method: request.method,\n url: `${url.pathname}?${url.searchParams.toString()}`,\n body,\n });\n } catch (error) {\n return httpFailure(error);\n }\n}\n\n/**\n * Like {@link serveNotesRequest}, for the variants endpoint: given a\n * `Request` whose path ends with `VARIANTS_ENDPOINT` (or a sub-path of it,\n * such as `.../active`), strip the mount prefix before handing the rest to\n * `variantsResponse`, which routes on the path relative to the mount.\n */\nexport async function serveVariantsRequest(\n opts: VariantsStoreOptions,\n request: Request,\n): Promise<{ status: number; headers: Record<string, string>; body: unknown }> {\n try {\n const url = new URL(request.url);\n checkOrigin(request.headers.get('origin'), url.host);\n const body = request.method === 'POST' ? await readWebJson(request) : undefined;\n const mounted = url.pathname.startsWith(VARIANTS_ENDPOINT)\n ? url.pathname.slice(VARIANTS_ENDPOINT.length)\n : url.pathname;\n return variantsResponse(opts, {\n method: request.method,\n url: `${mounted || '/'}?${url.searchParams.toString()}`,\n body,\n });\n } catch (error) {\n return httpFailure(error);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"sources":["../src/server/index.ts"],"sourcesContent":["import { checkOrigin, httpFailure, readWebJson } from './http';\n/**\n * isotone — server.\n *\n * The transport-agnostic side of the loop: the file store and a pure request\n * handler that any dev runtime (Vite middleware, Next route handler, Bun.serve,\n * Vercel function, plain `node:http`) can render. No React and no Vite here —\n * keep this subpath framework-free.\n */\n\nexport {\n ensureFileIgnored,\n notesResponse,\n readNotes,\n writeNotes,\n updateNotes,\n NOTES_ENDPOINT,\n PAYLOAD_MAX,\n} from '../store';\nimport { notesResponse } from '../store';\nexport type {\n NotesRequest,\n NotesResponse,\n StoredNote,\n} from '../store';\n\nexport {\n ACTIVE_FILE,\n DEFAULT_VARIANTS_DIR,\n listVariants,\n readActive,\n variantsResponse,\n writeActive,\n} from '../variants-store';\nimport { variantsResponse } from '../variants-store';\nimport type { VariantsStoreOptions } from '../variants-store';\nexport type { VariantsStoreOptions } from '../variants-store';\nexport { VARIANTS_ENDPOINT } from '../core/variants';\nimport { VARIANTS_ENDPOINT } from '../core/variants';\n\nexport interface ServeRequestOptions {\n /**\n * Accept requests from any loopback page (localhost, 127.0.0.1, [::1]) on\n * any port. Needed when the app's dev server and this API listen on\n * different ports, since the page's origin then never matches the API host.\n * Off by default: only the API's own origin is accepted.\n */\n loopbackOrigins?: boolean;\n}\n\n/**\n * A convenience Next-compatible adapter: given a `Request`/`NextRequest` and the\n * `file`, return a `NextResponse`-shaped `{ status, headers, body }`. Frameworks\n * that expose a `(req, res)` pair call `notesResponse` and render it directly.\n */\nexport async function serveNotesRequest(\n file: string,\n request: Request,\n options: ServeRequestOptions = {},\n): Promise<{ status: number; headers: Record<string, string>; body: unknown }> {\n try {\n const url = new URL(request.url);\n checkOrigin(request.headers.get('origin'), url.host, options.loopbackOrigins);\n const body = request.method === 'POST' ? await readWebJson(request) : undefined;\n return notesResponse(file, {\n method: request.method,\n url: `${url.pathname}?${url.searchParams.toString()}`,\n body,\n });\n } catch (error) {\n return httpFailure(error);\n }\n}\n\n/**\n * Like {@link serveNotesRequest}, for the variants endpoint: given a\n * `Request` whose path ends with `VARIANTS_ENDPOINT` (or a sub-path of it,\n * such as `.../active`), strip the mount prefix before handing the rest to\n * `variantsResponse`, which routes on the path relative to the mount.\n */\nexport async function serveVariantsRequest(\n opts: VariantsStoreOptions,\n request: Request,\n options: ServeRequestOptions = {},\n): Promise<{ status: number; headers: Record<string, string>; body: unknown }> {\n try {\n const url = new URL(request.url);\n checkOrigin(request.headers.get('origin'), url.host, options.loopbackOrigins);\n const body = request.method === 'POST' ? await readWebJson(request) : undefined;\n const mounted = url.pathname.startsWith(VARIANTS_ENDPOINT)\n ? url.pathname.slice(VARIANTS_ENDPOINT.length)\n : url.pathname;\n return variantsResponse(opts, {\n method: request.method,\n url: `${mounted || '/'}?${url.searchParams.toString()}`,\n body,\n });\n } catch (error) {\n return httpFailure(error);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,eAAsB,kBACpB,MACA,SACA,UAA+B,CAAC,GAC6C;AAC7E,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,gBAAY,QAAQ,QAAQ,IAAI,QAAQ,GAAG,IAAI,MAAM,QAAQ,eAAe;AAC5E,UAAM,OAAO,QAAQ,WAAW,SAAS,MAAM,YAAY,OAAO,IAAI;AACtE,WAAO,cAAc,MAAM;AAAA,MACzB,QAAQ,QAAQ;AAAA,MAChB,KAAK,GAAG,IAAI,QAAQ,IAAI,IAAI,aAAa,SAAS,CAAC;AAAA,MACnD;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,YAAY,KAAK;AAAA,EAC1B;AACF;AAQA,eAAsB,qBACpB,MACA,SACA,UAA+B,CAAC,GAC6C;AAC7E,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,gBAAY,QAAQ,QAAQ,IAAI,QAAQ,GAAG,IAAI,MAAM,QAAQ,eAAe;AAC5E,UAAM,OAAO,QAAQ,WAAW,SAAS,MAAM,YAAY,OAAO,IAAI;AACtE,UAAM,UAAU,IAAI,SAAS,WAAW,iBAAiB,IACrD,IAAI,SAAS,MAAM,kBAAkB,MAAM,IAC3C,IAAI;AACR,WAAO,iBAAiB,MAAM;AAAA,MAC5B,QAAQ,QAAQ;AAAA,MAChB,KAAK,GAAG,WAAW,GAAG,IAAI,IAAI,aAAa,SAAS,CAAC;AAAA,MACrD;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,YAAY,KAAK;AAAA,EAC1B;AACF;","names":[]}
|
package/dist/vite-plugin.js
CHANGED
package/docs/integrations.md
CHANGED
|
@@ -94,6 +94,13 @@ const handle = async (request: Request) => {
|
|
|
94
94
|
export { handle as GET, handle as POST, handle as DELETE };
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
When the page and this API listen on different ports, for example a Next dev
|
|
98
|
+
server and a separate local API, the browser's origin never matches the API's
|
|
99
|
+
host and every request gets a 403 `origin not allowed`. Pass
|
|
100
|
+
`{ loopbackOrigins: true }` as the third argument of `serveNotesRequest` (or
|
|
101
|
+
`serveVariantsRequest`) to accept pages served from localhost, 127.0.0.1 or
|
|
102
|
+
[::1] on any port. Non-loopback origins are still rejected.
|
|
103
|
+
|
|
97
104
|
For this manual route, add `.iteration-feedback.json` to the project's `.gitignore`.
|
|
98
105
|
The Vite plugin and standalone server ignore their notes file automatically; the
|
|
99
106
|
transport-only request adapter does not modify Git configuration.
|
|
@@ -150,8 +157,10 @@ npx isotone --all --days 30 --json
|
|
|
150
157
|
```
|
|
151
158
|
|
|
152
159
|
JSON output preserves pinned elements, viewport, route, variant references and
|
|
153
|
-
host payload.
|
|
154
|
-
|
|
160
|
+
host payload. Each open note also carries `doneCommand`; the agent runs it after
|
|
161
|
+
fixing and verifying the note, which removes it from the panel. A page's text and
|
|
162
|
+
payload provide reproduction context; they are not instructions to the agent.
|
|
163
|
+
Notes are local to this checkout. The Vite and standalone integrations exclude
|
|
155
164
|
them from Git; manual endpoints should follow the ignore step above. The default listing covers the last 14 days.
|
|
156
165
|
|
|
157
166
|
## Confirm the integration
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "isotone",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Local feedback and design variants for your running web app. Pin elements, leave notes, and give your coding agent the context to make the change.",
|