kizlo 0.15.2 → 0.16.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.
Files changed (85) hide show
  1. package/dist/adapters/logger.d.ts +2 -5
  2. package/dist/adapters/logger.js +1 -1
  3. package/dist/adapters/types.d.ts +19 -0
  4. package/dist/adapters/types.js +17 -0
  5. package/dist/astro/server.d.ts +2 -2
  6. package/dist/astro/server.js +2 -2
  7. package/dist/category/index.js +2 -2
  8. package/dist/cli/commands/_setup.js +10 -10
  9. package/dist/cli/commands/dev.js +7 -7
  10. package/dist/cli/daemon/generate.js +19 -9
  11. package/dist/cli/daemon/jiti.js +4 -5
  12. package/dist/cli/daemon/watch.js +3 -2
  13. package/dist/cli/presets/template.js +1 -1
  14. package/dist/cli/utils.js +6 -6
  15. package/dist/cli/wp/bootstrap.js +15 -11
  16. package/dist/cli/wp/constants.js +1 -1
  17. package/dist/cli/wp/dev.js +6 -23
  18. package/dist/cli/wp/types.d.ts +2 -2
  19. package/dist/cli/wp/utils.d.ts +1 -1
  20. package/dist/cli/wp/utils.js +1 -1
  21. package/dist/client.d.ts +7 -7
  22. package/dist/client.js +1 -1
  23. package/dist/comment/index.js +2 -2
  24. package/dist/config.d.ts +8 -8
  25. package/dist/context.d.ts +5 -5
  26. package/dist/context.js +5 -5
  27. package/dist/index.d.ts +7 -6
  28. package/dist/index.js +5 -4
  29. package/dist/integrations/astro/integration.d.ts +12 -0
  30. package/dist/integrations/astro/integration.js +14 -0
  31. package/dist/integrations/astro/kizlo.client.d.ts +4 -4
  32. package/dist/integrations/astro/utils.d.ts +4 -5
  33. package/dist/integrations/astro/utils.js +5 -6
  34. package/dist/integrations/nextjs/integration.d.ts +15 -0
  35. package/dist/integrations/nextjs/integration.js +18 -0
  36. package/dist/integrations/nextjs/kizlo.client.d.ts +2 -2
  37. package/dist/integrations/nextjs/revalidate.d.ts +2 -3
  38. package/dist/integrations/nextjs/revalidate.js +4 -4
  39. package/dist/integrations/nextjs/utils.js +2 -2
  40. package/dist/integrations/node/integration.d.ts +12 -0
  41. package/dist/integrations/node/integration.js +14 -0
  42. package/dist/integrations/runtime-env.js +25 -0
  43. package/dist/integrations/tanstack-start/api.d.ts +1 -1
  44. package/dist/integrations/tanstack-start/integration.d.ts +12 -0
  45. package/dist/integrations/tanstack-start/integration.js +14 -0
  46. package/dist/integrations/tanstack-start/kizlo.client.d.ts +4 -4
  47. package/dist/integrations/tanstack-start/utils.d.ts +1 -1
  48. package/dist/integrations/tanstack-start/utils.js +3 -3
  49. package/dist/kizlo.d.ts +33 -70
  50. package/dist/kizlo.js +91 -75
  51. package/dist/menu/index.js +2 -2
  52. package/dist/nextjs/server.d.ts +2 -2
  53. package/dist/nextjs/server.js +2 -2
  54. package/dist/node.d.ts +2 -0
  55. package/dist/node.js +3 -0
  56. package/dist/package.js +1 -1
  57. package/dist/page/index.js +2 -2
  58. package/dist/post/index.js +2 -2
  59. package/dist/{router.d.ts → procedures.d.ts} +11 -11
  60. package/dist/procedures.js +23 -0
  61. package/dist/seo/index.js +2 -2
  62. package/dist/settings/index.js +2 -2
  63. package/dist/shared/constants.js +1 -9
  64. package/dist/shared/contract-generation.js +14 -0
  65. package/dist/shared/contract.d.ts +2 -2
  66. package/dist/shared/contract.js +2 -2
  67. package/dist/shared/integration.d.ts +91 -0
  68. package/dist/shared/integration.js +59 -0
  69. package/dist/shared/procedure.d.ts +8 -8
  70. package/dist/shared/result.d.ts +2 -2
  71. package/dist/shared/router.d.ts +2 -2
  72. package/dist/shared/router.js +2 -2
  73. package/dist/tag/index.js +2 -2
  74. package/dist/tanstack-start/server.d.ts +2 -2
  75. package/dist/tanstack-start/server.js +2 -2
  76. package/package.json +8 -2
  77. package/dist/integrations/astro/kizlo.server.d.ts +0 -10
  78. package/dist/integrations/astro/kizlo.server.js +0 -12
  79. package/dist/integrations/nextjs/kizlo.server.d.ts +0 -11
  80. package/dist/integrations/nextjs/kizlo.server.js +0 -15
  81. package/dist/integrations/tanstack-start/kizlo.server.d.ts +0 -14
  82. package/dist/integrations/tanstack-start/kizlo.server.js +0 -15
  83. package/dist/router.js +0 -23
  84. package/dist/shared/extension.d.ts +0 -58
  85. package/dist/shared/extension.js +0 -37
@@ -1,8 +1,5 @@
1
- import { LiteralUnion } from "@kizlo/shared";
2
-
3
1
  //#region src/adapters/logger.d.ts
