cajonzero 0.1.1 → 0.1.2

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/dist/core.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { M as MapEntry, W as WorldSeed } from './providers-Dh-umPQ6.js';
2
- export { c as EMPTY_MAP_CATALOG, E as EnvProvider, d as MapCatalog, e as Repos, R as Room, f as RoomOptions, g as RuntimeProviders, h as SETTINGS, i as SETTING_KEYS, a as SettingDefaults, j as SettingDefinition, k as Settings, l as SettingsError, m as SettingsErrorCode, n as SettingsService, o as StorageFactory, S as StorageSource, p as Store, q as WorldSeedReader, r as configureDefaultKV, s as createMemoryStore, t as createRepos, u as createSettingsService, v as createStore, w as findMap, x as getRuntimeProviders, y as isSettingKey, z as memoryDriver, A as parseMapCatalog, B as resolveAdminToken, C as resolveEnvironment, F as resolveRooms, G as resolveSessionSecret, H as resolveSettingDefaults, I as resolveStore, J as setRuntimeProviders, K as setStorageFactory } from './providers-Dh-umPQ6.js';
3
- export { C as CajonzeroConfig, D as DEFAULT_CONFIG, G as GAME_NET_INBOUND_BASE, a as GAME_NET_OUTBOUND_BASE, I as INBOUND_LAYOUT, M as MAX_INBOUND_FRAME_BYTES, b as MapsConfig, N as NetCodec, c as NetCodecError, d as NetCodecErrorCode, e as NetCodecHandlers, f as NetCodecOptions, O as OFFICIAL_PREFIX, g as OUTBOUND_LAYOUT, P as ProtocolDirection, h as ProtocolLayout, i as ProtocolSchemaLike, R as RoomConfig, j as chainLayouts, l as layoutMessages, k as layoutProtocol, m as matchesLayout, n as messageIds, o as messageNameAt, r as readNetFrameHeader, p as readNetMessageType, q as resolveConfig } from './config-YtU8BYQM.js';
1
+ import { M as MapEntry, W as WorldSeed } from './providers-BX7e4pNW.js';
2
+ export { c as EMPTY_MAP_CATALOG, E as EnvProvider, d as MapCatalog, e as Repos, R as Room, f as RoomOptions, g as RuntimeProviders, h as SETTINGS, i as SETTING_KEYS, a as SettingDefaults, j as SettingDefinition, k as Settings, l as SettingsError, m as SettingsErrorCode, n as SettingsService, o as StorageFactory, S as StorageSource, p as Store, q as WorldSeedReader, r as configureDefaultKV, s as createMemoryStore, t as createRepos, u as createSettingsService, v as createStore, w as findMap, x as getRuntimeProviders, y as isSettingKey, z as memoryDriver, A as parseMapCatalog, B as resolveAdminToken, C as resolveEnvironment, F as resolveRooms, G as resolveSessionSecret, H as resolveSettingDefaults, I as resolveStore, J as setRuntimeProviders, K as setStorageFactory } from './providers-BX7e4pNW.js';
3
+ export { C as CajonzeroConfig, D as DEFAULT_CONFIG, G as GAME_NET_INBOUND_BASE, a as GAME_NET_OUTBOUND_BASE, I as INBOUND_LAYOUT, M as MAX_INBOUND_FRAME_BYTES, b as MapsConfig, N as NetCodec, c as NetCodecError, d as NetCodecErrorCode, e as NetCodecHandlers, f as NetCodecOptions, O as OFFICIAL_PREFIX, g as OUTBOUND_LAYOUT, P as ProtocolDirection, h as ProtocolLayout, i as ProtocolSchemaLike, R as RoomConfig, j as chainLayouts, l as layoutMessages, k as layoutProtocol, m as matchesLayout, n as messageIds, o as messageNameAt, r as readNetFrameHeader, p as readNetMessageType, q as resolveConfig } from './config-BOzAyP7m.js';
4
4
  import 'unstorage';
5
5
  import 'gl-matrix';
6
6
  import 'zod';
package/dist/core.js CHANGED
@@ -4989,7 +4989,6 @@ var KEY_PREFIX = {
4989
4989
  account: "account",
4990
4990
  session: "session",
4991
4991
  ban: "ban",
4992
- ratelimit: "ratelimit",
4993
4992
  settings: "settings",
4994
4993
  mapStorage: "mapstorage"
4995
4994
  };
