@rsc-kit/core 0.30.47 → 0.30.49

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.
@@ -1 +1 @@
1
- {"version":3,"file":"typegen.js","sourceRoot":"","sources":["../src/typegen.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// rsc-kit-typegen: write the route types without starting Vite.\n//\n// The types - every url the app has, for <Link href> and redirect() - are\n// written when the dev server or a build starts, and again when a dev server\n// sees a route added. A typecheck run with neither, by an agent or in CI,\n// read the types from the last start: a route added since failed with\n// '\"/admin\"' is not assignable to type Route until something started Vite.\n//\n// The app's own vite.config is loaded, through the app's own Vite, so the\n// plugin's options - sourceDir, outDir, a host's route file - are the ones it\n// builds with. Only the plugin's config step runs, which is what writes them.\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join, relative } from \"node:path\";\nimport { cwd, exit, stderr, stdout } from \"node:process\";\nimport { pathToFileURL } from \"node:url\";\n\ninterface PluginLike {\n name?: string;\n config?: (config: object, env: { command: string; mode: string }) => unknown;\n api?: { generatedFiles?: () => string[]; info?: () => Record<string, unknown> };\n}\n\nasync function flatten(option: unknown): Promise<PluginLike[]> {\n const value = await option;\n\n if (Array.isArray(value)) return (await Promise.all(value.map(flatten))).flat();\n\n return value && typeof value === \"object\" ? [value as PluginLike] : [];\n}\n\n/**\n * Write the types; or, with `check`, say which committed generated files are\n * not what the backend and the route tree produce now, and change nothing.\n *\n * For CI: `rsc-kit-typegen --check` fails when rsc-host.json or the types were\n * committed and the backend has moved on since. Only files that were already\n * there are compared - one that is not committed is written fresh by every\n * build and cannot be stale - and every one is put back as it was.\n */\nexport async function typegen(root = cwd(), check = false): Promise<string[]> {\n const local = createRequire(join(root, \"package.json\"));\n let vitePath: string;\n\n try {\n vitePath = local.resolve(\"vite\");\n } catch {\n throw new Error(\"No vite installed in \" + root + \". Run this from the app's directory.\");\n }\n\n const vite = (await import(pathToFileURL(vitePath).href)) as {\n loadConfigFromFile: (\n env: { command: string; mode: string },\n file?: string,\n root?: string,\n ) => Promise<{ config: { plugins?: unknown[] } } | null>;\n };\n\n // As a build would: a manifest command that fails is a failure, not a\n // warning, when the question is whether what is committed is current.\n const env = check ? { command: \"build\", mode: \"production\" } : { command: \"serve\", mode: \"development\" };\n const loaded = await vite.loadConfigFromFile(env, undefined, root);\n\n if (!loaded) throw new Error(\"No vite.config found in \" + root + \".\");\n\n const plugin = (await flatten(loaded.config.plugins ?? [])).find((p) => p.name === \"rsc-kit\");\n\n if (!plugin?.config) throw new Error(\"The vite.config in \" + root + \" does not use rscKit().\");\n\n if (!check) {\n await plugin.config({}, env);\n\n return [];\n }\n\n const files = plugin.api?.generatedFiles?.() ?? [];\n const before = new Map(files.filter((f) => existsSync(f)).map((f) => [f, readFileSync(f, \"utf-8\")]));\n\n try {\n await plugin.config({}, env);\n\n return [...before].filter(([f, text]) => !existsSync(f) || readFileSync(f, \"utf-8\") !== text).map(([f]) => f);\n } finally {\n for (const [f, text] of before) writeFileSync(f, text);\n }\n}\n\n// Run as a command, not when imported.\nif (import.meta.url === pathToFileURL(process.argv[1] ?? \"\").href || process.argv[1]?.endsWith(\"rsc-kit-typegen\")) {\n const check = process.argv.includes(\"--check\");\n\n typegen(cwd(), check)\n .then((stale) => {\n if (!check) {\n stdout.write(\"rsc-kit: route types written\\n\");\n\n return;\n }\n\n if (stale.length === 0) {\n stdout.write(\"rsc-kit: generated files are current\\n\");\n\n return;\n }\n\n stderr.write(\n \"rsc-kit-typegen --check: these are committed and no longer what the backend and the routes produce:\\n\" +\n stale.map((f) => \" \" + relative(cwd(), f)).join(\"\\n\") +\n \"\\nRun rsc-kit-typegen and commit the result.\\n\",\n );\n exit(1);\n })\n .catch((error: unknown) => {\n stderr.write(\"rsc-kit-typegen: \" + (error instanceof Error ? error.message : String(error)) + \"\\n\");\n exit(1);\n });\n}\n\n/**\n * What a build of the app in `root` will produce - `{ output: \"server\", ... }`\n * or `{ output: \"export\", dir }` - read before building, from the app's own\n * Vite config, evaluated the way a build evaluates it. A value computed in\n * the config, or RSC_OUTPUT in the environment, resolves exactly as the build\n * resolves it, because it is the same code deciding.\n */\nexport async function appInfo(root = cwd()): Promise<Record<string, unknown>> {\n const local = createRequire(join(root, \"package.json\"));\n let vitePath: string;\n\n try {\n vitePath = local.resolve(\"vite\");\n } catch {\n throw new Error(\"No vite installed in \" + root + \". Run this from the app's directory.\");\n }\n\n const vite = (await import(pathToFileURL(vitePath).href)) as {\n loadConfigFromFile: (\n env: { command: string; mode: string },\n file?: string,\n root?: string,\n ) => Promise<{ config: { plugins?: unknown[] } } | null>;\n };\n // From inside the app, as a build runs: rscKit() takes its project root\n // from the working directory when the config creates it.\n const from = cwd();\n\n process.chdir(root);\n\n try {\n const loaded = await vite.loadConfigFromFile({ command: \"build\", mode: \"production\" }, undefined, root);\n\n if (!loaded) throw new Error(\"No vite.config found in \" + root + \".\");\n\n const plugin = (await flatten(loaded.config.plugins ?? [])).find((p) => p.name === \"rsc-kit\");\n\n if (!plugin?.api?.info) throw new Error(\"The vite.config in \" + root + \" does not use rscKit().\");\n\n return plugin.api.info();\n } finally {\n process.chdir(from);\n }\n}\n\n"]}
1
+ {"version":3,"file":"typegen.js","sourceRoot":"","sources":["../src/typegen.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n// rsc-kit-typegen: write the route types without starting Vite.\n//\n// The types - every url the app has, for <Link href> and redirect() - are\n// written when the dev server or a build starts, and again when a dev server\n// sees a route added. A typecheck run with neither, by an agent or in CI,\n// read the types from the last start: a route added since failed with\n// '\"/admin\"' is not assignable to type Route until something started Vite.\n//\n// The app's own vite.config is loaded, through the app's own Vite, so the\n// plugin's options - sourceDir, outDir, a host's route file - are the ones it\n// builds with. Only the plugin's config step runs, which is what writes them.\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { basename, join, relative } from \"node:path\";\nimport { cwd, exit, stderr, stdout } from \"node:process\";\nimport { pathToFileURL } from \"node:url\";\n\ninterface PluginLike {\n name?: string;\n config?: (config: object, env: { command: string; mode: string }) => unknown;\n api?: { generatedFiles?: () => string[]; info?: () => Record<string, unknown> };\n}\n\nasync function flatten(option: unknown): Promise<PluginLike[]> {\n const value = await option;\n\n if (Array.isArray(value)) return (await Promise.all(value.map(flatten))).flat();\n\n return value && typeof value === \"object\" ? [value as PluginLike] : [];\n}\n\n/**\n * Write the types; or, with `check`, say which committed generated files are\n * not what the backend and the route tree produce now, and change nothing.\n *\n * For CI: `rsc-kit-typegen --check` fails when rsc-host.json or the types were\n * committed and the backend has moved on since. Only files that were already\n * there are compared - one that is not committed is written fresh by every\n * build and cannot be stale - and every one is put back as it was.\n */\nexport async function typegen(root = cwd(), check = false): Promise<string[]> {\n const local = createRequire(join(root, \"package.json\"));\n let vitePath: string;\n\n try {\n vitePath = local.resolve(\"vite\");\n } catch {\n throw new Error(\"No vite installed in \" + root + \". Run this from the app's directory.\");\n }\n\n const vite = (await import(pathToFileURL(vitePath).href)) as {\n loadConfigFromFile: (\n env: { command: string; mode: string },\n file?: string,\n root?: string,\n ) => Promise<{ config: { plugins?: unknown[] } } | null>;\n };\n\n // As a build would: a manifest command that fails is a failure, not a\n // warning, when the question is whether what is committed is current.\n const env = check ? { command: \"build\", mode: \"production\" } : { command: \"serve\", mode: \"development\" };\n const loaded = await vite.loadConfigFromFile(env, undefined, root);\n\n if (!loaded) throw new Error(\"No vite.config found in \" + root + \".\");\n\n const plugin = (await flatten(loaded.config.plugins ?? [])).find((p) => p.name === \"rsc-kit\");\n\n if (!plugin?.config) throw new Error(\"The vite.config in \" + root + \" does not use rscKit().\");\n\n if (!check) {\n await plugin.config({}, env);\n\n return [];\n }\n\n const files = plugin.api?.generatedFiles?.() ?? [];\n const before = new Map(files.filter((f) => existsSync(f)).map((f) => [f, readFileSync(f, \"utf-8\")]));\n\n try {\n await plugin.config({}, env);\n\n return [...before].filter(([f, text]) => !existsSync(f) || readFileSync(f, \"utf-8\") !== text).map(([f]) => f);\n } finally {\n for (const [f, text] of before) writeFileSync(f, text);\n }\n}\n\n// Run as a command, not when imported.\nif (import.meta.url === pathToFileURL(process.argv[1] ?? \"\").href || process.argv[1]?.endsWith(\"rsc-kit-typegen\")) {\n const check = process.argv.includes(\"--check\");\n\n typegen(cwd(), check)\n .then((stale) => {\n if (!check) {\n stdout.write(\"rsc-kit: route types written\\n\");\n\n return;\n }\n\n if (stale.length === 0) {\n stdout.write(\"rsc-kit: generated files are current\\n\");\n\n return;\n }\n\n stderr.write(\n \"rsc-kit-typegen --check: these are committed and no longer what the backend and the routes produce:\\n\" +\n stale.map((f) => \" \" + relative(cwd(), f)).join(\"\\n\") +\n \"\\nRun rsc-kit-typegen and commit the result.\\n\",\n );\n exit(1);\n })\n .catch((error: unknown) => {\n stderr.write(\"rsc-kit-typegen: \" + (error instanceof Error ? error.message : String(error)) + \"\\n\");\n exit(1);\n });\n}\n\n/**\n * What a build of the app in `root` will produce - `{ output: \"server\", ... }`\n * or `{ output: \"export\", dir }` - read before building, from the app's own\n * Vite config, evaluated the way a build evaluates it. A value computed in\n * the config, or RSC_OUTPUT in the environment, resolves exactly as the build\n * resolves it, because it is the same code deciding.\n */\nexport async function appInfo(root = cwd()): Promise<Record<string, unknown>> {\n const local = createRequire(join(root, \"package.json\"));\n let vitePath: string;\n\n try {\n vitePath = local.resolve(\"vite\");\n } catch {\n throw new Error(\"No vite installed in \" + root + \". Run this from the app's directory.\");\n }\n\n const vite = (await import(pathToFileURL(vitePath).href)) as {\n loadConfigFromFile: (\n env: { command: string; mode: string },\n file?: string,\n root?: string,\n ) => Promise<{ config: { plugins?: unknown[] } } | null>;\n };\n // From inside the app, as a build runs: rscKit() takes its project root\n // from the working directory when the config creates it.\n const from = cwd();\n\n process.chdir(root);\n\n try {\n const loaded = await vite.loadConfigFromFile({ command: \"build\", mode: \"production\" }, undefined, root);\n\n if (!loaded) throw new Error(\"No vite.config found in \" + root + \".\");\n\n const plugin = (await flatten(loaded.config.plugins ?? [])).find((p) => p.name === \"rsc-kit\");\n\n if (!plugin?.api?.info) throw new Error(\"The vite.config in \" + root + \" does not use rscKit().\");\n\n return plugin.api.info();\n } finally {\n process.chdir(from);\n }\n}\n\n\n/** A form's name from its action's: contactSend is contact-send. */\nfunction formName(action: string): string {\n return action.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n}\n\n/**\n * Write `<sourceDir>/forms/<name>.ts`: a public form drawn from a backend\n * action, the way the docs write it by hand. The backend is asked first, as a\n * dev server start asks it, so an action added a moment ago is there.\n *\n * The file is the app's to edit afterwards - a theme, labels, `done` - and is\n * never overwritten unless `force` says so.\n */\nexport async function makeForm(\n root: string,\n action: string,\n options: { name?: string; force?: boolean } = {},\n): Promise<string> {\n await typegen(root);\n\n const local = createRequire(join(root, \"package.json\"));\n const vite = (await import(pathToFileURL(local.resolve(\"vite\")).href)) as {\n loadConfigFromFile: (env: { command: string; mode: string }, file?: string, root?: string) => Promise<{ config: { plugins?: unknown[] } } | null>;\n };\n const loaded = await vite.loadConfigFromFile({ command: \"serve\", mode: \"development\" }, undefined, root);\n const plugin = (await flatten(loaded?.config.plugins ?? [])).find((p) => p.name === \"rsc-kit\");\n const files = plugin?.api?.generatedFiles?.() ?? [];\n const manifestFile = files.find((f) => f.endsWith(\"rsc-host.json\"));\n const actionsFile = files.find((f) => f.endsWith(\"server-actions.generated.ts\"));\n\n if (!manifestFile || !actionsFile || !existsSync(manifestFile)) {\n throw new Error(\"No rsc-host.json: this app has no backend that describes its actions (rscKit({ hostManifest }) or a Go registry).\");\n }\n\n const manifest = JSON.parse(readFileSync(manifestFile, \"utf-8\")) as {\n actions?: Record<string, string>;\n types?: Record<string, { params?: unknown[] }>;\n };\n const actions = manifest.actions ?? {};\n const target = actions[action];\n\n if (!target) {\n const known = Object.keys(actions);\n\n throw new Error(\n `The backend has no action named ${action}.` +\n (known.length ? ` It has: ${known.join(\", \")}.` : \" It has none: a form posts to an action, which is a class in app/Rsc/Actions in Laravel, or reg.HandleAction in Go.\"),\n );\n }\n\n const name = options.name ?? formName(action).replace(/-(send|submit|store|create)$/, \"\");\n\n if (!/^[a-z0-9-]+$/.test(name)) throw new Error(`A form's name is lowercase letters, digits and dashes: ${name}`);\n\n const sourceDir = join(actionsFile, \"..\");\n const file = join(sourceDir, \"forms\", name + \".ts\");\n\n if (existsSync(file) && !options.force) throw new Error(`${relative(root, file)} is already there. Pass --force to write over it.`);\n\n const exported = name.replace(/-([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n const text = `import { defineForm } from '@rsc-kit/press/forms'\nimport { shadcn } from '@rsc-kit/press/shadcn'\nimport { ${action} } from '../${basename(actionsFile, \".ts\")}'\n\n// The fields and every check are ${target}'s: the backend says what it takes,\n// and its refusals land under the fields. Place it in any page: <${exported}.Form />\nexport const ${exported} = defineForm({\n name: '${name}',\n action: ${action},\n theme: shadcn,\n})\n`;\n\n const { mkdirSync } = await import(\"node:fs\");\n\n mkdirSync(join(sourceDir, \"forms\"), { recursive: true });\n writeFileSync(file, text);\n\n return file;\n}\n"]}
package/dist/vite.d.ts CHANGED
@@ -146,7 +146,7 @@ export interface RscKitOptions {
146
146
  * caller that is not a browser - a webhook, a server - is never refused.
147
147
  */
148
148
  trustedOrigins?: string[];
149
- /** Where the server bundles and generated entries go. Defaults to `.rsc`. */
149
+ /** Where the server bundles and generated entries go. Defaults to `.rsc-kit`, beside the types; leave it there. */
150
150
  outDir?: string;
151
151
  /**
152
152
  * A file the dev server writes its own url into, and removes on shutdown.
package/dist/vite.js CHANGED
@@ -21,6 +21,7 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:pat
21
21
  import { fileURLToPath, pathToFileURL } from "node:url";
22
22
  import rsc, { getPluginApi } from "@vitejs/plugin-rsc";
23
23
  import { loadEnv, parseAst } from "vite";
24
+ import { formInputs } from "./hostInputs.js";
24
25
  import { stampDisplayNames } from "./stableNames.js";
25
26
  import { REPORT_FILE, buildReport } from "./buildReport.js";
26
27
  import { contractPath, edgeGuarded, edgeMarker, edgeShells, edgeStatic } from "./edgeShells.js";
@@ -3464,7 +3465,12 @@ import { depthOf, fileWins, folderOf, nearestShareImage } from ${JSON.stringify(
3464
3465
  import { SlotBoundary } from ${JSON.stringify(join(packageDir, "js/SlotBoundary"))}
3465
3466
  import { RouteErrorBoundary } from ${JSON.stringify(join(packageDir, "js/RouteErrorBoundary"))}
3466
3467
  import __rsc_assets from 'virtual:vite-rsc/assets-manifest'
3467
- import { isSharedSection, sectionComponent } from ${JSON.stringify(join(packageDir, "js/section"))}
3468
+ ${
3469
+ // The backend's actions, so defineForm({ action: contactSend }) can tell
3470
+ // which backend function a stub calls: the stub is the key, by identity.
3471
+ Object.keys(hostActions).length > 0
3472
+ ? `import * as __rsc_host_actions from ${JSON.stringify(join(sourceDir, HOST_ACTIONS_MODULE))}\n`
3473
+ : ""}import { isSharedSection, sectionComponent } from ${JSON.stringify(join(packageDir, "js/section"))}
3468
3474
  import { shareRender } from ${JSON.stringify(join(packageDir, "sharedRenders"))}
3469
3475
  import { PathnameProvider } from ${JSON.stringify(join(packageDir, "js/PathnameProvider"))}
3470
3476
  import { DefaultRouteError } from ${JSON.stringify(join(packageDir, "js/DefaultRouteError"))}
@@ -3859,6 +3865,17 @@ export async function getStaticParams(component: string): Promise<Record<string,
3859
3865
  // not reach the Flight render.
3860
3866
  const HOST_GLOBAL = ${JSON.stringify(hostGlobal)}
3861
3867
 
3868
+ // For defineForm({ action: contactSend }): which backend function each
3869
+ // generated action calls, and what each function takes. On the global because
3870
+ // a form is defined as its module loads, and read when it first renders, by
3871
+ // which time this entry has run.
3872
+ ;(globalThis as Record<symbol, unknown>)[Symbol.for('rsc-kit.host-forms')] = {
3873
+ actions: new Map<unknown, string>(${Object.keys(hostActions).length > 0
3874
+ ? `Object.entries(${JSON.stringify(hostActions)}).map(([name, target]) => [(__rsc_host_actions as Record<string, unknown>)[name], target])`
3875
+ : ""}),
3876
+ inputs: ${JSON.stringify(formInputs(hostTypes, hostDefs))},
3877
+ }
3878
+
3862
3879
  /**
3863
3880
  * The reserved name a host answers route middleware on.
3864
3881
  *