@camada/sveltekit 0.1.4 → 0.2.0
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/README.md +3 -2
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -67,8 +67,9 @@ if camada were not installed.
|
|
|
67
67
|
4. **Block** → `403` with `x-block-reason` before `resolve()`; the event still ships, with
|
|
68
68
|
`st: 403` and `blk: <reason>` so the analyst counts SDK blocks apart from your own 403s.
|
|
69
69
|
5. **Skip** → a skip rule or the allow list wins over a wider block.
|
|
70
|
-
6. **Challenge** → a `403` proof-of-work page (HTML navigations)
|
|
71
|
-
|
|
70
|
+
6. **Challenge** → a `403` proof-of-work page (HTML navigations); API and `fetch()` calls
|
|
71
|
+
pass to your app with `x-camada-challenge: 1` on the response (and `chs: 1` on the event) so your
|
|
72
|
+
frontend can choose to challenge; `POST /__camada/challenge` verifies the solution, sets `_cch` and 302s back.
|
|
72
73
|
The solve is a form POST, so SvelteKit's own cross-site form check (`csrf.checkOrigin`) applies
|
|
73
74
|
to it: on **adapter-node served over plain http** (a local run, or a proxy that terminates TLS
|
|
74
75
|
without forwarding the scheme) set the `ORIGIN` env var to the public origin
|
package/dist/index.cjs
CHANGED
|
@@ -44,7 +44,7 @@ var import_iife_string = __toESM(require("@camada/browser/iife-string"), 1);
|
|
|
44
44
|
|
|
45
45
|
// package.json
|
|
46
46
|
var name = "@camada/sveltekit";
|
|
47
|
-
var version = "0.
|
|
47
|
+
var version = "0.2.0";
|
|
48
48
|
|
|
49
49
|
// src/version.ts
|
|
50
50
|
var SDK_ID = `${name}/${version}`;
|
|
@@ -115,7 +115,7 @@ function camada(opts = {}) {
|
|
|
115
115
|
return new Response(null, { status: 302, headers: { location: (0, import_core.safeReturnTo)(url.searchParams.get("to")), "cache-control": "no-store" } });
|
|
116
116
|
}, null);
|
|
117
117
|
if (bounce) return bounce;
|
|
118
|
-
const r = await cam.before(event.request, ctx);
|
|
118
|
+
const r = await cam.before(event.request, { ...ctx, navigation: event.isDataRequest });
|
|
119
119
|
if (!r) return resolve(event);
|
|
120
120
|
if (r.response) return forNavigation(event.request, r.response, bouncePath);
|
|
121
121
|
const vars = r.vars;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/camada.ts","../package.json","../src/version.ts"],"sourcesContent":["// @camada/sveltekit — the one-line install for a SvelteKit app, in src/hooks.server.ts:\n// export const handle = camada(); // env: CAMADA_KEY (+ CAMADA_INGEST_URL / CAMADA_SNAPSHOT_URL in dev)\n// scriptTag(event) // the first-party beacon, returned from a load() into the page\n// track(event, 'login_failed', { user }) // an outcome the wire cannot show\nexport { camada, track, scriptTag, resetCamada, type CamadaSvelteKitOptions, type CamadaSvelteKitVars } from './camada.js';\n","// @camada/sveltekit — the `handle` hook that binds @camada/core/fetch to a SvelteKit app. The\n// pipeline (verdict, block, challenge, beacon, the event) lives in core; this file only says what\n// SvelteKit knows: the adapter-resolved client address, the per-request env and execution context\n// an edge adapter hands over, the cookie API, and `event.locals` as the per-request slot.\nimport type { Handle, RequestEvent } from '@sveltejs/kit';\nimport { guarded, safeReturnTo, TAP_SVELTEKIT } from '@camada/core';\nimport { createFetchCamada, withRid, withSetCookie, track as coreTrack, scriptTag as coreScriptTag, type FetchCamada, type FetchCamadaOptions, type FetchRequestContext, type FetchVars } from '@camada/core/fetch';\nimport iife from '@camada/browser/iife-string';\nimport { SDK_ID } from './version.js';\n\nexport type CamadaSvelteKitOptions = FetchCamadaOptions;\nexport type CamadaSvelteKitVars = FetchVars;\n\nconst VAR = '__camada'; // private: track() and scriptTag() are the API, not event.locals\nconst instances = new Set<FetchCamada>();\n\ntype Env = Record<string, string | undefined>;\n\n/** What adapter-cloudflare puts on `event.platform`; every field is optional because other adapters put nothing there. */\ninterface CfPlatform {\n env?: Env;\n context?: { waitUntil(p: Promise<unknown>): void };\n cf?: { asn?: number; country?: string; tlsClientExtensionsSha1?: string; httpProtocol?: string };\n}\n\nconst slotOf = (event: RequestEvent): FetchVars | undefined =>\n guarded(() => (event.locals as Record<string, unknown>)[VAR] as FetchVars | undefined, undefined);\n\n/** Everything the runtime vouches for. Nothing here is read from a client header. */\nfunction contextOf(event: RequestEvent): FetchRequestContext {\n const platform = event.platform as CfPlatform | undefined;\n // process.env on adapter-node (and nodejs_compat Workers), the bindings on adapter-cloudflare;\n // a binding can be a KV namespace, so the merge is guarded and core reads only CAMADA_* keys.\n const env = guarded<Env>(() => ({ ...(globalThis as { process?: { env?: Env } }).process?.env, ...platform?.env }), {});\n let peer: string | null = null;\n try { peer = event.getClientAddress(); } catch { /* prerendering, or an adapter with no socket: nothing vouched for */ }\n const exec = platform?.context;\n const cf = platform?.cf;\n return {\n peer, env,\n waitUntil: exec ? (p) => exec.waitUntil(p) : undefined,\n asn: cf?.asn ?? null,\n country: cf?.country ?? null,\n tlsx: cf?.tlsClientExtensionsSha1 ?? null,\n // The connection terminates at Cloudflare, so `cf.httpProtocol` is the visitor's own hop.\n httpVersion: cf?.httpProtocol ? cf.httpProtocol.replace(/^HTTP\\//i, '') : null,\n };\n}\n\nconst DATA_SUFFIX = '/__data.json';\nconst HTML_DATA_SUFFIX = '.html__data.json';\n\n/** The page a SvelteKit `__data.json` request loads data for, or null when `url` is not one\n * (kit's own strip_data_suffix, plus its trailing-slash and invalidation params). */\nfunction dataRequestPage(url: URL): string | null {\n let path: string;\n if (url.pathname.endsWith(HTML_DATA_SUFFIX)) path = url.pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';\n else if (url.pathname.endsWith(DATA_SUFFIX)) path = url.pathname.slice(0, -DATA_SUFFIX.length) || '/';\n else return null;\n const q = new URLSearchParams(url.search);\n if (q.get('x-sveltekit-trailing-slash') === '1' && !path.endsWith('/')) path += '/';\n q.delete('x-sveltekit-trailing-slash');\n q.delete('x-sveltekit-invalidated');\n const search = q.toString();\n return path + (search ? '?' + search : '');\n}\n\n/**\n * A challenged client-side navigation (camada-all-wjln). SvelteKit's client fetches\n * `<path>/__data.json` and renders the root error page for a 403 there, so the visitor would never\n * meet the challenge. A data `{\"type\":\"redirect\"}` to the page itself does not help: the client\n * follows it client-side, fetches `__data.json` again and loops into its 20-redirect error. So the\n * redirect points at camada's bounce path (`<scriptPath dir>/reload?to=<page>`). No app route\n * matches it, so the client falls back to a native navigation (`location.href`), and the bounce\n * then 302s that document request to the page, which gets the HTML challenge. Every other answer,\n * and any request that is not a `__data.json` fetch (an API call from app code), is left as it is.\n */\nfunction forNavigation(req: Request, res: Response, bouncePath: string): Response {\n return guarded(() => {\n if (res.status !== 403 || res.headers.get('x-camada-challenge') !== '1') return res;\n const page = dataRequestPage(new URL(req.url));\n if (page === null) return res;\n void res.body?.cancel().catch(() => {});\n return new Response(JSON.stringify({ type: 'redirect', location: `${bouncePath}?to=${encodeURIComponent(page)}` }), {\n status: 200, headers: { 'content-type': 'application/json', 'cache-control': 'no-store', 'x-camada-challenge': '1' },\n });\n }, res);\n}\n\n/**\n * The `handle` for `src/hooks.server.ts`: `export const handle = camada()`, or first in a\n * `sequence()`. Reads `CAMADA_KEY` (+ `CAMADA_INGEST_URL` / `CAMADA_SNAPSHOT_URL`) from\n * `process.env` or the Cloudflare bindings; inert without a key. One pipeline per call.\n */\nexport function camada(opts: CamadaSvelteKitOptions = {}): Handle {\n const cam = createFetchCamada({ tap: TAP_SVELTEKIT, sdk: SDK_ID, iife }, opts); // mode defaults to lazy in core: the handle may run on edge/serverless\n instances.add(cam);\n const bouncePath = (opts.scriptPath ?? '/_cam/b.js').replace(/[^/]*$/, 'reload'); // beside the beacon: camada's own directory\n return async ({ event, resolve }) => {\n // A server-side `event.fetch` to the app's own routes runs the handle again on a fresh event\n // with no user-agent or accept: one page view is one event, and the page-level verdict must\n // not be re-applied to the server's own load().\n if (event.isSubRequest) return resolve(event);\n const ctx = contextOf(event);\n // The bounce a challenged data request sends the client through (see forNavigation): a\n // same-site 302 back to the page, which then meets the verdict as a document request. Only\n // while camada is active (core's own inert test: a key, and no CAMADA_DISABLED=1); otherwise\n // the path is the app's.\n const bounce = guarded(() => {\n const url = new URL(event.request.url);\n if (event.request.method !== 'GET' || url.pathname !== bouncePath) return null;\n if (!cam.active(ctx)) return null;\n return new Response(null, { status: 302, headers: { location: safeReturnTo(url.searchParams.get('to')), 'cache-control': 'no-store' } });\n }, null);\n if (bounce) return bounce;\n const r = await cam.before(event.request, ctx);\n if (!r) return resolve(event);\n if (r.response) return forNavigation(event.request, r.response, bouncePath);\n const vars = r.vars;\n guarded(() => { (event.locals as Record<string, unknown>)[VAR] = vars; }, undefined);\n // The _sfp cookie rides the response, not `event.cookies.set`: SvelteKit appends those in place\n // after resolve(), which throws on an immutable Response (a `fetch()` result, `Response.redirect()`).\n // withSetCookie copies such a response; the hook sees it, so the 500 never happens.\n const res = await resolve(event);\n // SvelteKit swaps a 200 carrying an etag for a bodiless 304 after this hook when the client's\n // If-None-Match matches, dropping the body unread: waiting on it would never ship, so an\n // etagged response ships now even when it is an event stream. (That 304 is built by SvelteKit\n // from a fixed header allow-list, so it carries no x-rid; the hook cannot change that.)\n const out = guarded(() => (vars.sessionCookie ? withSetCookie(res, vars.sessionCookie) : res), res);\n if (out.headers.has('etag')) { cam.after(event.request, vars, out.status); return guarded(() => withRid(out, vars), out); }\n return cam.finish(event.request, vars, out); // an SSE body ships once it has gone out; anything else ships now, untouched\n };\n}\n\n/**\n * Records an outcome the app knows and the wire cannot show (`login_failed`, `signup`,\n * `payment_failed`, ...), joined to this request's event by rid and session. The user identifier\n * is HMAC-hashed in-process. Never throws; a no-op where the handle did not run for this event.\n */\nexport const track = (event: RequestEvent, et: string, data?: { user?: string }): Promise<void> => coreTrack(slotOf(event), et, data);\n\n/** The beacon `<script>` tag for this request's page; `''` where the handle did not run or the tenant turned the beacon off. */\nexport const scriptTag = (event: RequestEvent): string => coreScriptTag(slotOf(event));\n\n/** Test/reset hook: stops and drops every engine of every handle this module created. */\nexport function resetCamada(): void {\n for (const cam of instances) cam.reset();\n}\n","{\n \"name\": \"@camada/sveltekit\",\n \"version\": \"0.1.4\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"check\": \"tsc --noEmit\"\n },\n \"description\": \"camada SDK for SvelteKit (hooks.server.ts handle): snapshot enforcement, first-party challenge and beacon, track() outcomes, waitUntil-flushed event shipping on Cloudflare\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"dependencies\": {\n \"@camada/core\": \"file:../camada-core\",\n \"@camada/browser\": \"file:../camada-browser\"\n },\n \"peerDependencies\": {\n \"@sveltejs/kit\": \">=2\"\n },\n \"devDependencies\": {\n \"@sveltejs/kit\": \"^2.0.0\",\n \"@types/node\": \"^22.10.0\",\n \"svelte\": \"^5.0.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^8.0.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n","// The SDK's wire identity (SDK-03): x-camada-sdk: <package>/<version>. Named JSON imports are\n// inlined and tree-shaken by tsup at build, so dist carries two literals — no runtime fs read.\nimport { name, version } from '../package.json';\nexport const SDK_ID = `${name}/${version}`;\n"],"mappings":"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","names":["iife","coreTrack","coreScriptTag"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/camada.ts","../package.json","../src/version.ts"],"sourcesContent":["// @camada/sveltekit — the one-line install for a SvelteKit app, in src/hooks.server.ts:\n// export const handle = camada(); // env: CAMADA_KEY (+ CAMADA_INGEST_URL / CAMADA_SNAPSHOT_URL in dev)\n// scriptTag(event) // the first-party beacon, returned from a load() into the page\n// track(event, 'login_failed', { user }) // an outcome the wire cannot show\nexport { camada, track, scriptTag, resetCamada, type CamadaSvelteKitOptions, type CamadaSvelteKitVars } from './camada.js';\n","// @camada/sveltekit — the `handle` hook that binds @camada/core/fetch to a SvelteKit app. The\n// pipeline (verdict, block, challenge, beacon, the event) lives in core; this file only says what\n// SvelteKit knows: the adapter-resolved client address, the per-request env and execution context\n// an edge adapter hands over, the cookie API, and `event.locals` as the per-request slot.\nimport type { Handle, RequestEvent } from '@sveltejs/kit';\nimport { guarded, safeReturnTo, TAP_SVELTEKIT } from '@camada/core';\nimport { createFetchCamada, withRid, withSetCookie, track as coreTrack, scriptTag as coreScriptTag, type FetchCamada, type FetchCamadaOptions, type FetchRequestContext, type FetchVars } from '@camada/core/fetch';\nimport iife from '@camada/browser/iife-string';\nimport { SDK_ID } from './version.js';\n\nexport type CamadaSvelteKitOptions = FetchCamadaOptions;\nexport type CamadaSvelteKitVars = FetchVars;\n\nconst VAR = '__camada'; // private: track() and scriptTag() are the API, not event.locals\nconst instances = new Set<FetchCamada>();\n\ntype Env = Record<string, string | undefined>;\n\n/** What adapter-cloudflare puts on `event.platform`; every field is optional because other adapters put nothing there. */\ninterface CfPlatform {\n env?: Env;\n context?: { waitUntil(p: Promise<unknown>): void };\n cf?: { asn?: number; country?: string; tlsClientExtensionsSha1?: string; httpProtocol?: string };\n}\n\nconst slotOf = (event: RequestEvent): FetchVars | undefined =>\n guarded(() => (event.locals as Record<string, unknown>)[VAR] as FetchVars | undefined, undefined);\n\n/** Everything the runtime vouches for. Nothing here is read from a client header. */\nfunction contextOf(event: RequestEvent): FetchRequestContext {\n const platform = event.platform as CfPlatform | undefined;\n // process.env on adapter-node (and nodejs_compat Workers), the bindings on adapter-cloudflare;\n // a binding can be a KV namespace, so the merge is guarded and core reads only CAMADA_* keys.\n const env = guarded<Env>(() => ({ ...(globalThis as { process?: { env?: Env } }).process?.env, ...platform?.env }), {});\n let peer: string | null = null;\n try { peer = event.getClientAddress(); } catch { /* prerendering, or an adapter with no socket: nothing vouched for */ }\n const exec = platform?.context;\n const cf = platform?.cf;\n return {\n peer, env,\n waitUntil: exec ? (p) => exec.waitUntil(p) : undefined,\n asn: cf?.asn ?? null,\n country: cf?.country ?? null,\n tlsx: cf?.tlsClientExtensionsSha1 ?? null,\n // The connection terminates at Cloudflare, so `cf.httpProtocol` is the visitor's own hop.\n httpVersion: cf?.httpProtocol ? cf.httpProtocol.replace(/^HTTP\\//i, '') : null,\n };\n}\n\nconst DATA_SUFFIX = '/__data.json';\nconst HTML_DATA_SUFFIX = '.html__data.json';\n\n/** The page a SvelteKit `__data.json` request loads data for, or null when `url` is not one\n * (kit's own strip_data_suffix, plus its trailing-slash and invalidation params). */\nfunction dataRequestPage(url: URL): string | null {\n let path: string;\n if (url.pathname.endsWith(HTML_DATA_SUFFIX)) path = url.pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';\n else if (url.pathname.endsWith(DATA_SUFFIX)) path = url.pathname.slice(0, -DATA_SUFFIX.length) || '/';\n else return null;\n const q = new URLSearchParams(url.search);\n if (q.get('x-sveltekit-trailing-slash') === '1' && !path.endsWith('/')) path += '/';\n q.delete('x-sveltekit-trailing-slash');\n q.delete('x-sveltekit-invalidated');\n const search = q.toString();\n return path + (search ? '?' + search : '');\n}\n\n/**\n * A challenged client-side navigation (camada-all-wjln). SvelteKit's client fetches\n * `<path>/__data.json` and renders the root error page for a 403 there, so the visitor would never\n * meet the challenge. A data `{\"type\":\"redirect\"}` to the page itself does not help: the client\n * follows it client-side, fetches `__data.json` again and loops into its 20-redirect error. So the\n * redirect points at camada's bounce path (`<scriptPath dir>/reload?to=<page>`). No app route\n * matches it, so the client falls back to a native navigation (`location.href`), and the bounce\n * then 302s that document request to the page, which gets the HTML challenge. Every other answer,\n * and any request that is not a `__data.json` fetch, is left as it is.\n */\nfunction forNavigation(req: Request, res: Response, bouncePath: string): Response {\n return guarded(() => {\n if (res.status !== 403 || res.headers.get('x-camada-challenge') !== '1') return res;\n const page = dataRequestPage(new URL(req.url));\n if (page === null) return res;\n void res.body?.cancel().catch(() => {});\n return new Response(JSON.stringify({ type: 'redirect', location: `${bouncePath}?to=${encodeURIComponent(page)}` }), {\n status: 200, headers: { 'content-type': 'application/json', 'cache-control': 'no-store', 'x-camada-challenge': '1' },\n });\n }, res);\n}\n\n/**\n * The `handle` for `src/hooks.server.ts`: `export const handle = camada()`, or first in a\n * `sequence()`. Reads `CAMADA_KEY` (+ `CAMADA_INGEST_URL` / `CAMADA_SNAPSHOT_URL`) from\n * `process.env` or the Cloudflare bindings; inert without a key. One pipeline per call.\n */\nexport function camada(opts: CamadaSvelteKitOptions = {}): Handle {\n const cam = createFetchCamada({ tap: TAP_SVELTEKIT, sdk: SDK_ID, iife }, opts); // mode defaults to lazy in core: the handle may run on edge/serverless\n instances.add(cam);\n const bouncePath = (opts.scriptPath ?? '/_cam/b.js').replace(/[^/]*$/, 'reload'); // beside the beacon: camada's own directory\n return async ({ event, resolve }) => {\n // A server-side `event.fetch` to the app's own routes runs the handle again on a fresh event\n // with no user-agent or accept: one page view is one event, and the page-level verdict must\n // not be re-applied to the server's own load().\n if (event.isSubRequest) return resolve(event);\n const ctx = contextOf(event);\n // The bounce a challenged data request sends the client through (see forNavigation): a\n // same-site 302 back to the page, which then meets the verdict as a document request. Only\n // while camada is active (core's own inert test: a key, and no CAMADA_DISABLED=1); otherwise\n // the path is the app's.\n const bounce = guarded(() => {\n const url = new URL(event.request.url);\n if (event.request.method !== 'GET' || url.pathname !== bouncePath) return null;\n if (!cam.active(ctx)) return null;\n return new Response(null, { status: 302, headers: { location: safeReturnTo(url.searchParams.get('to')), 'cache-control': 'no-store' } });\n }, null);\n if (bounce) return bounce;\n const r = await cam.before(event.request, { ...ctx, navigation: event.isDataRequest });\n if (!r) return resolve(event);\n if (r.response) return forNavigation(event.request, r.response, bouncePath);\n const vars = r.vars;\n guarded(() => { (event.locals as Record<string, unknown>)[VAR] = vars; }, undefined);\n // The _sfp cookie rides the response, not `event.cookies.set`: SvelteKit appends those in place\n // after resolve(), which throws on an immutable Response (a `fetch()` result, `Response.redirect()`).\n // withSetCookie copies such a response; the hook sees it, so the 500 never happens.\n const res = await resolve(event);\n // SvelteKit swaps a 200 carrying an etag for a bodiless 304 after this hook when the client's\n // If-None-Match matches, dropping the body unread: waiting on it would never ship, so an\n // etagged response ships now even when it is an event stream. (That 304 is built by SvelteKit\n // from a fixed header allow-list, so it carries no x-rid; the hook cannot change that.)\n const out = guarded(() => (vars.sessionCookie ? withSetCookie(res, vars.sessionCookie) : res), res);\n if (out.headers.has('etag')) { cam.after(event.request, vars, out.status); return guarded(() => withRid(out, vars), out); }\n return cam.finish(event.request, vars, out); // an SSE body ships once it has gone out; anything else ships now, untouched\n };\n}\n\n/**\n * Records an outcome the app knows and the wire cannot show (`login_failed`, `signup`,\n * `payment_failed`, ...), joined to this request's event by rid and session. The user identifier\n * is HMAC-hashed in-process. Never throws; a no-op where the handle did not run for this event.\n */\nexport const track = (event: RequestEvent, et: string, data?: { user?: string }): Promise<void> => coreTrack(slotOf(event), et, data);\n\n/** The beacon `<script>` tag for this request's page; `''` where the handle did not run or the tenant turned the beacon off. */\nexport const scriptTag = (event: RequestEvent): string => coreScriptTag(slotOf(event));\n\n/** Test/reset hook: stops and drops every engine of every handle this module created. */\nexport function resetCamada(): void {\n for (const cam of instances) cam.reset();\n}\n","{\n \"name\": \"@camada/sveltekit\",\n \"version\": \"0.2.0\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"check\": \"tsc --noEmit\"\n },\n \"description\": \"camada SDK for SvelteKit (hooks.server.ts handle): snapshot enforcement, first-party challenge and beacon, track() outcomes, waitUntil-flushed event shipping on Cloudflare\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"dependencies\": {\n \"@camada/core\": \"file:../camada-core\",\n \"@camada/browser\": \"file:../camada-browser\"\n },\n \"peerDependencies\": {\n \"@sveltejs/kit\": \">=2\"\n },\n \"devDependencies\": {\n \"@sveltejs/kit\": \"^2.0.0\",\n \"@types/node\": \"^22.10.0\",\n \"svelte\": \"^5.0.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^8.0.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n","// The SDK's wire identity (SDK-03): x-camada-sdk: <package>/<version>. Named JSON imports are\n// inlined and tree-shaken by tsup at build, so dist carries two literals — no runtime fs read.\nimport { name, version } from '../package.json';\nexport const SDK_ID = `${name}/${version}`;\n"],"mappings":"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","names":["iife","coreTrack","coreScriptTag"]}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import iife from "@camada/browser/iife-string";
|
|
|
5
5
|
|
|
6
6
|
// package.json
|
|
7
7
|
var name = "@camada/sveltekit";
|
|
8
|
-
var version = "0.
|
|
8
|
+
var version = "0.2.0";
|
|
9
9
|
|
|
10
10
|
// src/version.ts
|
|
11
11
|
var SDK_ID = `${name}/${version}`;
|
|
@@ -76,7 +76,7 @@ function camada(opts = {}) {
|
|
|
76
76
|
return new Response(null, { status: 302, headers: { location: safeReturnTo(url.searchParams.get("to")), "cache-control": "no-store" } });
|
|
77
77
|
}, null);
|
|
78
78
|
if (bounce) return bounce;
|
|
79
|
-
const r = await cam.before(event.request, ctx);
|
|
79
|
+
const r = await cam.before(event.request, { ...ctx, navigation: event.isDataRequest });
|
|
80
80
|
if (!r) return resolve(event);
|
|
81
81
|
if (r.response) return forNavigation(event.request, r.response, bouncePath);
|
|
82
82
|
const vars = r.vars;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/camada.ts","../package.json","../src/version.ts"],"sourcesContent":["// @camada/sveltekit — the `handle` hook that binds @camada/core/fetch to a SvelteKit app. The\n// pipeline (verdict, block, challenge, beacon, the event) lives in core; this file only says what\n// SvelteKit knows: the adapter-resolved client address, the per-request env and execution context\n// an edge adapter hands over, the cookie API, and `event.locals` as the per-request slot.\nimport type { Handle, RequestEvent } from '@sveltejs/kit';\nimport { guarded, safeReturnTo, TAP_SVELTEKIT } from '@camada/core';\nimport { createFetchCamada, withRid, withSetCookie, track as coreTrack, scriptTag as coreScriptTag, type FetchCamada, type FetchCamadaOptions, type FetchRequestContext, type FetchVars } from '@camada/core/fetch';\nimport iife from '@camada/browser/iife-string';\nimport { SDK_ID } from './version.js';\n\nexport type CamadaSvelteKitOptions = FetchCamadaOptions;\nexport type CamadaSvelteKitVars = FetchVars;\n\nconst VAR = '__camada'; // private: track() and scriptTag() are the API, not event.locals\nconst instances = new Set<FetchCamada>();\n\ntype Env = Record<string, string | undefined>;\n\n/** What adapter-cloudflare puts on `event.platform`; every field is optional because other adapters put nothing there. */\ninterface CfPlatform {\n env?: Env;\n context?: { waitUntil(p: Promise<unknown>): void };\n cf?: { asn?: number; country?: string; tlsClientExtensionsSha1?: string; httpProtocol?: string };\n}\n\nconst slotOf = (event: RequestEvent): FetchVars | undefined =>\n guarded(() => (event.locals as Record<string, unknown>)[VAR] as FetchVars | undefined, undefined);\n\n/** Everything the runtime vouches for. Nothing here is read from a client header. */\nfunction contextOf(event: RequestEvent): FetchRequestContext {\n const platform = event.platform as CfPlatform | undefined;\n // process.env on adapter-node (and nodejs_compat Workers), the bindings on adapter-cloudflare;\n // a binding can be a KV namespace, so the merge is guarded and core reads only CAMADA_* keys.\n const env = guarded<Env>(() => ({ ...(globalThis as { process?: { env?: Env } }).process?.env, ...platform?.env }), {});\n let peer: string | null = null;\n try { peer = event.getClientAddress(); } catch { /* prerendering, or an adapter with no socket: nothing vouched for */ }\n const exec = platform?.context;\n const cf = platform?.cf;\n return {\n peer, env,\n waitUntil: exec ? (p) => exec.waitUntil(p) : undefined,\n asn: cf?.asn ?? null,\n country: cf?.country ?? null,\n tlsx: cf?.tlsClientExtensionsSha1 ?? null,\n // The connection terminates at Cloudflare, so `cf.httpProtocol` is the visitor's own hop.\n httpVersion: cf?.httpProtocol ? cf.httpProtocol.replace(/^HTTP\\//i, '') : null,\n };\n}\n\nconst DATA_SUFFIX = '/__data.json';\nconst HTML_DATA_SUFFIX = '.html__data.json';\n\n/** The page a SvelteKit `__data.json` request loads data for, or null when `url` is not one\n * (kit's own strip_data_suffix, plus its trailing-slash and invalidation params). */\nfunction dataRequestPage(url: URL): string | null {\n let path: string;\n if (url.pathname.endsWith(HTML_DATA_SUFFIX)) path = url.pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';\n else if (url.pathname.endsWith(DATA_SUFFIX)) path = url.pathname.slice(0, -DATA_SUFFIX.length) || '/';\n else return null;\n const q = new URLSearchParams(url.search);\n if (q.get('x-sveltekit-trailing-slash') === '1' && !path.endsWith('/')) path += '/';\n q.delete('x-sveltekit-trailing-slash');\n q.delete('x-sveltekit-invalidated');\n const search = q.toString();\n return path + (search ? '?' + search : '');\n}\n\n/**\n * A challenged client-side navigation (camada-all-wjln). SvelteKit's client fetches\n * `<path>/__data.json` and renders the root error page for a 403 there, so the visitor would never\n * meet the challenge. A data `{\"type\":\"redirect\"}` to the page itself does not help: the client\n * follows it client-side, fetches `__data.json` again and loops into its 20-redirect error. So the\n * redirect points at camada's bounce path (`<scriptPath dir>/reload?to=<page>`). No app route\n * matches it, so the client falls back to a native navigation (`location.href`), and the bounce\n * then 302s that document request to the page, which gets the HTML challenge. Every other answer,\n * and any request that is not a `__data.json` fetch (an API call from app code), is left as it is.\n */\nfunction forNavigation(req: Request, res: Response, bouncePath: string): Response {\n return guarded(() => {\n if (res.status !== 403 || res.headers.get('x-camada-challenge') !== '1') return res;\n const page = dataRequestPage(new URL(req.url));\n if (page === null) return res;\n void res.body?.cancel().catch(() => {});\n return new Response(JSON.stringify({ type: 'redirect', location: `${bouncePath}?to=${encodeURIComponent(page)}` }), {\n status: 200, headers: { 'content-type': 'application/json', 'cache-control': 'no-store', 'x-camada-challenge': '1' },\n });\n }, res);\n}\n\n/**\n * The `handle` for `src/hooks.server.ts`: `export const handle = camada()`, or first in a\n * `sequence()`. Reads `CAMADA_KEY` (+ `CAMADA_INGEST_URL` / `CAMADA_SNAPSHOT_URL`) from\n * `process.env` or the Cloudflare bindings; inert without a key. One pipeline per call.\n */\nexport function camada(opts: CamadaSvelteKitOptions = {}): Handle {\n const cam = createFetchCamada({ tap: TAP_SVELTEKIT, sdk: SDK_ID, iife }, opts); // mode defaults to lazy in core: the handle may run on edge/serverless\n instances.add(cam);\n const bouncePath = (opts.scriptPath ?? '/_cam/b.js').replace(/[^/]*$/, 'reload'); // beside the beacon: camada's own directory\n return async ({ event, resolve }) => {\n // A server-side `event.fetch` to the app's own routes runs the handle again on a fresh event\n // with no user-agent or accept: one page view is one event, and the page-level verdict must\n // not be re-applied to the server's own load().\n if (event.isSubRequest) return resolve(event);\n const ctx = contextOf(event);\n // The bounce a challenged data request sends the client through (see forNavigation): a\n // same-site 302 back to the page, which then meets the verdict as a document request. Only\n // while camada is active (core's own inert test: a key, and no CAMADA_DISABLED=1); otherwise\n // the path is the app's.\n const bounce = guarded(() => {\n const url = new URL(event.request.url);\n if (event.request.method !== 'GET' || url.pathname !== bouncePath) return null;\n if (!cam.active(ctx)) return null;\n return new Response(null, { status: 302, headers: { location: safeReturnTo(url.searchParams.get('to')), 'cache-control': 'no-store' } });\n }, null);\n if (bounce) return bounce;\n const r = await cam.before(event.request, ctx);\n if (!r) return resolve(event);\n if (r.response) return forNavigation(event.request, r.response, bouncePath);\n const vars = r.vars;\n guarded(() => { (event.locals as Record<string, unknown>)[VAR] = vars; }, undefined);\n // The _sfp cookie rides the response, not `event.cookies.set`: SvelteKit appends those in place\n // after resolve(), which throws on an immutable Response (a `fetch()` result, `Response.redirect()`).\n // withSetCookie copies such a response; the hook sees it, so the 500 never happens.\n const res = await resolve(event);\n // SvelteKit swaps a 200 carrying an etag for a bodiless 304 after this hook when the client's\n // If-None-Match matches, dropping the body unread: waiting on it would never ship, so an\n // etagged response ships now even when it is an event stream. (That 304 is built by SvelteKit\n // from a fixed header allow-list, so it carries no x-rid; the hook cannot change that.)\n const out = guarded(() => (vars.sessionCookie ? withSetCookie(res, vars.sessionCookie) : res), res);\n if (out.headers.has('etag')) { cam.after(event.request, vars, out.status); return guarded(() => withRid(out, vars), out); }\n return cam.finish(event.request, vars, out); // an SSE body ships once it has gone out; anything else ships now, untouched\n };\n}\n\n/**\n * Records an outcome the app knows and the wire cannot show (`login_failed`, `signup`,\n * `payment_failed`, ...), joined to this request's event by rid and session. The user identifier\n * is HMAC-hashed in-process. Never throws; a no-op where the handle did not run for this event.\n */\nexport const track = (event: RequestEvent, et: string, data?: { user?: string }): Promise<void> => coreTrack(slotOf(event), et, data);\n\n/** The beacon `<script>` tag for this request's page; `''` where the handle did not run or the tenant turned the beacon off. */\nexport const scriptTag = (event: RequestEvent): string => coreScriptTag(slotOf(event));\n\n/** Test/reset hook: stops and drops every engine of every handle this module created. */\nexport function resetCamada(): void {\n for (const cam of instances) cam.reset();\n}\n","{\n \"name\": \"@camada/sveltekit\",\n \"version\": \"0.1.4\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"check\": \"tsc --noEmit\"\n },\n \"description\": \"camada SDK for SvelteKit (hooks.server.ts handle): snapshot enforcement, first-party challenge and beacon, track() outcomes, waitUntil-flushed event shipping on Cloudflare\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"dependencies\": {\n \"@camada/core\": \"file:../camada-core\",\n \"@camada/browser\": \"file:../camada-browser\"\n },\n \"peerDependencies\": {\n \"@sveltejs/kit\": \">=2\"\n },\n \"devDependencies\": {\n \"@sveltejs/kit\": \"^2.0.0\",\n \"@types/node\": \"^22.10.0\",\n \"svelte\": \"^5.0.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^8.0.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n","// The SDK's wire identity (SDK-03): x-camada-sdk: <package>/<version>. Named JSON imports are\n// inlined and tree-shaken by tsup at build, so dist carries two literals — no runtime fs read.\nimport { name, version } from '../package.json';\nexport const SDK_ID = `${name}/${version}`;\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/camada.ts","../package.json","../src/version.ts"],"sourcesContent":["// @camada/sveltekit — the `handle` hook that binds @camada/core/fetch to a SvelteKit app. The\n// pipeline (verdict, block, challenge, beacon, the event) lives in core; this file only says what\n// SvelteKit knows: the adapter-resolved client address, the per-request env and execution context\n// an edge adapter hands over, the cookie API, and `event.locals` as the per-request slot.\nimport type { Handle, RequestEvent } from '@sveltejs/kit';\nimport { guarded, safeReturnTo, TAP_SVELTEKIT } from '@camada/core';\nimport { createFetchCamada, withRid, withSetCookie, track as coreTrack, scriptTag as coreScriptTag, type FetchCamada, type FetchCamadaOptions, type FetchRequestContext, type FetchVars } from '@camada/core/fetch';\nimport iife from '@camada/browser/iife-string';\nimport { SDK_ID } from './version.js';\n\nexport type CamadaSvelteKitOptions = FetchCamadaOptions;\nexport type CamadaSvelteKitVars = FetchVars;\n\nconst VAR = '__camada'; // private: track() and scriptTag() are the API, not event.locals\nconst instances = new Set<FetchCamada>();\n\ntype Env = Record<string, string | undefined>;\n\n/** What adapter-cloudflare puts on `event.platform`; every field is optional because other adapters put nothing there. */\ninterface CfPlatform {\n env?: Env;\n context?: { waitUntil(p: Promise<unknown>): void };\n cf?: { asn?: number; country?: string; tlsClientExtensionsSha1?: string; httpProtocol?: string };\n}\n\nconst slotOf = (event: RequestEvent): FetchVars | undefined =>\n guarded(() => (event.locals as Record<string, unknown>)[VAR] as FetchVars | undefined, undefined);\n\n/** Everything the runtime vouches for. Nothing here is read from a client header. */\nfunction contextOf(event: RequestEvent): FetchRequestContext {\n const platform = event.platform as CfPlatform | undefined;\n // process.env on adapter-node (and nodejs_compat Workers), the bindings on adapter-cloudflare;\n // a binding can be a KV namespace, so the merge is guarded and core reads only CAMADA_* keys.\n const env = guarded<Env>(() => ({ ...(globalThis as { process?: { env?: Env } }).process?.env, ...platform?.env }), {});\n let peer: string | null = null;\n try { peer = event.getClientAddress(); } catch { /* prerendering, or an adapter with no socket: nothing vouched for */ }\n const exec = platform?.context;\n const cf = platform?.cf;\n return {\n peer, env,\n waitUntil: exec ? (p) => exec.waitUntil(p) : undefined,\n asn: cf?.asn ?? null,\n country: cf?.country ?? null,\n tlsx: cf?.tlsClientExtensionsSha1 ?? null,\n // The connection terminates at Cloudflare, so `cf.httpProtocol` is the visitor's own hop.\n httpVersion: cf?.httpProtocol ? cf.httpProtocol.replace(/^HTTP\\//i, '') : null,\n };\n}\n\nconst DATA_SUFFIX = '/__data.json';\nconst HTML_DATA_SUFFIX = '.html__data.json';\n\n/** The page a SvelteKit `__data.json` request loads data for, or null when `url` is not one\n * (kit's own strip_data_suffix, plus its trailing-slash and invalidation params). */\nfunction dataRequestPage(url: URL): string | null {\n let path: string;\n if (url.pathname.endsWith(HTML_DATA_SUFFIX)) path = url.pathname.slice(0, -HTML_DATA_SUFFIX.length) + '.html';\n else if (url.pathname.endsWith(DATA_SUFFIX)) path = url.pathname.slice(0, -DATA_SUFFIX.length) || '/';\n else return null;\n const q = new URLSearchParams(url.search);\n if (q.get('x-sveltekit-trailing-slash') === '1' && !path.endsWith('/')) path += '/';\n q.delete('x-sveltekit-trailing-slash');\n q.delete('x-sveltekit-invalidated');\n const search = q.toString();\n return path + (search ? '?' + search : '');\n}\n\n/**\n * A challenged client-side navigation (camada-all-wjln). SvelteKit's client fetches\n * `<path>/__data.json` and renders the root error page for a 403 there, so the visitor would never\n * meet the challenge. A data `{\"type\":\"redirect\"}` to the page itself does not help: the client\n * follows it client-side, fetches `__data.json` again and loops into its 20-redirect error. So the\n * redirect points at camada's bounce path (`<scriptPath dir>/reload?to=<page>`). No app route\n * matches it, so the client falls back to a native navigation (`location.href`), and the bounce\n * then 302s that document request to the page, which gets the HTML challenge. Every other answer,\n * and any request that is not a `__data.json` fetch, is left as it is.\n */\nfunction forNavigation(req: Request, res: Response, bouncePath: string): Response {\n return guarded(() => {\n if (res.status !== 403 || res.headers.get('x-camada-challenge') !== '1') return res;\n const page = dataRequestPage(new URL(req.url));\n if (page === null) return res;\n void res.body?.cancel().catch(() => {});\n return new Response(JSON.stringify({ type: 'redirect', location: `${bouncePath}?to=${encodeURIComponent(page)}` }), {\n status: 200, headers: { 'content-type': 'application/json', 'cache-control': 'no-store', 'x-camada-challenge': '1' },\n });\n }, res);\n}\n\n/**\n * The `handle` for `src/hooks.server.ts`: `export const handle = camada()`, or first in a\n * `sequence()`. Reads `CAMADA_KEY` (+ `CAMADA_INGEST_URL` / `CAMADA_SNAPSHOT_URL`) from\n * `process.env` or the Cloudflare bindings; inert without a key. One pipeline per call.\n */\nexport function camada(opts: CamadaSvelteKitOptions = {}): Handle {\n const cam = createFetchCamada({ tap: TAP_SVELTEKIT, sdk: SDK_ID, iife }, opts); // mode defaults to lazy in core: the handle may run on edge/serverless\n instances.add(cam);\n const bouncePath = (opts.scriptPath ?? '/_cam/b.js').replace(/[^/]*$/, 'reload'); // beside the beacon: camada's own directory\n return async ({ event, resolve }) => {\n // A server-side `event.fetch` to the app's own routes runs the handle again on a fresh event\n // with no user-agent or accept: one page view is one event, and the page-level verdict must\n // not be re-applied to the server's own load().\n if (event.isSubRequest) return resolve(event);\n const ctx = contextOf(event);\n // The bounce a challenged data request sends the client through (see forNavigation): a\n // same-site 302 back to the page, which then meets the verdict as a document request. Only\n // while camada is active (core's own inert test: a key, and no CAMADA_DISABLED=1); otherwise\n // the path is the app's.\n const bounce = guarded(() => {\n const url = new URL(event.request.url);\n if (event.request.method !== 'GET' || url.pathname !== bouncePath) return null;\n if (!cam.active(ctx)) return null;\n return new Response(null, { status: 302, headers: { location: safeReturnTo(url.searchParams.get('to')), 'cache-control': 'no-store' } });\n }, null);\n if (bounce) return bounce;\n const r = await cam.before(event.request, { ...ctx, navigation: event.isDataRequest });\n if (!r) return resolve(event);\n if (r.response) return forNavigation(event.request, r.response, bouncePath);\n const vars = r.vars;\n guarded(() => { (event.locals as Record<string, unknown>)[VAR] = vars; }, undefined);\n // The _sfp cookie rides the response, not `event.cookies.set`: SvelteKit appends those in place\n // after resolve(), which throws on an immutable Response (a `fetch()` result, `Response.redirect()`).\n // withSetCookie copies such a response; the hook sees it, so the 500 never happens.\n const res = await resolve(event);\n // SvelteKit swaps a 200 carrying an etag for a bodiless 304 after this hook when the client's\n // If-None-Match matches, dropping the body unread: waiting on it would never ship, so an\n // etagged response ships now even when it is an event stream. (That 304 is built by SvelteKit\n // from a fixed header allow-list, so it carries no x-rid; the hook cannot change that.)\n const out = guarded(() => (vars.sessionCookie ? withSetCookie(res, vars.sessionCookie) : res), res);\n if (out.headers.has('etag')) { cam.after(event.request, vars, out.status); return guarded(() => withRid(out, vars), out); }\n return cam.finish(event.request, vars, out); // an SSE body ships once it has gone out; anything else ships now, untouched\n };\n}\n\n/**\n * Records an outcome the app knows and the wire cannot show (`login_failed`, `signup`,\n * `payment_failed`, ...), joined to this request's event by rid and session. The user identifier\n * is HMAC-hashed in-process. Never throws; a no-op where the handle did not run for this event.\n */\nexport const track = (event: RequestEvent, et: string, data?: { user?: string }): Promise<void> => coreTrack(slotOf(event), et, data);\n\n/** The beacon `<script>` tag for this request's page; `''` where the handle did not run or the tenant turned the beacon off. */\nexport const scriptTag = (event: RequestEvent): string => coreScriptTag(slotOf(event));\n\n/** Test/reset hook: stops and drops every engine of every handle this module created. */\nexport function resetCamada(): void {\n for (const cam of instances) cam.reset();\n}\n","{\n \"name\": \"@camada/sveltekit\",\n \"version\": \"0.2.0\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"engines\": {\n \"node\": \">=20\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"check\": \"tsc --noEmit\"\n },\n \"description\": \"camada SDK for SvelteKit (hooks.server.ts handle): snapshot enforcement, first-party challenge and beacon, track() outcomes, waitUntil-flushed event shipping on Cloudflare\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n }\n },\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"dependencies\": {\n \"@camada/core\": \"file:../camada-core\",\n \"@camada/browser\": \"file:../camada-browser\"\n },\n \"peerDependencies\": {\n \"@sveltejs/kit\": \">=2\"\n },\n \"devDependencies\": {\n \"@sveltejs/kit\": \"^2.0.0\",\n \"@types/node\": \"^22.10.0\",\n \"svelte\": \"^5.0.0\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.7.2\",\n \"vite\": \"^8.0.0\",\n \"vitest\": \"^3.0.0\"\n }\n}\n","// The SDK's wire identity (SDK-03): x-camada-sdk: <package>/<version>. Named JSON imports are\n// inlined and tree-shaken by tsup at build, so dist carries two literals — no runtime fs read.\nimport { name, version } from '../package.json';\nexport const SDK_ID = `${name}/${version}`;\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camada/sveltekit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"module": "./dist/index.js",
|
|
29
29
|
"types": "./dist/index.d.ts",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@camada/core": "^0.
|
|
32
|
-
"@camada/browser": "^0.
|
|
31
|
+
"@camada/core": "^0.6.0",
|
|
32
|
+
"@camada/browser": "^0.4.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@sveltejs/kit": ">=2"
|