@@ -5021,9 +5020,6 @@ function banAccountKey(subjectId) {
5021
5020
  function banIdentityKey(kind, hash) {
5022
5021
  return `ban:identity:${kind}:${seg2(hash)}`;
5023
5022
  }
5024
- function ratelimitKey(scope, hash) {
5025
- return `ratelimit:${seg2(scope)}:${seg2(hash)}`;
5026
- }
5027
5023
  function settingsKey(key) {
5028
5024
  return `settings:${seg2(key)}`;
5029
5025
  }
@@ -5066,12 +5062,6 @@ function parseKey(key) {
5066
5062
  }
5067
5063
  return void 0;
5068
5064
  }
5069
- case KEY_PREFIX.ratelimit: {
5070
- if (parts2.length !== 3) return void 0;
5071
- const scope = decode(parts2[1]);
5072
- const hash = decode(parts2[2]);
5073
- return scope === void 0 || hash === void 0 ? void 0 : { kind: "ratelimit", scope, hash };
5074
- }
5075
5065
  case KEY_PREFIX.settings: {
5076
5066
  if (parts2.length !== 2) return void 0;
5077
5067
  const settingKey = decode(parts2[1]);
@@ -15214,34 +15204,6 @@ function banDetails(input, at) {
15214
15204
  const expiresAt = input.expiresAt ?? (input.durationSeconds === void 0 ? void 0 : at + input.durationSeconds * 1e3);
15215
15205
  return { reason: input.reason, expiresAt, createdBy: input.createdBy };
15216
15206
  }
15217
- function createRateLimitsRepo(store, now) {
15218
- const repo = {
15219
- async increment(scope, hash, options = {}) {
15220
- const windowSeconds = Math.max(1, options.windowSeconds ?? 60);
15221
- const amount = options.amount ?? 1;
15222
- const at = now();
15223
- const current = await repo.get(scope, hash);
15224
- const windowStart = current !== void 0 && current.expiresAt > at ? current.windowStart : at;
15225
- const expiresAt = windowStart + windowSeconds * 1e3;
15226
- const next = {
15227
- count: (current !== void 0 && current.expiresAt > at ? current.count : 0) + amount,
15228
- windowStart,
15229
- expiresAt
15230
- };
15231
- const ttl = Math.max(1, Math.ceil((expiresAt - at) / 1e3));
15232
- await store.setItem(ratelimitKey(scope, hash), next, { ttl });
15233
- return next;
15234
- },
15235
- async get(scope, hash) {
15236
- const record = await store.getItem(ratelimitKey(scope, hash));
15237
- return record ?? void 0;
15238
- },
15239
- async reset(scope, hash) {
15240
- await store.removeItem(ratelimitKey(scope, hash));
15241
- }
15242
- };
15243
- return repo;
15244
- }
15245
15207
  function createSettingsRepo(store) {
15246
15208
  return {
15247
15209
  async get(key) {
@@ -15506,7 +15468,6 @@ function createRepos(store, options = {}) {
15506
15468
  accounts: createAccountsRepo(store, now),
15507
15469
  sessions: createSessionsRepo(store, now),
15508
15470
  bans: createBansRepo(store, now),
15509
- ratelimits: createRateLimitsRepo(store, now),
15510
15471
  settings: createSettingsRepo(store),
15511
15472
  mapStorage: (scope, namespace) => createMapStorageRepo(store, {
15512
15473
  scope,
@@ -16660,6 +16621,8 @@ var Room = class {
16660
16621
  mapLoading;
16661
16622
  worldReady = false;
16662
16623
  snapshotRestored = false;
16624
+ /** One-shot guard for the "proof without sessionSecret" diagnostic. */
16625
+ guestWarningLogged = false;
16663
16626
  persistence;
16664
16627
  socketsStarted = false;
16665
16628
  perf = { minPing: 0, maxPing: 0, avgPing: 0, pingCount: 0 };
@@ -17005,6 +16968,13 @@ var Room = class {
17005
16968
  this.pendingIdentities.set(sessionId, identity2);
17006
16969
  }
17007
16970
  } else {
16971
+ const proof = extractSessionProof(request.headers.get("sec-websocket-protocol"));
16972
+ if (proof !== void 0 && !this.guestWarningLogged) {
16973
+ this.guestWarningLogged = true;
16974
+ this.logger.error(
16975
+ "cajonzero: a session proof was supplied but no sessionSecret is configured; players join as guest. Pass serve({ sessionSecret: (env) => env.<SECRET> })."
16976
+ );
16977
+ }
17008
16978
  identity2 = guestIdentity(sessionId);
17009
16979
  }
17010
16980
  const ip = resolveClientIp(request);
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { Context, Hono } from 'hono';
2
2
  import { ContentfulStatusCode } from 'hono/utils/http-status';
3
- import { b as Env, d as MapCatalog, e as Repos, L as SessionsRepo, D as DurableObjectNamespace } from './providers-Dh-umPQ6.js';
3
+ import { b as Env, d as MapCatalog, e as Repos, L as SessionsRepo, D as DurableObjectNamespace } from './providers-BX7e4pNW.js';
4
4
  import { Store, SettingDefaults } from './core.js';
5
- export { c as EMPTY_MAP_CATALOG, M as MapEntry, R as Room, w as findMap, A as parseMapCatalog } from './providers-Dh-umPQ6.js';
6
- import { C as CajonzeroConfig } from './config-YtU8BYQM.js';
7
- export { D as DEFAULT_CONFIG, G as GAME_NET_INBOUND_BASE, a as GAME_NET_OUTBOUND_BASE, b as MapsConfig, N as NetCodec, e as NetCodecHandlers, R as RoomConfig, q as resolveConfig } from './config-YtU8BYQM.js';
5
+ export { c as EMPTY_MAP_CATALOG, M as MapEntry, R as Room, w as findMap, A as parseMapCatalog } from './providers-BX7e4pNW.js';
6
+ import { C as CajonzeroConfig } from './config-BOzAyP7m.js';
7
+ export { D as DEFAULT_CONFIG, G as GAME_NET_INBOUND_BASE, a as GAME_NET_OUTBOUND_BASE, b as MapsConfig, N as NetCodec, e as NetCodecHandlers, R as RoomConfig, q as resolveConfig } from './config-BOzAyP7m.js';
8
8
  export { DO_CLASSES, ServeOptions, WorkersEntry, WorkersModule, serve } from './serve.js';
9
9
  import 'unstorage';
10
10
  import 'gl-matrix';
@@ -18,7 +18,7 @@ import 'zod';
18
18
  * can read the version without creating a circular import.
19
19
  */
20
20
  declare const NAME = "cajonzero";
21
- declare const VERSION = "0.1.0";
21
+ declare const VERSION = "0.1.1";
22
22
 
23
23
  /** The authenticated principal carried by a login session (T11 supplies it). */
24
24
  interface SessionIdentity {
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import 'unstorage/drivers/memory';
11
11
 
12
12
  // src/version.ts
13
13
  var NAME = "cajonzero";
14
- var VERSION = "0.1.0";
14
+ var VERSION = "0.1.1";
15
15
 
16
16
  // src/core/config.ts
17
17
  var ConfigError = class extends Error {
@@ -288,7 +288,6 @@ var KEY_PREFIX = {
288
288
  account: "account",
289
289
  session: "session",
290
290
  ban: "ban",
291
- ratelimit: "ratelimit",
292
291
  settings: "settings",
293
292
  mapStorage: "mapstorage"
294
293
  };
@@ -320,9 +319,6 @@ function banAccountKey(subjectId) {
320
319
  function banIdentityKey(kind, hash) {
321
320
  return `ban:identity:${kind}:${seg(hash)}`;
322
321
  }
323
- function ratelimitKey(scope, hash) {
324
- return `ratelimit:${seg(scope)}:${seg(hash)}`;
325
- }
326
322
  function settingsKey(key) {
327
323
  return `settings:${seg(key)}`;
328
324
  }
@@ -365,12 +361,6 @@ function parseKey(key) {
365
361
  }
366
362
  return void 0;
367
363
  }
368
- case KEY_PREFIX.ratelimit: {
369
- if (parts2.length !== 3) return void 0;
370
- const scope = decode(parts2[1]);
371
- const hash = decode(parts2[2]);
372
- return scope === void 0 || hash === void 0 ? void 0 : { kind: "ratelimit", scope, hash };
373
- }
374
364
  case KEY_PREFIX.settings: {
375
365
  if (parts2.length !== 2) return void 0;
376
366
  const settingKey = decode(parts2[1]);
@@ -594,34 +584,6 @@ function banDetails(input, at) {
594
584
  const expiresAt = input.expiresAt ?? (input.durationSeconds === void 0 ? void 0 : at + input.durationSeconds * 1e3);
595
585
  return { reason: input.reason, expiresAt, createdBy: input.createdBy };
596
586
  }
597
- function createRateLimitsRepo(store, now) {
598
- const repo = {
599
- async increment(scope, hash, options = {}) {
600
- const windowSeconds = Math.max(1, options.windowSeconds ?? 60);
601
- const amount = options.amount ?? 1;
602
- const at = now();
603
- const current = await repo.get(scope, hash);
604
- const windowStart = current !== void 0 && current.expiresAt > at ? current.windowStart : at;
605
- const expiresAt = windowStart + windowSeconds * 1e3;
606
- const next = {
607
- count: (current !== void 0 && current.expiresAt > at ? current.count : 0) + amount,
608
- windowStart,
609
- expiresAt
610
- };
611
- const ttl = Math.max(1, Math.ceil((expiresAt - at) / 1e3));
612
- await store.setItem(ratelimitKey(scope, hash), next, { ttl });
613
- return next;
614
- },
615
- async get(scope, hash) {
616
- const record = await store.getItem(ratelimitKey(scope, hash));
617
- return record ?? void 0;
618
- },
619
- async reset(scope, hash) {
620
- await store.removeItem(ratelimitKey(scope, hash));
621
- }
622
- };
623
- return repo;
624
- }
625
587
  function createSettingsRepo(store) {
626
588
  return {
627
589
  async get(key) {
@@ -886,7 +848,6 @@ function createRepos(store, options = {}) {
886
848
  accounts: createAccountsRepo(store, now),
887
849
  sessions: createSessionsRepo(store, now),
888
850
  bans: createBansRepo(store, now),
889
- ratelimits: createRateLimitsRepo(store, now),
890
851
  settings: createSettingsRepo(store),
891
852
  mapStorage: (scope, namespace) => createMapStorageRepo(store, {
892
853
  scope,
@@ -9331,8 +9292,6 @@ var skinRegistry = new SkinRegistry();
9331
9292
 
9332
9293
  // src/core/identity/account-routes.ts
9333
9294
  var SESSION_COOKIE_NAME = "cajonzero_session";
9334
- var RATE_LIMIT_MAX_ATTEMPTS = 5;
9335
- var RATE_LIMIT_WINDOW_SECONDS = 300;
9336
9295
  var USERNAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]{2,31}$/;
9337
9296
  var MIN_PASSWORD_LENGTH = 10;
9338
9297
  var MAX_PASSWORD_LENGTH = 128;
@@ -9401,22 +9360,6 @@ function clientIp(request) {
9401
9360
  }
9402
9361
  return "unknown";
9403
9362
  }
9404
- async function enforceAttempts(c, deps, attempts) {
9405
- let retryAfter = null;
9406
- for (const attempt of attempts) {
9407
- const state = await deps.ratelimits.increment(attempt.scope, attempt.key, {
9408
- windowSeconds: RATE_LIMIT_WINDOW_SECONDS
9409
- });
9410
- if (state.count > RATE_LIMIT_MAX_ATTEMPTS) {
9411
- const seconds = Math.max(1, Math.ceil((state.expiresAt - deps.now()) / 1e3));
9412
- retryAfter = retryAfter === null ? seconds : Math.max(retryAfter, seconds);
9413
- }
9414
- }
9415
- if (retryAfter !== null) {
9416
- c.header("Retry-After", String(retryAfter));
9417
- throw new HttpError(429, "rate_limited");
9418
- }
9419
- }
9420
9363
  async function issueSession(c, deps, account, ip) {
9421
9364
  const minted = await mintSessionToken(
9422
9365
  {
@@ -9449,10 +9392,6 @@ function accountRoutes(deps) {
9449
9392
  const username = body.username;
9450
9393
  const password = body.password;
9451
9394
  const ip = clientIp(c.req.raw);
9452
- await enforceAttempts(c, deps, [
9453
- { scope: "register-ip", key: ip },
9454
- { scope: "register-account", key: username.toLowerCase() }
9455
- ]);
9456
9395
  const saltBytes = randomSalt();
9457
9396
  const passwordHash = await derivePassword(password, saltBytes);
9458
9397
  let account;
@@ -9477,11 +9416,6 @@ function accountRoutes(deps) {
9477
9416
  const username = body.username;
9478
9417
  const password = body.password;
9479
9418
  const ip = clientIp(c.req.raw);
9480
- const attempts = [{ scope: "login-ip", key: ip }];
9481
- if (username.length > 0) {
9482
- attempts.push({ scope: "login-account", key: username.toLowerCase() });
9483
- }
9484
- await enforceAttempts(c, deps, attempts);
9485
9419
  const account = username.length > 0 ? await deps.accounts.getByUsername(username) : void 0;
9486
9420
  if (account === void 0 || account.disabled) {
9487
9421
  await dummyVerify(password);
@@ -10180,7 +10114,6 @@ function registerRoutes(app, deps) {
10180
10114
  now: deps.now,
10181
10115
  accounts: repos.accounts,
10182
10116
  sessions: repos.sessions,
10183
- ratelimits: repos.ratelimits,
10184
10117
  getSession,
10185
10118
  sessionSecret: deps.sessionSecret,
10186
10119
  environment: deps.environment,
@@ -24633,6 +24566,8 @@ var Room = class {
24633
24566
  mapLoading;
24634
24567
  worldReady = false;
24635
24568
  snapshotRestored = false;
24569
+ /** One-shot guard for the "proof without sessionSecret" diagnostic. */
24570
+ guestWarningLogged = false;
24636
24571
  persistence;
24637
24572
  socketsStarted = false;
24638
24573
  perf = { minPing: 0, maxPing: 0, avgPing: 0, pingCount: 0 };
@@ -24978,6 +24913,13 @@ var Room = class {
24978
24913
  this.pendingIdentities.set(sessionId, identity2);
24979
24914
  }
24980
24915
  } else {
24916
+ const proof = extractSessionProof(request.headers.get("sec-websocket-protocol"));
24917
+ if (proof !== void 0 && !this.guestWarningLogged) {
24918
+ this.guestWarningLogged = true;
24919
+ this.logger.error(
24920
+ "cajonzero: a session proof was supplied but no sessionSecret is configured; players join as guest. Pass serve({ sessionSecret: (env) => env.<SECRET> })."
24921
+ );
24922
+ }
24981
24923
  identity2 = guestIdentity(sessionId);
24982
24924
  }
24983
24925
  const ip = resolveClientIp(request);
@@ -199,7 +199,7 @@ declare function createMemoryStore(): Store;
199
199
  * cajonzero — typed repositories over the unstorage layer (T4).
200
200
  *
201
201
  * Thin, dependency-injected repositories for the embedded account system
202
- * (`accounts`, `sessions`, `bans`, `ratelimits`), runtime settings, and the
202
+ * (`accounts`, `sessions`, `bans`), runtime settings, and the
203
203
  * map-script storage-kv API (`mapStorage`). Each is a small closure over a
204
204
  * {@link Store}; no repository knows about HTTP, Hono, or Cloudflare globals, so
205
205
  * every one is exercisable on the in-memory driver.
@@ -332,21 +332,6 @@ interface BansRepo {
332
332
  deleteByKey(key: string): Promise<boolean>;
333
333
  isActive(ban: BanRecord, at?: number): boolean;
334
334
  }
335
- /** Fixed-window rate-limit state. */
336
- interface RateLimitState {
337
- count: number;
338
- windowStart: number;
339
- expiresAt: number;
340
- }
341
- interface RateLimitIncrementOptions {
342
- readonly windowSeconds?: number;
343
- readonly amount?: number;
344
- }
345
- interface RateLimitsRepo {
346
- increment(scope: string, hash: string, options?: RateLimitIncrementOptions): Promise<RateLimitState>;
347
- get(scope: string, hash: string): Promise<RateLimitState | undefined>;
348
- reset(scope: string, hash: string): Promise<void>;
349
- }
350
335
  interface SettingsRepo {
351
336
  get<T = JSONValue>(key: string): Promise<T | undefined>;
352
337
  set(key: string, value: JSONValue): Promise<void>;
@@ -384,7 +369,6 @@ interface Repos {
384
369
  readonly accounts: AccountsRepo;
385
370
  readonly sessions: SessionsRepo;
386
371
  readonly bans: BansRepo;
387
- readonly ratelimits: RateLimitsRepo;
388
372
  readonly settings: SettingsRepo;
389
373
  /** Builds a map-script storage repo for one `(scope, namespace)`. */
390
374
  mapStorage(scope: string, namespace: string): MapStorageRepo;
@@ -5093,6 +5077,8 @@ declare class Room {
5093
5077
  private mapLoading;
5094
5078
  private worldReady;
5095
5079
  private snapshotRestored;
5080
+ /** One-shot guard for the "proof without sessionSecret" diagnostic. */
5081
+ private guestWarningLogged;
5096
5082
  private persistence;
5097
5083
  private socketsStarted;
5098
5084
  private perf;
@@ -146,5 +146,63 @@ declare function toPackageName(folder: string): string;
146
146
  */
147
147
  declare function createProject(folder: string, options?: CreateProjectOptions): ScaffoldResult;
148
148
 
149
- export { SCAFFOLD_COMPATIBILITY_DATE, SCAFFOLD_CONFIG_CONTENT, SCAFFOLD_ENTRY_CONTENT, SCAFFOLD_ENTRY_PATH, SCAFFOLD_KV_PLACEHOLDER_ID, SCAFFOLD_MAPS_CONTENT, ScaffoldError, buildScaffoldFiles, createProject, readCajonzeroPackage, toPackageName };
150
- export type { CajonzeroPackageInfo, CreateProjectOptions, ScaffoldErrorCode, ScaffoldFile, ScaffoldResult, ScaffoldTemplateOptions };
149
+ /** Where one setup value is written. */
150
+ type SetupKind = "var" | "secret";
151
+ /** One configurable value. */
152
+ interface SetupField {
153
+ readonly name: string;
154
+ /** Chinese prompt label. */
155
+ readonly label: string;
156
+ readonly kind: SetupKind;
157
+ /** `true` for the values a project cannot run without. */
158
+ readonly required: boolean;
159
+ /** Default shown in the prompt (secrets: generated when absent). */
160
+ readonly default?: string;
161
+ /** Short explanation printed next to the prompt. */
162
+ readonly hint?: string;
163
+ }
164
+ /** Every value `setup` manages. */
165
+ declare const SETUP_FIELDS: readonly SetupField[];
166
+ /** Files `setup` touched. */
167
+ interface SetupResult {
168
+ readonly configPath: string;
169
+ readonly devVarsPath: string;
170
+ /** Non-secret values written to `wrangler.jsonc`. */
171
+ readonly vars: Record<string, string>;
172
+ /** Secrets written to `.dev.vars`. */
173
+ readonly secrets: Record<string, string>;
174
+ }
175
+ interface SetupOptions {
176
+ readonly cwd?: string;
177
+ /** Wrangler config path (default `wrangler.jsonc`). */
178
+ readonly configPath?: string;
179
+ /** Values to write; managed keys absent here are removed. */
180
+ readonly values: Readonly<Record<string, string>>;
181
+ }
182
+ /** Generated default for a required secret. */
183
+ declare function generateSecret(): string;
184
+ /** Generated default for the owner token (shorter, URL-safe). */
185
+ declare function generateAdminToken(): string;
186
+ /** Default value for a field when it has no configured value yet. */
187
+ declare function suggestedValue(field: SetupField): string | undefined;
188
+ /** Parse `.dev.vars` (`KEY=value`, `#` comments). */
189
+ declare function parseDevVars(text: string): Record<string, string>;
190
+ /** Serialize `.dev.vars` (stable order, trailing newline). */
191
+ declare function serializeDevVars(values: Record<string, string>): string;
192
+ /**
193
+ * Merge `vars` into the `wrangler.jsonc` `"vars"` object.
194
+ *
195
+ * Keys not managed by cajonzero are preserved; managed keys absent from `vars`
196
+ * are removed so clearing a setting falls back to its default.
197
+ */
198
+ declare function setWranglerVars(raw: string, vars: Readonly<Record<string, string>>): string;
199
+ /** Read currently configured values (wrangler vars + `.dev.vars`). */
200
+ declare function readSetupValues(cwd: string, configPath: string, devVarsPath: string): Record<string, string>;
201
+ /**
202
+ * Apply the answers: non-secret values to `wrangler.jsonc`, secrets to
203
+ * `.dev.vars`. Throws when the project files are missing.
204
+ */
205
+ declare function applySetup(options: SetupOptions): SetupResult;
206
+
207
+ export { SCAFFOLD_COMPATIBILITY_DATE, SCAFFOLD_CONFIG_CONTENT, SCAFFOLD_ENTRY_CONTENT, SCAFFOLD_ENTRY_PATH, SCAFFOLD_KV_PLACEHOLDER_ID, SCAFFOLD_MAPS_CONTENT, SETUP_FIELDS, ScaffoldError, applySetup, buildScaffoldFiles, createProject, generateAdminToken, generateSecret, parseDevVars, readCajonzeroPackage, readSetupValues, serializeDevVars, setWranglerVars, suggestedValue, toPackageName };
208
+ export type { CajonzeroPackageInfo, CreateProjectOptions, ScaffoldErrorCode, ScaffoldFile, ScaffoldResult, ScaffoldTemplateOptions, SetupField, SetupKind, SetupOptions, SetupResult };