@lunora/codegen 1.0.0-alpha.14 → 1.0.0-alpha.16
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 +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.mjs +6 -5
- package/dist/packem_shared/FLAGS_FILENAME-B1vE0LIo.mjs +139 -0
- package/dist/packem_shared/{GENERATED_HEADER-BEA7oWGC.mjs → GENERATED_HEADER-CkZUgM4_.mjs} +114 -11
- package/dist/packem_shared/{OPENRPC_VERSION-CQ3f8YQ-.mjs → OPENRPC_VERSION-VINwUAxf.mjs} +1 -1
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-BXtduJFE.mjs → SCHEMA_SNAPSHOT_FILENAME-DsBxQ5C_.mjs} +13 -4
- package/dist/packem_shared/{buildOpenApiDocument-699G4RP4.mjs → buildOpenApiDocument-BSoDzIn8.mjs} +1 -1
- package/dist/packem_shared/{emitApp-DiK0QSBn.mjs → emitApp-DGmlt5fq.mjs} +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -343,6 +343,30 @@ interface QueueIR {
|
|
|
343
343
|
};
|
|
344
344
|
}
|
|
345
345
|
/**
|
|
346
|
+
* The feature-flag provider declared by the default export of `lunora/flags.ts`
|
|
347
|
+
* (`defineFlags({ provider, … })`). Discovery is **metadata-only** — codegen
|
|
348
|
+
* imports the real module at runtime for the provider value; this IR exists so
|
|
349
|
+
* the config layer can reconcile/validate the wrangler `flagship` binding when
|
|
350
|
+
* the app uses Flagship in binding mode. A `custom` provider (any other
|
|
351
|
+
* OpenFeature factory) carries no binding to reconcile.
|
|
352
|
+
*/
|
|
353
|
+
interface FlagsIR {
|
|
354
|
+
/**
|
|
355
|
+
* The wrangler `flagship[].binding` name — set **only** for a flagship
|
|
356
|
+
* `provider` in binding mode (`flagshipProvider({ binding: "FLAGS" })`). The
|
|
357
|
+
* config layer hints/validates a matching `flagship` binding from this.
|
|
358
|
+
*/
|
|
359
|
+
bindingName?: string;
|
|
360
|
+
/**
|
|
361
|
+
* Flagship operating mode — `"binding"` (wrangler binding, needs a
|
|
362
|
+
* `flagship` entry) or `"http"` (no binding); `undefined` for a `custom`
|
|
363
|
+
* provider or when the mode can't be read statically.
|
|
364
|
+
*/
|
|
365
|
+
mode?: "binding" | "http";
|
|
366
|
+
/** `"flagship"` when the provider is `flagshipProvider(...)`, else `"custom"` (any other OpenFeature provider factory). */
|
|
367
|
+
provider: "custom" | "flagship";
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
346
370
|
* A `ctx.workflows.get("name")…` call discovered in a function body — the
|
|
347
371
|
* use-site analog of {@link WorkflowIR} (which is the declaration side). Feeds
|
|
348
372
|
* the `workflow_unused` lint (a declared workflow with zero call sites) and the
|
|
@@ -817,6 +841,21 @@ declare const discoverContainers: (project: Project, lunoraDirectory: string) =>
|
|
|
817
841
|
* workflow start. Names must be unique across the project.
|
|
818
842
|
*/
|
|
819
843
|
declare const discoverCrons: (project: Project, lunoraDirectory: string, workflows?: ReadonlyArray<WorkflowIR>) => CronJobIR[];
|
|
844
|
+
/** The only file a feature-flag provider may be declared in — mirrors `lunora/queues.ts`. */
|
|
845
|
+
declare const FLAGS_FILENAME = "flags.ts";
|
|
846
|
+
/** One statically-discovered flag read: the key plus the value type its `ctx.flags.<type>` call implies. */
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Discover the feature-flag provider a project declares in `lunora/flags.ts`.
|
|
850
|
+
* Returns `undefined` when the file doesn't exist (the app has no flags). The
|
|
851
|
+
* read is metadata-only and lenient: codegen wires `ctx.flags` purely from the
|
|
852
|
+
* file's *existence* (`run-codegen.ts`) and imports the real module for the
|
|
853
|
+
* provider value — this IR exists solely so the config layer can reconcile the
|
|
854
|
+
* wrangler `flagship` binding for the Flagship binding-mode provider. Anything
|
|
855
|
+
* it can't read statically degrades to a `custom` provider (no binding), never
|
|
856
|
+
* a thrown error.
|
|
857
|
+
*/
|
|
858
|
+
declare const discoverFlags: (project: Project, lunoraDirectory: string) => FlagsIR | undefined;
|
|
820
859
|
/**
|
|
821
860
|
* Scan all .ts files under `lunoraDir` (skipping `_generated/` and `schema.ts`)
|
|
822
861
|
* for top-level `export const x = query/mutation/action({...})` registrations.
|
|
@@ -969,6 +1008,8 @@ interface EmitServerOptions {
|
|
|
969
1008
|
hasAnalytics?: boolean;
|
|
970
1009
|
/** A `lunora/` source uses `@lunora/browser` / `ctx.browser` — wires `ctx.browser` onto ActionCtx only. */
|
|
971
1010
|
hasBrowser?: boolean;
|
|
1011
|
+
/** The project declares `lunora/flags.ts` — wires `ctx.flags` (OpenFeature) onto every ctx. */
|
|
1012
|
+
hasFlags?: boolean;
|
|
972
1013
|
/** A `lunora/` source uses `@lunora/hyperdrive` / `ctx.sql` — wires `ctx.sql` onto ActionCtx only. */
|
|
973
1014
|
hasHyperdrive?: boolean;
|
|
974
1015
|
/** A `lunora/` source uses `@lunora/bindings/images` / `ctx.images` — wires `ctx.images` onto ActionCtx only. */
|
|
@@ -993,6 +1034,7 @@ declare const emitServer: ({
|
|
|
993
1034
|
hasAi,
|
|
994
1035
|
hasAnalytics,
|
|
995
1036
|
hasBrowser,
|
|
1037
|
+
hasFlags,
|
|
996
1038
|
hasHyperdrive,
|
|
997
1039
|
hasImages,
|
|
998
1040
|
hasKv,
|
|
@@ -1044,11 +1086,18 @@ declare const emitWorkflows: (workflows: ReadonlyArray<WorkflowIR>) => string;
|
|
|
1044
1086
|
interface EmitShardOptions {
|
|
1045
1087
|
advisories?: ReadonlyArray<Finding>;
|
|
1046
1088
|
containers?: ReadonlyArray<ContainerIR>;
|
|
1089
|
+
/** Statically-discovered `ctx.flags.<type>("key")` reads — the studio Flags page + reactive evaluation iterate these. */
|
|
1090
|
+
flagKeys?: ReadonlyArray<{
|
|
1091
|
+
key: string;
|
|
1092
|
+
type: "boolean" | "number" | "object" | "string";
|
|
1093
|
+
}>;
|
|
1047
1094
|
hasAi?: boolean;
|
|
1048
1095
|
/** A `lunora/` source reads `ctx.analytics` — wires the Analytics Engine write helper onto every ctx. */
|
|
1049
1096
|
hasAnalytics?: boolean;
|
|
1050
1097
|
/** A `lunora/` source reads `ctx.browser` — wires `ctx.browser` onto the ActionCtx only. */
|
|
1051
1098
|
hasBrowser?: boolean;
|
|
1099
|
+
/** The project declares `lunora/flags.ts` — wires `ctx.flags` (OpenFeature) onto every ctx. */
|
|
1100
|
+
hasFlags?: boolean;
|
|
1052
1101
|
/** A `lunora/` source reads `ctx.sql` (Hyperdrive) — wires `ctx.sql` onto the ActionCtx only. */
|
|
1053
1102
|
hasHyperdrive?: boolean;
|
|
1054
1103
|
/** A `lunora/` source reads `ctx.images` — wires `ctx.images` onto the ActionCtx only. */
|
|
@@ -1074,9 +1123,11 @@ interface EmitShardOptions {
|
|
|
1074
1123
|
declare const emitShard: ({
|
|
1075
1124
|
advisories,
|
|
1076
1125
|
containers,
|
|
1126
|
+
flagKeys,
|
|
1077
1127
|
hasAi,
|
|
1078
1128
|
hasAnalytics,
|
|
1079
1129
|
hasBrowser,
|
|
1130
|
+
hasFlags,
|
|
1080
1131
|
hasHyperdrive,
|
|
1081
1132
|
hasImages,
|
|
1082
1133
|
hasKv,
|
|
@@ -1674,4 +1725,4 @@ declare const LUNORA_SOLUTION_RULES: ReadonlyArray<LunoraSolutionRule>;
|
|
|
1674
1725
|
*/
|
|
1675
1726
|
declare const findLunoraSolution: (message: string) => LunoraSolution | undefined;
|
|
1676
1727
|
declare const VERSION = "0.0.0";
|
|
1677
|
-
export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
|
|
1728
|
+
export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, FLAGS_FILENAME, type FieldSnapshot, type FlagsIR, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFlags, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -343,6 +343,30 @@ interface QueueIR {
|
|
|
343
343
|
};
|
|
344
344
|
}
|
|
345
345
|
/**
|
|
346
|
+
* The feature-flag provider declared by the default export of `lunora/flags.ts`
|
|
347
|
+
* (`defineFlags({ provider, … })`). Discovery is **metadata-only** — codegen
|
|
348
|
+
* imports the real module at runtime for the provider value; this IR exists so
|
|
349
|
+
* the config layer can reconcile/validate the wrangler `flagship` binding when
|
|
350
|
+
* the app uses Flagship in binding mode. A `custom` provider (any other
|
|
351
|
+
* OpenFeature factory) carries no binding to reconcile.
|
|
352
|
+
*/
|
|
353
|
+
interface FlagsIR {
|
|
354
|
+
/**
|
|
355
|
+
* The wrangler `flagship[].binding` name — set **only** for a flagship
|
|
356
|
+
* `provider` in binding mode (`flagshipProvider({ binding: "FLAGS" })`). The
|
|
357
|
+
* config layer hints/validates a matching `flagship` binding from this.
|
|
358
|
+
*/
|
|
359
|
+
bindingName?: string;
|
|
360
|
+
/**
|
|
361
|
+
* Flagship operating mode — `"binding"` (wrangler binding, needs a
|
|
362
|
+
* `flagship` entry) or `"http"` (no binding); `undefined` for a `custom`
|
|
363
|
+
* provider or when the mode can't be read statically.
|
|
364
|
+
*/
|
|
365
|
+
mode?: "binding" | "http";
|
|
366
|
+
/** `"flagship"` when the provider is `flagshipProvider(...)`, else `"custom"` (any other OpenFeature provider factory). */
|
|
367
|
+
provider: "custom" | "flagship";
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
346
370
|
* A `ctx.workflows.get("name")…` call discovered in a function body — the
|
|
347
371
|
* use-site analog of {@link WorkflowIR} (which is the declaration side). Feeds
|
|
348
372
|
* the `workflow_unused` lint (a declared workflow with zero call sites) and the
|
|
@@ -817,6 +841,21 @@ declare const discoverContainers: (project: Project, lunoraDirectory: string) =>
|
|
|
817
841
|
* workflow start. Names must be unique across the project.
|
|
818
842
|
*/
|
|
819
843
|
declare const discoverCrons: (project: Project, lunoraDirectory: string, workflows?: ReadonlyArray<WorkflowIR>) => CronJobIR[];
|
|
844
|
+
/** The only file a feature-flag provider may be declared in — mirrors `lunora/queues.ts`. */
|
|
845
|
+
declare const FLAGS_FILENAME = "flags.ts";
|
|
846
|
+
/** One statically-discovered flag read: the key plus the value type its `ctx.flags.<type>` call implies. */
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Discover the feature-flag provider a project declares in `lunora/flags.ts`.
|
|
850
|
+
* Returns `undefined` when the file doesn't exist (the app has no flags). The
|
|
851
|
+
* read is metadata-only and lenient: codegen wires `ctx.flags` purely from the
|
|
852
|
+
* file's *existence* (`run-codegen.ts`) and imports the real module for the
|
|
853
|
+
* provider value — this IR exists solely so the config layer can reconcile the
|
|
854
|
+
* wrangler `flagship` binding for the Flagship binding-mode provider. Anything
|
|
855
|
+
* it can't read statically degrades to a `custom` provider (no binding), never
|
|
856
|
+
* a thrown error.
|
|
857
|
+
*/
|
|
858
|
+
declare const discoverFlags: (project: Project, lunoraDirectory: string) => FlagsIR | undefined;
|
|
820
859
|
/**
|
|
821
860
|
* Scan all .ts files under `lunoraDir` (skipping `_generated/` and `schema.ts`)
|
|
822
861
|
* for top-level `export const x = query/mutation/action({...})` registrations.
|
|
@@ -969,6 +1008,8 @@ interface EmitServerOptions {
|
|
|
969
1008
|
hasAnalytics?: boolean;
|
|
970
1009
|
/** A `lunora/` source uses `@lunora/browser` / `ctx.browser` — wires `ctx.browser` onto ActionCtx only. */
|
|
971
1010
|
hasBrowser?: boolean;
|
|
1011
|
+
/** The project declares `lunora/flags.ts` — wires `ctx.flags` (OpenFeature) onto every ctx. */
|
|
1012
|
+
hasFlags?: boolean;
|
|
972
1013
|
/** A `lunora/` source uses `@lunora/hyperdrive` / `ctx.sql` — wires `ctx.sql` onto ActionCtx only. */
|
|
973
1014
|
hasHyperdrive?: boolean;
|
|
974
1015
|
/** A `lunora/` source uses `@lunora/bindings/images` / `ctx.images` — wires `ctx.images` onto ActionCtx only. */
|
|
@@ -993,6 +1034,7 @@ declare const emitServer: ({
|
|
|
993
1034
|
hasAi,
|
|
994
1035
|
hasAnalytics,
|
|
995
1036
|
hasBrowser,
|
|
1037
|
+
hasFlags,
|
|
996
1038
|
hasHyperdrive,
|
|
997
1039
|
hasImages,
|
|
998
1040
|
hasKv,
|
|
@@ -1044,11 +1086,18 @@ declare const emitWorkflows: (workflows: ReadonlyArray<WorkflowIR>) => string;
|
|
|
1044
1086
|
interface EmitShardOptions {
|
|
1045
1087
|
advisories?: ReadonlyArray<Finding>;
|
|
1046
1088
|
containers?: ReadonlyArray<ContainerIR>;
|
|
1089
|
+
/** Statically-discovered `ctx.flags.<type>("key")` reads — the studio Flags page + reactive evaluation iterate these. */
|
|
1090
|
+
flagKeys?: ReadonlyArray<{
|
|
1091
|
+
key: string;
|
|
1092
|
+
type: "boolean" | "number" | "object" | "string";
|
|
1093
|
+
}>;
|
|
1047
1094
|
hasAi?: boolean;
|
|
1048
1095
|
/** A `lunora/` source reads `ctx.analytics` — wires the Analytics Engine write helper onto every ctx. */
|
|
1049
1096
|
hasAnalytics?: boolean;
|
|
1050
1097
|
/** A `lunora/` source reads `ctx.browser` — wires `ctx.browser` onto the ActionCtx only. */
|
|
1051
1098
|
hasBrowser?: boolean;
|
|
1099
|
+
/** The project declares `lunora/flags.ts` — wires `ctx.flags` (OpenFeature) onto every ctx. */
|
|
1100
|
+
hasFlags?: boolean;
|
|
1052
1101
|
/** A `lunora/` source reads `ctx.sql` (Hyperdrive) — wires `ctx.sql` onto the ActionCtx only. */
|
|
1053
1102
|
hasHyperdrive?: boolean;
|
|
1054
1103
|
/** A `lunora/` source reads `ctx.images` — wires `ctx.images` onto the ActionCtx only. */
|
|
@@ -1074,9 +1123,11 @@ interface EmitShardOptions {
|
|
|
1074
1123
|
declare const emitShard: ({
|
|
1075
1124
|
advisories,
|
|
1076
1125
|
containers,
|
|
1126
|
+
flagKeys,
|
|
1077
1127
|
hasAi,
|
|
1078
1128
|
hasAnalytics,
|
|
1079
1129
|
hasBrowser,
|
|
1130
|
+
hasFlags,
|
|
1080
1131
|
hasHyperdrive,
|
|
1081
1132
|
hasImages,
|
|
1082
1133
|
hasKv,
|
|
@@ -1674,4 +1725,4 @@ declare const LUNORA_SOLUTION_RULES: ReadonlyArray<LunoraSolutionRule>;
|
|
|
1674
1725
|
*/
|
|
1675
1726
|
declare const findLunoraSolution: (message: string) => LunoraSolution | undefined;
|
|
1676
1727
|
declare const VERSION = "0.0.0";
|
|
1677
|
-
export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
|
|
1728
|
+
export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, FLAGS_FILENAME, type FieldSnapshot, type FlagsIR, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFlags, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
|
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,7 @@ export { CodegenDiagnosticError, diagnosticAt } from './packem_shared/CodegenDia
|
|
|
3
3
|
export { default as discoverAuthApiCalls } from './packem_shared/discoverAuthApiCalls-CoirYbg6.mjs';
|
|
4
4
|
export { CONTAINERS_FILENAME, discoverContainers } from './packem_shared/CONTAINERS_FILENAME-DlP6YM_Q.mjs';
|
|
5
5
|
export { default as discoverCrons } from './packem_shared/discoverCrons-Cev7RRAf.mjs';
|
|
6
|
+
export { FLAGS_FILENAME, discoverFlags } from './packem_shared/FLAGS_FILENAME-B1vE0LIo.mjs';
|
|
6
7
|
export { discoverFunctions } from './packem_shared/discoverFunctions-BWMczzBx.mjs';
|
|
7
8
|
export { default as discoverHttpRoutes } from './packem_shared/discoverHttpRoutes-CfP6cMzt.mjs';
|
|
8
9
|
export { default as discoverInserts } from './packem_shared/discoverInserts-C7zxXkUf.mjs';
|
|
@@ -16,11 +17,11 @@ export { discoverRlsMetadata, default as discoverRlsProcedures } from './packem_
|
|
|
16
17
|
export { default as discoverSchema } from './packem_shared/discoverSchema-BnWHHJ4T.mjs';
|
|
17
18
|
export { default as discoverStorageRulesMetadata } from './packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
18
19
|
export { WORKFLOWS_FILENAME, discoverWorkflows } from './packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
19
|
-
export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-
|
|
20
|
-
export { emitApp } from './packem_shared/emitApp-
|
|
21
|
-
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-
|
|
22
|
-
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-
|
|
23
|
-
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-
|
|
20
|
+
export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-CkZUgM4_.mjs';
|
|
21
|
+
export { emitApp } from './packem_shared/emitApp-DGmlt5fq.mjs';
|
|
22
|
+
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-BSoDzIn8.mjs';
|
|
23
|
+
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-VINwUAxf.mjs';
|
|
24
|
+
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-DsBxQ5C_.mjs';
|
|
24
25
|
export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
25
26
|
export { schemaFromIr } from './packem_shared/schemaFromIr-DTYsLBaA.mjs';
|
|
26
27
|
export { LUNORA_ERROR_CODES, validatorIrToJsonSchema } from './packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { SyntaxKind, Node } from 'ts-morph';
|
|
4
|
+
import { listLunoraSourceFiles } from './discoverFunctions-BWMczzBx.mjs';
|
|
5
|
+
|
|
6
|
+
const FLAGS_FILENAME = "flags.ts";
|
|
7
|
+
const FLAG_TYPES = /* @__PURE__ */ new Set(["boolean", "number", "object", "string"]);
|
|
8
|
+
const FLAGSHIP_PROVIDER_MODULE = "@lunora/flags/providers/flagship";
|
|
9
|
+
const isFlagshipProvider = (identifier) => {
|
|
10
|
+
const symbol = identifier.getSymbol();
|
|
11
|
+
if (!symbol) {
|
|
12
|
+
return identifier.getText() === "flagshipProvider";
|
|
13
|
+
}
|
|
14
|
+
for (const declaration of symbol.getDeclarations()) {
|
|
15
|
+
if (!Node.isImportSpecifier(declaration)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (declaration.getImportDeclaration().getModuleSpecifierValue() !== FLAGSHIP_PROVIDER_MODULE) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return declaration.getNameNode().getText() === "flagshipProvider";
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
25
|
+
const stringPropertyOrUndefined = (argument, property) => {
|
|
26
|
+
const node = argument.getProperty(property);
|
|
27
|
+
if (!node || !Node.isPropertyAssignment(node)) {
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
const initializer = node.getInitializerOrThrow();
|
|
31
|
+
if (Node.isStringLiteral(initializer) || Node.isNoSubstitutionTemplateLiteral(initializer)) {
|
|
32
|
+
return initializer.getLiteralValue();
|
|
33
|
+
}
|
|
34
|
+
return void 0;
|
|
35
|
+
};
|
|
36
|
+
const flagshipIrFromCall = (call) => {
|
|
37
|
+
const argument = call.getArguments()[0];
|
|
38
|
+
if (argument && Node.isObjectLiteralExpression(argument)) {
|
|
39
|
+
const bindingName = stringPropertyOrUndefined(argument, "binding");
|
|
40
|
+
if (bindingName !== void 0 && bindingName.length > 0) {
|
|
41
|
+
return { bindingName, mode: "binding", provider: "flagship" };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { mode: "http", provider: "flagship" };
|
|
45
|
+
};
|
|
46
|
+
const defaultExportExpression = (source) => {
|
|
47
|
+
const assignment = source.getExportAssignment((declaration2) => !declaration2.isExportEquals());
|
|
48
|
+
if (!assignment) {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
const expression = assignment.getExpression();
|
|
52
|
+
if (!Node.isIdentifier(expression)) {
|
|
53
|
+
return expression;
|
|
54
|
+
}
|
|
55
|
+
const declaration = expression.getSymbol()?.getValueDeclaration();
|
|
56
|
+
if (declaration && Node.isVariableDeclaration(declaration)) {
|
|
57
|
+
return declaration.getInitializer();
|
|
58
|
+
}
|
|
59
|
+
return expression;
|
|
60
|
+
};
|
|
61
|
+
const providerInitializer = (defineFlagsCall) => {
|
|
62
|
+
const argument = defineFlagsCall.getArguments()[0];
|
|
63
|
+
if (!argument || !Node.isObjectLiteralExpression(argument)) {
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
const property = argument.getProperty("provider");
|
|
67
|
+
return property && Node.isPropertyAssignment(property) ? property.getInitializer() : void 0;
|
|
68
|
+
};
|
|
69
|
+
const discoverFlags = (project, lunoraDirectory) => {
|
|
70
|
+
const flagsPath = join(lunoraDirectory, FLAGS_FILENAME);
|
|
71
|
+
if (!existsSync(flagsPath)) {
|
|
72
|
+
return void 0;
|
|
73
|
+
}
|
|
74
|
+
const source = project.getSourceFile(flagsPath) ?? project.addSourceFileAtPath(flagsPath);
|
|
75
|
+
const exported = defaultExportExpression(source);
|
|
76
|
+
if (!exported || !Node.isCallExpression(exported)) {
|
|
77
|
+
return { provider: "custom" };
|
|
78
|
+
}
|
|
79
|
+
const provider = providerInitializer(exported);
|
|
80
|
+
if (provider && Node.isCallExpression(provider)) {
|
|
81
|
+
const callee = provider.getExpression();
|
|
82
|
+
if (Node.isIdentifier(callee) && isFlagshipProvider(callee)) {
|
|
83
|
+
return flagshipIrFromCall(provider);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { provider: "custom" };
|
|
87
|
+
};
|
|
88
|
+
const isContextIdentifier = (node) => Node.isIdentifier(node) && node.getText() === "ctx";
|
|
89
|
+
const flagTypeFromAccess = (access) => {
|
|
90
|
+
const name = access.getName();
|
|
91
|
+
if (!FLAG_TYPES.has(name)) {
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
const receiver = access.getExpression();
|
|
95
|
+
if (!Node.isPropertyAccessExpression(receiver)) {
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
98
|
+
if (receiver.getName() === "flags" && isContextIdentifier(receiver.getExpression())) {
|
|
99
|
+
return name;
|
|
100
|
+
}
|
|
101
|
+
const inner = receiver.getExpression();
|
|
102
|
+
if (receiver.getName() === "details" && Node.isPropertyAccessExpression(inner) && inner.getName() === "flags" && isContextIdentifier(inner.getExpression())) {
|
|
103
|
+
return name;
|
|
104
|
+
}
|
|
105
|
+
return void 0;
|
|
106
|
+
};
|
|
107
|
+
const flagKeyFromCall = (call) => {
|
|
108
|
+
const callee = call.getExpression();
|
|
109
|
+
if (!Node.isPropertyAccessExpression(callee)) {
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
const type = flagTypeFromAccess(callee);
|
|
113
|
+
if (type === void 0) {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
const argument = call.getArguments()[0];
|
|
117
|
+
if (!argument || !(Node.isStringLiteral(argument) || Node.isNoSubstitutionTemplateLiteral(argument))) {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
const key = argument.getLiteralValue();
|
|
121
|
+
return key.length > 0 ? { key, type } : void 0;
|
|
122
|
+
};
|
|
123
|
+
const discoverFlagKeys = (project, lunoraDirectory) => {
|
|
124
|
+
const found = /* @__PURE__ */ new Map();
|
|
125
|
+
for (const filePath of listLunoraSourceFiles(lunoraDirectory)) {
|
|
126
|
+
const sourceFile = project.getSourceFile(filePath) ?? project.addSourceFileAtPath(filePath);
|
|
127
|
+
for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
128
|
+
const candidate = flagKeyFromCall(call);
|
|
129
|
+
if (candidate && !found.has(candidate.key)) {
|
|
130
|
+
found.set(candidate.key, candidate.type);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return [...found.entries()].map(([key, type]) => {
|
|
135
|
+
return { key, type };
|
|
136
|
+
}).toSorted((a, b) => a.key.localeCompare(b.key));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export { FLAGS_FILENAME, discoverFlagKeys, discoverFlags };
|
|
@@ -716,6 +716,7 @@ const emitServer = ({
|
|
|
716
716
|
hasAi = false,
|
|
717
717
|
hasAnalytics = false,
|
|
718
718
|
hasBrowser = false,
|
|
719
|
+
hasFlags = false,
|
|
719
720
|
hasHyperdrive = false,
|
|
720
721
|
hasImages = false,
|
|
721
722
|
hasKv = false,
|
|
@@ -784,6 +785,9 @@ ${envBindingFields}` : ""}
|
|
|
784
785
|
export type Env = CloudflareBindings;`;
|
|
785
786
|
const kvContextField = hasKv ? `
|
|
786
787
|
readonly kv: import("@lunora/bindings/kv").Kv;` : "";
|
|
788
|
+
const flagsContextField = hasFlags ? `
|
|
789
|
+
/** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
|
|
790
|
+
readonly flags: import("@lunora/flags").LunoraFlags;` : "";
|
|
787
791
|
const hyperdriveActionField = hasHyperdrive ? `
|
|
788
792
|
/**
|
|
789
793
|
* External database access via Hyperdrive. Non-deterministic — available only in actions. Writes here are NOT tracked by Lunora live queries; subscriptions will not re-run on external DB changes.
|
|
@@ -898,19 +902,19 @@ type TypedTableGet = <T extends TableName>(id: IdOfTable<T>) => Promise<Doc<T> |
|
|
|
898
902
|
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"> {
|
|
899
903
|
readonly db: Omit<DatabaseReader, "query" | "get"> & DatabaseReaderFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
900
904
|
readonly orm: OrmReader;
|
|
901
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${analyticsContextField}
|
|
905
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${flagsContextField}${analyticsContextField}
|
|
902
906
|
}
|
|
903
907
|
|
|
904
908
|
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${workflowsOmit}> {
|
|
905
909
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
906
910
|
readonly orm: OrmWriter;
|
|
907
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${analyticsContextField}${workflowsContextField}${queuesContextField}
|
|
911
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${flagsContextField}${analyticsContextField}${workflowsContextField}${queuesContextField}
|
|
908
912
|
}
|
|
909
913
|
|
|
910
914
|
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${workflowsOmit}> {
|
|
911
915
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
912
916
|
readonly orm: OrmWriter;
|
|
913
|
-
readonly storage: StorageBase<StorageBucketName>;${aiActionField}${paymentsActionField}${containersActionField}${kvContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${workflowsContextField}${queuesContextField}
|
|
917
|
+
readonly storage: StorageBase<StorageBucketName>;${aiActionField}${paymentsActionField}${containersActionField}${kvContextField}${flagsContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${workflowsContextField}${queuesContextField}
|
|
914
918
|
}
|
|
915
919
|
|
|
916
920
|
/**
|
|
@@ -1281,6 +1285,98 @@ const kvStub: Kv = {
|
|
|
1281
1285
|
`
|
|
1282
1286
|
};
|
|
1283
1287
|
};
|
|
1288
|
+
const emitFlagsFragments = (hasFlags) => {
|
|
1289
|
+
if (!hasFlags) {
|
|
1290
|
+
return EMPTY_HELPER_FRAGMENTS;
|
|
1291
|
+
}
|
|
1292
|
+
return {
|
|
1293
|
+
build: `
|
|
1294
|
+
const flags: import("@lunora/flags").LunoraFlags = createFlags({
|
|
1295
|
+
hooks: flagsConfig.hooks,
|
|
1296
|
+
logger: flagsConfig.logger,
|
|
1297
|
+
provider: () => config.flags?.(env) ?? flagsConfig.provider(env),
|
|
1298
|
+
targetingKey: () => flagsConfig.identify?.({ identity: identity ?? null, userId: userId ?? null }),
|
|
1299
|
+
});
|
|
1300
|
+
`,
|
|
1301
|
+
configField: `
|
|
1302
|
+
flags?: (env: Record<string, unknown>) => import("@lunora/flags").Provider;`,
|
|
1303
|
+
contextField: `
|
|
1304
|
+
flags,`,
|
|
1305
|
+
importLines: [`import { createFlags } from "@lunora/flags";`, `import flagsConfig from "../flags.js";`],
|
|
1306
|
+
stub: ""
|
|
1307
|
+
};
|
|
1308
|
+
};
|
|
1309
|
+
const emitFlagsOverrides = (flagKeys, hasFlags) => {
|
|
1310
|
+
if (!hasFlags) {
|
|
1311
|
+
return { constant: "", evaluateOverride: "", subscriptionOverride: "" };
|
|
1312
|
+
}
|
|
1313
|
+
const clientBuild = (targetingKey) => `
|
|
1314
|
+
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
1315
|
+
const flags: import("@lunora/flags").LunoraFlags = createFlags({
|
|
1316
|
+
hooks: flagsConfig.hooks,
|
|
1317
|
+
logger: flagsConfig.logger,
|
|
1318
|
+
provider: () => config.flags?.(env) ?? flagsConfig.provider(env),
|
|
1319
|
+
targetingKey: ${targetingKey},
|
|
1320
|
+
});`;
|
|
1321
|
+
const constant = `
|
|
1322
|
+
/** Statically-discovered feature flags (\`ctx.flags.<type>("key")\` reads) served via \`__lunora_admin__:listFlags\` + the reactive \`__lunora_flags__:\` channel. */
|
|
1323
|
+
const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }> = ${JSON.stringify(flagKeys, void 0, 4)};
|
|
1324
|
+
`;
|
|
1325
|
+
const evaluateOverride = `
|
|
1326
|
+
protected override async evaluateFlags(context?: Record<string, unknown>): Promise<FlagsResult> {${clientBuild("undefined")}
|
|
1327
|
+
const evalContext = context as import("@lunora/flags").EvaluationContext | undefined;
|
|
1328
|
+
const evaluations: FlagsResult["flags"] = [];
|
|
1329
|
+
|
|
1330
|
+
for (const entry of LUNORA_FLAG_KEYS) {
|
|
1331
|
+
// eslint-disable-next-line no-await-in-loop -- flags evaluate sequentially; each shares the single memoized provider client
|
|
1332
|
+
const details =
|
|
1333
|
+
entry.type === "boolean"
|
|
1334
|
+
? await flags.details.boolean(entry.key, false, evalContext)
|
|
1335
|
+
: entry.type === "number"
|
|
1336
|
+
? await flags.details.number(entry.key, 0, evalContext)
|
|
1337
|
+
: entry.type === "string"
|
|
1338
|
+
? await flags.details.string(entry.key, "", evalContext)
|
|
1339
|
+
: await flags.details.object(entry.key, {}, evalContext);
|
|
1340
|
+
|
|
1341
|
+
evaluations.push({ errorCode: details.errorCode, key: entry.key, reason: details.reason, type: entry.type, value: details.value, variant: details.variant });
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
return { configured: true, flags: evaluations };
|
|
1345
|
+
}
|
|
1346
|
+
`;
|
|
1347
|
+
const subscriptionOverride = `
|
|
1348
|
+
protected override runFlagSubscriptionRead(_functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<unknown> {${clientBuild("() => flagsConfig.identify?.({ identity: identity?.identity ?? null, userId: identity?.userId ?? null })")}
|
|
1349
|
+
const key = typeof args.key === "string" ? args.key : "";
|
|
1350
|
+
const rawContext = typeof args.context === "object" && args.context !== null ? (args.context as Record<string, unknown>) : undefined;
|
|
1351
|
+
// The reactive channel is public (any socket, no auth required): never
|
|
1352
|
+
// let a subscriber-supplied targetingKey override the verified identity
|
|
1353
|
+
// resolved above, or a client could read another user's flags. Other
|
|
1354
|
+
// (non-identity) targeting attributes pass through unchanged.
|
|
1355
|
+
const { targetingKey: _clientTargetingKey, ...safeContext } = rawContext ?? {};
|
|
1356
|
+
const context = (rawContext === undefined ? undefined : safeContext) as import("@lunora/flags").EvaluationContext | undefined;
|
|
1357
|
+
|
|
1358
|
+
// eslint-disable-next-line unicorn/no-null -- the base hook's "nothing to deliver" sentinel
|
|
1359
|
+
if (key.length === 0) {
|
|
1360
|
+
return Promise.resolve(null);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
if (args.type === "number") {
|
|
1364
|
+
return flags.number(key, typeof args.default === "number" ? args.default : 0, context);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
if (args.type === "string") {
|
|
1368
|
+
return flags.string(key, typeof args.default === "string" ? args.default : "", context);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
if (args.type === "object") {
|
|
1372
|
+
return flags.object(key, (args.default ?? {}) as import("@lunora/flags").JsonValue, context);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
|
|
1376
|
+
}
|
|
1377
|
+
`;
|
|
1378
|
+
return { constant, evaluateOverride, subscriptionOverride };
|
|
1379
|
+
};
|
|
1284
1380
|
const emitAnalyticsFragments = (hasAnalytics) => {
|
|
1285
1381
|
if (!hasAnalytics) {
|
|
1286
1382
|
return EMPTY_HELPER_FRAGMENTS;
|
|
@@ -1772,10 +1868,11 @@ const paymentStub: LunoraPayment = {
|
|
|
1772
1868
|
`
|
|
1773
1869
|
};
|
|
1774
1870
|
};
|
|
1775
|
-
const buildDoTypeImports = (hasVectors, hasWorkflows, hasQueues) => [
|
|
1871
|
+
const buildDoTypeImports = (hasVectors, hasWorkflows, hasQueues, hasFlags) => [
|
|
1776
1872
|
"AdvisoryFinding",
|
|
1777
1873
|
"DatabaseWriterLike",
|
|
1778
1874
|
"DataMigrationLike",
|
|
1875
|
+
...hasFlags ? ["FlagsResult"] : [],
|
|
1779
1876
|
"LogSink",
|
|
1780
1877
|
"MaskPoliciesResult",
|
|
1781
1878
|
"MigrationRunResult",
|
|
@@ -1801,9 +1898,11 @@ const buildDoTypeImports = (hasVectors, hasWorkflows, hasQueues) => [
|
|
|
1801
1898
|
const emitShard = ({
|
|
1802
1899
|
advisories = [],
|
|
1803
1900
|
containers = [],
|
|
1901
|
+
flagKeys = [],
|
|
1804
1902
|
hasAi = false,
|
|
1805
1903
|
hasAnalytics = false,
|
|
1806
1904
|
hasBrowser = false,
|
|
1905
|
+
hasFlags = false,
|
|
1807
1906
|
hasHyperdrive = false,
|
|
1808
1907
|
hasImages = false,
|
|
1809
1908
|
hasKv = false,
|
|
@@ -1822,6 +1921,8 @@ const emitShard = ({
|
|
|
1822
1921
|
const base = baseSpecifiers(useUmbrella);
|
|
1823
1922
|
const { build: aiBuild, configField: aiConfigField, contextField: aiContextField, stub: aiStub } = emitAiFragments(hasAi);
|
|
1824
1923
|
const kvFragments = emitKvFragments(hasKv);
|
|
1924
|
+
const flagsFragments = emitFlagsFragments(hasFlags);
|
|
1925
|
+
const flagsOverrides = emitFlagsOverrides(flagKeys, hasFlags);
|
|
1825
1926
|
const analyticsFragments = emitAnalyticsFragments(hasAnalytics);
|
|
1826
1927
|
const imagesFragments = emitImagesFragments(hasImages);
|
|
1827
1928
|
const hyperdriveFragments = emitHyperdriveFragments(hasHyperdrive);
|
|
@@ -1853,6 +1954,7 @@ const emitShard = ({
|
|
|
1853
1954
|
const maskData = maskMetadata ?? { columns: [] };
|
|
1854
1955
|
const storageRulesData = storageRules ?? { rules: [] };
|
|
1855
1956
|
const studioFeaturesData = studioFeatures ?? {
|
|
1957
|
+
flags: false,
|
|
1856
1958
|
mail: false,
|
|
1857
1959
|
payments: false,
|
|
1858
1960
|
queues: false,
|
|
@@ -1877,7 +1979,7 @@ const emitShard = ({
|
|
|
1877
1979
|
const tableIndexes = buildTableIndexes(schema);
|
|
1878
1980
|
const tableColumns = buildTableColumns(schema);
|
|
1879
1981
|
const storageColumns = buildStorageColumns(schema);
|
|
1880
|
-
const doTypeImports = buildDoTypeImports(hasVectors, workflows.length > 0, queues.length > 0);
|
|
1982
|
+
const doTypeImports = buildDoTypeImports(hasVectors, workflows.length > 0, queues.length > 0, hasFlags);
|
|
1881
1983
|
const relationFanout = emitRelationFanout(hasGlobalTables);
|
|
1882
1984
|
const importLines = [
|
|
1883
1985
|
`import type { ${doTypeImports.join(", ")} } from "${base.do}";`,
|
|
@@ -1902,6 +2004,7 @@ const emitShard = ({
|
|
|
1902
2004
|
}
|
|
1903
2005
|
importLines.push(
|
|
1904
2006
|
...kvFragments.importLines,
|
|
2007
|
+
...flagsFragments.importLines,
|
|
1905
2008
|
...analyticsFragments.importLines,
|
|
1906
2009
|
...imagesFragments.importLines,
|
|
1907
2010
|
...hyperdriveFragments.importLines,
|
|
@@ -2055,8 +2158,8 @@ ${schema.tables.map(
|
|
|
2055
2158
|
const secretsBuild = `
|
|
2056
2159
|
const secrets = createSecrets(env);
|
|
2057
2160
|
`;
|
|
2058
|
-
const everyContextBuild = `${kvFragments.build}${analyticsFragments.build}${secretsBuild}`;
|
|
2059
|
-
const everyContextField = `${kvFragments.contextField}${analyticsFragments.contextField}
|
|
2161
|
+
const everyContextBuild = `${kvFragments.build}${flagsFragments.build}${analyticsFragments.build}${secretsBuild}`;
|
|
2162
|
+
const everyContextField = `${kvFragments.contextField}${flagsFragments.contextField}${analyticsFragments.contextField}
|
|
2060
2163
|
secrets,`;
|
|
2061
2164
|
const actionOnlyHasAny = hasImages || hasHyperdrive || hasBrowser || hasR2sql || hasPipelines;
|
|
2062
2165
|
const actionOnlyBlock = actionOnlyHasAny ? `
|
|
@@ -2108,14 +2211,14 @@ const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(storageRulesDa
|
|
|
2108
2211
|
|
|
2109
2212
|
/** Which optional package-backed features this app wires up (discovered from imports / \`ctx.*\` reads / schema signals) served via \`__lunora_admin__:studioFeatures\` so the studio hides nav pages whose package isn't enabled. */
|
|
2110
2213
|
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(studioFeaturesData, void 0, 4)};
|
|
2111
|
-
${workflowsMetadataConst}${queuesMetadataConst}${containerSpecs}${workflowSpecs}${queueSpecs}
|
|
2214
|
+
${flagsOverrides.constant}${workflowsMetadataConst}${queuesMetadataConst}${containerSpecs}${workflowSpecs}${queueSpecs}
|
|
2112
2215
|
export interface ShardDOConfig {
|
|
2113
2216
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
2114
2217
|
cdc?: boolean;
|
|
2115
2218
|
/** Optional telemetry sink. When supplied, each \`ctx.log.*\` call is forwarded to \`sink.onLog\`. Pass the SAME sink you give \`createWorker({ observability })\` (which drives \`onRpc\`) to route both RPC and log events. */
|
|
2116
2219
|
observability?: (env: Record<string, unknown>) => LogSink | undefined;
|
|
2117
2220
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
2118
|
-
storage?: (env: Record<string, unknown>) => unknown;${vectorsConfigField}${aiConfigField}${kvFragments.configField}${analyticsFragments.configField}${imagesFragments.configField}${hyperdriveFragments.configField}${browserFragments.configField}${r2sqlFragments.configField}${pipelinesFragments.configField}${paymentsConfigField}${d1ConfigField}${hyperdriveGlobalConfigField}
|
|
2221
|
+
storage?: (env: Record<string, unknown>) => unknown;${vectorsConfigField}${aiConfigField}${kvFragments.configField}${flagsFragments.configField}${analyticsFragments.configField}${imagesFragments.configField}${hyperdriveFragments.configField}${browserFragments.configField}${r2sqlFragments.configField}${pipelinesFragments.configField}${paymentsConfigField}${d1ConfigField}${hyperdriveGlobalConfigField}
|
|
2119
2222
|
}
|
|
2120
2223
|
|
|
2121
2224
|
const schedulerStub = {
|
|
@@ -2153,7 +2256,7 @@ const storageStub = {
|
|
|
2153
2256
|
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
2154
2257
|
},
|
|
2155
2258
|
};
|
|
2156
|
-
${globalDatabaseStub}${vectorsStub}${aiStub}${kvFragments.stub}${analyticsFragments.stub}${imagesFragments.stub}${hyperdriveFragments.stub}${browserFragments.stub}${r2sqlFragments.stub}${pipelinesFragments.stub}${paymentStub}${bindTableHelper}
|
|
2259
|
+
${globalDatabaseStub}${vectorsStub}${aiStub}${kvFragments.stub}${flagsFragments.stub}${analyticsFragments.stub}${imagesFragments.stub}${hyperdriveFragments.stub}${browserFragments.stub}${r2sqlFragments.stub}${pipelinesFragments.stub}${paymentStub}${bindTableHelper}
|
|
2157
2260
|
// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
|
|
2158
2261
|
// referencing call fails loudly with a clear error instead of overflowing the
|
|
2159
2262
|
// stack. Tracked across the awaited handler chain (one DO invocation is
|
|
@@ -2298,7 +2401,7 @@ ${relationFanout.override}
|
|
|
2298
2401
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
2299
2402
|
return LUNORA_STUDIO_FEATURES;
|
|
2300
2403
|
}
|
|
2301
|
-
${workflowsMetadataOverride}${queuesMetadataOverride}
|
|
2404
|
+
${flagsOverrides.evaluateOverride}${flagsOverrides.subscriptionOverride}${workflowsMetadataOverride}${queuesMetadataOverride}
|
|
2302
2405
|
protected override advisories(): AdvisoryFinding[] {
|
|
2303
2406
|
return LUNORA_ADVISORIES;
|
|
2304
2407
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-CkZUgM4_.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { argsObjectSchema, LUNORA_ERROR_CODES } from './LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import { listLunoraSourceFiles, lunoraRelativePath, classifyProcedureCall, disco
|
|
|
7
7
|
import discoverAuthApiCalls from './discoverAuthApiCalls-CoirYbg6.mjs';
|
|
8
8
|
import { discoverContainers } from './CONTAINERS_FILENAME-DlP6YM_Q.mjs';
|
|
9
9
|
import discoverCrons from './discoverCrons-Cev7RRAf.mjs';
|
|
10
|
+
import { discoverFlagKeys } from './FLAGS_FILENAME-B1vE0LIo.mjs';
|
|
10
11
|
import discoverHttpRoutes from './discoverHttpRoutes-CfP6cMzt.mjs';
|
|
11
12
|
import discoverInserts from './discoverInserts-C7zxXkUf.mjs';
|
|
12
13
|
import discoverMaskProcedures, { discoverMaskMetadata } from './discoverMaskProcedures-Cm81kwrb.mjs';
|
|
@@ -20,10 +21,10 @@ import discoverSchema from './discoverSchema-BnWHHJ4T.mjs';
|
|
|
20
21
|
import discoverStorageRulesMetadata from './discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
21
22
|
import { e as enclosingExportName$1 } from './discover-ast-CT6BgBr4.mjs';
|
|
22
23
|
import { discoverWorkflows } from './WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
23
|
-
import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-
|
|
24
|
-
import { emitApp } from './emitApp-
|
|
25
|
-
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-
|
|
26
|
-
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-
|
|
24
|
+
import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-CkZUgM4_.mjs';
|
|
25
|
+
import { emitApp } from './emitApp-DGmlt5fq.mjs';
|
|
26
|
+
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-BSoDzIn8.mjs';
|
|
27
|
+
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-VINwUAxf.mjs';
|
|
27
28
|
import { buildSchemaSnapshot, serializeSchemaSnapshot } from './SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
28
29
|
|
|
29
30
|
const HTTP_VERBS = /* @__PURE__ */ new Set(["delete", "get", "head", "options", "patch", "post", "put"]);
|
|
@@ -243,6 +244,7 @@ const PROBES = {
|
|
|
243
244
|
ai: { contextProperty: "ai", moduleSpecifier: "@lunora/ai" },
|
|
244
245
|
analytics: { contextProperty: "analytics", moduleSpecifier: "@lunora/bindings/analytics" },
|
|
245
246
|
browser: { contextProperty: "browser", moduleSpecifier: "@lunora/browser" },
|
|
247
|
+
flags: { contextProperty: "flags", moduleSpecifier: "@lunora/flags" },
|
|
246
248
|
hyperdrive: { contextProperty: "sql", moduleSpecifier: "@lunora/hyperdrive" },
|
|
247
249
|
images: { contextProperty: "images", moduleSpecifier: "@lunora/bindings/images" },
|
|
248
250
|
kv: { contextProperty: "kv", moduleSpecifier: "@lunora/bindings/kv" },
|
|
@@ -278,6 +280,7 @@ const discoverFeatureUsage = (project, lunoraDirectory) => {
|
|
|
278
280
|
ai: false,
|
|
279
281
|
analytics: false,
|
|
280
282
|
browser: false,
|
|
283
|
+
flags: false,
|
|
281
284
|
hyperdrive: false,
|
|
282
285
|
images: false,
|
|
283
286
|
kv: false,
|
|
@@ -315,6 +318,7 @@ const discoverFeatureUsage = (project, lunoraDirectory) => {
|
|
|
315
318
|
};
|
|
316
319
|
const buildStudioFeatures = (usage, signals) => {
|
|
317
320
|
return {
|
|
321
|
+
flags: usage.flags || signals.dependencies.has("@lunora/flags"),
|
|
318
322
|
mail: usage.mail || signals.dependencies.has("@lunora/mail"),
|
|
319
323
|
payments: usage.payments || signals.dependencies.has("@lunora/payment"),
|
|
320
324
|
queues: signals.queueCount > 0 || signals.dependencies.has("@lunora/queue"),
|
|
@@ -768,6 +772,8 @@ const runCodegen = (options) => {
|
|
|
768
772
|
const hasAi = featureUsage.ai;
|
|
769
773
|
const hasPayments = featureUsage.payments;
|
|
770
774
|
const hasKv = featureUsage.kv;
|
|
775
|
+
const hasFlags = existsSync(join(lunoraDirectory, "flags.ts"));
|
|
776
|
+
const flagKeys = hasFlags ? discoverFlagKeys(project, lunoraDirectory) : [];
|
|
771
777
|
const hasHyperdrive = featureUsage.hyperdrive;
|
|
772
778
|
const hasBrowser = featureUsage.browser;
|
|
773
779
|
const hasImages = featureUsage.images;
|
|
@@ -793,6 +799,7 @@ const runCodegen = (options) => {
|
|
|
793
799
|
hasAi,
|
|
794
800
|
hasAnalytics,
|
|
795
801
|
hasBrowser,
|
|
802
|
+
hasFlags,
|
|
796
803
|
hasHyperdrive,
|
|
797
804
|
hasImages,
|
|
798
805
|
hasKv,
|
|
@@ -809,9 +816,11 @@ const runCodegen = (options) => {
|
|
|
809
816
|
const shardContent = emitShard({
|
|
810
817
|
advisories,
|
|
811
818
|
containers,
|
|
819
|
+
flagKeys,
|
|
812
820
|
hasAi,
|
|
813
821
|
hasAnalytics,
|
|
814
822
|
hasBrowser,
|
|
823
|
+
hasFlags,
|
|
815
824
|
hasHyperdrive,
|
|
816
825
|
hasImages,
|
|
817
826
|
hasKv,
|
package/dist/packem_shared/{buildOpenApiDocument-699G4RP4.mjs → buildOpenApiDocument-BSoDzIn8.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-CkZUgM4_.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { LUNORA_ERROR_CODES, objectSchema, argsObjectSchema, validatorIrToJsonSchema } from './LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/codegen",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.16",
|
|
4
4
|
"description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@lunora/advisor": "1.0.0-alpha.7",
|
|
50
|
-
"@lunora/container": "1.0.0-alpha.
|
|
50
|
+
"@lunora/container": "1.0.0-alpha.5",
|
|
51
51
|
"@lunora/queue": "1.0.0-alpha.1",
|
|
52
52
|
"@lunora/scheduler": "1.0.0-alpha.3",
|
|
53
53
|
"@lunora/values": "1.0.0-alpha.3",
|