@lunora/config 1.0.0-alpha.23 → 1.0.0-alpha.24

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/index.d.mts CHANGED
@@ -240,6 +240,13 @@ interface InferredBindings {
240
240
  containers: InferredContainer[];
241
241
  /** Durable Objects the worker entry exports → safe to bind. */
242
242
  durableObjects: DurableObjectSpec[];
243
+ /**
244
+ * The wrangler `flagship[].binding` name implied by `lunora/flags.ts` when it
245
+ * uses the Flagship provider in binding mode — `undefined` for HTTP-mode
246
+ * Flagship, a custom OpenFeature provider, or no flags. The binding needs an
247
+ * un-mintable `app_id`, so it is reconciled as a hint, not auto-written.
248
+ */
249
+ flagshipBinding?: string;
243
250
  /** Schema declares a `.global()` table → needs the `DB` D1 binding. */
244
251
  needsD1: boolean;
245
252
  /** Queues declared in `lunora/queues.ts` → reconciled into `queues.producers[]` / `queues.consumers[]`. */
@@ -254,6 +261,8 @@ interface InferredBindings {
254
261
  usesAuth: boolean;
255
262
  /** `@lunora/browser` is imported → self-describing `browser` binding (auto-writeable). */
256
263
  usesBrowser: boolean;
264
+ /** `lunora/flags.ts` declares a feature-flag provider (any OpenFeature provider — Flagship or custom). */
265
+ usesFlags: boolean;
257
266
  /** `@lunora/hyperdrive` is imported (binding needs an un-mintable remote `id`; hint-only). */
258
267
  usesHyperdrive: boolean;
259
268
  /** `@lunora/bindings/images` is imported → self-describing `images` binding (auto-writeable). */
@@ -1199,6 +1208,10 @@ interface WranglerConfig {
1199
1208
  durable_objects?: {
1200
1209
  bindings?: ReadonlyArray<WranglerDurableObjectBinding>;
1201
1210
  };
1211
+ flagship?: ReadonlyArray<{
1212
+ app_id?: string;
1213
+ binding?: string;
1214
+ } | null | undefined>;
1202
1215
  hyperdrive?: ReadonlyArray<{
1203
1216
  binding?: string;
1204
1217
  id?: string;
package/dist/index.d.ts CHANGED
@@ -240,6 +240,13 @@ interface InferredBindings {
240
240
  containers: InferredContainer[];
241
241
  /** Durable Objects the worker entry exports → safe to bind. */
242
242
  durableObjects: DurableObjectSpec[];
243
+ /**
244
+ * The wrangler `flagship[].binding` name implied by `lunora/flags.ts` when it
245
+ * uses the Flagship provider in binding mode — `undefined` for HTTP-mode
246
+ * Flagship, a custom OpenFeature provider, or no flags. The binding needs an
247
+ * un-mintable `app_id`, so it is reconciled as a hint, not auto-written.
248
+ */
249
+ flagshipBinding?: string;
243
250
  /** Schema declares a `.global()` table → needs the `DB` D1 binding. */
244
251
  needsD1: boolean;
245
252
  /** Queues declared in `lunora/queues.ts` → reconciled into `queues.producers[]` / `queues.consumers[]`. */
@@ -254,6 +261,8 @@ interface InferredBindings {
254
261
  usesAuth: boolean;
255
262
  /** `@lunora/browser` is imported → self-describing `browser` binding (auto-writeable). */
256
263
  usesBrowser: boolean;
264
+ /** `lunora/flags.ts` declares a feature-flag provider (any OpenFeature provider — Flagship or custom). */
265
+ usesFlags: boolean;
257
266
  /** `@lunora/hyperdrive` is imported (binding needs an un-mintable remote `id`; hint-only). */
258
267
  usesHyperdrive: boolean;
259
268
  /** `@lunora/bindings/images` is imported → self-describing `images` binding (auto-writeable). */
@@ -1199,6 +1208,10 @@ interface WranglerConfig {
1199
1208
  durable_objects?: {
1200
1209
  bindings?: ReadonlyArray<WranglerDurableObjectBinding>;
1201
1210
  };
1211
+ flagship?: ReadonlyArray<{
1212
+ app_id?: string;
1213
+ binding?: string;
1214
+ } | null | undefined>;
1202
1215
  hyperdrive?: ReadonlyArray<{
1203
1216
  binding?: string;
1204
1217
  id?: string;
package/dist/index.mjs CHANGED
@@ -3,14 +3,14 @@ export { discoverContainerInfo } from './packem_shared/discoverContainerInfo-BXF
3
3
  export { streamContainerLogs } from './packem_shared/streamContainerLogs-BZ4cOZwH.mjs';
4
4
  export { detectFramework } from './packem_shared/detectFramework-Br-BcPBq.mjs';
5
5
  export { DEV_VARS_EXAMPLE_FILE, DEV_VARS_FILE, DEV_VARS_KEY_PATTERN, parseDevVariableEntries } from './packem_shared/DEV_VARS_EXAMPLE_FILE-dJPNTEnK.mjs';
6
- export { inferLunoraBindings, packageNamesFromBindings } from './packem_shared/inferLunoraBindings-b9SJwb2s.mjs';
6
+ export { inferLunoraBindings, packageNamesFromBindings } from './packem_shared/inferLunoraBindings-ByMwG-gH.mjs';
7
7
  export { LINKED_PROJECT_DIR, LINKED_PROJECT_FILE, readLinkedProject, writeLinkedProject } from './packem_shared/LINKED_PROJECT_DIR-CXwXzV_C.mjs';
8
8
  export { LUNORA_EVENT_SOURCE, formatLunoraEvent } from './packem_shared/LUNORA_EVENT_SOURCE-D2fDeGB6.mjs';
9
9
  export { default as LunoraReporter } from './packem_shared/LunoraReporter-Ci-bDCK9.mjs';
10
10
  export { PACKAGE_SECRETS_REGISTRY, secretsForPackages } from './packem_shared/PACKAGE_SECRETS_REGISTRY-B8t_SdoZ.mjs';
11
11
  export { LUNORA_CONFIG_FILE, interpretRemote, readProjectRemotePreference } from './packem_shared/LUNORA_CONFIG_FILE-CtcIcB5-.mjs';
12
12
  export { createConfirm, isInteractive, promptMultiSelect, promptSelect, promptYesNo } from './packem_shared/createConfirm-fvpdgJ9s.mjs';
13
- export { reconcileWranglerBindings } from './packem_shared/reconcileWranglerBindings-27af-Qvt.mjs';
13
+ export { reconcileWranglerBindings } from './packem_shared/reconcileWranglerBindings-Cruwwx1M.mjs';
14
14
  export { REMOTE_ELIGIBLE_KEYS, injectRemoteFlags, isRemoteEnvEnabled, materializeRemoteWranglerConfig, planRemoteBindings, resolveRemoteEnabled } from './packem_shared/REMOTE_ELIGIBLE_KEYS-BC7_e9Bz.mjs';
15
15
  export { buildPackageSecretsBlock, ensureDevVariables, ensureDevVarsExample, fillDevSecrets, generateSecretValue, isMintableSecretKey, isPlaceholderValue, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, requiredSecrets } from './packem_shared/buildPackageSecretsBlock-DWDKHViT.mjs';
16
16
  export { applyAdditiveEdit, classifyEdit } from './packem_shared/applyAdditiveEdit-C-snTFEV.mjs';
@@ -20,4 +20,4 @@ export { discoverSchemaInfo } from './packem_shared/discoverSchemaInfo-BB-CKlTK.
20
20
  export { ACCENT, BADGES, BADGE_COLUMN_WIDTH, LUNA_ART, LUNA_BUNNY, LUNA_NAME, LUNA_SIGNOFF, STEP_BADGE_NAMES, badgeLead, badgeWidth, padBadge, paintAnswer, paintBadge } from './packem_shared/ACCENT-DW1XJn8i.mjs';
21
21
  export { discoverWorkflowInfo } from './packem_shared/discoverWorkflowInfo-CedvR0mn.mjs';
22
22
  export { WRANGLER_FILES, findWranglerFile, readWranglerJsonc } from './packem_shared/WRANGLER_FILES-DwSuC-Kn.mjs';
23
- export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer } from './packem_shared/REQUIRED_COMPATIBILITY_DATE-USQQ7NfE.mjs';
23
+ export { REQUIRED_COMPATIBILITY_DATE, REQUIRED_FLAG, validateWrangler, validateWranglerConfig, validateWranglerProject, withTailConsumer } from './packem_shared/REQUIRED_COMPATIBILITY_DATE-2YYyWJUq.mjs';
@@ -213,6 +213,13 @@ const HINT_BINDING_RULES = [
213
213
  hintMessage: (label, binding) => `${label} ("${binding}") has no "id" — run \`wrangler kv namespace create\` and set the namespace id, or the binding can't resolve`,
214
214
  key: "kv_namespaces"
215
215
  },
216
+ {
217
+ arrayMessage: "flagship must be an array of { binding, app_id } entries",
218
+ bindingMessage: (label) => `${label} must have a non-empty "binding" naming the Flagship binding`,
219
+ hintField: "app_id",
220
+ hintMessage: (label, binding) => `${label} ("${binding}") has no "app_id" — create a Flagship app and set its id, or the binding can't resolve`,
221
+ key: "flagship"
222
+ },
216
223
  {
217
224
  arrayMessage: "hyperdrive must be an array of { binding, id } entries",
218
225
  bindingMessage: (label) => `${label} must have a non-empty "binding" naming the Hyperdrive binding`,
@@ -1,13 +1,26 @@
1
1
  import { existsSync, statSync, readFileSync, readdirSync } from 'node:fs';
2
2
  import { init, parse } from 'es-module-lexer';
3
3
  import { discoverContainerInfo } from './discoverContainerInfo-BXFs6Wav.mjs';
4
- import { QUEUES_FILENAME, discoverQueues } from '@lunora/codegen';
4
+ import { FLAGS_FILENAME, discoverFlags, QUEUES_FILENAME, discoverQueues } from '@lunora/codegen';
5
5
  import { Project } from 'ts-morph';
6
6
  import { join } from 'node:path';
7
7
  import { discoverSchemaInfo } from './discoverSchemaInfo-BB-CKlTK.mjs';
8
8
  import { discoverWorkflowInfo } from './discoverWorkflowInfo-CedvR0mn.mjs';
9
9
  import { WRANGLER_FILES, readWranglerJsonc } from './WRANGLER_FILES-DwSuC-Kn.mjs';
10
10
 
11
+ const discoverFlagsInfo = (projectRoot, schemaDirectory) => {
12
+ const flagsPath = join(projectRoot, schemaDirectory, FLAGS_FILENAME);
13
+ if (!existsSync(flagsPath)) {
14
+ return {};
15
+ }
16
+ try {
17
+ const project = new Project({ skipAddingFilesFromTsConfig: true, useInMemoryFileSystem: false });
18
+ return { flags: discoverFlags(project, join(projectRoot, schemaDirectory)) };
19
+ } catch (error) {
20
+ return { error: error instanceof Error ? error.message : String(error) };
21
+ }
22
+ };
23
+
11
24
  const discoverQueueInfo = (projectRoot, schemaDirectory) => {
12
25
  const queuesPath = join(projectRoot, schemaDirectory, QUEUES_FILENAME);
13
26
  if (!existsSync(queuesPath)) {
@@ -302,16 +315,26 @@ const inferLunoraBindings = async (options) => {
302
315
  const containers = detectContainerExports(entryPath, discoverContainerInfo(options.projectRoot, schemaDirectory).containers);
303
316
  const workflows = detectWorkflowExports(entryPath, discoverWorkflowInfo(options.projectRoot, schemaDirectory).workflows);
304
317
  const queues = [...discoverQueueInfo(options.projectRoot, schemaDirectory).queues];
318
+ const { flags } = discoverFlagsInfo(options.projectRoot, schemaDirectory);
319
+ const flagshipBinding = flags?.provider === "flagship" && flags.mode === "binding" ? flags.bindingName : void 0;
305
320
  const capabilityFlags = {};
306
321
  for (const flag of CAPABILITY_FLAGS) {
307
322
  capabilityFlags[flag] = capabilities[flag];
308
323
  }
324
+ const signals = describeSignals(durableObjects, needsD1, capabilities, containers, workflows);
325
+ if (flagshipBinding !== void 0) {
326
+ signals.push(
327
+ `hint: lunora/flags.ts uses Flagship in binding mode; add a flagship binding ({ binding: "${flagshipBinding}", app_id }) — the app_id can't be auto-provisioned`
328
+ );
329
+ }
309
330
  return {
310
331
  containers,
311
332
  durableObjects,
333
+ flagshipBinding,
312
334
  needsD1,
313
335
  queues,
314
- signals: describeSignals(durableObjects, needsD1, capabilities, containers, workflows),
336
+ signals,
337
+ usesFlags: flags !== void 0,
315
338
  workflows,
316
339
  ...capabilityFlags
317
340
  };
@@ -20,6 +20,7 @@ const collectExportGaps = (inferred) => {
20
20
  return gaps;
21
21
  };
22
22
  const collectHintBindingWarnings = (inferred, parsed) => {
23
+ const flagshipBindingMissing = inferred.flagshipBinding !== void 0 && !(parsed?.flagship ?? []).some((entry) => entry.binding === inferred.flagshipBinding);
23
24
  const rules = [
24
25
  [
25
26
  inferred.usesKv && (parsed?.kv_namespaces?.length ?? 0) === 0,
@@ -32,6 +33,10 @@ const collectHintBindingWarnings = (inferred, parsed) => {
32
33
  [
33
34
  inferred.usesPipelines && (parsed?.pipelines?.length ?? 0) === 0,
34
35
  "ctx.pipelines is used but no pipelines binding exists; run 'wrangler pipelines create <name>' and add a 'pipelines' binding ({ binding, pipeline }) — the pipeline resource can't be auto-provisioned."
36
+ ],
37
+ [
38
+ flagshipBindingMissing,
39
+ `lunora/flags.ts uses Flagship in binding mode but no flagship binding "${inferred.flagshipBinding ?? ""}" exists; add a flagship entry ({ binding: "${inferred.flagshipBinding ?? ""}", app_id }) — the app_id can't be auto-provisioned.`
35
40
  ]
36
41
  ];
37
42
  return rules.filter(([active]) => active).map(([, warning]) => warning);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/config",
3
- "version": "1.0.0-alpha.23",
3
+ "version": "1.0.0-alpha.24",
4
4
  "description": "Internal shared CLI + Vite config layer for Lunora: wrangler.jsonc validation, binding inference, and .dev.vars scaffolding",
5
5
  "keywords": [
6
6
  "bindings",
@@ -50,7 +50,7 @@
50
50
  "access": "public"
51
51
  },
52
52
  "dependencies": {
53
- "@lunora/codegen": "1.0.0-alpha.14",
53
+ "@lunora/codegen": "1.0.0-alpha.15",
54
54
  "@lunora/container": "1.0.0-alpha.4",
55
55
  "@lunora/seed": "1.0.0-alpha.6",
56
56
  "@visulima/colorize": "2.0.0-alpha.14",
@@ -60,7 +60,7 @@
60
60
  "ts-morph": "^28.0.0"
61
61
  },
62
62
  "peerDependencies": {
63
- "@lunora/studio": "1.0.0-alpha.11"
63
+ "@lunora/studio": "1.0.0-alpha.12"
64
64
  },
65
65
  "peerDependenciesMeta": {
66
66
  "@lunora/studio": {