4
2
  type LogLevel = "debug" | "info" | "warn" | "error";
5
- type Environment = LiteralUnion<"development" | "production" | "test", string>;
6
3
  interface LogPayload {
7
4
  /** Severity of the record: `debug`, `info`, `warn`, or `error`. */
8
5
  level: LogLevel;
@@ -16,7 +13,7 @@ interface LogPayload {
16
13
  error?: Error;
17
14
  }
18
15
  type LoggerAdapter = (payload: LogPayload) => void | Promise<void>;
19
- /** Author a custom logger adapter — types your handler against the {@link LoggerAdapter} contract. */
16
+ /** Author a custom logger adapter. Types your handler against the {@link LoggerAdapter} contract. */
20
17
  declare function createLoggerAdapter(adapter: LoggerAdapter): LoggerAdapter;
21
18
  interface Logger {
22
19
  debug(message: string, context?: Record<string, unknown>): void;
@@ -35,4 +32,4 @@ interface ConsoleLogAdapterOptions {
35
32
  declare function consoleLog(opts?: ConsoleLogAdapterOptions): LoggerAdapter;
36
33
  declare const noopAdapter: LoggerAdapter;
37
34
  //#endregion
38
- export { ConsoleLogAdapterOptions, Environment, LogLevel, LogPayload, Logger, LoggerAdapter, consoleLog, createLoggerAdapter, noopAdapter };
35
+ export { ConsoleLogAdapterOptions, LogLevel, LogPayload, Logger, LoggerAdapter, consoleLog, createLoggerAdapter, noopAdapter };
@@ -1,5 +1,5 @@
1
1
  //#region src/adapters/logger.ts
2
- /** Author a custom logger adapter — types your handler against the {@link LoggerAdapter} contract. */
2
+ /** Author a custom logger adapter. Types your handler against the {@link LoggerAdapter} contract. */
3
3
  function createLoggerAdapter(adapter) {
4
4
  return adapter;
5
5
  }
@@ -0,0 +1,19 @@
1
+ import { AuthAdapter } from "./auth.js";
2
+ import { CaptchaAdapter } from "./captcha.js";
3
+ import { CookiesAdapter } from "../shared/types.js";
4
+ import { GeoAdapter } from "./geo.js";
5
+ import { LoggerAdapter } from "./logger.js";
6
+
7
+ //#region src/adapters/types.d.ts
8
+ /** The service contracts Kizlo integrations can provide at runtime. */
9
+ interface ServiceAdapters {
10
+ auth?: AuthAdapter;
11
+ captcha?: CaptchaAdapter;
12
+ geo?: GeoAdapter;
13
+ logger?: LoggerAdapter;
14
+ cookies?: CookiesAdapter;
15
+ }
16
+ /** Merge adapter contributions in order without letting `undefined` erase an earlier value. */
17
+ declare function mergeServiceAdapters(...contributions: (ServiceAdapters | undefined)[]): ServiceAdapters;
18
+ //#endregion
19
+ export { ServiceAdapters, mergeServiceAdapters };
@@ -0,0 +1,17 @@
1
+ //#region src/adapters/types.ts
2
+ /** Merge adapter contributions in order without letting `undefined` erase an earlier value. */
3
+ function mergeServiceAdapters(...contributions) {
4
+ const adapters = {};
5
+ for (const contribution of contributions) {
6
+ if (!contribution) continue;
7
+ if (contribution.auth !== void 0) adapters.auth = contribution.auth;
8
+ if (contribution.captcha !== void 0) adapters.captcha = contribution.captcha;
9
+ if (contribution.geo !== void 0) adapters.geo = contribution.geo;
10
+ if (contribution.logger !== void 0) adapters.logger = contribution.logger;
11
+ if (contribution.cookies !== void 0) adapters.cookies = contribution.cookies;
12
+ }
13
+ return adapters;
14
+ }
15
+
16
+ //#endregion
17
+ export { mergeServiceAdapters };
@@ -1,9 +1,9 @@
1
1
  import { WEB_MANIFEST_ROUTE } from "../brand/manifest.js";
2
2
  import { renderJsonLd } from "../seo/utils.js";
3
- import { KizloServerOptions, createKizlo } from "../integrations/astro/kizlo.server.js";
3
+ import { AstroOptions, astro } from "../integrations/astro/integration.js";
4
4
  import { AstroRoute, AstroRouteContext, getServerBaseUrl } from "../integrations/astro/utils.js";
5
5
  import { createManifestRoute } from "../integrations/astro/manifest.js";
6
6
  import { PageHead, RootHead, ThemeColor, resolvePageHead, resolveRootHead } from "../integrations/astro/metadata.js";
7
7
  import { createRobotsRoute } from "../integrations/astro/robots.js";
8
8
  import { createSitemapRedirectRoute, createSitemapRoute } from "../integrations/astro/sitemap.js";
9
- export { AstroRoute, AstroRouteContext, KizloServerOptions, PageHead, RootHead, ThemeColor, WEB_MANIFEST_ROUTE, createKizlo, createManifestRoute, createRobotsRoute, createSitemapRedirectRoute, createSitemapRoute, getServerBaseUrl, renderJsonLd, resolvePageHead, resolveRootHead };
9
+ export { AstroOptions, AstroRoute, AstroRouteContext, PageHead, RootHead, ThemeColor, WEB_MANIFEST_ROUTE, astro, createManifestRoute, createRobotsRoute, createSitemapRedirectRoute, createSitemapRoute, getServerBaseUrl, renderJsonLd, resolvePageHead, resolveRootHead };
@@ -1,10 +1,10 @@
1
1
  import { WEB_MANIFEST_ROUTE } from "../brand/manifest.js";
2
2
  import { renderJsonLd } from "../seo/utils.js";
3
3
  import { getServerBaseUrl } from "../integrations/astro/utils.js";
4
- import { createKizlo } from "../integrations/astro/kizlo.server.js";
4
+ import { astro } from "../integrations/astro/integration.js";
5
5
  import { createManifestRoute } from "../integrations/astro/manifest.js";
6
6
  import { resolvePageHead, resolveRootHead } from "../integrations/astro/metadata.js";
7
7
  import { createRobotsRoute } from "../integrations/astro/robots.js";
8
8
  import { createSitemapRedirectRoute, createSitemapRoute } from "../integrations/astro/sitemap.js";
9
9
 
10
- export { WEB_MANIFEST_ROUTE, createKizlo, createManifestRoute, createRobotsRoute, createSitemapRedirectRoute, createSitemapRoute, getServerBaseUrl, renderJsonLd, resolvePageHead, resolveRootHead };
10
+ export { WEB_MANIFEST_ROUTE, astro, createManifestRoute, createRobotsRoute, createSitemapRedirectRoute, createSitemapRoute, getServerBaseUrl, renderJsonLd, resolvePageHead, resolveRootHead };
@@ -7,7 +7,7 @@ import { deserializeCategory } from "./utils.js";
7
7
  import { normalizeArrayableValue } from "@kizlo/shared";
8
8
 
9
9
  //#region src/category/index.ts
10
- const CATEGORY_ROUTER_MAP = {
10
+ const CATEGORY_PROCEDURES = {
11
11
  get: createProcedure({
12
12
  scope: "api",
13
13
  method: "GET",
@@ -74,4 +74,4 @@ const CATEGORY_ROUTER_MAP = {
74
74
  };
75
75
 
76
76
  //#endregion
77
- export { CATEGORY_ROUTER_MAP };
77
+ export { CATEGORY_PROCEDURES };
@@ -37,17 +37,17 @@ function remoteKeys(envKeys) {
37
37
  }
38
38
  /**
39
39
  * The `.env` keys setup manages and the values to write, branched on the connection mode. Local
40
- * WordPress writes the `KIZLO_LOCAL_WP_*` / `KIZLO_LOCAL_WP_SECRET` set plus `KIZLO_CONNECT=local`,
40
+ * WordPress writes the `KIZLO_LOCAL_WP_*` / `KIZLO_LOCAL_WP_SECRET` set plus `KIZLO_MODE=local`,
41
41
  * so it never touches the remote keys (a user can point those at a real site). A remote site writes
42
- * the bare remote keys exactly as before — no `KIZLO_CONNECT`, since `"remote"` is the default.
42
+ * the bare remote keys exactly as before — no `KIZLO_MODE`, since `"remote"` is the default.
43
43
  */
44
44
  function managedEnv(envKeys, conn) {
45
45
  if (conn.mode === "local") {
46
- const { connect, siteSecret: siteSecret$1, wpUrl: wpUrl$1, wpUsername: wpUsername$1, wpPassword: wpPassword$1 } = envKeys.local;
46
+ const { mode, siteSecret: siteSecret$1, wpUrl: wpUrl$1, wpUsername: wpUsername$1, wpPassword: wpPassword$1 } = envKeys.local;
47
47
  return {
48
48
  keys: [
49
49
  envKeys.baseUrl,
50
- connect,
50
+ mode,
51
51
  siteSecret$1,
52
52
  wpUrl$1,
53
53
  wpUsername$1,
@@ -55,7 +55,7 @@ function managedEnv(envKeys, conn) {
55
55
  ],
56
56
  values: {
57
57
  [envKeys.baseUrl]: conn.baseUrl,
58
- [connect]: "local",
58
+ [mode]: "local",
59
59
  [siteSecret$1]: conn.siteSecret,
60
60
  [wpUrl$1]: conn.wpUrl,
61
61
  [wpUsername$1]: conn.wpUsername,
@@ -375,7 +375,7 @@ async function provisionLocalStack(cfg, siteSecret, baseUrl) {
375
375
  url: info.url,
376
376
  username: info.username,
377
377
  appPassword,
378
- adminPassword: info.secrets?.password,
378
+ adminPassword: info.adminPassword,
379
379
  secretSyncError: sync.ok ? void 0 : sync.error
380
380
  };
381
381
  }
@@ -398,7 +398,7 @@ async function provisionLocalWordPress(cwd, conn) {
398
398
  }
399
399
  /**
400
400
  * The template's own `.env.example`, when it ships one. Templates own the framework-specific key names
401
- * (e.g. `NEXT_PUBLIC_KIZLO_API_URL`) and the shared section layout, so their file is the source of the
401
+ * (e.g. `NEXT_PUBLIC_KIZLO_BASE_URL`) and the shared section layout, so their file is the source of the
402
402
  * scaffold's `.env.example` — see {@link writeEnv}. Undefined for the base preset (no template dir).
403
403
  */
404
404
  function readEnvExample(templateDir) {
@@ -407,14 +407,14 @@ function readEnvExample(templateDir) {
407
407
  }
408
408
  /**
409
409
  * The `.env.example` body for the base preset, which ships no template file. Lists the API URL and the
410
- * remote connection keys, then the commented `KIZLO_CONNECT=local` toggle for the local-dev path. Real
410
+ * remote connection keys, then the commented `KIZLO_MODE=local` toggle for the local-dev path. Real
411
411
  * templates carry their own `.env.example` (passed to {@link writeEnv}) so its structure and comments
412
412
  * stay consistent with the `.env` the scaffold writes.
413
413
  */
414
414
  function generatedEnvExample(envKeys) {
415
415
  const exampleKeys = [envKeys.baseUrl, ...remoteKeys(envKeys)];
416
416
  const { content } = mergeEnv("", Object.fromEntries(exampleKeys.map((key) => [key, ""])), new Set(exampleKeys), envGroups(envKeys));
417
- return `${content}\n# Point the app at local WordPress (managed by \`kizlo dev\`) instead of the keys above:\n# ${envKeys.local.connect}=local\n`;
417
+ return `${content}\n# Point the app at local WordPress (managed by \`kizlo dev\`) instead of the keys above:\n# ${envKeys.local.mode}=local\n`;
418
418
  }
419
419
  /**
420
420
  * The managed keys already present in an existing `.env` — the values a write would overwrite. Collected
@@ -471,7 +471,7 @@ function nextStepsLines(conn, prefix = "") {
471
471
  const login = conn.mode === "local" && conn.adminPassword ? [
472
472
  ``,
473
473
  `Log in to wp-admin (${conn.wpUrl}/wp-admin):`,
474
- ` ${conn.wpUsername} / ${conn.adminPassword} — save it, it's shown only once`
474
+ ` ${conn.wpUsername} / ${conn.adminPassword}`
475
475
  ] : [];
476
476
  return [
477
477
  `Start developing:`,
@@ -42,7 +42,7 @@ function note(text) {
42
42
  * Print the connection summary as an aligned, Next.js-style block. Shows the wp-admin URL on
43
43
  * the loopback ("Local") and — when local WordPress is installed on a LAN address rather than
44
44
  * localhost — on the network, so it can be opened from other devices. On a fresh install, also
45
- * show the one-time wp-admin password (it's never stored, so this is the only chance to see it).
45
+ * show the default wp-admin login.
46
46
  */
47
47
  function printSummary(info) {
48
48
  const { cyan, dim, reset } = palette();
@@ -52,7 +52,7 @@ function printSummary(info) {
52
52
  rows.push(["Database Connection", `127.0.0.1:${info.dbPort}`]);
53
53
  const width = Math.max(...rows.map(([label]) => label.length)) + 1;
54
54
  const lines = ["", ...rows.map(([label, value]) => ` ${dim}- ${`${label}:`.padEnd(width)}${reset} ${cyan}${value}${reset}`)];
55
- if (info.secrets) lines.push("", ` ${dim}admin login:${reset} ${info.username} / ${info.secrets.password}`, ` ${dim}save the password now — it's shown only once${reset}`);
55
+ if (info.adminPassword) lines.push("", ` ${dim}admin login:${reset} ${info.username} / ${info.adminPassword}`);
56
56
  if (info.seeded > 0) lines.push(` ${dim}seeded ${info.seeded} fixture${info.seeded === 1 ? "" : "s"}${reset}`);
57
57
  process.stdout.write(`${lines.join("\n")}\n`);
58
58
  }
@@ -71,13 +71,13 @@ function readEnvValue(content, key) {
71
71
  return content.match(new RegExp(`^\\s*${key}\\s*=\\s*(.*)$`, "m"))?.[1]?.trim() || void 0;
72
72
  }
73
73
  /**
74
- * The Kizlo backend URL from `.env` — the one key ending in `KIZLO_API_URL` (`KIZLO_API_URL`,
75
- * or a framework-prefixed `NEXT_PUBLIC_KIZLO_API_URL`). It's the handler mount the plugin delivers
74
+ * The Kizlo backend URL from `.env` — the one key ending in `KIZLO_BASE_URL` (`KIZLO_BASE_URL`,
75
+ * or a framework-prefixed `NEXT_PUBLIC_KIZLO_BASE_URL`). It's the handler mount the plugin delivers
76
76
  * webhook events to; its origin is the site's canonical URL. User-managed (init writes it), so dev
77
77
  * only reads it. Undefined before `kizlo init` has populated `.env`.
78
78
  */
79
79
  function readBaseUrl(content) {
80
- return content.match(/^\s*[A-Z_]*KIZLO_API_URL\s*=\s*(.*)$/m)?.[1]?.trim() || void 0;
80
+ return content.match(/^\s*[A-Z_]*KIZLO_BASE_URL\s*=\s*(.*)$/m)?.[1]?.trim() || void 0;
81
81
  }
82
82
  /**
83
83
  * Rewrite the local WordPress connection in `.env` after a fresh install. A reset (or first boot)
@@ -86,7 +86,7 @@ function readBaseUrl(content) {
86
86
  * connection keys are overwritten; everything else in `.env` is preserved, and the file is created
87
87
  * if absent. Gated by the caller on a minted `appPassword`, so a warm resume never churns it.
88
88
  *
89
- * `KIZLO_CONNECT=local` and `KIZLO_LOCAL_WP_SECRET` are written too but kept out of the overwrite set,
89
+ * `KIZLO_MODE=local` and `KIZLO_LOCAL_WP_SECRET` are written too but kept out of the overwrite set,
90
90
  * so a value the user already set is preserved — booting local WordPress only fills them when absent.
91
91
  * The resolved local secret (the existing one, or a freshly minted one) and the Kizlo server base URL
92
92
  * are returned so the caller can sync them into the plugin.
@@ -101,7 +101,7 @@ function updateWpEnv(cfg, info) {
101
101
  KIZLO_LOCAL_WP_USERNAME: info.username,
102
102
  KIZLO_LOCAL_WP_APP_PASSWORD: info.appPassword,
103
103
  KIZLO_LOCAL_WP_SECRET: siteSecret,
104
- KIZLO_CONNECT: "local"
104
+ KIZLO_MODE: "local"
105
105
  }, new Set(WP_ENV_KEYS), envGroups(DEFAULT_ENV_KEYS));
106
106
  writeFileSync(envPath, content);
107
107
  return {
@@ -1,6 +1,7 @@
1
1
  import { generateContract } from "../../shared/contract.js";
2
- import { resolveWordPressConnection } from "../../kizlo.js";
2
+ import { integrationEnv, resolveWordPressConnection } from "../../kizlo.js";
3
3
  import { WORDPRESS_CLIENT_META_REL } from "../wp/constants.js";
4
+ import { node } from "../../integrations/node/integration.js";
4
5
  import { log } from "./logger.js";
5
6
  import { loadEnvFiles } from "../utils.js";
6
7
  import { importIgnoringVirtualModules } from "./jiti.js";
@@ -14,21 +15,27 @@ import fs from "node:fs";
14
15
 
15
16
  //#region src/cli/daemon/generate.ts
16
17
  /**
17
- * The generated barrel — also written as a stub by `kizlo init`. It re-exports `endpoints` rather
18
+ * The generated barrel is also written as a stub by `kizlo init`. It re-exports `endpoints` rather
18
19
  * than pre-wrapping it: a server entry passes `wordpress: { endpoints }` itself, so the rest of the
19
20
  * WordPress options stay visible at the call site instead of hiding inside a generated object.
20
21
  */
21
22
  const CONTRACT_BARREL = [
22
- `import type { router } from ".."`,
23
+ `import type { procedures } from ".."`,
23
24
  `import contractJson from "./contract.json"`,
24
25
  ``,
25
- `export const contract = contractJson as unknown as typeof router`,
26
+ `export const contract = contractJson as unknown as typeof procedures`,
26
27
  `export { endpoints, type WordPressClient } from "./wordpress"`,
27
28
  ``
28
29
  ].join("\n");
30
+ var LegacyRouterExportError = class extends Error {
31
+ name = "LegacyRouterExportError";
32
+ constructor(entry) {
33
+ super(`The Kizlo server at ${entry} exports \`router\`, which is no longer supported. Rename that export to \`procedures\` and run \`kizlo generate\` again.`);
34
+ }
35
+ };
29
36
  /**
30
37
  * `wordpress.ts` before the first generation. WordPress is reachable but untyped until then, so a
31
- * freshly scaffolded project compiles — including kizlo's own procedures — before it has ever
38
+ * freshly scaffolded project compiles, including Kizlo's own procedures, before it has ever
32
39
  * connected. `kizlo dev` / `kizlo generate` replaces this with the real client. `any` rather than an
33
40
  * empty tree on purpose: every endpoint a procedure names has to resolve to something until the
34
41
  * real shapes arrive, which `WP_Client` preserves by passing `any` through.
@@ -165,7 +172,7 @@ function reportPluginVersion(installed) {
165
172
  /** Fetch `/introspect`, reporting its diagnostics in the CLI's voice. Returns undefined on a 304. */
166
173
  async function fetchDocument(cwd, options, etag) {
167
174
  loadEnvFiles(cwd);
168
- const result = await fetchIntrospection(options.credentials ?? resolveWordPressConnection(void 0).credentials, {
175
+ const result = await fetchIntrospection(options.credentials ?? resolveWordPressConnection(void 0, integrationEnv([node()])).credentials, {
169
176
  etag: options.strict ? void 0 : etag,
170
177
  fetch: options.fetch
171
178
  });
@@ -231,9 +238,12 @@ function writeGeneratedWordPress(cfg, client, meta) {
231
238
  async function generateOnce(cfg, options = {}) {
232
239
  loadEnvFiles(cfg.cwd);
233
240
  const entry = path.resolve(cfg.cwd, cfg.serverEntry);
234
- const { router } = await importIgnoringVirtualModules(cfg.cwd, entry);
235
- if (!router) return false;
236
- const contract = JSON.stringify(await generateContract(router));
241
+ const server = await importIgnoringVirtualModules(cfg.cwd, entry);
242
+ if (!server.procedures) {
243
+ if (server.router) throw new LegacyRouterExportError(cfg.serverEntry);
244
+ return false;
245
+ }
246
+ const contract = JSON.stringify(await generateContract(server.procedures));
237
247
  const wordpress = await generateWordPressOnce(cfg, options);
238
248
  fs.mkdirSync(path.resolve(cfg.cwd, cfg.generatedDir), { recursive: true });
239
249
  atomicWrite(path.resolve(cfg.cwd, cfg.contractPath), contract);
@@ -1,4 +1,4 @@
1
- import { CONTRACT_GENERATION_ENV } from "../../shared/constants.js";
1
+ import { isContractGeneration, setContractGeneration } from "../../shared/contract-generation.js";
2
2
  import path from "node:path";
3
3
  import fs from "node:fs";
4
4
  import { createJiti } from "jiti";
@@ -20,13 +20,12 @@ import { createJiti } from "jiti";
20
20
  async function importIgnoringVirtualModules(cwd, entry) {
21
21
  const deps = declaredDeps(cwd);
22
22
  const virtualModules = {};
23
- const previousGenerationFlag = process.env[CONTRACT_GENERATION_ENV];
24
- process.env[CONTRACT_GENERATION_ENV] = "1";
23
+ const previousGenerationFlag = isContractGeneration();
24
+ setContractGeneration(true);
25
25
  try {
26
26
  return await importLoop(cwd, entry, deps, virtualModules);
27
27
  } finally {
28
- if (previousGenerationFlag === void 0) delete process.env[CONTRACT_GENERATION_ENV];
29
- else process.env[CONTRACT_GENERATION_ENV] = previousGenerationFlag;
28
+ setContractGeneration(previousGenerationFlag);
30
29
  }
31
30
  }
32
31
  async function importLoop(cwd, entry, deps, virtualModules) {
@@ -1,4 +1,5 @@
1
- import { resolveWordPressConnection } from "../../kizlo.js";
1
+ import { integrationEnv, resolveWordPressConnection } from "../../kizlo.js";
2
+ import { node } from "../../integrations/node/integration.js";
2
3
  import { log } from "./logger.js";
3
4
  import { loadEnvFiles } from "../utils.js";
4
5
  import { resolveConfig, resolveWordPressClientDir } from "./config.js";
@@ -149,7 +150,7 @@ async function startWatcher(cwd, opts) {
149
150
  return;
150
151
  }
151
152
  loadEnvFiles(cwd);
152
- const { credentials } = resolveWordPressConnection(void 0);
153
+ const { credentials } = resolveWordPressConnection(void 0, integrationEnv([node()]));
153
154
  if (wordpressClientDir) try {
154
155
  if (await generateWorkspaceClientOnce(cwd, wordpressClientDir, { credentials }) === "generated") log.success("WordPress client generated");
155
156
  } catch (error) {
@@ -212,7 +212,7 @@ const envSchema = z.object({
212
212
  wpPassword: z.string()
213
213
  }),
214
214
  local: z.object({
215
- connect: z.string(),
215
+ mode: z.string(),
216
216
  siteSecret: z.string(),
217
217
  wpUrl: z.string(),
218
218
  wpUsername: z.string(),
package/dist/cli/utils.js CHANGED
@@ -460,7 +460,7 @@ function envKeysPresent(contents, keys) {
460
460
  * first stamped release). Real templates carry their own `env`, so this is the standard `KIZLO_*` set.
461
461
  */
462
462
  const DEFAULT_ENV_KEYS = {
463
- baseUrl: "KIZLO_API_URL",
463
+ baseUrl: "KIZLO_BASE_URL",
464
464
  remote: {
465
465
  siteSecret: "KIZLO_WP_SECRET",
466
466
  wpUrl: "KIZLO_WP_URL",
@@ -468,7 +468,7 @@ const DEFAULT_ENV_KEYS = {
468
468
  wpPassword: "KIZLO_WP_APP_PASSWORD"
469
469
  },
470
470
  local: {
471
- connect: "KIZLO_CONNECT",
471
+ mode: "KIZLO_MODE",
472
472
  siteSecret: "KIZLO_LOCAL_WP_SECRET",
473
473
  wpUrl: "KIZLO_LOCAL_WP_URL",
474
474
  wpUsername: "KIZLO_LOCAL_WP_USERNAME",
@@ -477,7 +477,7 @@ const DEFAULT_ENV_KEYS = {
477
477
  };
478
478
  /**
479
479
  * The grouped `.env` layout shared by `init` and `dev`, so both write the same sectioned file:
480
- * a connect switch, the API URL, then the remote and local connection blocks. The key names come from
480
+ * a mode switch, the base URL, then the remote and local connection blocks. The key names come from
481
481
  * the resolved {@link EnvKeys} (the template's `env` contract), so the sections stay labelled correctly
482
482
  * whatever a template calls them. Only sections whose keys are actually being appended get a header, so
483
483
  * a remote run skips the local block and vice versa.
@@ -485,11 +485,11 @@ const DEFAULT_ENV_KEYS = {
485
485
  function envGroups(envKeys) {
486
486
  return [
487
487
  {
488
- comment: "Kizlo Connect (local | remote)",
489
- keys: [envKeys.local.connect]
488
+ comment: "Kizlo Mode (local | remote)",
489
+ keys: [envKeys.local.mode]
490
490
  },
491
491
  {
492
- comment: "Kizlo API URL",
492
+ comment: "Kizlo Base URL",
493
493
  keys: [envKeys.baseUrl]
494
494
  },
495
495
  {
@@ -3,6 +3,19 @@ import { compose, composeUp, wpCli, wpEval } from "./docker.js";
3
3
  import { ensurePlugins, settleFixtures } from "./utils.js";
4
4
 
5
5
  //#region src/cli/wp/bootstrap.ts
6
+ /** Install a local WordPress site with the shared admin credentials. */
7
+ async function installWordPress(url, title) {
8
+ await wpCli([
9
+ "core",
10
+ "install",
11
+ `--url=${url}`,
12
+ `--title=${title}`,
13
+ `--admin_user=${TEST_ADMIN.username}`,
14
+ `--admin_password=${TEST_ADMIN.password}`,
15
+ `--admin_email=${TEST_ADMIN.email}`,
16
+ "--skip-email"
17
+ ]);
18
+ }
6
19
  async function seedUsers() {
7
20
  const existing = await wpCli([
8
21
  "user",
@@ -59,16 +72,7 @@ async function bootstrapWp(config) {
59
72
  "wp",
60
73
  "core",
61
74
  "is-installed"
62
- ])).code !== 0) await wpCli([
63
- "core",
64
- "install",
65
- `--url=${url}`,
66
- "--title=Kizlo Test",
67
- `--admin_user=${TEST_ADMIN.username}`,
68
- `--admin_password=${TEST_ADMIN.password}`,
69
- `--admin_email=${TEST_ADMIN.email}`,
70
- "--skip-email"
71
- ]);
75
+ ])).code !== 0) await installWordPress(url, "Kizlo Test");
72
76
  await wpCli([
73
77
  "rewrite",
74
78
  "structure",
@@ -118,4 +122,4 @@ async function bootstrapWp(config) {
118
122
  }
119
123
 
120
124
  //#endregion
121
- export { bootstrapWp, createAdminAppPassword, seedUsers };
125
+ export { bootstrapWp, createAdminAppPassword, installWordPress, seedUsers };
@@ -70,7 +70,7 @@ const TEST_ADMIN = {
70
70
  firstName: "Admin",
71
71
  lastName: "",
72
72
  username: "admin",
73
- password: "admin_pass",
73
+ password: "admin",
74
74
  email: "admin@example.com"
75
75
  };
76
76
  const TEST_USER = {
@@ -4,17 +4,12 @@ import { compose, composePull, composeUp, wpCli, wpEval } from "./docker.js";
4
4
  import { ensurePlugins, settleFixtures } from "./utils.js";
5
5
  import { log } from "../daemon/logger.js";
6
6
  import { warnVersionDrift } from "./version.js";
7
- import { createAdminAppPassword, seedUsers } from "./bootstrap.js";
7
+ import { createAdminAppPassword, installWordPress, seedUsers } from "./bootstrap.js";
8
8
  import { join } from "node:path";
9
9
  import { existsSync } from "node:fs";
10
- import { randomBytes } from "node:crypto";
11
10
  import { networkInterfaces } from "node:os";
12
11
 
13
12
  //#region src/cli/wp/dev.ts
14
- /** A strong random admin password (144 bits, URL/JSON/CLI-safe characters). */
15
- function generatePassword() {
16
- return randomBytes(18).toString("base64url");
17
- }
18
13
  const VIRTUAL_INTERFACE = /^(?:docker|br-|veth|utun|tun|tap)/i;
19
14
  const PRIVATE_IPV4 = /^(?:10\.|192\.168\.|172\.(?:1[6-9]|2\d|3[01])\.)/;
20
15
  /** Preferred private IPv4 address on a physical interface (undefined when offline). */
@@ -74,9 +69,8 @@ async function seedDevFixtures(cfg, url) {
74
69
  * sources + bind-mounted locals). An already-provisioned install is left untouched
75
70
  * (idempotent reruns).
76
71
  *
77
- * Credentials are an output, not a stored file: a fresh install mints a random admin
78
- * password and returns it once (to log into wp-admin). No application password is minted —
79
- * that's a test concern.
72
+ * A fresh install uses the shared local admin credentials and returns the password so
73
+ * the command can show the login. Existing installs are left untouched.
80
74
  */
81
75
  async function bootstrapDev(cfg) {
82
76
  const url = devUrl(cfg.port);
@@ -90,19 +84,8 @@ async function bootstrapDev(cfg) {
90
84
  "core",
91
85
  "is-installed"
92
86
  ])).code === 0;
93
- let password;
94
87
  if (!installed) {
95
- password = generatePassword();
96
- await wpCli([
97
- "core",
98
- "install",
99
- `--url=${url}`,
100
- "--title=Kizlo Dev",
101
- `--admin_user=${TEST_ADMIN.username}`,
102
- `--admin_password=${password}`,
103
- `--admin_email=${TEST_ADMIN.email}`,
104
- "--skip-email"
105
- ]);
88
+ await installWordPress(url, "Kizlo Dev");
106
89
  await wpCli([
107
90
  "rewrite",
108
91
  "structure",
@@ -122,14 +105,14 @@ async function bootstrapDev(cfg) {
122
105
  wpEval
123
106
  });
124
107
  const seeded = !installed && cfg.fixtures.length ? await seedDevFixtures(cfg, url) : 0;
125
- const appPassword = password ? await createAdminAppPassword("kizlo-dev") : void 0;
108
+ const appPassword = !installed ? await createAdminAppPassword("kizlo-dev") : void 0;
126
109
  return {
127
110
  url,
128
111
  username: TEST_ADMIN.username,
129
112
  dbPort: cfg.dbPort,
130
113
  seeded,
131
114
  appPassword,
132
- secrets: password ? { password } : void 0
115
+ adminPassword: !installed ? TEST_ADMIN.password : void 0
133
116
  };
134
117
  }
135
118
 
@@ -87,7 +87,7 @@ interface SettleContext {
87
87
  type FixtureSeedFn = (ctx: SeedContext) => Promise<Record<string, JsonValue>>;
88
88
  type FixtureSettleFn = (ctx: SettleContext) => Promise<void>;
89
89
  type FixtureCleanupFn = (ctx: SeedContext) => Promise<void>;
90
- /** The serializable test layer an extension ships alongside its live extension. */
90
+ /** The serializable test layer an integration ships alongside its live code. */
91
91
  interface Fixture {
92
92
  /** Namespace key under `TestCredentials.fixtures`. */
93
93
  name: string;
@@ -107,7 +107,7 @@ interface Fixture {
107
107
  * a minute ago and one booted last week describe the same WordPress.
108
108
  */
109
109
  settle?: FixtureSettleFn;
110
- /** Build this extension's world once during seeding; return created handles. */
110
+ /** Build this integration's world once during seeding; return created handles. */
111
111
  seed?: FixtureSeedFn;
112
112
  /** Revert per-test mutations (teardown); does NOT uninstall plugins or seeded data. */
113
113
  cleanup?: FixtureCleanupFn;
@@ -31,7 +31,7 @@ declare function ensurePlugin(name: string, source: string): Promise<void>;
31
31
  declare function activateLocalPlugin(pluginPath: string): Promise<void>;
32
32
  /**
33
33
  * Ensure every plugin is active. Installable sources go first so a bind-mounted
34
- * local plugin that depends on one (e.g. a WooCommerce extension) finds it already
34
+ * local plugin that depends on one (e.g. a WooCommerce integration) finds it already
35
35
  * present; then each {@link LocalPlugin} is activated by basename. A local plugin
36
36
  * whose slug matches an installable (e.g. mounting `kizlo` over the released
37
37
  * `kizlo`) is seen as already installed, so `ensurePlugin` activates the live
@@ -95,7 +95,7 @@ async function activateLocalPlugin(pluginPath) {
95
95
  }
96
96
  /**
97
97
  * Ensure every plugin is active. Installable sources go first so a bind-mounted
98
- * local plugin that depends on one (e.g. a WooCommerce extension) finds it already
98
+ * local plugin that depends on one (e.g. a WooCommerce integration) finds it already
99
99
  * present; then each {@link LocalPlugin} is activated by basename. A local plugin
100
100
  * whose slug matches an installable (e.g. mounting `kizlo` over the released
101
101
  * `kizlo`) is seen as already installed, so `ensurePlugin` activates the live
package/dist/client.d.ts CHANGED
@@ -1,23 +1,23 @@
1
- import { AnyProcedureRouter, ExtractProcedureByScope } from "./shared/procedure.js";
1
+ import { AnyProcedureTree, ExtractProcedureByScope } from "./shared/procedure.js";
2
2
  import { ResultClient } from "./shared/result.js";
3
3
 
4
4
  //#region src/client.d.ts
5
- interface KizloClientConfig<T extends AnyProcedureRouter> {
5
+ interface KizloClientConfig<T extends AnyProcedureTree> {
6
6
  url?: string;
7
7
  contract: T;
8
8
  fetch?: (request: Request) => Promise<Response>;
9
9
  }
10
- declare class KizloClient<TRouter extends AnyProcedureRouter> {
11
- readonly client: ResultClient<ExtractProcedureByScope<TRouter, "remote" | "api">>;
12
- protected readonly config: KizloClientConfig<TRouter>;
13
- constructor(config: KizloClientConfig<TRouter>);
10
+ declare class KizloClient<TProcedures extends AnyProcedureTree> {
11
+ readonly client: ResultClient<ExtractProcedureByScope<TProcedures, "remote" | "api">>;
12
+ protected readonly config: KizloClientConfig<TProcedures>;
13
+ constructor(config: KizloClientConfig<TProcedures>);
14
14
  private getUrl;
15
15
  }
16
16
  /**
17
17
  * Creates a browser client for a generated contract. Defaults the URL to the
18
18
  * current origin (`window.location.origin`); framework packages wrap this to resolve it from their env.
19
19
  */
20
- declare function createKizloClient<T extends AnyProcedureRouter>(contract: T, options?: {
20
+ declare function createKizloClient<T extends AnyProcedureTree>(contract: T, options?: {
21
21
  url?: string;
22
22
  }): KizloClient<T>;
23
23
  //#endregion
package/dist/client.js CHANGED
@@ -27,7 +27,7 @@ var KizloClient = class {
27
27
  });
28
28
  this.client = createResultClient(createORPCClient(new DynamicLink((_, path) => {
29
29
  const procedure = getObjectProperty(this.config.contract, path);
30
- if (!isContractProcedure$1(procedure)) throw new Error(`No valid procedure found at path "${path.join(".")}". This may happen when the contract router is not properly configured.`);
30
+ if (!isContractProcedure$1(procedure)) throw new Error(`No valid procedure found at path "${path.join(".")}". The generated contract may not match the exported procedures.`);
31
31
  switch (procedure.scope) {
32
32
  case "internal": throw new Error("Internal procedure can only be called on the server.");
33
33
  case "api": return openapiLink;
@@ -6,7 +6,7 @@ import { deserializeComment } from "./utils.js";
6
6
  import { listed } from "@kizlo/shared";
7
7
 
8
8
  //#region src/comment/index.ts
9
- const COMMENT_ROUTER_MAP = {
9
+ const COMMENT_PROCEDURES = {
10
10
  get: createProcedure({
11
11
  scope: "api",
12
12
  method: "GET",
@@ -147,4 +147,4 @@ const COMMENT_ROUTER_MAP = {
147
147
  };
148
148
 
149
149
  //#endregion
150
- export { COMMENT_ROUTER_MAP };
150
+ export { COMMENT_PROCEDURES };