blimu 1.2.0 → 1.2.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/index.cjs CHANGED
@@ -78,7 +78,8 @@ var BlimuConfigSchema = import_zod.z.object({
78
78
 
79
79
  // src/config/define-config.ts
80
80
  function defineConfig(config) {
81
- const validated = BlimuConfigSchema.parse(config);
81
+ const _validated = BlimuConfigSchema.parse(config);
82
+ void _validated;
82
83
  return config;
83
84
  }
84
85
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config/schema.ts","../src/config/define-config.ts"],"sourcesContent":["// Library exports for programmatic usage\n\n/**\n * Configuration utilities\n */\nexport { defineConfig } from './config/define-config';\nexport type {\n BlimuConfig,\n ResourceDefinition,\n EntitlementDefinition,\n FeatureDefinition,\n PlanDefinition,\n} from './config/schema';\nexport {\n BlimuConfigSchema,\n ResourceDefinitionSchema,\n EntitlementDefinitionSchema,\n FeatureDefinitionSchema,\n PlanDefinitionSchema,\n} from './config/schema';\n\n/**\n * Type inference utilities\n */\nexport type {\n InferResourceTypes,\n InferEntitlementTypes,\n InferPlanTypes,\n InferLimitTypes,\n InferUsageLimitTypes,\n} from './types/infer';\n","import { z } from 'zod';\n\n/**\n * Zod schema for resource definition\n */\nexport const ResourceDefinitionSchema = z.object({\n is_tenant: z.boolean().optional(),\n roles: z.array(z.string()).min(1, 'At least one role must be defined'),\n parents: z.record(z.string(), z.object({ required: z.boolean() })).optional(),\n roles_inheritance: z\n .record(\n z.string().min(1), // local role\n // Allow tokens containing letters, numbers, underscores or dashes\n // Examples: parent->editor, organization->admin, workspace_v2->viewer\n z.array(z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1),\n )\n .optional(),\n});\n\n/**\n * Zod schema for entitlement definition\n */\nexport const EntitlementDefinitionSchema = z.object({\n roles: z.array(z.string()).min(1).optional(),\n plans: z.array(z.string()).optional(),\n limit: z.string().optional(), // Reference to usage-based limit\n});\n\n/**\n * Zod schema for feature definition\n */\nexport const FeatureDefinitionSchema = z.object({\n name: z.string(),\n summary: z.string().optional(),\n entitlements: z.array(z.string()).optional(),\n plans: z.array(z.string()).optional(),\n default_enabled: z.boolean().optional(),\n});\n\n/**\n * Zod schema for plan definition\n */\nexport const PlanDefinitionSchema = z.object({\n name: z.string().min(1, 'Plan name is required'),\n summary: z.string().optional(),\n description: z.string().min(1, 'Plan description is required').optional(),\n resource_limits: z.record(z.string(), z.number().int().min(0)).optional(),\n usage_based_limits: z\n .record(\n z.string(),\n z.object({\n value: z.number().int().min(0),\n period: z.enum(['monthly', 'yearly', 'lifetime']),\n }),\n )\n .optional(),\n});\n\n/**\n * Zod schema for complete Blimu configuration\n */\nexport const BlimuConfigSchema = z.object({\n resources: z.record(z.string().min(1), ResourceDefinitionSchema),\n entitlements: z.record(z.string().min(1), EntitlementDefinitionSchema).optional(),\n features: z.record(z.string().min(1), FeatureDefinitionSchema).optional(),\n plans: z.record(z.string().min(1), PlanDefinitionSchema).optional(),\n});\n\n/**\n * Type inference from schemas\n */\nexport type ResourceDefinition = z.infer<typeof ResourceDefinitionSchema>;\nexport type EntitlementDefinition = z.infer<typeof EntitlementDefinitionSchema>;\nexport type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;\nexport type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;\nexport type BlimuConfig = z.infer<typeof BlimuConfigSchema>;\n","import {\n BlimuConfigSchema,\n type BlimuConfig,\n type ResourceDefinition,\n type EntitlementDefinition,\n type FeatureDefinition,\n type PlanDefinition,\n} from './schema';\n\n/**\n * Input type for defineConfig (allows partial config during definition)\n * Uses proper types inferred from Zod schemas for full type safety\n */\nexport type BlimuConfigInput = {\n resources: Record<string, ResourceDefinition>;\n entitlements?: Record<string, EntitlementDefinition>;\n features?: Record<string, FeatureDefinition>;\n plans?: Record<string, PlanDefinition>;\n};\n\n/**\n * Defines and validates a Blimu configuration.\n *\n * This function validates the config using Zod schemas and returns\n * a type-safe, validated configuration object.\n *\n * @param config - The Blimu configuration object\n * @returns The validated configuration\n * @throws {z.ZodError} If the configuration is invalid\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'blimu';\n *\n * export default defineConfig({\n * resources: {\n * workspace: {\n * roles: ['admin', 'editor', 'viewer'],\n * is_tenant: true,\n * },\n * },\n * entitlements: {\n * 'workspace:read': {\n * roles: ['admin', 'editor', 'viewer'],\n * },\n * },\n * });\n * ```\n */\nexport function defineConfig<T extends BlimuConfigInput>(config: T): T {\n // Validate the config using Zod schema\n const validated = BlimuConfigSchema.parse(config);\n\n // Return the original config (with proper typing) after validation\n // This preserves the exact structure and types from the input\n return config as T & BlimuConfig;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAkB;AAKX,IAAM,2BAA2B,aAAE,OAAO;AAAA,EAC/C,WAAW,aAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,IAAI,GAAG,mCAAmC;AAAA,EACrE,SAAS,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,EAAE,UAAU,aAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5E,mBAAmB,aAChB;AAAA,IACC,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,IAGhB,aAAE,MAAM,aAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC,EAAE,IAAI,CAAC;AAAA,EACnE,EACC,SAAS;AACd,CAAC;AAKM,IAAM,8BAA8B,aAAE,OAAO;AAAA,EAClD,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA;AAC7B,CAAC;AAKM,IAAM,0BAA0B,aAAE,OAAO;AAAA,EAC9C,MAAM,aAAE,OAAO;AAAA,EACf,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,cAAc,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,iBAAiB,aAAE,QAAQ,EAAE,SAAS;AACxC,CAAC;AAKM,IAAM,uBAAuB,aAAE,OAAO;AAAA,EAC3C,MAAM,aAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AAAA,EAC/C,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,aAAE,OAAO,EAAE,IAAI,GAAG,8BAA8B,EAAE,SAAS;AAAA,EACxE,iBAAiB,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACxE,oBAAoB,aACjB;AAAA,IACC,aAAE,OAAO;AAAA,IACT,aAAE,OAAO;AAAA,MACP,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,MAC7B,QAAQ,aAAE,KAAK,CAAC,WAAW,UAAU,UAAU,CAAC;AAAA,IAClD,CAAC;AAAA,EACH,EACC,SAAS;AACd,CAAC;AAKM,IAAM,oBAAoB,aAAE,OAAO;AAAA,EACxC,WAAW,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,wBAAwB;AAAA,EAC/D,cAAc,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,2BAA2B,EAAE,SAAS;AAAA,EAChF,UAAU,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,uBAAuB,EAAE,SAAS;AAAA,EACxE,OAAO,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,oBAAoB,EAAE,SAAS;AACpE,CAAC;;;ACjBM,SAAS,aAAyC,QAAc;AAErE,QAAM,YAAY,kBAAkB,MAAM,MAAM;AAIhD,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config/schema.ts","../src/config/define-config.ts"],"sourcesContent":["// Library exports for programmatic usage\n\n/**\n * Configuration utilities\n */\nexport { defineConfig } from './config/define-config';\nexport type {\n BlimuConfig,\n ResourceDefinition,\n EntitlementDefinition,\n FeatureDefinition,\n PlanDefinition,\n} from './config/schema';\nexport {\n BlimuConfigSchema,\n ResourceDefinitionSchema,\n EntitlementDefinitionSchema,\n FeatureDefinitionSchema,\n PlanDefinitionSchema,\n} from './config/schema';\n\n/**\n * Type inference utilities\n */\nexport type {\n InferResourceTypes,\n InferEntitlementTypes,\n InferPlanTypes,\n InferLimitTypes,\n InferUsageLimitTypes,\n} from './types/infer';\n","import { z } from 'zod';\n\n/**\n * Zod schema for resource definition\n */\nexport const ResourceDefinitionSchema = z.object({\n is_tenant: z.boolean().optional(),\n roles: z.array(z.string()).min(1, 'At least one role must be defined'),\n parents: z.record(z.string(), z.object({ required: z.boolean() })).optional(),\n roles_inheritance: z\n .record(\n z.string().min(1), // local role\n // Allow tokens containing letters, numbers, underscores or dashes\n // Examples: parent->editor, organization->admin, workspace_v2->viewer\n z.array(z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1)\n )\n .optional(),\n});\n\n/**\n * Zod schema for entitlement definition\n */\nexport const EntitlementDefinitionSchema = z.object({\n roles: z.array(z.string()).min(1).optional(),\n plans: z.array(z.string()).optional(),\n limit: z.string().optional(), // Reference to usage-based limit\n});\n\n/**\n * Zod schema for feature definition\n */\nexport const FeatureDefinitionSchema = z.object({\n name: z.string(),\n summary: z.string().optional(),\n entitlements: z.array(z.string()).optional(),\n plans: z.array(z.string()).optional(),\n default_enabled: z.boolean().optional(),\n});\n\n/**\n * Zod schema for plan definition\n */\nexport const PlanDefinitionSchema = z.object({\n name: z.string().min(1, 'Plan name is required'),\n summary: z.string().optional(),\n description: z.string().min(1, 'Plan description is required').optional(),\n resource_limits: z.record(z.string(), z.number().int().min(0)).optional(),\n usage_based_limits: z\n .record(\n z.string(),\n z.object({\n value: z.number().int().min(0),\n period: z.enum(['monthly', 'yearly', 'lifetime']),\n })\n )\n .optional(),\n});\n\n/**\n * Zod schema for complete Blimu configuration\n */\nexport const BlimuConfigSchema = z.object({\n resources: z.record(z.string().min(1), ResourceDefinitionSchema),\n entitlements: z.record(z.string().min(1), EntitlementDefinitionSchema).optional(),\n features: z.record(z.string().min(1), FeatureDefinitionSchema).optional(),\n plans: z.record(z.string().min(1), PlanDefinitionSchema).optional(),\n});\n\n/**\n * Type inference from schemas\n */\nexport type ResourceDefinition = z.infer<typeof ResourceDefinitionSchema>;\nexport type EntitlementDefinition = z.infer<typeof EntitlementDefinitionSchema>;\nexport type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;\nexport type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;\nexport type BlimuConfig = z.infer<typeof BlimuConfigSchema>;\n","import {\n BlimuConfigSchema,\n type BlimuConfig,\n type ResourceDefinition,\n type EntitlementDefinition,\n type FeatureDefinition,\n type PlanDefinition,\n} from './schema';\n\n/**\n * Input type for defineConfig (allows partial config during definition)\n * Uses proper types inferred from Zod schemas for full type safety\n */\nexport interface BlimuConfigInput {\n resources: Record<string, ResourceDefinition>;\n entitlements?: Record<string, EntitlementDefinition>;\n features?: Record<string, FeatureDefinition>;\n plans?: Record<string, PlanDefinition>;\n}\n\n/**\n * Defines and validates a Blimu configuration.\n *\n * This function validates the config using Zod schemas and returns\n * a type-safe, validated configuration object.\n *\n * @param config - The Blimu configuration object\n * @returns The validated configuration\n * @throws {z.ZodError} If the configuration is invalid\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'blimu';\n *\n * export default defineConfig({\n * resources: {\n * workspace: {\n * roles: ['admin', 'editor', 'viewer'],\n * is_tenant: true,\n * },\n * },\n * entitlements: {\n * 'workspace:read': {\n * roles: ['admin', 'editor', 'viewer'],\n * },\n * },\n * });\n * ```\n */\nexport function defineConfig<T extends BlimuConfigInput>(config: T): T {\n // Validate the config using Zod schema\n const _validated = BlimuConfigSchema.parse(config);\n void _validated;\n\n // Return the original config (with proper typing) after validation\n // This preserves the exact structure and types from the input\n return config as T & BlimuConfig;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAAkB;AAKX,IAAM,2BAA2B,aAAE,OAAO;AAAA,EAC/C,WAAW,aAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,IAAI,GAAG,mCAAmC;AAAA,EACrE,SAAS,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,EAAE,UAAU,aAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5E,mBAAmB,aAChB;AAAA,IACC,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,IAGhB,aAAE,MAAM,aAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC,EAAE,IAAI,CAAC;AAAA,EACnE,EACC,SAAS;AACd,CAAC;AAKM,IAAM,8BAA8B,aAAE,OAAO;AAAA,EAClD,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA;AAC7B,CAAC;AAKM,IAAM,0BAA0B,aAAE,OAAO;AAAA,EAC9C,MAAM,aAAE,OAAO;AAAA,EACf,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,cAAc,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,iBAAiB,aAAE,QAAQ,EAAE,SAAS;AACxC,CAAC;AAKM,IAAM,uBAAuB,aAAE,OAAO;AAAA,EAC3C,MAAM,aAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AAAA,EAC/C,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,aAAE,OAAO,EAAE,IAAI,GAAG,8BAA8B,EAAE,SAAS;AAAA,EACxE,iBAAiB,aAAE,OAAO,aAAE,OAAO,GAAG,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACxE,oBAAoB,aACjB;AAAA,IACC,aAAE,OAAO;AAAA,IACT,aAAE,OAAO;AAAA,MACP,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,MAC7B,QAAQ,aAAE,KAAK,CAAC,WAAW,UAAU,UAAU,CAAC;AAAA,IAClD,CAAC;AAAA,EACH,EACC,SAAS;AACd,CAAC;AAKM,IAAM,oBAAoB,aAAE,OAAO;AAAA,EACxC,WAAW,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,wBAAwB;AAAA,EAC/D,cAAc,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,2BAA2B,EAAE,SAAS;AAAA,EAChF,UAAU,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,uBAAuB,EAAE,SAAS;AAAA,EACxE,OAAO,aAAE,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,GAAG,oBAAoB,EAAE,SAAS;AACpE,CAAC;;;ACjBM,SAAS,aAAyC,QAAc;AAErE,QAAM,aAAa,kBAAkB,MAAM,MAAM;AACjD,OAAK;AAIL,SAAO;AACT;","names":[]}
package/dist/index.d.mts CHANGED
@@ -76,32 +76,32 @@ type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;
76
76
  type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;
77
77
  type BlimuConfig = z.infer<typeof BlimuConfigSchema>;
78
78
 
79
- type BlimuConfigInput = {
79
+ interface BlimuConfigInput {
80
80
  resources: Record<string, ResourceDefinition>;
81
81
  entitlements?: Record<string, EntitlementDefinition>;
82
82
  features?: Record<string, FeatureDefinition>;
83
83
  plans?: Record<string, PlanDefinition>;
84
- };
84
+ }
85
85
  declare function defineConfig<T extends BlimuConfigInput>(config: T): T;
86
86
 
87
87
  type InferResourceTypes<T> = T extends {
88
88
  resources: infer R;
89
- } ? R extends Record<string, any> ? keyof R : never : never;
89
+ } ? R extends Record<string, unknown> ? keyof R : never : never;
90
90
  type InferEntitlementTypes<T> = T extends {
91
91
  entitlements: infer E;
92
- } ? E extends Record<string, any> ? keyof E : never : never;
92
+ } ? E extends Record<string, unknown> ? keyof E : never : never;
93
93
  type InferPlanTypes<T> = T extends {
94
94
  plans: infer P;
95
- } ? P extends Record<string, any> ? keyof P : never : never;
95
+ } ? P extends Record<string, unknown> ? keyof P : never : never;
96
96
  type InferLimitTypes<T> = T extends {
97
97
  plans: infer P;
98
- } ? P extends Record<string, any> ? P[keyof P] extends {
98
+ } ? P extends Record<string, unknown> ? P[keyof P] extends {
99
99
  resource_limits?: infer RL;
100
- } ? RL extends Record<string, any> ? keyof RL : never : never : never : never;
100
+ } ? RL extends Record<string, unknown> ? keyof RL : never : never : never : never;
101
101
  type InferUsageLimitTypes<T> = T extends {
102
102
  plans: infer P;
103
- } ? P extends Record<string, any> ? P[keyof P] extends {
103
+ } ? P extends Record<string, unknown> ? P[keyof P] extends {
104
104
  usage_based_limits?: infer UL;
105
- } ? UL extends Record<string, any> ? keyof UL : never : never : never : never;
105
+ } ? UL extends Record<string, unknown> ? keyof UL : never : never : never : never;
106
106
 
107
107
  export { type BlimuConfig, BlimuConfigSchema, type EntitlementDefinition, EntitlementDefinitionSchema, type FeatureDefinition, FeatureDefinitionSchema, type InferEntitlementTypes, type InferLimitTypes, type InferPlanTypes, type InferResourceTypes, type InferUsageLimitTypes, type PlanDefinition, PlanDefinitionSchema, type ResourceDefinition, ResourceDefinitionSchema, defineConfig };
package/dist/index.d.ts CHANGED
@@ -76,32 +76,32 @@ type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;
76
76
  type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;
77
77
  type BlimuConfig = z.infer<typeof BlimuConfigSchema>;
78
78
 
79
- type BlimuConfigInput = {
79
+ interface BlimuConfigInput {
80
80
  resources: Record<string, ResourceDefinition>;
81
81
  entitlements?: Record<string, EntitlementDefinition>;
82
82
  features?: Record<string, FeatureDefinition>;
83
83
  plans?: Record<string, PlanDefinition>;
84
- };
84
+ }
85
85
  declare function defineConfig<T extends BlimuConfigInput>(config: T): T;
86
86
 
87
87
  type InferResourceTypes<T> = T extends {
88
88
  resources: infer R;
89
- } ? R extends Record<string, any> ? keyof R : never : never;
89
+ } ? R extends Record<string, unknown> ? keyof R : never : never;
90
90
  type InferEntitlementTypes<T> = T extends {
91
91
  entitlements: infer E;
92
- } ? E extends Record<string, any> ? keyof E : never : never;
92
+ } ? E extends Record<string, unknown> ? keyof E : never : never;
93
93
  type InferPlanTypes<T> = T extends {
94
94
  plans: infer P;
95
- } ? P extends Record<string, any> ? keyof P : never : never;
95
+ } ? P extends Record<string, unknown> ? keyof P : never : never;
96
96
  type InferLimitTypes<T> = T extends {
97
97
  plans: infer P;
98
- } ? P extends Record<string, any> ? P[keyof P] extends {
98
+ } ? P extends Record<string, unknown> ? P[keyof P] extends {
99
99
  resource_limits?: infer RL;
100
- } ? RL extends Record<string, any> ? keyof RL : never : never : never : never;
100
+ } ? RL extends Record<string, unknown> ? keyof RL : never : never : never : never;
101
101
  type InferUsageLimitTypes<T> = T extends {
102
102
  plans: infer P;
103
- } ? P extends Record<string, any> ? P[keyof P] extends {
103
+ } ? P extends Record<string, unknown> ? P[keyof P] extends {
104
104
  usage_based_limits?: infer UL;
105
- } ? UL extends Record<string, any> ? keyof UL : never : never : never : never;
105
+ } ? UL extends Record<string, unknown> ? keyof UL : never : never : never : never;
106
106
 
107
107
  export { type BlimuConfig, BlimuConfigSchema, type EntitlementDefinition, EntitlementDefinitionSchema, type FeatureDefinition, FeatureDefinitionSchema, type InferEntitlementTypes, type InferLimitTypes, type InferPlanTypes, type InferResourceTypes, type InferUsageLimitTypes, type PlanDefinition, PlanDefinitionSchema, type ResourceDefinition, ResourceDefinitionSchema, defineConfig };
package/dist/index.mjs CHANGED
@@ -47,7 +47,8 @@ var BlimuConfigSchema = z.object({
47
47
 
48
48
  // src/config/define-config.ts
49
49
  function defineConfig(config) {
50
- const validated = BlimuConfigSchema.parse(config);
50
+ const _validated = BlimuConfigSchema.parse(config);
51
+ void _validated;
51
52
  return config;
52
53
  }
53
54
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/schema.ts","../src/config/define-config.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Zod schema for resource definition\n */\nexport const ResourceDefinitionSchema = z.object({\n is_tenant: z.boolean().optional(),\n roles: z.array(z.string()).min(1, 'At least one role must be defined'),\n parents: z.record(z.string(), z.object({ required: z.boolean() })).optional(),\n roles_inheritance: z\n .record(\n z.string().min(1), // local role\n // Allow tokens containing letters, numbers, underscores or dashes\n // Examples: parent->editor, organization->admin, workspace_v2->viewer\n z.array(z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1),\n )\n .optional(),\n});\n\n/**\n * Zod schema for entitlement definition\n */\nexport const EntitlementDefinitionSchema = z.object({\n roles: z.array(z.string()).min(1).optional(),\n plans: z.array(z.string()).optional(),\n limit: z.string().optional(), // Reference to usage-based limit\n});\n\n/**\n * Zod schema for feature definition\n */\nexport const FeatureDefinitionSchema = z.object({\n name: z.string(),\n summary: z.string().optional(),\n entitlements: z.array(z.string()).optional(),\n plans: z.array(z.string()).optional(),\n default_enabled: z.boolean().optional(),\n});\n\n/**\n * Zod schema for plan definition\n */\nexport const PlanDefinitionSchema = z.object({\n name: z.string().min(1, 'Plan name is required'),\n summary: z.string().optional(),\n description: z.string().min(1, 'Plan description is required').optional(),\n resource_limits: z.record(z.string(), z.number().int().min(0)).optional(),\n usage_based_limits: z\n .record(\n z.string(),\n z.object({\n value: z.number().int().min(0),\n period: z.enum(['monthly', 'yearly', 'lifetime']),\n }),\n )\n .optional(),\n});\n\n/**\n * Zod schema for complete Blimu configuration\n */\nexport const BlimuConfigSchema = z.object({\n resources: z.record(z.string().min(1), ResourceDefinitionSchema),\n entitlements: z.record(z.string().min(1), EntitlementDefinitionSchema).optional(),\n features: z.record(z.string().min(1), FeatureDefinitionSchema).optional(),\n plans: z.record(z.string().min(1), PlanDefinitionSchema).optional(),\n});\n\n/**\n * Type inference from schemas\n */\nexport type ResourceDefinition = z.infer<typeof ResourceDefinitionSchema>;\nexport type EntitlementDefinition = z.infer<typeof EntitlementDefinitionSchema>;\nexport type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;\nexport type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;\nexport type BlimuConfig = z.infer<typeof BlimuConfigSchema>;\n","import {\n BlimuConfigSchema,\n type BlimuConfig,\n type ResourceDefinition,\n type EntitlementDefinition,\n type FeatureDefinition,\n type PlanDefinition,\n} from './schema';\n\n/**\n * Input type for defineConfig (allows partial config during definition)\n * Uses proper types inferred from Zod schemas for full type safety\n */\nexport type BlimuConfigInput = {\n resources: Record<string, ResourceDefinition>;\n entitlements?: Record<string, EntitlementDefinition>;\n features?: Record<string, FeatureDefinition>;\n plans?: Record<string, PlanDefinition>;\n};\n\n/**\n * Defines and validates a Blimu configuration.\n *\n * This function validates the config using Zod schemas and returns\n * a type-safe, validated configuration object.\n *\n * @param config - The Blimu configuration object\n * @returns The validated configuration\n * @throws {z.ZodError} If the configuration is invalid\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'blimu';\n *\n * export default defineConfig({\n * resources: {\n * workspace: {\n * roles: ['admin', 'editor', 'viewer'],\n * is_tenant: true,\n * },\n * },\n * entitlements: {\n * 'workspace:read': {\n * roles: ['admin', 'editor', 'viewer'],\n * },\n * },\n * });\n * ```\n */\nexport function defineConfig<T extends BlimuConfigInput>(config: T): T {\n // Validate the config using Zod schema\n const validated = BlimuConfigSchema.parse(config);\n\n // Return the original config (with proper typing) after validation\n // This preserves the exact structure and types from the input\n return config as T & BlimuConfig;\n}\n"],"mappings":";AAAA,SAAS,SAAS;AAKX,IAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,mCAAmC;AAAA,EACrE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5E,mBAAmB,EAChB;AAAA,IACC,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,IAGhB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC,EAAE,IAAI,CAAC;AAAA,EACnE,EACC,SAAS;AACd,CAAC;AAKM,IAAM,8BAA8B,EAAE,OAAO;AAAA,EAClD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA;AAC7B,CAAC;AAKM,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,iBAAiB,EAAE,QAAQ,EAAE,SAAS;AACxC,CAAC;AAKM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AAAA,EAC/C,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,EAAE,OAAO,EAAE,IAAI,GAAG,8BAA8B,EAAE,SAAS;AAAA,EACxE,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACxE,oBAAoB,EACjB;AAAA,IACC,EAAE,OAAO;AAAA,IACT,EAAE,OAAO;AAAA,MACP,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,MAC7B,QAAQ,EAAE,KAAK,CAAC,WAAW,UAAU,UAAU,CAAC;AAAA,IAClD,CAAC;AAAA,EACH,EACC,SAAS;AACd,CAAC;AAKM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,wBAAwB;AAAA,EAC/D,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,2BAA2B,EAAE,SAAS;AAAA,EAChF,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,uBAAuB,EAAE,SAAS;AAAA,EACxE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,oBAAoB,EAAE,SAAS;AACpE,CAAC;;;ACjBM,SAAS,aAAyC,QAAc;AAErE,QAAM,YAAY,kBAAkB,MAAM,MAAM;AAIhD,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/config/schema.ts","../src/config/define-config.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Zod schema for resource definition\n */\nexport const ResourceDefinitionSchema = z.object({\n is_tenant: z.boolean().optional(),\n roles: z.array(z.string()).min(1, 'At least one role must be defined'),\n parents: z.record(z.string(), z.object({ required: z.boolean() })).optional(),\n roles_inheritance: z\n .record(\n z.string().min(1), // local role\n // Allow tokens containing letters, numbers, underscores or dashes\n // Examples: parent->editor, organization->admin, workspace_v2->viewer\n z.array(z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1)\n )\n .optional(),\n});\n\n/**\n * Zod schema for entitlement definition\n */\nexport const EntitlementDefinitionSchema = z.object({\n roles: z.array(z.string()).min(1).optional(),\n plans: z.array(z.string()).optional(),\n limit: z.string().optional(), // Reference to usage-based limit\n});\n\n/**\n * Zod schema for feature definition\n */\nexport const FeatureDefinitionSchema = z.object({\n name: z.string(),\n summary: z.string().optional(),\n entitlements: z.array(z.string()).optional(),\n plans: z.array(z.string()).optional(),\n default_enabled: z.boolean().optional(),\n});\n\n/**\n * Zod schema for plan definition\n */\nexport const PlanDefinitionSchema = z.object({\n name: z.string().min(1, 'Plan name is required'),\n summary: z.string().optional(),\n description: z.string().min(1, 'Plan description is required').optional(),\n resource_limits: z.record(z.string(), z.number().int().min(0)).optional(),\n usage_based_limits: z\n .record(\n z.string(),\n z.object({\n value: z.number().int().min(0),\n period: z.enum(['monthly', 'yearly', 'lifetime']),\n })\n )\n .optional(),\n});\n\n/**\n * Zod schema for complete Blimu configuration\n */\nexport const BlimuConfigSchema = z.object({\n resources: z.record(z.string().min(1), ResourceDefinitionSchema),\n entitlements: z.record(z.string().min(1), EntitlementDefinitionSchema).optional(),\n features: z.record(z.string().min(1), FeatureDefinitionSchema).optional(),\n plans: z.record(z.string().min(1), PlanDefinitionSchema).optional(),\n});\n\n/**\n * Type inference from schemas\n */\nexport type ResourceDefinition = z.infer<typeof ResourceDefinitionSchema>;\nexport type EntitlementDefinition = z.infer<typeof EntitlementDefinitionSchema>;\nexport type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;\nexport type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;\nexport type BlimuConfig = z.infer<typeof BlimuConfigSchema>;\n","import {\n BlimuConfigSchema,\n type BlimuConfig,\n type ResourceDefinition,\n type EntitlementDefinition,\n type FeatureDefinition,\n type PlanDefinition,\n} from './schema';\n\n/**\n * Input type for defineConfig (allows partial config during definition)\n * Uses proper types inferred from Zod schemas for full type safety\n */\nexport interface BlimuConfigInput {\n resources: Record<string, ResourceDefinition>;\n entitlements?: Record<string, EntitlementDefinition>;\n features?: Record<string, FeatureDefinition>;\n plans?: Record<string, PlanDefinition>;\n}\n\n/**\n * Defines and validates a Blimu configuration.\n *\n * This function validates the config using Zod schemas and returns\n * a type-safe, validated configuration object.\n *\n * @param config - The Blimu configuration object\n * @returns The validated configuration\n * @throws {z.ZodError} If the configuration is invalid\n *\n * @example\n * ```typescript\n * import { defineConfig } from 'blimu';\n *\n * export default defineConfig({\n * resources: {\n * workspace: {\n * roles: ['admin', 'editor', 'viewer'],\n * is_tenant: true,\n * },\n * },\n * entitlements: {\n * 'workspace:read': {\n * roles: ['admin', 'editor', 'viewer'],\n * },\n * },\n * });\n * ```\n */\nexport function defineConfig<T extends BlimuConfigInput>(config: T): T {\n // Validate the config using Zod schema\n const _validated = BlimuConfigSchema.parse(config);\n void _validated;\n\n // Return the original config (with proper typing) after validation\n // This preserves the exact structure and types from the input\n return config as T & BlimuConfig;\n}\n"],"mappings":";AAAA,SAAS,SAAS;AAKX,IAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,mCAAmC;AAAA,EACrE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5E,mBAAmB,EAChB;AAAA,IACC,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,IAGhB,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC,EAAE,IAAI,CAAC;AAAA,EACnE,EACC,SAAS;AACd,CAAC;AAKM,IAAM,8BAA8B,EAAE,OAAO;AAAA,EAClD,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA;AAC7B,CAAC;AAKM,IAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC3C,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACpC,iBAAiB,EAAE,QAAQ,EAAE,SAAS;AACxC,CAAC;AAKM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,uBAAuB;AAAA,EAC/C,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,EAAE,OAAO,EAAE,IAAI,GAAG,8BAA8B,EAAE,SAAS;AAAA,EACxE,iBAAiB,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACxE,oBAAoB,EACjB;AAAA,IACC,EAAE,OAAO;AAAA,IACT,EAAE,OAAO;AAAA,MACP,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,MAC7B,QAAQ,EAAE,KAAK,CAAC,WAAW,UAAU,UAAU,CAAC;AAAA,IAClD,CAAC;AAAA,EACH,EACC,SAAS;AACd,CAAC;AAKM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,wBAAwB;AAAA,EAC/D,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,2BAA2B,EAAE,SAAS;AAAA,EAChF,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,uBAAuB,EAAE,SAAS;AAAA,EACxE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,oBAAoB,EAAE,SAAS;AACpE,CAAC;;;ACjBM,SAAS,aAAyC,QAAc;AAErE,QAAM,aAAa,kBAAkB,MAAM,MAAM;AACjD,OAAK;AAIL,SAAO;AACT;","names":[]}
package/dist/main.mjs ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ var le=Object.defineProperty;var kt=Object.getOwnPropertyDescriptor;var bt=Object.getOwnPropertyNames;var Rt=Object.prototype.hasOwnProperty;var S=(o,e)=>()=>(o&&(e=o(o=0)),e);var be=(o,e)=>{for(var t in e)le(o,t,{get:e[t],enumerable:!0})},Tt=(o,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of bt(e))!Rt.call(o,n)&&n!==t&&le(o,n,{get:()=>e[n],enumerable:!(r=kt(e,n))||r.enumerable});return o};var St=o=>Tt(le({},"__esModule",{value:!0}),o);import{useState as xt,useEffect as Pt}from"react";import{Text as b}from"ink";import{Fragment as $t,jsx as P,jsxs as K}from"react/jsx-runtime";var Et,Ut,Ot,de,xe=S(()=>{"use strict";Et={pending:"\u25CB",running:"\u25CB",success:"\u25CF",failed:"\u25CF"},Ut={pending:"gray",running:"cyan",success:"greenBright",failed:"red"},Ot=({color:o})=>{let[e,t]=xt(0);return Pt(()=>{let s=setInterval(()=>{t(a=>(a+1)%3)},400);return()=>clearInterval(s)},[]),P(b,{color:o,dimColor:e===0,bold:e===2,children:"\u25CB"})},de=({name:o,status:e,message:t,indent:r=0,isSubItem:n=!1,isFirstSubItem:s=!1})=>{let a=Et[e],m=Ut[e],d=t??o;return n?K(b,{children:[P(b,{children:s?" \u23BF ":" "}),P(b,{dimColor:e==="success",children:d})]}):K(b,{children:[e==="running"?K($t,{children:[P(Ot,{color:m}),P(b,{children:" "})]}):K(b,{color:m,children:[a," "]}),P(b,{dimColor:e==="success"||e==="pending",children:d})]})}});import{Text as Pe}from"ink";import{jsx as _t,jsxs as At}from"react/jsx-runtime";var fe,Ee=S(()=>{"use strict";fe=({type:o,message:e,indent:t=0,isSubItem:r=!1,isFirstSubItem:n=!1,dimmed:s=!1})=>At(Pe,{children:[r?n?" \u23BF ":" ":"",_t(Pe,{color:{info:"blueBright",warn:"yellow",error:"redBright",success:"greenBright"}[o],dimColor:s,children:e})]})});import{useState as Dt,useEffect as qt}from"react";import{Text as _,useInput as Bt}from"ink";import Mt from"clipboardy";import{jsx as W,jsxs as he}from"react/jsx-runtime";var Ft,Lt,Gt,Ue,Oe=S(()=>{"use strict";Ft=()=>process.stdin.isTTY&&typeof process.stdin.setRawMode=="function",Lt=({text:o,dimmed:e=!1,isSubItem:t=!1,isFirstSubItem:r=!1})=>he(_,{children:[t?r?" \u23BF ":" ":"",W(_,{color:"blueBright",dimColor:e,children:o})]}),Gt=({text:o,dimmed:e=!1,isSubItem:t=!1,isFirstSubItem:r=!1})=>{let[n,s]=Dt(!1),a=t?r?" \u23BF ":" ":"";return Bt(m=>{m==="c"&&Mt.write(o).then(()=>{s(!0)}).catch(()=>{})}),qt(()=>{if(n){let m=setTimeout(()=>{s(!1)},2e3);return()=>clearTimeout(m)}},[n]),he(_,{children:[a,W(_,{color:"blueBright",dimColor:e,children:o}),n&&he(_,{color:"green",dimColor:!1,children:[" ","(Copied!)"]})]})},Ue=o=>Ft()?W(Gt,{...o}):W(Lt,{...o})});import{Box as $e}from"ink";import{jsx as A,jsxs as _e}from"react/jsx-runtime";var Nt,ge,Ae=S(()=>{"use strict";xe();Ee();Oe();Nt=o=>{let e=o.filter(s=>s.type==="task"),t=o.filter(s=>s.type==="message"),r=t.some(s=>s.messageType==="error"),n=t.some(s=>s.messageType==="success");if(r)return"failed";if(n)return"success";if(e.length>0){if(e.some(s=>s.status==="failed"))return"failed";if(e.every(s=>s.status==="success"))return"success"}return"running"},ge=({groups:o,globalMessages:e})=>_e($e,{flexDirection:"column",children:[o.map(t=>{let r=Nt(t.items);return _e($e,{flexDirection:"column",children:[A(de,{name:t.name,status:r,indent:0,isSubItem:!1}),t.items.map((n,s)=>n.type==="task"?A(de,{name:n.name,status:n.status,...n.message!==void 0&&{message:n.message},indent:1,isSubItem:!0,isFirstSubItem:s===0},n.id):n.type==="copyable-text"?A(Ue,{text:n.text,isSubItem:!0,isFirstSubItem:s===0,...n.dimmed!==void 0&&{dimmed:n.dimmed}},n.id):A(fe,{type:n.messageType,message:n.message,isSubItem:!0,isFirstSubItem:s===0,...n.dimmed!==void 0&&{dimmed:n.dimmed}},n.id))]},t.id)}),e.map(t=>A(fe,{type:t.messageType,message:t.message,indent:0},t.id))]})});var qe={};be(qe,{InkTaskRunner:()=>Ie});import{render as jt}from"ink";import{jsx as De}from"react/jsx-runtime";var D,ye,ve,Ie,Be=S(()=>{"use strict";Ae();D=0,ye=class{constructor(e,t,r,n){this.groupId=e;this.taskId=t;this.state=r;this.rerender=n}updateTask(e){let t=this.state.groups.find(n=>n.id===this.groupId);if(!t)return;let r=t.items.find(n=>n.type==="task"&&n.id===this.taskId);r?.type==="task"&&(Object.assign(r,e),this.rerender())}update(e){this.updateTask({message:e})}succeed(e){let t={status:"success"};e!==void 0&&(t.message=e),this.updateTask(t)}fail(e){let t={status:"failed"};e!==void 0&&(t.message=e),this.updateTask(t)}},ve=class{constructor(e,t,r){this.groupId=e;this.state=t;this.rerender=r}getGroup(){let e=this.state.groups.find(t=>t.id===this.groupId);if(!e)throw new Error(`Group ${this.groupId} not found`);return e}async task(e,t){let r=`task-${D++}`,n=this.getGroup(),s={type:"task",id:r,name:e,status:"running"};n.items.push(s),this.rerender();let a=new ye(this.groupId,r,this.state,this.rerender);try{await t(a),s.status==="running"&&a.succeed()}catch(m){throw a.fail(),m}}addMessage(e,t,r){let n=this.getGroup(),s={type:"message",id:`msg-${D++}`,messageType:e,message:t};r?.clearable!==void 0&&(s.clearable=r.clearable),r?.dimmed!==void 0&&(s.dimmed=r.dimmed),n.items.push(s),this.rerender()}clearClearableItems(){let e=this.getGroup();e.items=e.items.filter(t=>!(t.type==="message"&&t.clearable||t.type==="copyable-text"&&t.clearable)),this.rerender()}info(e,t){this.addMessage("info",e,t)}warn(e,t){this.addMessage("warn",e,t)}error(e,t){this.addMessage("error",e,t)}success(e,t){this.clearClearableItems(),this.addMessage("success",e,t)}copyableText(e,t){let r=this.getGroup(),n={type:"copyable-text",id:`copyable-${D++}`,text:e};t?.clearable!==void 0&&(n.clearable=t.clearable),t?.dimmed!==void 0&&(n.dimmed=t.dimmed),r.items.push(n),this.rerender()}},Ie=class{state={groups:[],globalMessages:[]};renderInstance=null;isRendering=!1;rerender(){this.renderInstance&&this.renderInstance.rerender(De(ge,{groups:this.state.groups,globalMessages:this.state.globalMessages}))}ensureRendering(){if(!this.isRendering){this.renderInstance=jt(De(ge,{groups:this.state.groups,globalMessages:this.state.globalMessages})),this.isRendering=!0;let e=()=>{this.renderInstance&&this.renderInstance.cleanup()};process.on("exit",e),process.on("SIGINT",()=>{e(),process.exit(0)}),process.on("SIGTERM",()=>{e(),process.exit(0)})}}group(e){this.ensureRendering();let t=`group-${D++}`,r={id:t,name:e,items:[]};return this.state.groups.push(r),this.rerender(),new ve(t,this.state,this.rerender.bind(this))}addGlobalMessage(e,t,r){this.ensureRendering();let n={type:"message",id:`msg-${D++}`,messageType:e,message:t};r?.clearable!==void 0&&(n.clearable=r.clearable),r?.dimmed!==void 0&&(n.dimmed=r.dimmed),this.state.globalMessages.push(n),this.rerender()}info(e,t){this.addGlobalMessage("info",e,t)}warn(e,t){this.addGlobalMessage("warn",e,t)}error(e,t){this.addGlobalMessage("error",e,t)}success(e,t){this.addGlobalMessage("success",e,t)}async wait(){this.renderInstance&&(await this.renderInstance.waitUntilExit(),this.renderInstance.cleanup())}}});var ze={};be(ze,{CLIENT_IDS:()=>We,DEFAULT_ENVIRONMENT:()=>Qt,getClientId:()=>M});function M(o){let e=We[o];if(!e||e.startsWith("client_id_for_"))throw new Error(`Client ID not configured for environment: ${o}. Please update CLIENT_IDS in client-ids.ts`);return e}var We,Qt,oe=S(()=>{"use strict";We={"local-dev":"9MhKB71lI9jF5p5OSfykG4juDo5hiGYm","local-prod":"client_id_for_local_prod","cloud-dev":"client_id_for_cloud_dev","cloud-prod":"Vu_yzofw-d7AzNvR4k8ZHyj05zrQ8Qxp"};Qt="cloud-prod"});import{Command as xn}from"commander";import*as w from"path";import*as Me from"fs";import*as x from"fs";import*as k from"path";function Re(o){let{configPath:e,outputPath:t,typesPackages:r=["@blimu/types","@blimu/backend"]}=o,n=[],s=r.join(" and ");n.push("/**"),n.push(` * Type Augmentation for ${s}`),n.push(" *"),n.push(` * This file augments the ${s} packages with union types`),n.push(" * specific to your environment configuration."),n.push(" *"),n.push(" * Types are automatically inferred from your blimu.config.ts file."),n.push(" * No regeneration needed when you update your config!"),n.push(" *"),n.push(" * Make sure to include this file in your tsconfig.json:"),n.push(" * {"),n.push(' * "include": ["blimu-types.d.ts"]'),n.push(" * }"),n.push(" */"),n.push("");let a=k.dirname(t),m=k.isAbsolute(e)?k.resolve(e):k.resolve(a,e),c=k.relative(a,m).replace(/\.(ts|mjs|js)$/,""),p=c.startsWith(".")?c:`./${c}`;n.push(`import type config from '${p}';`),n.push("import type {"),n.push(" InferResourceTypes,"),n.push(" InferEntitlementTypes,"),n.push(" InferPlanTypes,"),n.push(" InferLimitTypes,"),n.push(" InferUsageLimitTypes,"),n.push("} from 'blimu';"),n.push("");for(let u of r)n.push(`declare module '${u}' {`),n.push(" /**"),n.push(" * Resource types inferred from your Blimu configuration."),n.push(" */"),n.push(" type ResourceType = InferResourceTypes<typeof config>;"),n.push(""),n.push(" /**"),n.push(" * Entitlement types inferred from your Blimu configuration."),n.push(" */"),n.push(" type EntitlementType = InferEntitlementTypes<typeof config>;"),n.push(""),n.push(" /**"),n.push(" * Plan types inferred from your Blimu configuration."),n.push(" */"),n.push(" type PlanType = InferPlanTypes<typeof config>;"),n.push(""),n.push(" /**"),n.push(" * Limit types inferred from your Blimu configuration."),n.push(" */"),n.push(" type LimitType = InferLimitTypes<typeof config>;"),n.push(""),n.push(" /**"),n.push(" * Usage limit types inferred from your Blimu configuration."),n.push(" */"),n.push(" type UsageLimitType = InferUsageLimitTypes<typeof config>;"),n.push("}"),n.push("");x.existsSync(a)||x.mkdirSync(a,{recursive:!0}),x.writeFileSync(t,n.join(`
3
+ `),"utf-8")}import*as v from"path";import*as $ from"fs";function j(){let o=[v.join(process.cwd(),"blimu.config.ts"),v.join(process.cwd(),"blimu.config.mjs"),v.join(process.cwd(),"blimu.config.js"),v.join(process.cwd(),"blimu.config.json")];for(let e of o)if($.existsSync(e))return e;return null}async function Te(o){let e=v.isAbsolute(o)?o:v.resolve(process.cwd(),o);if(!$.existsSync(e))throw new Error(`Config file not found: ${e}`);if(v.extname(e).toLowerCase()===".json"){let n=$.readFileSync(e,"utf-8");return JSON.parse(n)}let r=await import(e);return r.default??r}function Se(o,e){let r=v.relative(o,e).replace(/\.(ts|mjs|js)$/,"");return r.startsWith(".")?r:`./${r}`}async function C(){let{InkTaskRunner:o}=await Promise.resolve().then(()=>(Be(),qe));return new o}function Fe(o){o.command("codegen").description("Generate type augmentation file from Blimu config").option("--config <path>","Path to Blimu config file (defaults to blimu.config.ts in project root)").option("--output <path>","Output path for generated type augmentation file (defaults to blimu-types.d.ts in project root)").action(async e=>{let t=await C();try{let r=e.config||j();r||(t.error("No config file found. Please provide --config or ensure blimu.config.ts exists in project root."),await t.wait(),process.exit(1));let n=w.isAbsolute(r)?r:w.resolve(process.cwd(),r);Me.existsSync(n)||(t.error(`Config file not found: ${n}`),await t.wait(),process.exit(1)),t.info(`Using config file: ${n}`);let s=e.output?w.isAbsolute(e.output)?e.output:w.resolve(process.cwd(),e.output):w.join(process.cwd(),"blimu-types.d.ts");t.info(`Output: ${s}`),await t.group("Generating type augmentation").task("Generate types",m=>{let d=w.dirname(s),c=Se(d,n);m.update("Generating type augmentation file with type inference..."),Re({configPath:c,outputPath:s}),m.succeed("Type augmentation file generated")}),t.success(`Generated at: ${s}`),t.info("\u{1F4A1} Tip: Types are automatically inferred from your config."),t.info(" No regeneration needed when you update blimu.config.ts!"),await t.wait()}catch(r){t.error(`Failed to generate type augmentation: ${r instanceof Error?r.message:String(r)}`),r instanceof Error&&r.stack&&t.error(r.stack),await t.wait(),process.exit(1)}})}import{z as i}from"zod";var Kt=i.object({is_tenant:i.boolean().optional(),roles:i.array(i.string()).min(1,"At least one role must be defined"),parents:i.record(i.string(),i.object({required:i.boolean()})).optional(),roles_inheritance:i.record(i.string().min(1),i.array(i.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1)).optional()}),Wt=i.object({roles:i.array(i.string()).min(1).optional(),plans:i.array(i.string()).optional(),limit:i.string().optional()}),zt=i.object({name:i.string(),summary:i.string().optional(),entitlements:i.array(i.string()).optional(),plans:i.array(i.string()).optional(),default_enabled:i.boolean().optional()}),Vt=i.object({name:i.string().min(1,"Plan name is required"),summary:i.string().optional(),description:i.string().min(1,"Plan description is required").optional(),resource_limits:i.record(i.string(),i.number().int().min(0)).optional(),usage_based_limits:i.record(i.string(),i.object({value:i.number().int().min(0),period:i.enum(["monthly","yearly","lifetime"])})).optional()}),Le=i.object({resources:i.record(i.string().min(1),Kt),entitlements:i.record(i.string().min(1),Wt).optional(),features:i.record(i.string().min(1),zt).optional(),plans:i.record(i.string().min(1),Vt).optional()});import q from"chalk";var f={info:o=>{console.log(q.dim(o))},step:o=>{console.log(q.cyan(o))},success:o=>{console.log(q.green("\u2714"),o)},warn:o=>{console.log(q.yellow("\u26A0"),o)},error:o=>{console.error(q.red("\u2716"),o)}};import{FetchClient as Jt,FetchError as kr}from"@blimu/fetch";function Ge(o){let e=[...o?.authStrategies??[]];return o.bearer&&e.push({type:"bearer",token:o.bearer}),o.apiKey&&e.push({type:"apiKey",key:o.apiKey,location:"header",name:"X-API-KEY"}),e}var z=class{constructor(e){this.core=e}list(e,t,r){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/api-keys`,...r??{}})}create(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/api-keys`,body:r,...n??{}})}delete(e,t,r,n){return this.core.request({method:"DELETE",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/api-keys/${encodeURIComponent(r)}`,...n??{}})}get(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/api-keys/${encodeURIComponent(r)}`,...n??{}})}reveal(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/api-keys/${encodeURIComponent(r)}/reveal`,...n??{}})}};var V=class{constructor(e){this.core=e}get(e,t,r){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/definitions`,...r??{}})}update(e,t,r,n){return this.core.request({method:"PUT",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/definitions`,body:r,...n??{}})}validate(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/definitions/validate`,body:r,...n??{}})}};var J=class{constructor(e){this.core=e}getRecords(e,t,r){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/dns/records`,...r??{}})}validate(e,t,r){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/dns/validate`,...r??{}})}};var Q=class{constructor(e){this.core=e}list(e,t,r){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments`,query:t,...r??{}})}create(e,t,r){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/environments`,body:t,...r??{}})}delete(e,t,r){return this.core.request({method:"DELETE",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}`,...r??{}})}read(e,t,r){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}`,...r??{}})}update(e,t,r,n){return this.core.request({method:"PUT",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}`,body:r,...n??{}})}getAuthConfig(e,t,r){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/auth-config`,...r??{}})}updateAuthConfig(e,t,r,n){return this.core.request({method:"PUT",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/auth-config`,body:r,...n??{}})}};var H=class{constructor(e){this.core=e}getAccess(e){return this.core.request({method:"GET",path:"/v1/me/access",...e??{}})}};var Y=class{constructor(e){this.core=e}list(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps`,query:r,...n??{}})}create(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps`,body:r,...n??{}})}delete(e,t,r,n){return this.core.request({method:"DELETE",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps/${encodeURIComponent(r)}`,...n??{}})}getById(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps/${encodeURIComponent(r)}`,...n??{}})}update(e,t,r,n,s){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps/${encodeURIComponent(r)}`,body:n,...s??{}})}revokeAllTokens(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps/${encodeURIComponent(r)}/revoke-all`,...n??{}})}rotateSecret(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps/${encodeURIComponent(r)}/rotate-secret`,...n??{}})}listTokens(e,t,r,n,s){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/oauth-apps/${encodeURIComponent(r)}/tokens`,query:n,...s??{}})}};var X=class{constructor(e){this.core=e}list(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources`,query:r,...n??{}})}create(e,t,r,n){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources`,body:r,...n??{}})}delete(e,t,r,n,s){return this.core.request({method:"DELETE",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources/${encodeURIComponent(r)}/${encodeURIComponent(n)}`,...s??{}})}get(e,t,r,n,s){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources/${encodeURIComponent(r)}/${encodeURIComponent(n)}`,...s??{}})}update(e,t,r,n,s,a){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources/${encodeURIComponent(r)}/${encodeURIComponent(n)}`,body:s,...a??{}})}listChildren(e,t,r,n,s,a){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources/${encodeURIComponent(r)}/${encodeURIComponent(n)}/children`,query:s,...a??{}})}getResourceUsers(e,t,r,n,s,a){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/resources/${encodeURIComponent(r)}/${encodeURIComponent(n)}/users`,query:s,...a??{}})}};var Z=class{constructor(e){this.core=e}provision(e,t,r){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/ssl/provision`,...r??{}})}getStatus(e,t,r){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/ssl/status`,...r??{}})}};var ee=class{constructor(e){this.core=e}list(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/users`,query:r,...n??{}})}get(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/users/${encodeURIComponent(r)}`,...n??{}})}getUserResources(e,t,r,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(t)}/users/${encodeURIComponent(r)}/resources`,...n??{}})}};var te=class{constructor(e){this.core=e}list(e,t,r){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/members`,query:t,...r??{}})}remove(e,t,r){return this.core.request({method:"DELETE",path:`/v1/workspaces/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}`,...r??{}})}updateRole(e,t,r,n){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}/members/${encodeURIComponent(t)}/role`,body:r,...n??{}})}invite(e,t,r){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/members/invite`,body:t,...r??{}})}};var ne=class{constructor(e){this.core=e}list(e){return this.core.request({method:"GET",path:"/v1/workspaces",...e??{}})}create(e,t){return this.core.request({method:"POST",path:"/v1/workspaces",body:e,...t??{}})}getCurrent(e,t){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}`,...t??{}})}update(e,t,r){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}`,body:t,...r??{}})}};var E=class{apiKeys;definitions;dns;environments;me;oauthApps;resources;ssl;users;workspaceMembers;workspaces;constructor(e){let t={...e??{}};delete t.apiKey,delete t.bearer;let r=Ge(e??{}),n=new Jt({...t,baseURL:e?.baseURL??"https://runtime.blimu.dev",...r.length>0?{authStrategies:r}:{}});this.apiKeys=new z(n),this.definitions=new V(n),this.dns=new J(n),this.environments=new Q(n),this.me=new H(n),this.oauthApps=new Y(n),this.resources=new X(n),this.ssl=new Z(n),this.users=new ee(n),this.workspaceMembers=new te(n),this.workspaces=new ne(n)}};import{readFileSync as Ht}from"fs";import{homedir as je}from"os";import{join as B}from"path";import{existsSync as Ne}from"fs";var re=B(je(),".config","blimu"),l={configDir:re,credentials:B(re,"credentials.json"),preferences:B(re,"preferences.json"),config:{primary:B(re,"config.json"),legacy:B(je(),".blimurc.json")}};function Ke(){return Ne(l.config.primary)?l.config.primary:Ne(l.config.legacy)?l.config.legacy:null}function se(){let o=Ke();if(!o)return null;try{let e=Ht(o,"utf-8");return JSON.parse(e)}catch{return null}}function Qe(o,e){return o||(e?.blimuInternalEnvironment?e.blimuInternalEnvironment:(oe(),St(ze)).DEFAULT_ENVIRONMENT)}var Ve={"local-dev":"https://runtime-api.dev-blimu.dev","local-prod":"https://runtime-api.dev-blimu.dev","cloud-dev":"https://api.blimu.dev","cloud-prod":"https://api.blimu.dev"},Je={"local-dev":"https://platform-api.dev-blimu.dev","local-prod":"https://platform.blimu.dev","cloud-dev":"https://platform.blimu.dev","cloud-prod":"https://platform.blimu.dev"};function ie(o,e,t){return o||(e?.runtimeApiBaseUrl?e.runtimeApiBaseUrl:t&&Ve[t]?Ve[t]:"https://runtime.blimu.dev")}function He(o,e,t){return o||(e?.platformApiBaseUrl?e.platformApiBaseUrl:t&&Je[t]?Je[t]:"https://platform.blimu.dev")}import{readFileSync as Ce,writeFileSync as Yt,mkdirSync as Xt,existsSync as U,chmodSync as Zt,unlinkSync as en}from"fs";import{dirname as tn}from"path";var F="blimu-cli",ae=null,Ye=null;async function L(){return ae||(Ye??=import("@napi-rs/keyring"),ae=await Ye),ae.Entry}async function Xe(){try{let o=await L(),e=new o(F,"test-availability");return e.setPassword("test"),e.deletePassword(),!0}catch{return!1}}async function Ze(o){let e=`refresh-token-${o}`;try{let t=await L(),n=new t(F,e).getPassword();if(n)return n}catch{}if(U(l.credentials))try{let t=Ce(l.credentials,"utf-8"),r=JSON.parse(t);if(r._keychain_unavailable&&r.refresh_token)return r.refresh_token}catch{}return null}async function ce(o,e){let t=`refresh-token-${o}`;try{let s=await L();return new s(F,t).setPassword(e),{usedKeychain:!0}}catch{}let n={...y(),refresh_token:e,_keychain_unavailable:!0,environment:o};return O(n),{usedKeychain:!1}}async function et(o){let e=`refresh-token-${o}`;try{let t=await L();new t(F,e).deletePassword()}catch{}if(U(l.credentials))try{let t=Ce(l.credentials,"utf-8"),r=JSON.parse(t);if(r._keychain_unavailable){let{refresh_token:n,_keychain_unavailable:s,...a}=r;O(a)}}catch{}}async function tt(o,e){let t=`code-verifier-${o}`;try{let r=await L();return new r(F,t).setPassword(e),{usedKeychain:!0}}catch{return{usedKeychain:!1}}}function y(){if(!U(l.credentials))throw new Error("No credentials found. Please run `blimu login` first.");try{let o=Ce(l.credentials,"utf-8");return JSON.parse(o)}catch(o){throw new Error(`Failed to read credentials: ${o instanceof Error?o.message:String(o)}`)}}function O(o){let e=tn(l.credentials);U(e)||Xt(e,{recursive:!0,mode:448}),Yt(l.credentials,JSON.stringify(o,null,2),"utf-8"),Zt(l.credentials,384)}function nt(){U(l.credentials)&&en(l.credentials)}function G(){return U(l.credentials)}async function nn(o,e,t){let r=await Ze(t);if(!r)throw new Error("No refresh token found. Please run `blimu login` again.");let n=await fetch(`${o}/v1/oauth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({grant_type:"refresh_token",client_id:e,refresh_token:r})});if(!n.ok){let d=await n.json().catch(()=>({}));throw new Error(d.error_description??d.error??`HTTP ${n.status}: ${n.statusText}`)}let s=await n.json(),a=Math.floor(Date.now()/1e3)+s.expires_in,m=y();return O({...m,access_token:s.access_token,expires_at:a,environment:t}),s.refresh_token!==r&&await ce(t,s.refresh_token),{access_token:s.access_token,expires_at:a,refresh_token:s.refresh_token}}function rn(o=60){try{let e=y(),t=Math.floor(Date.now()/1e3);return e.expires_at-t<o}catch{return!0}}async function rt(o,e,t){return rn()?(await nn(o,e,t)).access_token:y().access_token}oe();async function me(o={}){let{apiKey:e,bearer:t,platformApiUrl:r,requireAuth:n=!0}=o,s=se(),a;if(G())try{a=y().environment??s?.blimuInternalEnvironment}catch{a=s?.blimuInternalEnvironment}else a=s?.blimuInternalEnvironment;let m=r??He(void 0,s,a)??"https://platform.blimu.dev",d=e,c=t;if(d||c)return new E({baseURL:m,...d?{apiKey:d}:{},...c?{bearer:c}:{}});if(!n)return new E({baseURL:m});if(!G())throw new Error("Authentication required. Please run `blimu login` first or provide --api-key <key> or --bearer <token>");try{let u=y().environment??s?.blimuInternalEnvironment??"cloud-prod",I=ie(void 0,s,u),g=M(u);c=await rt(I,g,u)}catch(p){throw new Error(`Failed to authenticate: ${p instanceof Error?p.message:String(p)}
4
+ Please run \`blimu login\` again.`)}return new E({baseURL:m,bearer:c})}import{readFileSync as on,writeFileSync as sn,mkdirSync as an,existsSync as ot,chmodSync as cn}from"fs";import{dirname as mn}from"path";function pn(o){try{let e=o.split(".");if(e.length!==3)return null;let t=e[1];if(!t)return null;let r=t.replace(/-/g,"+").replace(/_/g,"/"),n=Buffer.from(r,"base64").toString("utf-8"),s=JSON.parse(n);return typeof s.sub=="string"?s.sub:null}catch{return null}}function st(){if(!G())return null;try{let o=y();return pn(o.access_token)}catch{return null}}function it(){if(!ot(l.preferences))return{};try{let o=on(l.preferences,"utf-8");return JSON.parse(o)}catch{return{}}}function un(o){let e=mn(l.preferences);ot(e)||an(e,{recursive:!0,mode:448}),sn(l.preferences,JSON.stringify(o,null,2),"utf-8"),cn(l.preferences,384)}function at(){let o=st();return o?it()[o]?.default_workspace_id??null:null}function we(o){let e=st();if(!e)throw new Error("Cannot set workspace preference: No authenticated user found");let t=it();t[e]={...t[e],default_workspace_id:o},un(t)}function ln(){return process.env.CI==="true"||process.env.CI==="1"}function dn(){if(ln()||!process.stdout.isTTY)return!1;let o=process.env.TERM;return!(!o||o==="dumb")}function ke(){return dn()}import{select as fn}from"@inquirer/prompts";async function N(o){try{return await fn({message:o.title,choices:o.choices.map(t=>{let r={name:t.label,value:t.value};return t.description!=null?{...r,description:t.description}:r})})}catch{return null}}function ct(o){o.command("push").description("Push definitions to Blimu API").option("--config <path>","Path to Blimu config file (defaults to blimu.config.ts in project root)").option("--workspace-id <id>","Workspace ID (prompts if not specified)").option("--environment-id <id>","Environment ID (prompts if not specified)").option("--platform-api-url <url>","Override Platform API base URL").action(async e=>{try{let t=await C(),r=t.group("Connecting to Blimu"),n;await r.task("Authenticate",async u=>{n=await me({...e.apiKey?{apiKey:e.apiKey}:{},...e.bearer?{bearer:e.bearer}:{},...e.platformApiUrl?{platformApiUrl:e.platformApiUrl}:{},requireAuth:!0}),u.succeed("Connected")}),n||(r.error("Failed to connect to Blimu API"),await t.wait(),process.exit(1)),r.success("Ready"),await t.wait();let s=e.workspaceId??at();if(!s)if(ke()){let{data:u}=await n.workspaces.list();u.length===0&&(f.error("No workspaces found. Please create a workspace first."),process.exit(1));let I=u.map(h=>({label:h.name,value:h.id,description:`ID: ${h.id}`})),g=await N({title:"Select a workspace:",choices:I});g||(f.error("Workspace selection cancelled"),process.exit(1)),s=g}else f.error("No workspace specified. Use --workspace-id <id> or run `blimu login` to set a default workspace."),process.exit(1);let a=e.environmentId;if(!a)if(ke()){let{data:u}=await n.environments.list(s);u.length===0&&(f.error("No environments found in this workspace. Please create an environment first."),process.exit(1));let I=u.map(h=>({label:`${h.name} (${h.variant})`,value:h.id,description:`ID: ${h.id}`})),g=await N({title:"Select an environment:",choices:I});g||(f.error("Environment selection cancelled"),process.exit(1)),a=g}else f.error("No environment specified. Use --environment-id <id>"),process.exit(1);let m=e.config??j();m||(f.error("No config file found. Please provide --config or ensure blimu.config.ts exists in project root."),process.exit(1));let d=await C(),c=d.group("Pushing definitions");c.info(`Config: ${m}`),c.info(`Workspace: ${s}`),c.info(`Environment: ${a}`);let p;await c.task("Load and validate config",async u=>{u.update("Loading config file...");let I=await Te(m);u.update("Validating schema...");let g=Le.safeParse(I);g.success||(u.fail("Config validation failed"),c.error("Config validation errors:"),g.error.issues.forEach(h=>{c.error(` - ${h.path.join(".")}: ${h.message}`)}),await d.wait(),process.exit(1)),p=g.data,u.succeed("Config validated")}),await c.task("Push to environment",async u=>{if(!n)throw new Error("Client is not connected");if(!p)throw new Error("Config is not loaded");await n.definitions.update(s,a,{resources:p.resources,...p.entitlements?{entitlements:p.entitlements}:{},...p.features?{features:p.features}:{},...p.plans?{plans:p.plans}:{}}),u.succeed("Pushed successfully")}),c.success("Definitions updated"),await d.wait()}catch(t){f.error(`Failed to push definitions: ${t instanceof Error?t.message:String(t)}`),t instanceof Error&&t.stack&&console.error(t.stack),process.exit(1)}})}import bn from"open";import{Blimu as vn,FetchError as dt,BadRequestError as In}from"@blimu/backend";import{createHash as hn,randomBytes as gn}from"crypto";function mt(){let o=gn(96);return ut(o)}function pt(o){let e=hn("sha256").update(o).digest();return ut(e)}function ut(o){return o.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}async function lt(o,e={}){let{initialInterval:t=5,maxInterval:r=60,maxAttempts:n=120,timeout:s=6e5}=e,a=Date.now(),m=t,d=0;for(;d<n;){if(Date.now()-a>s)throw new Error("Login timed out");d>0&&await yn(m*1e3),d++;try{let c=await o();if(c.success)return c.data;let p=c.error;if(p.error==="authorization_pending")continue;if(p.error==="slow_down"){m=Math.min(m+5,r);continue}throw p.error==="access_denied"?new Error("Authorization was denied"):p.error==="expired_token"?new Error("Login session has expired"):new Error(p.error_description??p.error??"Authorization failed")}catch(c){throw c instanceof Error?c:new Error(`Polling error: ${String(c)}`)}}throw new Error("Login timed out")}function yn(o){return new Promise(e=>setTimeout(e,o))}import{Agent as Cn,fetch as wn}from"undici";function kn(){let o=new Cn({connect:{rejectUnauthorized:!1}});return async(e,t)=>wn(e,{...t,dispatcher:o})}var pe=class{constructor(e,t,r){this.runtimeApiBaseUrl=e;this.clientId=t;this.environment=r;let n=this.environment==="local-dev"||this.environment==="local-prod"?kn():void 0;this.client=new vn({baseURL:e,...n?{fetch:n}:{}})}client;async requestDeviceCode(){let e=mt(),t=pt(e);try{return{deviceCodeResponse:await this.client.oauth.requestDeviceCode({client_id:this.clientId,code_challenge:t,code_challenge_method:"S256"}),codeVerifier:e,codeChallenge:t}}catch(r){if(r instanceof dt){let n=r.data||{};if(r.status===0){let s=r.message||"Unknown network error";throw new Error(`Failed to connect to ${this.runtimeApiBaseUrl}. ${s}
5
+ This usually means:
6
+ - The server is not running or not reachable
7
+ - DNS resolution failed
8
+ - SSL/TLS certificate issues
9
+ - Network connectivity problems
10
+
11
+ Please verify that the Runtime API is accessible at: ${this.runtimeApiBaseUrl}`)}throw new Error(n.error_description??n.error??r.message??"Request failed")}throw r}}async pollForTokens(e,t,r){return lt(async()=>{try{return{success:!0,data:await this.client.oauth.exchangeDeviceCode({grant_type:"urn:ietf:params:oauth:grant-type:device_code",device_code:e,client_id:this.clientId,code_verifier:t})}}catch(n){if(n instanceof In)return{success:!1,error:{error:n.message,error_description:n.message}};if(n instanceof dt){if(n.status===0)throw new Error(`Network error while polling for tokens: ${n.message||"Connection failed"}
12
+ Please verify that the Runtime API is accessible at: ${this.runtimeApiBaseUrl}`);return{success:!1,error:{error:`http_${n.status}`,error_description:n.message||`HTTP ${n.status} error`}}}let s=n instanceof Error?n.message:String(n);throw new Error(`Unexpected error while polling for tokens: ${s}`)}},{initialInterval:r,maxInterval:60,maxAttempts:120,timeout:6e5})}};oe();function ft(o){o.command("login").description("Authenticate with Blimu using OAuth2 device flow").option("--exec-env <env>","Blimu internal environment (local-dev, local-prod, cloud-dev, cloud-prod)").option("--runtime-api-url <url>","Override Runtime API base URL").option("--verbose","Show detailed output",!1).action(async e=>{let t=e.verbose;try{let r=await C(),n=se(),s=Qe(e.execEnv,n),a=ie(e.runtimeApiUrl,n,s);t&&r.info(`Runtime API: ${a}`);let m=M(s),d=s==="cloud-prod"?"Blimu platform":`${s} environment`,c=r.group(`Authenticating to ${d}`);await Xe()||c.warn("System keychain not available. Refresh token will be stored in plaintext at ~/.config/blimu/credentials.json");let u=new pe(a,m,s),{deviceCodeResponse:I,codeVerifier:g}=await u.requestDeviceCode();c.info("Browser didn't open? Use the url below to sign in (c to copy)",{clearable:!0}),c.copyableText(I.verification_uri_complete,{clearable:!0,dimmed:!0});try{await bn(I.verification_uri_complete)}catch{}await tt(s,g);let h=await u.pollForTokens(I.device_code,g,I.interval),It=Math.floor(Date.now()/1e3)+h.expires_in;O({access_token:h.access_token,token_type:h.token_type,expires_at:It,environment:s});let{usedKeychain:Ct}=await ce(s,h.refresh_token);c.success("Login successful"),t&&(Ct?r.info("Refresh token stored in system keychain"):r.info("Refresh token stored in credentials file"));let ue=r;ue.renderInstance&&(ue.renderInstance.cleanup(),ue.isRendering=!1),await new Promise(wt=>setTimeout(wt,100)),await Rn()}catch(r){let n=r instanceof Error?r.message:String(r);f.error(`Authentication failed: ${Tn(n)}`),t&&r instanceof Error&&r.stack&&f.info(r.stack),process.exit(1)}})}async function Rn(){try{f.info("Fetching workspaces...");let o=await me({requireAuth:!0}),{data:e}=await o.workspaces.list();if(f.info(`Found ${e.length} workspace(s)`),e.length===1){let n=e[0];n&&(we(n.id),f.info(`Default workspace set to: ${n.name}`));return}if(e.length===0)return;let t=e.map(n=>({label:n.name,value:n.id,description:`ID: ${n.id}`})),r=await N({title:"Select a default workspace:",choices:t});if(r){we(r);let n=e.find(s=>s.id===r);f.success(`Default workspace set to: ${n?.name}`)}}catch(o){if(f.warn("Could not fetch workspaces for default selection"),o instanceof Error){f.info(`Reason: ${o.message}`);let e=o;console.error("Full error details:",o),e.status!==void 0&&console.error("HTTP Status:",e.status),e.data!==void 0&&console.error("Response data:",e.data)}}}function Tn(o){let e=o.replace(/^HTTP \d+:\s*/i,"");return{"Invalid request":"The authorization request was invalid. Please try again.","User denied authorization":"Authorization was denied.","Device code has expired":"The login session has expired. Please try again.","Polling timeout exceeded":"Login timed out. Please try again.","Maximum polling attempts exceeded":"Login timed out. Please try again."}[e]??e}function ht(o){o.command("logout").description("Log out and remove stored credentials").action(async()=>{try{let e=await C(),t;try{t=y().environment}catch{e.info("No credentials found. Already logged out."),await e.wait();return}await e.group("Logging out").task("Remove credentials",async n=>{t&&await et(t),nt(),n.succeed("Credentials removed")}),e.success("Successfully logged out!"),await e.wait()}catch(e){f.error(`Failed to logout: ${e instanceof Error?e.message:String(e)}`),process.exit(1)}})}function gt(o){return Object.entries(o).map(([e,t])=>{let r;return t==null?r="":typeof t=="object"?r=JSON.stringify(t):r=String(t),`${e}: ${r}`.trimEnd()}).join(`
13
+ `)}function yt(o){try{let e=o.split(".");if(e.length!==3)return null;let t=e[1];if(!t)return null;let r=Buffer.from(t,"base64url").toString("utf-8");return JSON.parse(r)}catch{return null}}import R from"chalk";function Sn(o){return new Date(o*1e3).toLocaleString()}function vt(o){o.command("whoami").description("Display current authentication information").action(async()=>{let e=await C();try{let t=y(),r=yt(t.access_token),n=Math.floor(Date.now()/1e3),s=t.expires_at-n,a={...r?.sub?{[`${R.cyan("@userid")}`]:r.sub}:{},...r?.email?{[`${R.cyan("@email")}`]:r.email}:{},...r?.name?{[`${R.cyan("@name")}`]:r.name}:{},[`${R.cyan("@environment")}`]:t.environment??"unknown",[`${R.cyan("@expires")}`]:Sn(t.expires_at),...s>0?{[`${R.cyan("@expires_in")}`]:`${Math.floor(s/60)} minutes`}:{[`${R.red("@expired")}`]:!0}};e.info(`Current authentication:
14
+
15
+ `+gt(a)+`
16
+ `)}catch(t){t instanceof Error&&t.message.includes("No credentials found")?e.error("Not authenticated. Please run `blimu login` first."):e.error(`Failed to get user info: ${t instanceof Error?t.message:String(t)}`),process.exit(1)}})}var T=new xn;T.name("blimu").description("Blimu - Authorization as a Service CLI").version(process.env.npm_package_version??"0.0.0");Fe(T);ct(T);ft(T);ht(T);vt(T);T.parse();
17
+ //# sourceMappingURL=main.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/components/Task.tsx","../src/ui/components/Message.tsx","../src/ui/components/CopyableText.tsx","../src/ui/components/TaskList.tsx","../src/ui/ink-adapter.tsx","../src/config/client-ids.ts","../src/main.ts","../src/commands/codegen.ts","../src/utils/type-augmentation-generator.ts","../src/utils/config-loader.ts","../src/ui/task-runner.ts","../src/config/schema.ts","../src/utils/logger.ts","../src/api-sdk/client.ts","../src/api-sdk/auth-strategies.ts","../src/api-sdk/services/api_keys.ts","../src/api-sdk/services/definitions.ts","../src/api-sdk/services/dns.ts","../src/api-sdk/services/environments.ts","../src/api-sdk/services/me.ts","../src/api-sdk/services/oauth_apps.ts","../src/api-sdk/services/resources.ts","../src/api-sdk/services/ssl.ts","../src/api-sdk/services/users.ts","../src/api-sdk/services/workspace_members.ts","../src/api-sdk/services/workspaces.ts","../src/config/rc-config.ts","../src/utils/paths.ts","../src/auth/credentials.ts","../src/auth/token-refresh.ts","../src/utils/api-client.ts","../src/auth/preferences.ts","../src/utils/interactive.ts","../src/ui/prompts.ts","../src/commands/push.ts","../src/commands/login.ts","../src/auth/oauth-client.ts","../src/utils/pkce.ts","../src/utils/polling.ts","../src/commands/logout.ts","../src/utils/format.ts","../src/utils/jwt.ts","../src/commands/whoami.ts"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { Text } from 'ink';\n\nexport type TaskStatus = 'pending' | 'running' | 'success' | 'failed';\n\ninterface TaskProps {\n name: string;\n status: TaskStatus;\n message?: string;\n indent?: number;\n isSubItem?: boolean;\n isFirstSubItem?: boolean;\n}\n\nconst statusSymbols: Record<TaskStatus, string> = {\n pending: '○',\n running: '○',\n success: '●',\n failed: '●',\n};\n\nconst statusColors: Record<TaskStatus, string> = {\n pending: 'gray',\n running: 'cyan',\n success: 'greenBright',\n failed: 'red',\n};\n\nconst PulsingDot: React.FC<{ color: string }> = ({ color }) => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const interval = setInterval(() => {\n setFrame((prev) => (prev + 1) % 3);\n }, 400);\n\n return () => clearInterval(interval);\n }, []);\n\n // Cycle through: dim -> normal -> bright\n const dimColor = frame === 0;\n const bright = frame === 2;\n\n return (\n <Text color={color} dimColor={dimColor} bold={bright}>\n ○\n </Text>\n );\n};\n\nexport const Task: React.FC<TaskProps> = ({\n name,\n status,\n message,\n indent: _indent = 0,\n isSubItem = false,\n isFirstSubItem = false,\n}) => {\n const symbol = statusSymbols[status];\n const color = statusColors[status];\n const displayMessage = message ?? name;\n\n // For sub-items, use tree connector only for first item\n if (isSubItem) {\n const prefix = isFirstSubItem ? ' ⎿ ' : ' ';\n return (\n <Text>\n <Text>{prefix}</Text>\n <Text dimColor={status === 'success'}>{displayMessage}</Text>\n </Text>\n );\n }\n\n // Main items show the dot/status\n return (\n <Text>\n {status === 'running' ? (\n <>\n <PulsingDot color={color} />\n <Text> </Text>\n </>\n ) : (\n <Text color={color}>{symbol} </Text>\n )}\n <Text dimColor={status === 'success' || status === 'pending'}>{displayMessage}</Text>\n </Text>\n );\n};\n","import React from 'react';\nimport { Text } from 'ink';\n\nexport type MessageType = 'info' | 'warn' | 'error' | 'success';\n\ninterface MessageProps {\n type: MessageType;\n message: string;\n indent?: number;\n isSubItem?: boolean;\n isFirstSubItem?: boolean;\n dimmed?: boolean;\n}\n\nexport const Message: React.FC<MessageProps> = ({\n type,\n message,\n indent: _indent = 0,\n isSubItem = false,\n isFirstSubItem = false,\n dimmed = false,\n}) => {\n const prefix = isSubItem ? (isFirstSubItem ? ' ⎿ ' : ' ') : '';\n\n const colorMap: Record<MessageType, string> = {\n info: 'blueBright',\n warn: 'yellow',\n error: 'redBright',\n success: 'greenBright',\n };\n\n return (\n <Text>\n {prefix}\n <Text color={colorMap[type]} dimColor={dimmed}>\n {message}\n </Text>\n </Text>\n );\n};\n","import React, { useState, useEffect } from 'react';\nimport { Text, useInput } from 'ink';\nimport clipboardy from 'clipboardy';\n\ninterface CopyableTextProps {\n text: string;\n dimmed?: boolean;\n isSubItem?: boolean;\n isFirstSubItem?: boolean;\n}\n\n// Check if raw mode is supported (required for useInput)\nconst isRawModeSupported = () => {\n return process.stdin.isTTY && typeof process.stdin.setRawMode === 'function';\n};\n\n// Simple text component without copy functionality\nconst SimpleText: React.FC<CopyableTextProps> = ({\n text,\n dimmed = false,\n isSubItem = false,\n isFirstSubItem = false,\n}) => {\n const prefix = isSubItem ? (isFirstSubItem ? ' ⎿ ' : ' ') : '';\n\n return (\n <Text>\n {prefix}\n <Text color=\"blueBright\" dimColor={dimmed}>\n {text}\n </Text>\n </Text>\n );\n};\n\n// Interactive text component with copy functionality\nconst InteractiveCopyableText: React.FC<CopyableTextProps> = ({\n text,\n dimmed = false,\n isSubItem = false,\n isFirstSubItem = false,\n}) => {\n const [copied, setCopied] = useState(false);\n const prefix = isSubItem ? (isFirstSubItem ? ' ⎿ ' : ' ') : '';\n\n useInput((input) => {\n if (input === 'c') {\n clipboardy\n .write(text)\n .then(() => {\n setCopied(true);\n })\n .catch(() => {\n // Silently fail if clipboard access fails\n });\n }\n });\n\n // Reset \"Copied!\" message after 2 seconds\n useEffect(() => {\n if (copied) {\n const timeout = setTimeout(() => {\n setCopied(false);\n }, 2000);\n return () => clearTimeout(timeout);\n }\n }, [copied]);\n\n return (\n <Text>\n {prefix}\n <Text color=\"blueBright\" dimColor={dimmed}>\n {text}\n </Text>\n {copied && (\n <Text color=\"green\" dimColor={false}>\n {' '}\n (Copied!)\n </Text>\n )}\n </Text>\n );\n};\n\n// Main export - choose appropriate component based on raw mode support\nexport const CopyableText: React.FC<CopyableTextProps> = (props) => {\n if (isRawModeSupported()) {\n return <InteractiveCopyableText {...props} />;\n }\n return <SimpleText {...props} />;\n};\n","import React from 'react';\nimport { Box } from 'ink';\nimport { Task, type TaskStatus } from './Task.js';\nimport { Message, type MessageType } from './Message.js';\nimport { CopyableText } from './CopyableText.js';\n\nexport interface TaskItem {\n type: 'task';\n id: string;\n name: string;\n status: TaskStatus;\n message?: string;\n}\n\nexport interface MessageItem {\n type: 'message';\n id: string;\n messageType: MessageType;\n message: string;\n clearable?: boolean;\n dimmed?: boolean;\n}\n\nexport interface CopyableTextItem {\n type: 'copyable-text';\n id: string;\n text: string;\n clearable?: boolean;\n dimmed?: boolean;\n}\n\nexport type GroupItem = TaskItem | MessageItem | CopyableTextItem;\n\nexport interface TaskGroupItem {\n id: string;\n name: string;\n items: GroupItem[];\n}\n\ninterface TaskListProps {\n groups: TaskGroupItem[];\n globalMessages: MessageItem[];\n}\n\nconst getGroupStatus = (items: GroupItem[]): TaskStatus => {\n const tasks = items.filter((item): item is TaskItem => item.type === 'task');\n const messages = items.filter((item): item is MessageItem => item.type === 'message');\n\n // Check for success/error messages first (takes precedence)\n const hasErrorMessage = messages.some((msg) => msg.messageType === 'error');\n const hasSuccessMessage = messages.some((msg) => msg.messageType === 'success');\n\n if (hasErrorMessage) {\n return 'failed';\n }\n\n if (hasSuccessMessage) {\n return 'success';\n }\n\n // If there are tasks, derive status from them\n if (tasks.length > 0) {\n // If any task failed, group is failed\n if (tasks.some((task) => task.status === 'failed')) {\n return 'failed';\n }\n\n // If all tasks succeeded, group is successful\n if (tasks.every((task) => task.status === 'success')) {\n return 'success';\n }\n }\n\n // Otherwise, group is still running\n return 'running';\n};\n\nexport const TaskList: React.FC<TaskListProps> = ({ groups, globalMessages }) => {\n return (\n <Box flexDirection=\"column\">\n {groups.map((group) => {\n const groupStatus = getGroupStatus(group.items);\n\n return (\n <Box key={group.id} flexDirection=\"column\">\n <Task name={group.name} status={groupStatus} indent={0} isSubItem={false} />\n {group.items.map((item, index) => {\n if (item.type === 'task') {\n return (\n <Task\n key={item.id}\n name={item.name}\n status={item.status}\n {...(item.message !== undefined && { message: item.message })}\n indent={1}\n isSubItem={true}\n isFirstSubItem={index === 0}\n />\n );\n } else if (item.type === 'copyable-text') {\n return (\n <CopyableText\n key={item.id}\n text={item.text}\n isSubItem={true}\n isFirstSubItem={index === 0}\n {...(item.dimmed !== undefined && { dimmed: item.dimmed })}\n />\n );\n } else {\n return (\n <Message\n key={item.id}\n type={item.messageType}\n message={item.message}\n isSubItem={true}\n isFirstSubItem={index === 0}\n {...(item.dimmed !== undefined && { dimmed: item.dimmed })}\n />\n );\n }\n })}\n </Box>\n );\n })}\n {globalMessages.map((msg) => (\n <Message key={msg.id} type={msg.messageType} message={msg.message} indent={0} />\n ))}\n </Box>\n );\n};\n","/**\n * Ink adapter - TaskRunner implementation using Ink components\n * Provides modern, hierarchical UI for interactive terminals\n */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport type { TaskRunner, TaskGroup, Task, MessageOptions } from './task-runner.js';\nimport {\n TaskList,\n type TaskGroupItem,\n type TaskItem,\n type MessageItem,\n type CopyableTextItem,\n} from './components/TaskList.js';\nimport type { MessageType } from './components/Message.js';\n\nlet globalIdCounter = 0;\n\ninterface InkState {\n groups: TaskGroupItem[];\n globalMessages: MessageItem[];\n}\n\nclass InkTask implements Task {\n constructor(\n private groupId: string,\n private taskId: string,\n private state: InkState,\n private rerender: () => void\n ) {}\n\n private updateTask(updates: Partial<Omit<TaskItem, 'type' | 'id'>>): void {\n const group = this.state.groups.find((g) => g.id === this.groupId);\n if (!group) return;\n\n const task = group.items.find((item) => item.type === 'task' && item.id === this.taskId);\n if (task?.type !== 'task') return;\n\n Object.assign(task, updates);\n this.rerender();\n }\n\n update(message: string): void {\n this.updateTask({ message });\n }\n\n succeed(message?: string): void {\n const updates: Partial<Omit<TaskItem, 'type' | 'id'>> = {\n status: 'success',\n };\n if (message !== undefined) {\n updates.message = message;\n }\n this.updateTask(updates);\n }\n\n fail(message?: string): void {\n const updates: Partial<Omit<TaskItem, 'type' | 'id'>> = {\n status: 'failed',\n };\n if (message !== undefined) {\n updates.message = message;\n }\n this.updateTask(updates);\n }\n}\n\nclass InkTaskGroup implements TaskGroup {\n constructor(\n private groupId: string,\n private state: InkState,\n private rerender: () => void\n ) {}\n\n private getGroup(): TaskGroupItem {\n const group = this.state.groups.find((g) => g.id === this.groupId);\n if (!group) {\n throw new Error(`Group ${this.groupId} not found`);\n }\n return group;\n }\n\n async task(name: string, fn: (task: Task) => Promise<void> | void): Promise<void> {\n const taskId = `task-${globalIdCounter++}`;\n const group = this.getGroup();\n\n const taskItem: TaskItem = {\n type: 'task',\n id: taskId,\n name,\n status: 'running',\n };\n\n group.items.push(taskItem);\n this.rerender();\n\n const task = new InkTask(this.groupId, taskId, this.state, this.rerender);\n\n try {\n await fn(task);\n // If the task function didn't explicitly succeed/fail, mark as success\n if (taskItem.status === 'running') {\n task.succeed();\n }\n } catch (error) {\n task.fail();\n throw error;\n }\n }\n\n private addMessage(messageType: MessageType, message: string, options?: MessageOptions): void {\n const group = this.getGroup();\n const messageItem: MessageItem = {\n type: 'message',\n id: `msg-${globalIdCounter++}`,\n messageType,\n message,\n };\n\n if (options?.clearable !== undefined) {\n messageItem.clearable = options.clearable;\n }\n if (options?.dimmed !== undefined) {\n messageItem.dimmed = options.dimmed;\n }\n\n group.items.push(messageItem);\n this.rerender();\n }\n\n private clearClearableItems(): void {\n const group = this.getGroup();\n group.items = group.items.filter((item) => {\n if (item.type === 'message' && item.clearable) return false;\n if (item.type === 'copyable-text' && item.clearable) return false;\n return true;\n });\n this.rerender();\n }\n\n info(message: string, options?: MessageOptions): void {\n this.addMessage('info', message, options);\n }\n\n warn(message: string, options?: MessageOptions): void {\n this.addMessage('warn', message, options);\n }\n\n error(message: string, options?: MessageOptions): void {\n this.addMessage('error', message, options);\n }\n\n success(message: string, options?: MessageOptions): void {\n // Clear clearable items before adding success message\n this.clearClearableItems();\n this.addMessage('success', message, options);\n }\n\n copyableText(text: string, options?: MessageOptions): void {\n const group = this.getGroup();\n const item: CopyableTextItem = {\n type: 'copyable-text',\n id: `copyable-${globalIdCounter++}`,\n text,\n };\n\n if (options?.clearable !== undefined) {\n item.clearable = options.clearable;\n }\n if (options?.dimmed !== undefined) {\n item.dimmed = options.dimmed;\n }\n\n group.items.push(item);\n this.rerender();\n }\n}\n\nexport class InkTaskRunner implements TaskRunner {\n private state: InkState = {\n groups: [],\n globalMessages: [],\n };\n private renderInstance: ReturnType<typeof render> | null = null;\n private isRendering = false;\n\n private rerender(): void {\n if (this.renderInstance) {\n this.renderInstance.rerender(\n <TaskList groups={this.state.groups} globalMessages={this.state.globalMessages} />\n );\n }\n }\n\n private ensureRendering(): void {\n if (!this.isRendering) {\n this.renderInstance = render(\n <TaskList groups={this.state.groups} globalMessages={this.state.globalMessages} />\n );\n this.isRendering = true;\n\n // Ensure cursor is restored on process exit\n const cleanup = () => {\n if (this.renderInstance) {\n this.renderInstance.cleanup();\n }\n };\n\n process.on('exit', cleanup);\n process.on('SIGINT', () => {\n cleanup();\n process.exit(0);\n });\n process.on('SIGTERM', () => {\n cleanup();\n process.exit(0);\n });\n }\n }\n\n group(name: string): TaskGroup {\n this.ensureRendering();\n\n const groupId = `group-${globalIdCounter++}`;\n const groupItem: TaskGroupItem = {\n id: groupId,\n name,\n items: [],\n };\n\n this.state.groups.push(groupItem);\n this.rerender();\n\n return new InkTaskGroup(groupId, this.state, this.rerender.bind(this));\n }\n\n private addGlobalMessage(\n messageType: MessageType,\n message: string,\n options?: MessageOptions\n ): void {\n this.ensureRendering();\n const messageItem: MessageItem = {\n type: 'message',\n id: `msg-${globalIdCounter++}`,\n messageType,\n message,\n };\n\n if (options?.clearable !== undefined) {\n messageItem.clearable = options.clearable;\n }\n if (options?.dimmed !== undefined) {\n messageItem.dimmed = options.dimmed;\n }\n\n this.state.globalMessages.push(messageItem);\n this.rerender();\n }\n\n info(message: string, options?: MessageOptions): void {\n this.addGlobalMessage('info', message, options);\n }\n\n warn(message: string, options?: MessageOptions): void {\n this.addGlobalMessage('warn', message, options);\n }\n\n error(message: string, options?: MessageOptions): void {\n this.addGlobalMessage('error', message, options);\n }\n\n success(message: string, options?: MessageOptions): void {\n this.addGlobalMessage('success', message, options);\n }\n\n async wait(): Promise<void> {\n if (this.renderInstance) {\n await this.renderInstance.waitUntilExit();\n this.renderInstance.cleanup();\n }\n }\n}\n","/**\n * Hardcoded client IDs for Blimu internal environments\n * These are the OAuth2 app client IDs for different deployment environments\n */\n\nexport type BlimuInternalEnvironment = 'local-dev' | 'local-prod' | 'cloud-dev' | 'cloud-prod';\n\n/**\n * Client ID mapping for each environment\n * TODO: Replace with actual client IDs once OAuth apps are created\n */\nexport const CLIENT_IDS: Record<BlimuInternalEnvironment, string> = {\n 'local-dev': '9MhKB71lI9jF5p5OSfykG4juDo5hiGYm',\n 'local-prod': 'client_id_for_local_prod',\n 'cloud-dev': 'client_id_for_cloud_dev',\n 'cloud-prod': 'Vu_yzofw-d7AzNvR4k8ZHyj05zrQ8Qxp',\n};\n\n/**\n * Get client ID for an environment\n * @param environment - The internal environment\n * @returns Client ID string\n */\nexport function getClientId(environment: BlimuInternalEnvironment): string {\n const clientId = CLIENT_IDS[environment];\n if (!clientId || clientId.startsWith('client_id_for_')) {\n throw new Error(\n `Client ID not configured for environment: ${environment}. Please update CLIENT_IDS in client-ids.ts`\n );\n }\n return clientId;\n}\n\n/**\n * Default environment\n */\nexport const DEFAULT_ENVIRONMENT: BlimuInternalEnvironment = 'cloud-prod';\n","import { Command } from 'commander';\nimport { codegenCommand } from './commands/codegen';\nimport { pushCommand } from './commands/push';\nimport { loginCommand } from './commands/login';\nimport { logoutCommand } from './commands/logout';\nimport { whoamiCommand } from './commands/whoami';\n\nconst program = new Command();\n\nprogram\n .name('blimu')\n .description('Blimu - Authorization as a Service CLI')\n .version(process.env['npm_package_version'] ?? '0.0.0');\n\n// Register commands\ncodegenCommand(program);\npushCommand(program);\nloginCommand(program);\nlogoutCommand(program);\nwhoamiCommand(program);\n\n// Parse arguments\nprogram.parse();\n","import type { Command } from 'commander';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { generateTypeAugmentationFile } from '../utils/type-augmentation-generator';\nimport { findDefaultConfig, getRelativeImportPath } from '../utils/config-loader';\nimport { createTaskRunner } from '../ui/task-runner.js';\n\ninterface CodegenCommandOptions {\n config: string;\n output: string;\n}\n\n/**\n * Register the codegen command\n */\nexport function codegenCommand(program: Command): void {\n program\n .command('codegen')\n .description('Generate type augmentation file from Blimu config')\n .option(\n '--config <path>',\n 'Path to Blimu config file (defaults to blimu.config.ts in project root)'\n )\n .option(\n '--output <path>',\n 'Output path for generated type augmentation file (defaults to blimu-types.d.ts in project root)'\n )\n .action(async (options: CodegenCommandOptions) => {\n const runner = await createTaskRunner();\n try {\n // Find config file\n const configPath = options.config || findDefaultConfig();\n if (!configPath) {\n runner.error(\n 'No config file found. Please provide --config or ensure blimu.config.ts exists in project root.'\n );\n await runner.wait();\n process.exit(1);\n }\n\n // Resolve to absolute path\n const absoluteConfigPath = path.isAbsolute(configPath)\n ? configPath\n : path.resolve(process.cwd(), configPath);\n\n if (!fs.existsSync(absoluteConfigPath)) {\n runner.error(`Config file not found: ${absoluteConfigPath}`);\n await runner.wait();\n process.exit(1);\n }\n\n runner.info(`Using config file: ${absoluteConfigPath}`);\n\n // Determine output path\n const outputPath = options.output\n ? path.isAbsolute(options.output)\n ? options.output\n : path.resolve(process.cwd(), options.output)\n : path.join(process.cwd(), 'blimu-types.d.ts');\n\n runner.info(`Output: ${outputPath}`);\n\n const codegenGroup = runner.group('Generating type augmentation');\n\n await codegenGroup.task('Generate types', (task) => {\n // Calculate relative path from output to config for import statement\n const outputDir = path.dirname(outputPath);\n const relativeConfigPath = getRelativeImportPath(outputDir, absoluteConfigPath);\n\n task.update('Generating type augmentation file with type inference...');\n\n generateTypeAugmentationFile({\n configPath: relativeConfigPath,\n outputPath,\n // Always augment both @blimu/types and @blimu/backend\n // This is an internal implementation detail, not user-configurable\n });\n\n task.succeed('Type augmentation file generated');\n });\n\n runner.success(`Generated at: ${outputPath}`);\n runner.info('💡 Tip: Types are automatically inferred from your config.');\n runner.info(' No regeneration needed when you update blimu.config.ts!');\n\n await runner.wait();\n } catch (error) {\n runner.error(\n `Failed to generate type augmentation: ${error instanceof Error ? error.message : String(error)}`\n );\n if (error instanceof Error && error.stack) {\n runner.error(error.stack);\n }\n await runner.wait();\n process.exit(1);\n }\n });\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Options for generating type augmentation file\n */\nexport interface GenerateTypeAugmentationOptions {\n /** Path to the config file (relative to output directory or absolute) */\n configPath: string;\n /** Output path for the generated type augmentation file */\n outputPath: string;\n /** Types package names to augment (defaults to ['@blimu/types', '@blimu/backend']) */\n typesPackages?: string[];\n}\n\n/**\n * Generate type augmentation file for @blimu/types and @blimu/backend using type inference utilities.\n *\n * This generates a .d.ts file that imports the config and uses type inference\n * utilities to automatically extract types from the config structure.\n *\n * @param options - Generation options\n */\nexport function generateTypeAugmentationFile(options: GenerateTypeAugmentationOptions): void {\n const { configPath, outputPath, typesPackages = ['@blimu/types', '@blimu/backend'] } = options;\n\n const lines: string[] = [];\n\n // Header\n const packageNames = typesPackages.join(' and ');\n lines.push('/**');\n lines.push(` * Type Augmentation for ${packageNames}`);\n lines.push(' *');\n lines.push(` * This file augments the ${packageNames} packages with union types`);\n lines.push(' * specific to your environment configuration.');\n lines.push(' *');\n lines.push(' * Types are automatically inferred from your blimu.config.ts file.');\n lines.push(' * No regeneration needed when you update your config!');\n lines.push(' *');\n lines.push(' * Make sure to include this file in your tsconfig.json:');\n lines.push(' * {');\n lines.push(' * \"include\": [\"blimu-types.d.ts\"]');\n lines.push(' * }');\n lines.push(' */');\n lines.push('');\n\n // Calculate output directory and relative import path\n const outputDir = path.dirname(outputPath);\n const resolvedConfigPath = path.isAbsolute(configPath)\n ? path.resolve(configPath)\n : path.resolve(outputDir, configPath);\n const relativeConfigPath = path.relative(outputDir, resolvedConfigPath);\n // Remove .ts/.mjs/.js extension and ensure it starts with ./\n const importPath = relativeConfigPath.replace(/\\.(ts|mjs|js)$/, '');\n const finalImportPath = importPath.startsWith('.') ? importPath : `./${importPath}`;\n\n // Import config and type utilities\n lines.push(`import type config from '${finalImportPath}';`);\n lines.push('import type {');\n lines.push(' InferResourceTypes,');\n lines.push(' InferEntitlementTypes,');\n lines.push(' InferPlanTypes,');\n lines.push(' InferLimitTypes,');\n lines.push(' InferUsageLimitTypes,');\n lines.push(\"} from 'blimu';\");\n lines.push('');\n\n // Generate module augmentation for each package\n for (const typesPackage of typesPackages) {\n lines.push(`declare module '${typesPackage}' {`);\n lines.push(' /**');\n lines.push(' * Resource types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type ResourceType = InferResourceTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Entitlement types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type EntitlementType = InferEntitlementTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Plan types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type PlanType = InferPlanTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Limit types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type LimitType = InferLimitTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Usage limit types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type UsageLimitType = InferUsageLimitTypes<typeof config>;');\n lines.push('}');\n lines.push('');\n }\n\n // Ensure output directory exists\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Write file\n fs.writeFileSync(outputPath, lines.join('\\n'), 'utf-8');\n}\n","import * as path from 'path';\nimport * as fs from 'fs';\n\n/**\n * Find default config file in project root\n */\nexport function findDefaultConfig(): string | null {\n const possiblePaths = [\n path.join(process.cwd(), 'blimu.config.ts'),\n path.join(process.cwd(), 'blimu.config.mjs'),\n path.join(process.cwd(), 'blimu.config.js'),\n path.join(process.cwd(), 'blimu.config.json'),\n ];\n\n for (const configPath of possiblePaths) {\n if (fs.existsSync(configPath)) {\n return configPath;\n }\n }\n\n return null;\n}\n\n/**\n * Load and parse config file\n */\nexport async function loadConfig(configPath: string): Promise<unknown> {\n const absolutePath = path.isAbsolute(configPath)\n ? configPath\n : path.resolve(process.cwd(), configPath);\n\n if (!fs.existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`);\n }\n\n const ext = path.extname(absolutePath).toLowerCase();\n\n if (ext === '.json') {\n const content = fs.readFileSync(absolutePath, 'utf-8');\n return JSON.parse(content);\n }\n\n // For .ts, .mjs, .js files, use dynamic import\n const mod = (await import(absolutePath)) as { default?: unknown };\n return mod.default ?? mod;\n}\n\n/**\n * Get relative import path from output directory to config file\n * Handles both relative paths and ensures proper extension handling\n */\nexport function getRelativeImportPath(fromDir: string, toFile: string): string {\n const relative = path.relative(fromDir, toFile);\n // Remove .ts/.mjs/.js extension for import\n const withoutExt = relative.replace(/\\.(ts|mjs|js)$/, '');\n // Ensure it starts with ./ or ../\n if (!withoutExt.startsWith('.')) {\n return `./${withoutExt}`;\n }\n return withoutExt;\n}\n","/**\n * Task Runner API - UI rendering using Ink\n */\n\nexport type TaskStatus = 'pending' | 'running' | 'success' | 'failed';\n\nexport interface Task {\n update(message: string): void;\n succeed(message?: string): void;\n fail(message?: string): void;\n}\n\nexport interface MessageOptions {\n clearable?: boolean;\n dimmed?: boolean;\n}\n\nexport interface TaskGroup {\n task(name: string, fn: (task: Task) => Promise<void> | void): Promise<void>;\n info(message: string, options?: MessageOptions): void;\n warn(message: string, options?: MessageOptions): void;\n error(message: string, options?: MessageOptions): void;\n success(message: string, options?: MessageOptions): void;\n copyableText(text: string, options?: MessageOptions): void;\n}\n\nexport interface TaskRunner {\n group(name: string): TaskGroup;\n info(message: string, options?: MessageOptions): void;\n warn(message: string, options?: MessageOptions): void;\n error(message: string, options?: MessageOptions): void;\n success(message: string, options?: MessageOptions): void;\n wait(): Promise<void>;\n}\n\n/**\n * Create a task runner instance using Ink\n */\nexport async function createTaskRunner(): Promise<TaskRunner> {\n const { InkTaskRunner } = await import('./ink-adapter.js');\n return new InkTaskRunner();\n}\n","import { z } from 'zod';\n\n/**\n * Zod schema for resource definition\n */\nexport const ResourceDefinitionSchema = z.object({\n is_tenant: z.boolean().optional(),\n roles: z.array(z.string()).min(1, 'At least one role must be defined'),\n parents: z.record(z.string(), z.object({ required: z.boolean() })).optional(),\n roles_inheritance: z\n .record(\n z.string().min(1), // local role\n // Allow tokens containing letters, numbers, underscores or dashes\n // Examples: parent->editor, organization->admin, workspace_v2->viewer\n z.array(z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1)\n )\n .optional(),\n});\n\n/**\n * Zod schema for entitlement definition\n */\nexport const EntitlementDefinitionSchema = z.object({\n roles: z.array(z.string()).min(1).optional(),\n plans: z.array(z.string()).optional(),\n limit: z.string().optional(), // Reference to usage-based limit\n});\n\n/**\n * Zod schema for feature definition\n */\nexport const FeatureDefinitionSchema = z.object({\n name: z.string(),\n summary: z.string().optional(),\n entitlements: z.array(z.string()).optional(),\n plans: z.array(z.string()).optional(),\n default_enabled: z.boolean().optional(),\n});\n\n/**\n * Zod schema for plan definition\n */\nexport const PlanDefinitionSchema = z.object({\n name: z.string().min(1, 'Plan name is required'),\n summary: z.string().optional(),\n description: z.string().min(1, 'Plan description is required').optional(),\n resource_limits: z.record(z.string(), z.number().int().min(0)).optional(),\n usage_based_limits: z\n .record(\n z.string(),\n z.object({\n value: z.number().int().min(0),\n period: z.enum(['monthly', 'yearly', 'lifetime']),\n })\n )\n .optional(),\n});\n\n/**\n * Zod schema for complete Blimu configuration\n */\nexport const BlimuConfigSchema = z.object({\n resources: z.record(z.string().min(1), ResourceDefinitionSchema),\n entitlements: z.record(z.string().min(1), EntitlementDefinitionSchema).optional(),\n features: z.record(z.string().min(1), FeatureDefinitionSchema).optional(),\n plans: z.record(z.string().min(1), PlanDefinitionSchema).optional(),\n});\n\n/**\n * Type inference from schemas\n */\nexport type ResourceDefinition = z.infer<typeof ResourceDefinitionSchema>;\nexport type EntitlementDefinition = z.infer<typeof EntitlementDefinitionSchema>;\nexport type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;\nexport type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;\nexport type BlimuConfig = z.infer<typeof BlimuConfigSchema>;\n","import chalk from 'chalk';\n\n/**\n * Colored logger for consistent output across commands\n */\nexport const log = {\n /** Neutral / informational message (dim) */\n info: (message: string): void => {\n console.log(chalk.dim(message));\n },\n\n /** Step or action in progress (cyan) */\n step: (message: string): void => {\n console.log(chalk.cyan(message));\n },\n\n /** Success message (green) */\n success: (message: string): void => {\n console.log(chalk.green('✔'), message);\n },\n\n /** Warning message (yellow) */\n warn: (message: string): void => {\n console.log(chalk.yellow('⚠'), message);\n },\n\n /** Error message (red) */\n error: (message: string): void => {\n console.error(chalk.red('✖'), message);\n },\n};\n","import { FetchClient, FetchError } from '@blimu/fetch';\nimport {\n type FetchClientConfig,\n type BearerAuthStrategy,\n type ApiKeyAuthStrategy,\n} from '@blimu/fetch';\nimport { buildAuthStrategies } from './auth-strategies';\nimport { ApiKeysService } from './services/api_keys';\nimport { DefinitionsService } from './services/definitions';\nimport { DnsService } from './services/dns';\nimport { EnvironmentsService } from './services/environments';\nimport { MeService } from './services/me';\nimport { OauthAppsService } from './services/oauth_apps';\nimport { ResourcesService } from './services/resources';\nimport { SslService } from './services/ssl';\nimport { UsersService } from './services/users';\nimport { WorkspaceMembersService } from './services/workspace_members';\nimport { WorkspacesService } from './services/workspaces';\n\nexport type ClientOption = FetchClientConfig & {\n apiKey?: ApiKeyAuthStrategy['key'];\n bearer?: BearerAuthStrategy['token'];\n};\n\nexport class BlimuCli {\n readonly apiKeys: ApiKeysService;\n readonly definitions: DefinitionsService;\n readonly dns: DnsService;\n readonly environments: EnvironmentsService;\n readonly me: MeService;\n readonly oauthApps: OauthAppsService;\n readonly resources: ResourcesService;\n readonly ssl: SslService;\n readonly users: UsersService;\n readonly workspaceMembers: WorkspaceMembersService;\n readonly workspaces: WorkspacesService;\n\n constructor(options?: ClientOption) {\n const restCfg = { ...(options ?? {}) };\n delete restCfg.apiKey;\n delete restCfg.bearer;\n\n const authStrategies = buildAuthStrategies(options ?? {});\n\n const core = new FetchClient({\n ...restCfg,\n baseURL: options?.baseURL ?? 'https://runtime.blimu.dev',\n ...(authStrategies.length > 0 ? { authStrategies } : {}),\n });\n\n this.apiKeys = new ApiKeysService(core);\n this.definitions = new DefinitionsService(core);\n this.dns = new DnsService(core);\n this.environments = new EnvironmentsService(core);\n this.me = new MeService(core);\n this.oauthApps = new OauthAppsService(core);\n this.resources = new ResourcesService(core);\n this.ssl = new SslService(core);\n this.users = new UsersService(core);\n this.workspaceMembers = new WorkspaceMembersService(core);\n this.workspaces = new WorkspacesService(core);\n }\n}\n\n// Re-export FetchError for backward compatibility\nexport { FetchError };\nexport const BlimuCliError = FetchError;\n","import type { AuthStrategy } from '@blimu/fetch';\nimport type { ClientOption } from './client';\n\nexport function buildAuthStrategies(cfg: ClientOption): AuthStrategy[] {\n const authStrategies: AuthStrategy[] = [...(cfg?.authStrategies ?? [])];\n\n if (cfg.bearer) {\n authStrategies.push({\n type: 'bearer',\n token: cfg.bearer,\n });\n }\n if (cfg.apiKey) {\n authStrategies.push({\n type: 'apiKey',\n key: cfg.apiKey,\n location: 'header',\n name: 'X-API-KEY',\n });\n }\n return authStrategies;\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class ApiKeysService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}/api-keys*\n * @returns List API keys for an environment*/\n list(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/api-keys`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/environments/{environmentId}/api-keys*\n * @returns Create API key*/\n create(\n workspaceId: string,\n environmentId: string,\n body: Schema.ApiKeyCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/api-keys`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspace/{workspaceId}/environments/{environmentId}/api-keys/{id}*\n * @returns Delete API key*/\n delete(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/api-keys/${encodeURIComponent(id)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}/api-keys/{id}*\n * @returns Get API key*/\n get(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/api-keys/${encodeURIComponent(id)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/environments/{environmentId}/api-keys/{id}/reveal*\n * @returns Reveal API key*/\n reveal(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyRevealDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/api-keys/${encodeURIComponent(id)}/reveal`,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class DefinitionsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}/definitions*\n * @summary Get environment definitions*/\n get(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DefinitionDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/definitions`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspace/{workspaceId}/environments/{environmentId}/definitions*\n * @summary Update environment definitions*/\n update(\n workspaceId: string,\n environmentId: string,\n body: Schema.DefinitionUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/definitions`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/environments/{environmentId}/definitions/validate*\n * @summary Validate Blimu configuration*\n * @description Validates a complete Blimu configuration including resources, entitlements, features, and plans. Returns validation errors and optionally generates an OpenAPI spec if valid.*/\n validate(\n workspaceId: string,\n environmentId: string,\n body: Schema.DefinitionValidateRequestDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DefinitionValidateResponseDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/definitions/validate`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class DnsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/dns/records*\n * @summary Get DNS records for an environment*/\n getRecords(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DnsRecordListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/dns/records`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/dns/validate*\n * @summary Validate DNS records for an environment*/\n validate(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DnsRecordListDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/dns/validate`,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class EnvironmentsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspace/{workspaceId}/environments*\n * @summary List environments*/\n list(\n workspaceId: string,\n query?: Schema.EnvironmentsListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/environments*\n * @summary Create a new environment*/\n create(\n workspaceId: string,\n body: Schema.EnvironmentCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspace/{workspaceId}/environments/{environmentId}*\n * @summary Delete an environment*/\n delete(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}*\n * @summary Read an environment by ID*/\n read(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentWithDefinitionDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspace/{workspaceId}/environments/{environmentId}*\n * @summary Update an environment*/\n update(\n workspaceId: string,\n environmentId: string,\n body: Schema.EnvironmentUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}/auth-config*\n * @summary Get authentication configuration for environment*/\n getAuthConfig(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentAuthConfigDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/auth-config`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspace/{workspaceId}/environments/{environmentId}/auth-config*\n * @summary Update authentication configuration for environment*/\n updateAuthConfig(\n workspaceId: string,\n environmentId: string,\n body: Schema.EnvironmentAuthConfigUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentAuthConfigDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/auth-config`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class MeService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/me/access*\n * @summary Get active resources for current user*/\n getAccess(init?: Omit<RequestInit, 'method' | 'body'>): Promise<Schema.UserAccessDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/me/access`,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class OauthAppsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps*\n * @summary List OAuth apps*\n * @description Retrieves a paginated list of OAuth apps for the environment. Supports filtering by grant type and active status.*/\n list(\n workspaceId: string,\n environmentId: string,\n query?: Schema.OauthAppsListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.OAuthAppList_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps*\n * @summary Create OAuth app*\n * @description Creates a new OAuth application with client ID, secret (for confidential clients), and RSA key pair for token signing. Returns the client secret only once on creation.*/\n create(\n workspaceId: string,\n environmentId: string,\n body: Schema.OAuthAppCreateBodyDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.OAuthAppCreateResponse_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps/{id}*\n * @summary Delete OAuth app*\n * @description Deletes an OAuth app by ID. This operation is permanent and will cascade delete related tokens, device codes, and consents.*/\n delete(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps/${encodeURIComponent(id)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps/{id}*\n * @summary Get OAuth app*\n * @description Retrieves a single OAuth app by ID. Client secret is never returned.*/\n getById(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.OAuthApp_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps/${encodeURIComponent(id)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps/{id}*\n * @summary Update OAuth app*\n * @description Updates an existing OAuth app. You can update name, scopes, redirect URIs, PKCE requirement, consent requirement, and active status.*/\n update(\n workspaceId: string,\n environmentId: string,\n id: string,\n body: Schema.OAuthAppUpdateBodyDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.OAuthApp_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps/${encodeURIComponent(id)}`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps/{id}/revoke-all*\n * @summary Revoke all tokens for OAuth app*\n * @description Revokes all active tokens associated with an OAuth app. This is useful for security incidents or when rotating app credentials.*/\n revokeAllTokens(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps/${encodeURIComponent(id)}/revoke-all`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps/{id}/rotate-secret*\n * @summary Rotate client secret*\n * @description Rotates the client secret for an OAuth app. Returns the new secret only once. Subsequent calls return a success message without the secret.*/\n rotateSecret(\n workspaceId: string,\n environmentId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.OAuthAppRotateSecretResponse_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps/${encodeURIComponent(id)}/rotate-secret`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/oauth-apps/{id}/tokens*\n * @summary List tokens for OAuth app*\n * @description Retrieves a list of tokens (refresh tokens) associated with an OAuth app. Supports filtering by token type and active status. Token values are never returned.*/\n listTokens(\n workspaceId: string,\n environmentId: string,\n id: string,\n query?: Schema.OauthAppsListTokensQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.OAuthAppTokenList_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/oauth-apps/${encodeURIComponent(id)}/tokens`,\n query,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class ResourcesService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources*\n * @summary List resources for an environment*/\n list(\n workspaceId: string,\n environmentId: string,\n query?: Schema.ResourcesListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/resources*\n * @summary Create a new resource*/\n create(\n workspaceId: string,\n environmentId: string,\n body: Schema.ResourceCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}*\n * @summary Delete a resource*/\n delete(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}*\n * @summary Get a specific resource*/\n get(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}*\n * @summary Update a resource*/\n update(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n body: Schema.ResourceUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}/children*\n * @summary List children resources for a specific resource*/\n listChildren(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n query?: Schema.ResourcesListChildrenQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}/children`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}/users*\n * @summary Get users with roles on a resource*/\n getResourceUsers(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n query?: Schema.ResourcesGetResourceUsersQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceUserListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}/users`,\n query,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class SslService {\n constructor(private core: FetchClient) {}\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/ssl/provision*\n * @summary Provision custom domains and SSL certificates for an environment*/\n provision(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.CustomHostnameListDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/ssl/provision`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/ssl/status*\n * @summary Get SSL certificate status for an environment*/\n getStatus(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.SslStatusResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/ssl/status`,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class UsersService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/users*\n * @summary List users for an environment*/\n list(\n workspaceId: string,\n environmentId: string,\n query?: Schema.UsersListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.UserListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/users`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/users/{userId}*\n * @summary Get user details by ID*/\n get(\n workspaceId: string,\n environmentId: string,\n userId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.UserDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/users/${encodeURIComponent(userId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/users/{userId}/resources*\n * @summary Get user resource relationships*/\n getUserResources(\n workspaceId: string,\n environmentId: string,\n userId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.UserResourceDto_Output[]> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/users/${encodeURIComponent(userId)}/resources`,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class WorkspaceMembersService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/members*\n * @summary List workspace members with pagination and search*/\n list(\n workspaceId: string,\n query?: Schema.WorkspaceMembersListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.MemberListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspaces/{workspaceId}/members/{userId}*\n * @summary Remove member from workspace*/\n remove(\n workspaceId: string,\n userId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(userId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}/members/{userId}/role*\n * @summary Update member role*/\n updateRole(\n workspaceId: string,\n userId: string,\n body: Schema.UpdateRoleDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(userId)}/role`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/members/invite*\n * @summary Invite a member to the workspace*/\n invite(\n workspaceId: string,\n body: Schema.InviteMemberDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.InviteMemberResponseDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members/invite`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import type { FetchClient } from '@blimu/fetch';\nimport type * as Schema from '../schema';\n\nexport class WorkspacesService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces*\n * @summary Get all workspaces*/\n list(init?: Omit<RequestInit, 'method' | 'body'>): Promise<Schema.WorkspaceListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces*\n * @summary Create a new workspace*/\n create(\n body: Schema.WorkspaceCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.WorkspaceCreateResponseDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}*\n * @summary Get current authenticated workspace*/\n getCurrent(\n workspaceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.WorkspaceDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}*\n * @summary Update authenticated workspace*/\n update(\n workspaceId: string,\n body: Schema.WorkspaceUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.WorkspaceDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import { readFileSync } from 'fs';\nimport { getConfigPath } from '../utils/paths';\nimport type { BlimuInternalEnvironment } from './client-ids';\n\n/**\n * RC config file structure\n */\nexport interface RcConfig {\n blimuInternalEnvironment?: BlimuInternalEnvironment;\n runtimeApiBaseUrl?: string;\n platformApiBaseUrl?: string;\n}\n\n/**\n * Load RC config from file\n * Checks both ~/.config/blimu/config.json (XDG, preferred) and ~/.blimurc.json (legacy)\n * @returns Config object or null if file doesn't exist\n */\nexport function loadRcConfig(): RcConfig | null {\n const configPath = getConfigPath();\n if (!configPath) {\n return null;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const config = JSON.parse(content) as RcConfig;\n return config;\n } catch {\n // If file exists but can't be read/parsed, return null (will use defaults)\n return null;\n }\n}\n\n/**\n * Get environment from config with priority:\n * 1. CLI flag (passed as parameter)\n * 2. RC file\n * 3. Default\n */\nexport function getEnvironment(\n cliFlag?: BlimuInternalEnvironment,\n rcConfig?: RcConfig | null\n): BlimuInternalEnvironment {\n if (cliFlag) {\n return cliFlag;\n }\n if (rcConfig?.blimuInternalEnvironment) {\n return rcConfig.blimuInternalEnvironment;\n }\n // Import here to avoid circular dependency\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const clientIdsModule = require('./client-ids') as {\n DEFAULT_ENVIRONMENT: BlimuInternalEnvironment;\n };\n\n return clientIdsModule.DEFAULT_ENVIRONMENT;\n}\n\n/**\n * Environment-based Runtime API URL mapping\n */\nconst RUNTIME_API_URLS: Record<BlimuInternalEnvironment, string> = {\n 'local-dev': 'https://runtime-api.dev-blimu.dev',\n 'local-prod': 'https://runtime-api.dev-blimu.dev',\n 'cloud-dev': 'https://api.blimu.dev',\n 'cloud-prod': 'https://api.blimu.dev',\n};\n\n/**\n * Environment-based Platform API URL mapping\n */\nconst PLATFORM_API_URLS: Record<BlimuInternalEnvironment, string> = {\n 'local-dev': 'https://platform-api.dev-blimu.dev',\n 'local-prod': 'https://platform.blimu.dev',\n 'cloud-dev': 'https://platform.blimu.dev',\n 'cloud-prod': 'https://platform.blimu.dev',\n};\n\n/**\n * Get Runtime API base URL with priority:\n * 1. CLI flag (passed as parameter)\n * 2. RC file\n * 3. Environment-based default\n * 4. Fallback default\n */\nexport function getRuntimeApiBaseUrl(\n cliFlag?: string,\n rcConfig?: RcConfig | null,\n environment?: BlimuInternalEnvironment\n): string {\n if (cliFlag) {\n return cliFlag;\n }\n if (rcConfig?.runtimeApiBaseUrl) {\n return rcConfig.runtimeApiBaseUrl;\n }\n if (environment && RUNTIME_API_URLS[environment]) {\n return RUNTIME_API_URLS[environment];\n }\n return 'https://runtime.blimu.dev';\n}\n\n/**\n * Get Platform API base URL with priority:\n * 1. CLI flag (passed as parameter)\n * 2. RC file\n * 3. Environment-based default\n * 4. Fallback default\n */\nexport function getPlatformApiBaseUrl(\n cliFlag?: string,\n rcConfig?: RcConfig | null,\n environment?: BlimuInternalEnvironment\n): string {\n if (cliFlag) {\n return cliFlag;\n }\n if (rcConfig?.platformApiBaseUrl) {\n return rcConfig.platformApiBaseUrl;\n }\n if (environment && PLATFORM_API_URLS[environment]) {\n return PLATFORM_API_URLS[environment];\n }\n return 'https://platform.blimu.dev';\n}\n","import { homedir } from 'os';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\n\n/**\n * XDG Base Directory - industry standard for CLI tools\n * ~/.config/blimu/\n */\nconst CONFIG_DIR = join(homedir(), '.config', 'blimu');\n\n/**\n * Standard paths for Blimu CLI (following XDG Base Directory specification)\n */\nexport const paths = {\n /**\n * Config directory\n * ~/.config/blimu/\n */\n configDir: CONFIG_DIR,\n\n /**\n * Credentials file path\n * ~/.config/blimu/credentials.json\n */\n credentials: join(CONFIG_DIR, 'credentials.json'),\n\n /**\n * User preferences file path (per-user workspace defaults, etc.)\n * ~/.config/blimu/preferences.json\n */\n preferences: join(CONFIG_DIR, 'preferences.json'),\n\n /**\n * Config file paths (in priority order)\n * 1. ~/.config/blimu/config.json (XDG Base Directory spec - preferred)\n * 2. ~/.blimurc.json (legacy, for backward compatibility)\n */\n config: {\n primary: join(CONFIG_DIR, 'config.json'),\n legacy: join(homedir(), '.blimurc.json'),\n },\n} as const;\n\n/**\n * Get the config file path (checks both locations, prioritizing XDG)\n */\nexport function getConfigPath(): string | null {\n // Check XDG location first (preferred)\n if (existsSync(paths.config.primary)) {\n return paths.config.primary;\n }\n // Check legacy location for backward compatibility\n if (existsSync(paths.config.legacy)) {\n return paths.config.legacy;\n }\n return null;\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, unlinkSync } from 'fs';\nimport { dirname } from 'path';\nimport { paths } from '../utils/paths';\nimport type { BlimuInternalEnvironment } from '../config/client-ids';\n\n/**\n * Credentials file structure (when keychain available)\n */\nexport interface Credentials {\n access_token: string;\n token_type: 'Bearer';\n expires_at: number; // Unix timestamp\n environment?: BlimuInternalEnvironment;\n}\n\n/**\n * Credentials file structure (when keychain unavailable - fallback)\n */\nexport interface CredentialsWithRefreshToken extends Credentials {\n refresh_token: string;\n _keychain_unavailable?: boolean;\n}\n\nconst KEYCHAIN_SERVICE = 'blimu-cli';\n\n// Lazy-load keyring module to avoid loading native module at module load time\nlet keyringModule: typeof import('@napi-rs/keyring') | null = null;\nlet keyringLoadPromise: Promise<typeof import('@napi-rs/keyring')> | null = null;\n\n/**\n * Get the keyring Entry class, loading it dynamically if needed\n */\nasync function getKeyringEntry(): Promise<(typeof import('@napi-rs/keyring'))['Entry']> {\n if (keyringModule) {\n return keyringModule.Entry;\n }\n\n keyringLoadPromise ??= import('@napi-rs/keyring');\n\n keyringModule = await keyringLoadPromise;\n return keyringModule.Entry;\n}\n\n/**\n * Check if keychain is available\n */\nexport async function isKeychainAvailable(): Promise<boolean> {\n try {\n const Entry = await getKeyringEntry();\n const entry = new Entry(KEYCHAIN_SERVICE, 'test-availability');\n entry.setPassword('test');\n entry.deletePassword();\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get refresh token from keychain or credentials file\n */\nexport async function getRefreshToken(\n environment: BlimuInternalEnvironment\n): Promise<string | null> {\n const account = `refresh-token-${environment}`;\n\n // Try keychain first\n try {\n const Entry = await getKeyringEntry();\n const entry = new Entry(KEYCHAIN_SERVICE, account);\n const token = entry.getPassword();\n if (token) {\n return token;\n }\n } catch {\n // Keychain unavailable or token not found, try fallback\n }\n\n // Fallback to credentials file\n if (existsSync(paths.credentials)) {\n try {\n const content = readFileSync(paths.credentials, 'utf-8');\n const creds = JSON.parse(content) as CredentialsWithRefreshToken;\n if (creds._keychain_unavailable && creds.refresh_token) {\n return creds.refresh_token;\n }\n } catch {\n // Ignore errors\n }\n }\n\n return null;\n}\n\n/**\n * Set refresh token in keychain or credentials file (with fallback)\n */\nexport async function setRefreshToken(\n environment: BlimuInternalEnvironment,\n token: string\n): Promise<{ usedKeychain: boolean }> {\n const account = `refresh-token-${environment}`;\n\n // Try keychain first\n try {\n const Entry = await getKeyringEntry();\n const entry = new Entry(KEYCHAIN_SERVICE, account);\n entry.setPassword(token);\n return { usedKeychain: true };\n } catch {\n // Keychain unavailable, use fallback\n }\n\n // Fallback to credentials file\n const creds = readCredentials();\n const updatedCreds: CredentialsWithRefreshToken = {\n ...creds,\n refresh_token: token,\n _keychain_unavailable: true,\n environment,\n };\n writeCredentials(updatedCreds);\n\n return { usedKeychain: false };\n}\n\n/**\n * Delete refresh token from keychain and credentials file\n */\nexport async function deleteRefreshToken(environment: BlimuInternalEnvironment): Promise<void> {\n const account = `refresh-token-${environment}`;\n\n // Try to delete from keychain\n try {\n const Entry = await getKeyringEntry();\n const entry = new Entry(KEYCHAIN_SERVICE, account);\n entry.deletePassword();\n } catch {\n // Ignore errors (keychain might not be available or token might not exist)\n }\n\n // Also remove from credentials file if it exists there\n if (existsSync(paths.credentials)) {\n try {\n const content = readFileSync(paths.credentials, 'utf-8');\n const creds = JSON.parse(content) as CredentialsWithRefreshToken;\n if (creds._keychain_unavailable) {\n // Create new object without refresh_token and _keychain_unavailable\n const {\n refresh_token: _refreshToken,\n _keychain_unavailable: _unavailable,\n ...cleanCreds\n } = creds;\n writeCredentials(cleanCreds);\n }\n } catch {\n // Ignore errors\n }\n }\n}\n\n/**\n * Get code verifier from keychain or credentials file\n */\nexport async function getCodeVerifier(\n environment: BlimuInternalEnvironment\n): Promise<string | null> {\n const account = `code-verifier-${environment}`;\n\n // Try keychain first\n try {\n const Entry = await getKeyringEntry();\n const entry = new Entry(KEYCHAIN_SERVICE, account);\n const verifier = entry.getPassword();\n if (verifier) {\n return verifier;\n }\n } catch {\n // Keychain unavailable, try fallback\n }\n\n // Fallback not implemented for code verifier (less critical)\n return null;\n}\n\n/**\n * Set code verifier in keychain\n */\nexport async function setCodeVerifier(\n environment: BlimuInternalEnvironment,\n verifier: string\n): Promise<{ usedKeychain: boolean }> {\n const account = `code-verifier-${environment}`;\n\n // Try keychain first\n try {\n const Entry = await getKeyringEntry();\n const entry = new Entry(KEYCHAIN_SERVICE, account);\n entry.setPassword(verifier);\n return { usedKeychain: true };\n } catch {\n // Keychain unavailable, skip (code verifier is less critical)\n return { usedKeychain: false };\n }\n}\n\n/**\n * Read credentials from file\n */\nexport function readCredentials(): Credentials {\n if (!existsSync(paths.credentials)) {\n throw new Error('No credentials found. Please run `blimu login` first.');\n }\n\n try {\n const content = readFileSync(paths.credentials, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n throw new Error(\n `Failed to read credentials: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Write credentials to file with proper permissions\n */\nexport function writeCredentials(creds: Credentials | CredentialsWithRefreshToken): void {\n // Ensure directory exists\n const dir = dirname(paths.credentials);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n // Write file\n writeFileSync(paths.credentials, JSON.stringify(creds, null, 2), 'utf-8');\n\n // Set permissions to 600 (owner read/write only)\n chmodSync(paths.credentials, 0o600);\n}\n\n/**\n * Delete credentials file\n */\nexport function deleteCredentials(): void {\n if (existsSync(paths.credentials)) {\n unlinkSync(paths.credentials);\n }\n}\n\n/**\n * Check if credentials exist\n */\nexport function hasCredentials(): boolean {\n return existsSync(paths.credentials);\n}\n","import { readCredentials, writeCredentials, getRefreshToken, setRefreshToken } from './credentials';\nimport type { BlimuInternalEnvironment } from '../config/client-ids';\n\n/**\n * Token response from refresh endpoint\n */\nexport interface RefreshTokenResponse {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n scope?: string;\n}\n\n/**\n * Refresh access token using refresh token\n */\nexport async function refreshAccessToken(\n runtimeApiBaseUrl: string,\n clientId: string,\n environment: BlimuInternalEnvironment\n): Promise<{ access_token: string; expires_at: number; refresh_token: string }> {\n // Get refresh token from keychain or credentials file\n const refreshToken = await getRefreshToken(environment);\n if (!refreshToken) {\n throw new Error('No refresh token found. Please run `blimu login` again.');\n }\n\n // Request new tokens\n const response = await fetch(`${runtimeApiBaseUrl}/v1/oauth/token`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n client_id: clientId,\n refresh_token: refreshToken,\n }),\n });\n\n if (!response.ok) {\n const error = (await response.json().catch(() => ({}))) as {\n error_description?: string;\n error?: string;\n };\n throw new Error(\n error.error_description ?? error.error ?? `HTTP ${response.status}: ${response.statusText}`\n );\n }\n\n const tokenResponse = (await response.json()) as RefreshTokenResponse;\n\n // Calculate expiry timestamp\n const expiresAt = Math.floor(Date.now() / 1000) + tokenResponse.expires_in;\n\n // Update credentials file\n const creds = readCredentials();\n writeCredentials({\n ...creds,\n access_token: tokenResponse.access_token,\n expires_at: expiresAt,\n environment,\n });\n\n // Update refresh token (handle rotation)\n if (tokenResponse.refresh_token !== refreshToken) {\n // Token was rotated, update stored refresh token\n await setRefreshToken(environment, tokenResponse.refresh_token);\n }\n\n return {\n access_token: tokenResponse.access_token,\n expires_at: expiresAt,\n refresh_token: tokenResponse.refresh_token,\n };\n}\n\n/**\n * Check if access token is expired or about to expire\n * @param bufferSeconds - Number of seconds before expiry to consider token expired (default: 60)\n */\nexport function isTokenExpired(bufferSeconds = 60): boolean {\n try {\n const creds = readCredentials();\n const now = Math.floor(Date.now() / 1000);\n return creds.expires_at - now < bufferSeconds;\n } catch {\n return true; // If we can't read credentials, consider expired\n }\n}\n\n/**\n * Get valid access token, refreshing if necessary\n */\nexport async function getValidAccessToken(\n runtimeApiBaseUrl: string,\n clientId: string,\n environment: BlimuInternalEnvironment\n): Promise<string> {\n // Check if token is expired\n if (isTokenExpired()) {\n // Refresh token\n const refreshed = await refreshAccessToken(runtimeApiBaseUrl, clientId, environment);\n return refreshed.access_token;\n }\n\n // Token is still valid, return it\n const creds = readCredentials();\n return creds.access_token;\n}\n","import { BlimuCli } from '../api-sdk/client';\nimport { loadRcConfig, getPlatformApiBaseUrl } from '../config/rc-config';\nimport { hasCredentials, readCredentials } from '../auth/credentials';\nimport { getValidAccessToken } from '../auth/token-refresh';\nimport { getClientId, type BlimuInternalEnvironment } from '../config/client-ids';\nimport { getRuntimeApiBaseUrl } from '../config/rc-config';\n\nexport interface CreatePlatformClientOptions {\n apiKey?: string;\n bearer?: string;\n platformApiUrl?: string;\n requireAuth?: boolean;\n}\n\n/**\n * Create an authenticated Platform API client\n *\n * Handles authentication automatically:\n * - Uses explicit apiKey or bearer token if provided\n * - If requireAuth is false, creates client without auth\n * - Otherwise, checks for credentials and auto-refreshes OAuth token\n *\n * @param options - Client configuration options\n * @returns Configured BlimuCli instance\n * @throws Error if authentication is required but not available\n */\nexport async function createPlatformApiClient(\n options: CreatePlatformClientOptions = {}\n): Promise<BlimuCli> {\n const { apiKey, bearer, platformApiUrl, requireAuth = true } = options;\n\n // Load RC config\n const rcConfig = loadRcConfig();\n\n // Get environment for URL resolution\n let environment: BlimuInternalEnvironment | undefined;\n if (hasCredentials()) {\n try {\n const creds = readCredentials();\n environment = creds.environment ?? rcConfig?.blimuInternalEnvironment;\n } catch {\n // If credentials can't be read, use RC config\n environment = rcConfig?.blimuInternalEnvironment;\n }\n } else {\n environment = rcConfig?.blimuInternalEnvironment;\n }\n\n // Resolve Platform API base URL (CLI flag → RC config → environment-based default → fallback)\n const baseURL =\n platformApiUrl ??\n getPlatformApiBaseUrl(undefined, rcConfig, environment) ??\n 'https://platform.blimu.dev';\n\n // Handle authentication\n const finalApiKey: string | undefined = apiKey;\n let finalBearer: string | undefined = bearer;\n\n // If explicit auth provided, use it\n if (finalApiKey || finalBearer) {\n return new BlimuCli({\n baseURL,\n ...(finalApiKey ? { apiKey: finalApiKey } : {}),\n ...(finalBearer ? { bearer: finalBearer } : {}),\n });\n }\n\n // If auth not required, create client without auth\n if (!requireAuth) {\n return new BlimuCli({\n baseURL,\n });\n }\n\n // Auth is required but not provided - check for credentials\n if (!hasCredentials()) {\n throw new Error(\n 'Authentication required. Please run `blimu login` first or provide --api-key <key> or --bearer <token>'\n );\n }\n\n // Auto-load and refresh OAuth token\n try {\n const creds = readCredentials();\n const environment = creds.environment ?? rcConfig?.blimuInternalEnvironment ?? 'cloud-prod';\n const runtimeApiBaseUrl = getRuntimeApiBaseUrl(undefined, rcConfig, environment);\n const clientId = getClientId(environment);\n\n finalBearer = await getValidAccessToken(runtimeApiBaseUrl, clientId, environment);\n } catch (error) {\n throw new Error(\n `Failed to authenticate: ${error instanceof Error ? error.message : String(error)}\\n` +\n 'Please run `blimu login` again.'\n );\n }\n\n // Create client with refreshed token\n return new BlimuCli({\n baseURL,\n bearer: finalBearer,\n });\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'fs';\nimport { dirname } from 'path';\nimport { paths } from '../utils/paths';\nimport { readCredentials, hasCredentials } from './credentials';\n\n/**\n * User preferences structure - stored per user\n */\ninterface UserPreferences {\n default_workspace_id?: string;\n}\n\n/**\n * Preferences file structure - keyed by user ID\n */\ntype PreferencesFile = Record<string, UserPreferences>;\n\n/**\n * Decode JWT token to extract user ID (sub claim)\n */\nfunction decodeJwtUserId(token: string): string | null {\n try {\n // JWT format: header.payload.signature\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n // Decode base64url payload\n const payload = parts[1];\n if (!payload) {\n return null;\n }\n const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');\n const jsonPayload = Buffer.from(base64, 'base64').toString('utf-8');\n const claims = JSON.parse(jsonPayload) as Record<string, unknown>;\n\n // Return sub (subject) claim which contains user ID\n return typeof claims['sub'] === 'string' ? claims['sub'] : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get current user ID from access token\n */\nfunction getCurrentUserId(): string | null {\n if (!hasCredentials()) {\n return null;\n }\n\n try {\n const creds = readCredentials();\n return decodeJwtUserId(creds.access_token);\n } catch {\n return null;\n }\n}\n\n/**\n * Read preferences file\n */\nfunction readPreferencesFile(): PreferencesFile {\n if (!existsSync(paths.preferences)) {\n return {};\n }\n\n try {\n const content = readFileSync(paths.preferences, 'utf-8');\n return JSON.parse(content) as PreferencesFile;\n } catch {\n return {};\n }\n}\n\n/**\n * Write preferences file\n */\nfunction writePreferencesFile(prefs: PreferencesFile): void {\n // Ensure directory exists\n const dir = dirname(paths.preferences);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n\n // Write file\n writeFileSync(paths.preferences, JSON.stringify(prefs, null, 2), 'utf-8');\n\n // Set permissions to 600 (owner read/write only)\n chmodSync(paths.preferences, 0o600);\n}\n\n/**\n * Get default workspace ID for the current user\n */\nexport function getDefaultWorkspaceId(): string | null {\n const userId = getCurrentUserId();\n if (!userId) {\n return null;\n }\n\n const prefs = readPreferencesFile();\n return prefs[userId]?.default_workspace_id ?? null;\n}\n\n/**\n * Set default workspace ID for the current user\n */\nexport function setDefaultWorkspaceId(workspaceId: string): void {\n const userId = getCurrentUserId();\n if (!userId) {\n throw new Error('Cannot set workspace preference: No authenticated user found');\n }\n\n const prefs = readPreferencesFile();\n prefs[userId] = {\n ...prefs[userId],\n default_workspace_id: workspaceId,\n };\n writePreferencesFile(prefs);\n}\n","/**\n * Utilities for detecting interactive terminal environments\n */\n\n/**\n * Check if running in a CI environment\n */\nexport function isCI(): boolean {\n return process.env['CI'] === 'true' || process.env['CI'] === '1';\n}\n\n/**\n * Check if running in an interactive terminal (TTY)\n */\nexport function isInteractive(): boolean {\n // Not interactive if in CI\n if (isCI()) {\n return false;\n }\n\n // Not interactive if stdout is not a TTY\n if (!process.stdout.isTTY) {\n return false;\n }\n\n // Check TERM variable\n const term = process.env['TERM'];\n if (!term || term === 'dumb') {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if we should prompt for user input\n * (only in interactive, non-CI environments)\n */\nexport function shouldPrompt(): boolean {\n return isInteractive();\n}\n","/**\n * Interactive prompts for CLI\n */\n\nimport { select } from '@inquirer/prompts';\n\nexport interface SelectOption {\n label: string;\n value: string;\n description?: string;\n}\n\n/**\n * Prompt user to select from a list of options\n * Returns the selected value or null if cancelled\n */\nexport async function promptSelect(options: {\n title: string;\n choices: SelectOption[];\n}): Promise<string | null> {\n try {\n const answer = await select({\n message: options.title,\n choices: options.choices.map((choice) => {\n const base = { name: choice.label, value: choice.value };\n return choice.description != null ? { ...base, description: choice.description } : base;\n }),\n });\n return answer;\n } catch {\n // User cancelled (Ctrl+C)\n return null;\n }\n}\n","import type { Command } from 'commander';\nimport type { BlimuConfig } from '../config/schema';\nimport { BlimuConfigSchema } from '../config/schema';\nimport { log } from '../utils/logger';\nimport { findDefaultConfig, loadConfig } from '../utils/config-loader';\nimport { createPlatformApiClient } from '../utils/api-client';\nimport { createTaskRunner } from '../ui/task-runner.js';\nimport { getDefaultWorkspaceId } from '../auth/preferences';\nimport { shouldPrompt } from '../utils/interactive';\nimport { promptSelect, type SelectOption } from '../ui/prompts.js';\nimport type { BlimuCli } from '../api-sdk';\n\ninterface PushCommandOptions {\n config?: string;\n workspaceId?: string;\n environmentId?: string;\n platformApiUrl?: string;\n apiKey?: string;\n bearer?: string;\n}\n\n/**\n * Register the push command\n */\nexport function pushCommand(program: Command): void {\n program\n .command('push')\n .description('Push definitions to Blimu API')\n .option(\n '--config <path>',\n 'Path to Blimu config file (defaults to blimu.config.ts in project root)'\n )\n .option('--workspace-id <id>', 'Workspace ID (prompts if not specified)')\n .option('--environment-id <id>', 'Environment ID (prompts if not specified)')\n .option('--platform-api-url <url>', 'Override Platform API base URL')\n .action(async (options: PushCommandOptions) => {\n try {\n // Step 1: Connect to API\n const connectRunner = await createTaskRunner();\n const connectGroup = connectRunner.group('Connecting to Blimu');\n\n let client: BlimuCli | undefined;\n await connectGroup.task('Authenticate', async (task) => {\n client = await createPlatformApiClient({\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n ...(options.bearer ? { bearer: options.bearer } : {}),\n ...(options.platformApiUrl ? { platformApiUrl: options.platformApiUrl } : {}),\n requireAuth: true,\n });\n task.succeed('Connected');\n });\n\n if (!client) {\n connectGroup.error('Failed to connect to Blimu API');\n await connectRunner.wait();\n process.exit(1);\n }\n\n connectGroup.success('Ready');\n await connectRunner.wait();\n\n // Step 2: Get or prompt for workspace ID\n let workspaceId = options.workspaceId ?? getDefaultWorkspaceId();\n\n if (!workspaceId) {\n if (shouldPrompt()) {\n const { data: workspaces } = await client.workspaces.list();\n\n if (workspaces.length === 0) {\n log.error('No workspaces found. Please create a workspace first.');\n process.exit(1);\n }\n\n const workspaceChoices: SelectOption[] = workspaces.map(\n (ws: { id: string; name: string }) => ({\n label: ws.name,\n value: ws.id,\n description: `ID: ${ws.id}`,\n })\n );\n\n const selected = await promptSelect({\n title: 'Select a workspace:',\n choices: workspaceChoices,\n });\n\n if (!selected) {\n log.error('Workspace selection cancelled');\n process.exit(1);\n }\n\n workspaceId = selected;\n } else {\n log.error(\n 'No workspace specified. Use --workspace-id <id> or run `blimu login` to set a default workspace.'\n );\n process.exit(1);\n }\n }\n\n // Step 3: Get or prompt for environment ID\n let environmentId = options.environmentId;\n\n if (!environmentId) {\n if (shouldPrompt()) {\n const { data: environments } = await client.environments.list(workspaceId);\n\n if (environments.length === 0) {\n log.error(\n 'No environments found in this workspace. Please create an environment first.'\n );\n process.exit(1);\n }\n\n const envChoices: SelectOption[] = environments.map(\n (env: { id: string; name: string; variant: string }) => ({\n label: `${env.name} (${env.variant})`,\n value: env.id,\n description: `ID: ${env.id}`,\n })\n );\n\n const selected = await promptSelect({\n title: 'Select an environment:',\n choices: envChoices,\n });\n\n if (!selected) {\n log.error('Environment selection cancelled');\n process.exit(1);\n }\n\n environmentId = selected;\n } else {\n log.error('No environment specified. Use --environment-id <id>');\n process.exit(1);\n }\n }\n\n // Step 4: Find and load config file\n const configPath = options.config ?? findDefaultConfig();\n if (!configPath) {\n log.error(\n 'No config file found. Please provide --config or ensure blimu.config.ts exists in project root.'\n );\n process.exit(1);\n }\n\n // Step 5: Push definitions (new runner for the actual push)\n const pushRunner = await createTaskRunner();\n const pushGroup = pushRunner.group('Pushing definitions');\n\n pushGroup.info(`Config: ${configPath}`);\n pushGroup.info(`Workspace: ${workspaceId}`);\n pushGroup.info(`Environment: ${environmentId}`);\n\n let config: BlimuConfig | undefined;\n\n await pushGroup.task('Load and validate config', async (task) => {\n task.update('Loading config file...');\n const rawConfig = await loadConfig(configPath);\n\n task.update('Validating schema...');\n const validationResult = BlimuConfigSchema.safeParse(rawConfig);\n if (!validationResult.success) {\n task.fail('Config validation failed');\n pushGroup.error('Config validation errors:');\n validationResult.error.issues.forEach((err) => {\n pushGroup.error(` - ${err.path.join('.')}: ${err.message}`);\n });\n await pushRunner.wait();\n process.exit(1);\n }\n config = validationResult.data;\n task.succeed('Config validated');\n });\n\n await pushGroup.task('Push to environment', async (task) => {\n if (!client) throw new Error('Client is not connected');\n if (!config) throw new Error('Config is not loaded');\n\n await client.definitions.update(workspaceId, environmentId, {\n resources: config.resources,\n ...(config.entitlements ? { entitlements: config.entitlements } : {}),\n ...(config.features ? { features: config.features } : {}),\n ...(config.plans ? { plans: config.plans } : {}),\n });\n task.succeed('Pushed successfully');\n });\n\n pushGroup.success('Definitions updated');\n\n await pushRunner.wait();\n } catch (error) {\n log.error(\n `Failed to push definitions: ${error instanceof Error ? error.message : String(error)}`\n );\n if (error instanceof Error && error.stack) {\n console.error(error.stack);\n }\n process.exit(1);\n }\n });\n}\n","import type { Command } from 'commander';\nimport open from 'open';\nimport { log } from '../utils/logger';\nimport { OAuth2Client } from '../auth/oauth-client';\nimport {\n writeCredentials,\n setRefreshToken,\n setCodeVerifier,\n isKeychainAvailable,\n} from '../auth/credentials';\nimport { setDefaultWorkspaceId } from '../auth/preferences';\nimport { getClientId, type BlimuInternalEnvironment } from '../config/client-ids';\nimport { loadRcConfig, getEnvironment, getRuntimeApiBaseUrl } from '../config/rc-config';\nimport { createTaskRunner } from '../ui/task-runner.js';\nimport { promptSelect, type SelectOption } from '../ui/prompts.js';\nimport { createPlatformApiClient } from '../utils/api-client';\n\ninterface LoginCommandOptions {\n execEnv: BlimuInternalEnvironment;\n runtimeApiUrl: string;\n verbose: boolean;\n}\n\n/**\n * Register the login command\n */\nexport function loginCommand(program: Command): void {\n program\n .command('login')\n .description('Authenticate with Blimu using OAuth2 device flow')\n .option(\n '--exec-env <env>',\n 'Blimu internal environment (local-dev, local-prod, cloud-dev, cloud-prod)'\n )\n .option('--runtime-api-url <url>', 'Override Runtime API base URL')\n .option('--verbose', 'Show detailed output', false)\n .action(async (options: LoginCommandOptions) => {\n const verbose = options.verbose;\n\n try {\n const runner = await createTaskRunner();\n\n // Load RC config\n const rcConfig = loadRcConfig();\n\n // Get environment\n const environment = getEnvironment(\n options.execEnv as BlimuInternalEnvironment | undefined,\n rcConfig\n );\n\n // Get Runtime API base URL\n const runtimeApiBaseUrl = getRuntimeApiBaseUrl(\n options.runtimeApiUrl,\n rcConfig,\n environment\n );\n\n if (verbose) {\n runner.info(`Runtime API: ${runtimeApiBaseUrl}`);\n }\n\n // Get client ID\n const clientId = getClientId(environment);\n\n // Format environment name for display\n const envDisplay =\n environment === 'cloud-prod' ? 'Blimu platform' : `${environment} environment`;\n\n const authGroup = runner.group(`Authenticating to ${envDisplay}`);\n\n // Check keychain availability\n const keychainAvailable = await isKeychainAvailable();\n if (!keychainAvailable) {\n authGroup.warn(\n 'System keychain not available. Refresh token will be stored in plaintext at ~/.config/blimu/credentials.json'\n );\n }\n\n // Create OAuth2 client\n const oauthClient = new OAuth2Client(runtimeApiBaseUrl, clientId, environment);\n\n // Request device code\n const { deviceCodeResponse, codeVerifier } = await oauthClient.requestDeviceCode();\n\n // Display user instructions (clearable - will be removed on success)\n authGroup.info(\"Browser didn't open? Use the url below to sign in (c to copy)\", {\n clearable: true,\n });\n authGroup.copyableText(deviceCodeResponse.verification_uri_complete, {\n clearable: true,\n dimmed: true,\n });\n\n // Open the URL in the default browser\n try {\n await open(deviceCodeResponse.verification_uri_complete);\n } catch {\n // Ignore errors (e.g. headless/CI); user can still copy the URL above\n }\n\n // Store code verifier (for PKCE)\n await setCodeVerifier(environment, codeVerifier);\n\n // Poll for tokens\n const tokenResponse = await oauthClient.pollForTokens(\n deviceCodeResponse.device_code,\n codeVerifier,\n deviceCodeResponse.interval\n );\n\n // Calculate expiry timestamp\n const expiresAt = Math.floor(Date.now() / 1000) + tokenResponse.expires_in;\n\n // Store credentials\n writeCredentials({\n access_token: tokenResponse.access_token,\n token_type: tokenResponse.token_type as 'Bearer',\n expires_at: expiresAt,\n environment,\n });\n\n // Store refresh token (keychain preferred, fallback to file)\n const { usedKeychain } = await setRefreshToken(environment, tokenResponse.refresh_token);\n\n // Success message (this will clear all clearable items first)\n authGroup.success('Login successful');\n\n if (verbose) {\n if (usedKeychain) {\n runner.info('Refresh token stored in system keychain');\n } else {\n runner.info('Refresh token stored in credentials file');\n }\n }\n\n // Close the Ink UI by waiting for it to finish\n // We need to do this WITHOUT calling wait() as it seems to break HTTP requests\n // Get the render instance and manually cleanup\n const inkRunner = runner as {\n renderInstance?: { cleanup(): void };\n isRendering?: boolean;\n };\n if (inkRunner.renderInstance) {\n inkRunner.renderInstance.cleanup();\n inkRunner.isRendering = false;\n }\n\n // Small delay to let Ink fully cleanup\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n // Fetch workspaces and prompt for default selection if multiple exist\n await promptForDefaultWorkspace();\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n log.error(`Authentication failed: ${formatUserFriendlyError(errorMessage)}`);\n\n if (verbose && error instanceof Error && error.stack) {\n log.info(error.stack);\n }\n\n process.exit(1);\n }\n });\n}\n\n/**\n * Prompt user to select a default workspace if they have multiple workspaces\n */\nasync function promptForDefaultWorkspace(): Promise<void> {\n try {\n log.info('Fetching workspaces...');\n\n // Create API client using stored credentials\n const client = await createPlatformApiClient({\n requireAuth: true,\n });\n\n // Fetch workspaces\n const { data: workspaces } = await client.workspaces.list();\n\n log.info(`Found ${workspaces.length} workspace(s)`);\n\n // If only one workspace, set it as default automatically\n if (workspaces.length === 1) {\n const workspace = workspaces[0];\n if (workspace) {\n setDefaultWorkspaceId(workspace.id);\n log.info(`Default workspace set to: ${workspace.name}`);\n }\n return;\n }\n\n // If no workspaces, skip\n if (workspaces.length === 0) {\n return;\n }\n\n // Multiple workspaces - prompt for selection\n const options: SelectOption[] = workspaces.map((ws) => ({\n label: ws.name,\n value: ws.id,\n description: `ID: ${ws.id}`,\n }));\n\n const selected = await promptSelect({\n title: 'Select a default workspace:',\n choices: options,\n });\n\n if (selected) {\n setDefaultWorkspaceId(selected);\n const selectedWorkspace = workspaces.find((ws) => ws.id === selected);\n log.success(`Default workspace set to: ${selectedWorkspace?.name}`);\n }\n } catch (error) {\n // Silently fail workspace selection - not critical for login\n log.warn('Could not fetch workspaces for default selection');\n if (error instanceof Error) {\n log.info(`Reason: ${error.message}`);\n // Log full error details for debugging\n const err = error as Error & { status?: number; data?: unknown };\n console.error('Full error details:', error);\n if (err.status !== undefined) {\n console.error('HTTP Status:', err.status);\n }\n if (err.data !== undefined) {\n console.error('Response data:', err.data);\n }\n }\n }\n}\n\n/**\n * Format error messages to be user-friendly (remove technical details like HTTP codes)\n */\nfunction formatUserFriendlyError(message: string): string {\n // Remove HTTP status code prefixes like \"HTTP 502:\" or \"HTTP 400:\"\n const cleanedMessage = message.replace(/^HTTP \\d+:\\s*/i, '');\n\n // Map common technical errors to user-friendly messages\n const errorMappings: Record<string, string> = {\n 'Invalid request': 'The authorization request was invalid. Please try again.',\n 'User denied authorization': 'Authorization was denied.',\n 'Device code has expired': 'The login session has expired. Please try again.',\n 'Polling timeout exceeded': 'Login timed out. Please try again.',\n 'Maximum polling attempts exceeded': 'Login timed out. Please try again.',\n };\n\n return errorMappings[cleanedMessage] ?? cleanedMessage;\n}\n","import { Blimu, type Schema, FetchError, BadRequestError } from '@blimu/backend';\nimport { generateCodeVerifier, generateCodeChallenge } from '../utils/pkce';\nimport { poll } from '../utils/polling';\nimport type { RequestInfo } from 'undici';\nimport { Agent, fetch as undiciFetch } from 'undici';\nimport type { BlimuInternalEnvironment } from '../config/client-ids';\n\n/**\n * Create a custom fetch function that accepts self-signed certificates\n * This is needed for local development with self-signed SSL certificates\n */\nfunction createLocalDevFetch(): typeof fetch {\n // Create an undici Agent that accepts self-signed certificates\n // undici is built into Node.js 18+, so no need to install it\n const agent = new Agent({\n connect: {\n rejectUnauthorized: false, // Accept self-signed certificates for local dev\n },\n });\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n // Use undici's fetch with the custom agent\n return undiciFetch(input, {\n ...init,\n dispatcher: agent,\n }) as Promise<Response>;\n };\n}\n\n/**\n * OAuth2 client for device code flow\n */\nexport class OAuth2Client {\n private readonly client: Blimu;\n\n constructor(\n private readonly runtimeApiBaseUrl: string,\n private readonly clientId: string,\n private readonly environment?: BlimuInternalEnvironment\n ) {\n // For local-dev environment, use custom fetch that accepts self-signed certificates\n const fetchFn =\n this.environment === 'local-dev' || this.environment === 'local-prod'\n ? createLocalDevFetch()\n : undefined;\n\n this.client = new Blimu({\n baseURL: runtimeApiBaseUrl,\n ...(fetchFn ? { fetch: fetchFn } : {}),\n });\n }\n\n /**\n * Request device code with PKCE\n */\n async requestDeviceCode(): Promise<{\n deviceCodeResponse: Schema.DeviceCodeResponse;\n codeVerifier: string;\n codeChallenge: string;\n }> {\n // Generate PKCE verifier and challenge\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n\n // Request device code using backend SDK\n try {\n const deviceCodeResponse = await this.client.oauth.requestDeviceCode({\n client_id: this.clientId,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n return {\n deviceCodeResponse,\n codeVerifier,\n codeChallenge,\n };\n } catch (error: unknown) {\n // Handle FetchError from SDK\n if (error instanceof FetchError) {\n const errorBody =\n (error.data as {\n error_description?: string;\n error?: string;\n }) || {};\n\n // For HTTP 0 errors (network failures), provide more context\n if (error.status === 0) {\n const underlyingError = error.message || 'Unknown network error';\n throw new Error(\n `Failed to connect to ${this.runtimeApiBaseUrl}. ${underlyingError}\\n` +\n `This usually means:\\n` +\n ` - The server is not running or not reachable\\n` +\n ` - DNS resolution failed\\n` +\n ` - SSL/TLS certificate issues\\n` +\n ` - Network connectivity problems\\n\\n` +\n `Please verify that the Runtime API is accessible at: ${this.runtimeApiBaseUrl}`\n );\n }\n\n throw new Error(\n errorBody.error_description ?? errorBody.error ?? error.message ?? 'Request failed'\n );\n }\n throw error;\n }\n }\n\n /**\n * Poll for tokens using device code\n */\n async pollForTokens(\n deviceCode: string,\n codeVerifier: string,\n interval: number\n ): Promise<Schema.TokenResponse> {\n return poll<Schema.TokenResponse>(\n async () => {\n try {\n const tokenResponse = await this.client.oauth.exchangeDeviceCode({\n grant_type: 'urn:ietf:params:oauth:grant-type:device_code',\n device_code: deviceCode,\n client_id: this.clientId,\n code_verifier: codeVerifier,\n });\n return { success: true, data: tokenResponse };\n } catch (error: unknown) {\n if (error instanceof BadRequestError) {\n return {\n success: false,\n error: {\n error: error.message,\n error_description: error.message,\n },\n };\n }\n // FetchClient throws FetchError on non-2xx responses\n // Extract error details for polling logic\n if (error instanceof FetchError) {\n // For HTTP 0 errors (network failures), throw immediately\n if (error.status === 0) {\n throw new Error(\n `Network error while polling for tokens: ${error.message || 'Connection failed'}\\n` +\n `Please verify that the Runtime API is accessible at: ${this.runtimeApiBaseUrl}`\n );\n }\n\n // For other errors, create a poll error with user-friendly message\n return {\n success: false,\n error: {\n error: `http_${error.status}`,\n error_description: error.message || `HTTP ${error.status} error`,\n },\n };\n }\n\n // For non-FetchError exceptions, throw immediately (don't poll on these)\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`Unexpected error while polling for tokens: ${errorMessage}`);\n }\n },\n {\n initialInterval: interval,\n maxInterval: 60,\n maxAttempts: 120,\n timeout: 600000, // 10 minutes\n }\n );\n }\n}\n","import { createHash, randomBytes } from 'crypto';\n\n/**\n * Generate a random code verifier for PKCE\n * @returns Base64URL-encoded string (128 characters recommended)\n */\nexport function generateCodeVerifier(): string {\n // Generate 96 random bytes (128 base64url characters)\n const bytes = randomBytes(96);\n return base64UrlEncode(bytes);\n}\n\n/**\n * Generate a code challenge from a code verifier using S256 (SHA256)\n * @param verifier - The code verifier\n * @returns Base64URL-encoded SHA256 hash\n */\nexport function generateCodeChallenge(verifier: string): string {\n const hash = createHash('sha256').update(verifier).digest();\n return base64UrlEncode(hash);\n}\n\n/**\n * Validate that a code verifier produces the expected challenge\n * @param verifier - The code verifier\n * @param challenge - The expected code challenge\n * @returns True if the verifier produces the challenge\n */\nexport function validateCodeVerifier(verifier: string, challenge: string): boolean {\n const computedChallenge = generateCodeChallenge(verifier);\n return computedChallenge === challenge;\n}\n\n/**\n * Base64URL encode (RFC 4648 Section 5)\n * Converts base64 to base64url by replacing + with -, / with _, and removing padding\n */\nfunction base64UrlEncode(buffer: Buffer): string {\n return buffer.toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n","/**\n * Polling utility for device code flow\n * Handles exponential backoff and OAuth2 error responses\n */\n\nexport interface PollOptions {\n /**\n * Initial polling interval in seconds\n */\n initialInterval?: number;\n /**\n * Maximum polling interval in seconds\n */\n maxInterval?: number;\n /**\n * Maximum number of polling attempts\n */\n maxAttempts?: number;\n /**\n * Timeout in milliseconds\n */\n timeout?: number;\n}\n\nexport interface PollError {\n error: string;\n error_description?: string;\n}\n\n/**\n * Poll a function until it returns a non-error result or times out\n * Implements exponential backoff for authorization_pending and slow_down errors\n */\nexport async function poll<T>(\n fn: () => Promise<{ success: true; data: T } | { success: false; error: PollError }>,\n options: PollOptions = {}\n): Promise<T> {\n const {\n initialInterval = 5,\n maxInterval = 60,\n maxAttempts = 120, // 10 minutes at 5s intervals\n timeout = 600000, // 10 minutes\n } = options;\n\n const startTime = Date.now();\n let currentInterval = initialInterval;\n let attempts = 0;\n\n while (attempts < maxAttempts) {\n // Check timeout\n if (Date.now() - startTime > timeout) {\n throw new Error('Login timed out');\n }\n\n // Wait before polling (except first attempt)\n if (attempts > 0) {\n await sleep(currentInterval * 1000);\n }\n\n attempts++;\n\n try {\n const result = await fn();\n\n if (result.success) {\n return result.data;\n }\n\n const error = result.error;\n\n // Handle OAuth2 error responses\n if (error.error === 'authorization_pending') {\n // Continue polling with current interval\n continue;\n }\n\n if (error.error === 'slow_down') {\n // Increase interval by 5 seconds (RFC 8628)\n currentInterval = Math.min(currentInterval + 5, maxInterval);\n continue;\n }\n\n if (error.error === 'access_denied') {\n throw new Error('Authorization was denied');\n }\n\n if (error.error === 'expired_token') {\n throw new Error('Login session has expired');\n }\n\n // Other errors should be thrown with user-friendly message\n throw new Error(error.error_description ?? error.error ?? 'Authorization failed');\n } catch (error) {\n // If it's already an Error, rethrow\n if (error instanceof Error) {\n throw error;\n }\n // Otherwise, wrap it\n throw new Error(`Polling error: ${String(error)}`);\n }\n }\n\n throw new Error('Login timed out');\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { Command } from 'commander';\nimport { deleteCredentials, deleteRefreshToken, readCredentials } from '../auth/credentials';\nimport { log } from '../utils/logger';\nimport type { BlimuInternalEnvironment } from '../config/client-ids';\nimport { createTaskRunner } from '../ui/task-runner.js';\n\n/**\n * Register the logout command\n */\nexport function logoutCommand(program: Command): void {\n program\n .command('logout')\n .description('Log out and remove stored credentials')\n .action(async () => {\n try {\n const runner = await createTaskRunner();\n\n // Check if credentials exist\n let environment: BlimuInternalEnvironment | undefined;\n try {\n const creds = readCredentials();\n environment = creds.environment;\n } catch {\n // No credentials found, nothing to do\n runner.info('No credentials found. Already logged out.');\n await runner.wait();\n return;\n }\n\n const logoutGroup = runner.group('Logging out');\n\n await logoutGroup.task('Remove credentials', async (task) => {\n // Delete refresh token from keychain\n if (environment) {\n await deleteRefreshToken(environment);\n }\n\n // Delete credentials file\n deleteCredentials();\n\n task.succeed('Credentials removed');\n });\n\n runner.success('Successfully logged out!');\n await runner.wait();\n } catch (error) {\n log.error(`Failed to logout: ${error instanceof Error ? error.message : String(error)}`);\n process.exit(1);\n }\n });\n}\n","/**\n * Format an object as plain text \"key: value\", one property per line.\n * Suitable for use with log.info().\n */\nexport function toText(obj: Record<string, unknown>): string {\n return Object.entries(obj)\n .map(([key, value]) => {\n let text: string;\n if (value === null || value === undefined) {\n text = '';\n } else if (typeof value === 'object') {\n text = JSON.stringify(value);\n } else {\n text = String(value as string | number | boolean);\n }\n return `${key}: ${text}`.trimEnd();\n })\n .join('\\n');\n}\n","/**\n * Decode JWT payload (simple base64 decode, no verification)\n */\nexport function decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n const payload = parts[1];\n if (!payload) {\n return null;\n }\n const decoded = Buffer.from(payload, 'base64url').toString('utf-8');\n return JSON.parse(decoded) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n","import type { Command } from 'commander';\nimport { readCredentials } from '../auth/credentials';\nimport { toText } from '../utils/format';\nimport { decodeJwtPayload } from '../utils/jwt';\nimport chalk from 'chalk';\nimport { createTaskRunner } from '../ui/task-runner';\n\n/**\n * Format timestamp as readable date\n */\nfunction formatDate(timestamp: number): string {\n return new Date(timestamp * 1000).toLocaleString();\n}\n\n/**\n * Register the whoami command\n */\nexport function whoamiCommand(program: Command): void {\n program\n .command('whoami')\n .description('Display current authentication information')\n .action(async () => {\n const runner = await createTaskRunner();\n try {\n const creds = readCredentials();\n const payload = decodeJwtPayload(creds.access_token);\n\n const now = Math.floor(Date.now() / 1000);\n const timeUntilExpiry = creds.expires_at - now;\n\n const info: Record<string, unknown> = {\n ...(payload?.['sub'] ? { [`${chalk.cyan('@userid')}`]: payload['sub'] } : {}),\n ...(payload?.['email'] ? { [`${chalk.cyan('@email')}`]: payload['email'] } : {}),\n ...(payload?.['name'] ? { [`${chalk.cyan('@name')}`]: payload['name'] } : {}),\n [`${chalk.cyan('@environment')}`]: creds.environment ?? 'unknown',\n [`${chalk.cyan('@expires')}`]: formatDate(creds.expires_at),\n ...(timeUntilExpiry > 0\n ? { [`${chalk.cyan('@expires_in')}`]: `${Math.floor(timeUntilExpiry / 60)} minutes` }\n : { [`${chalk.red('@expired')}`]: true }),\n };\n\n runner.info('Current authentication:\\n\\n' + toText(info) + '\\n');\n } catch (error) {\n if (error instanceof Error && error.message.includes('No credentials found')) {\n runner.error('Not authenticated. Please run `blimu login` first.');\n } else {\n runner.error(\n `Failed to get user info: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n process.exit(1);\n }\n });\n}\n"],"mappings":"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","names":["useState","useEffect","Text","Fragment","jsx","jsxs","statusSymbols","statusColors","PulsingDot","Task","init_Task","__esmMin","color","frame","setFrame","interval","prev","name","status","message","_indent","isSubItem","isFirstSubItem","symbol","displayMessage","Text","jsx","jsxs","Message","init_Message","__esmMin","type","message","_indent","isSubItem","isFirstSubItem","dimmed","useState","useEffect","Text","useInput","clipboardy","jsx","jsxs","isRawModeSupported","SimpleText","InteractiveCopyableText","CopyableText","init_CopyableText","__esmMin","text","dimmed","isSubItem","isFirstSubItem","copied","setCopied","prefix","input","timeout","props","Box","jsx","jsxs","getGroupStatus","TaskList","init_TaskList","__esmMin","init_Task","init_Message","init_CopyableText","items","tasks","item","messages","hasErrorMessage","msg","hasSuccessMessage","task","groups","globalMessages","group","groupStatus","Task","index","CopyableText","Message","ink_adapter_exports","__export","InkTaskRunner","render","jsx","globalIdCounter","InkTask","InkTaskGroup","init_ink_adapter","__esmMin","init_TaskList","groupId","taskId","state","rerender","updates","group","g","task","item","message","name","fn","taskItem","error","messageType","options","messageItem","text","TaskList","cleanup","groupItem","client_ids_exports","__export","CLIENT_IDS","DEFAULT_ENVIRONMENT","getClientId","environment","clientId","init_client_ids","__esmMin","Command","path","fs","fs","path","generateTypeAugmentationFile","options","configPath","outputPath","typesPackages","lines","packageNames","outputDir","resolvedConfigPath","importPath","finalImportPath","typesPackage","path","fs","findDefaultConfig","possiblePaths","configPath","loadConfig","absolutePath","content","mod","getRelativeImportPath","fromDir","toFile","withoutExt","createTaskRunner","InkTaskRunner","codegenCommand","program","options","runner","createTaskRunner","configPath","findDefaultConfig","absoluteConfigPath","outputPath","task","outputDir","relativeConfigPath","getRelativeImportPath","generateTypeAugmentationFile","error","z","ResourceDefinitionSchema","EntitlementDefinitionSchema","FeatureDefinitionSchema","PlanDefinitionSchema","BlimuConfigSchema","chalk","log","message","FetchClient","FetchError","buildAuthStrategies","cfg","authStrategies","ApiKeysService","core","workspaceId","environmentId","init","body","id","DefinitionsService","core","workspaceId","environmentId","init","body","DnsService","core","workspaceId","environmentId","init","EnvironmentsService","core","workspaceId","query","init","body","environmentId","MeService","core","init","OauthAppsService","core","workspaceId","environmentId","query","init","body","id","ResourcesService","core","workspaceId","environmentId","query","init","body","resourceType","resourceId","SslService","core","workspaceId","environmentId","init","UsersService","core","workspaceId","environmentId","query","init","userId","WorkspaceMembersService","core","workspaceId","query","init","userId","body","WorkspacesService","core","init","body","workspaceId","BlimuCli","options","restCfg","authStrategies","buildAuthStrategies","core","FetchClient","ApiKeysService","DefinitionsService","DnsService","EnvironmentsService","MeService","OauthAppsService","ResourcesService","SslService","UsersService","WorkspaceMembersService","WorkspacesService","readFileSync","homedir","join","existsSync","CONFIG_DIR","paths","getConfigPath","loadRcConfig","configPath","getConfigPath","content","readFileSync","getEnvironment","cliFlag","rcConfig","RUNTIME_API_URLS","PLATFORM_API_URLS","getRuntimeApiBaseUrl","environment","getPlatformApiBaseUrl","readFileSync","writeFileSync","mkdirSync","existsSync","chmodSync","unlinkSync","dirname","KEYCHAIN_SERVICE","keyringModule","keyringLoadPromise","getKeyringEntry","isKeychainAvailable","Entry","entry","getRefreshToken","environment","account","token","existsSync","paths","content","readFileSync","creds","setRefreshToken","updatedCreds","readCredentials","writeCredentials","deleteRefreshToken","_refreshToken","_unavailable","cleanCreds","setCodeVerifier","environment","verifier","account","Entry","getKeyringEntry","KEYCHAIN_SERVICE","readCredentials","existsSync","paths","content","readFileSync","error","writeCredentials","creds","dir","dirname","mkdirSync","writeFileSync","chmodSync","deleteCredentials","unlinkSync","hasCredentials","refreshAccessToken","runtimeApiBaseUrl","clientId","environment","refreshToken","getRefreshToken","response","error","tokenResponse","expiresAt","creds","readCredentials","writeCredentials","setRefreshToken","isTokenExpired","bufferSeconds","now","getValidAccessToken","init_client_ids","createPlatformApiClient","options","apiKey","bearer","platformApiUrl","requireAuth","rcConfig","loadRcConfig","environment","hasCredentials","readCredentials","baseURL","getPlatformApiBaseUrl","finalApiKey","finalBearer","BlimuCli","runtimeApiBaseUrl","getRuntimeApiBaseUrl","clientId","getClientId","getValidAccessToken","error","readFileSync","writeFileSync","mkdirSync","existsSync","chmodSync","dirname","decodeJwtUserId","token","parts","payload","base64","jsonPayload","claims","getCurrentUserId","hasCredentials","creds","readCredentials","readPreferencesFile","existsSync","paths","content","readFileSync","writePreferencesFile","prefs","dir","dirname","mkdirSync","writeFileSync","chmodSync","getDefaultWorkspaceId","userId","setDefaultWorkspaceId","workspaceId","isCI","isInteractive","term","shouldPrompt","select","promptSelect","options","choice","base","pushCommand","program","options","connectRunner","createTaskRunner","connectGroup","client","task","createPlatformApiClient","workspaceId","getDefaultWorkspaceId","shouldPrompt","workspaces","log","workspaceChoices","ws","selected","promptSelect","environmentId","environments","envChoices","env","configPath","findDefaultConfig","pushRunner","pushGroup","config","rawConfig","loadConfig","validationResult","BlimuConfigSchema","err","error","open","Blimu","FetchError","BadRequestError","createHash","randomBytes","generateCodeVerifier","bytes","base64UrlEncode","generateCodeChallenge","verifier","hash","base64UrlEncode","buffer","poll","fn","options","initialInterval","maxInterval","maxAttempts","timeout","startTime","currentInterval","attempts","sleep","result","error","ms","resolve","Agent","undiciFetch","createLocalDevFetch","agent","input","init","OAuth2Client","runtimeApiBaseUrl","clientId","environment","fetchFn","Blimu","codeVerifier","generateCodeVerifier","codeChallenge","generateCodeChallenge","error","FetchError","errorBody","underlyingError","deviceCode","interval","poll","BadRequestError","errorMessage","init_client_ids","loginCommand","program","options","verbose","runner","createTaskRunner","rcConfig","loadRcConfig","environment","getEnvironment","runtimeApiBaseUrl","getRuntimeApiBaseUrl","clientId","getClientId","envDisplay","authGroup","isKeychainAvailable","oauthClient","OAuth2Client","deviceCodeResponse","codeVerifier","open","setCodeVerifier","tokenResponse","expiresAt","writeCredentials","usedKeychain","setRefreshToken","inkRunner","resolve","promptForDefaultWorkspace","error","errorMessage","log","formatUserFriendlyError","client","createPlatformApiClient","workspaces","workspace","setDefaultWorkspaceId","ws","selected","promptSelect","selectedWorkspace","err","message","cleanedMessage","logoutCommand","program","runner","createTaskRunner","environment","readCredentials","task","deleteRefreshToken","deleteCredentials","error","log","toText","obj","key","value","text","decodeJwtPayload","token","parts","payload","decoded","chalk","formatDate","timestamp","whoamiCommand","program","runner","createTaskRunner","creds","readCredentials","payload","decodeJwtPayload","now","timeUntilExpiry","info","chalk","toText","error","program","Command","codegenCommand","pushCommand","loginCommand","logoutCommand","whoamiCommand"]}
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "blimu",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Blimu - Authorization as a Service CLI",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
- "bin": "./dist/main.cjs",
8
+ "bin": "./dist/main.mjs",
9
9
  "files": [
10
10
  "dist",
11
11
  "README.md",
@@ -24,24 +24,35 @@
24
24
  "scripts": {
25
25
  "d:build": "npm run build && npm run typecheck",
26
26
  "build": "tsup",
27
- "dev": "tsx watch src/main.ts",
27
+ "dev": "tsup --watch",
28
+ "cli": "yarn build --silent && node dist/main.mjs",
28
29
  "typecheck": "tsc --noEmit",
29
30
  "test": "vitest run",
30
31
  "test:watch": "vitest",
31
32
  "prepublishOnly": "yarn build"
32
33
  },
33
34
  "dependencies": {
34
- "@blimu/fetch": "^0.4.0",
35
- "@clack/prompts": "^0.11.0",
35
+ "@blimu/backend": "1.2.2",
36
+ "@blimu/fetch": "^0.4.2",
37
+ "@inquirer/prompts": "^8.2.0",
38
+ "@napi-rs/keyring": "^1.2.0",
39
+ "chalk": "^5.6.2",
36
40
  "commander": "^14.0.2",
37
- "zod": "^4.3.5"
41
+ "ink": "^5.1.0",
42
+ "ink-spinner": "^5.0.0",
43
+ "open": "^11.0.0",
44
+ "react": "^18.3.1",
45
+ "undici": "^7.19.2",
46
+ "zod": ">=4.3.0"
38
47
  },
39
48
  "devDependencies": {
40
- "@types/node": "^25.0.9",
49
+ "@types/node": "^25.1.0",
50
+ "@types/react": "^18.3.18",
51
+ "msw": "^2.12.7",
41
52
  "tsup": "^8.5.1",
42
53
  "tsx": "^4.21.0",
43
54
  "typescript": "^5.9.3",
44
- "vitest": "^4.0.17"
55
+ "vitest": "^4.0.18"
45
56
  },
46
57
  "repository": {
47
58
  "type": "git",
package/dist/main.cjs DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";var M=Object.create;var E=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var J=(i,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of Q(e))!H.call(i,t)&&t!==n&&E(i,t,{get:()=>e[t],enumerable:!(o=N(e,t))||o.enumerable});return i};var d=(i,e,n)=>(n=i!=null?M(V(i)):{},J(e||!i||!i.__esModule?E(n,"default",{value:i,enumerable:!0}):n,i));var K=require("commander");var u=d(require("path")),F=d(require("fs")),p=d(require("@clack/prompts"));var l=d(require("fs")),h=d(require("path"));function x(i){let{configPath:e,outputPath:n,typesPackages:o=["@blimu/types","@blimu/backend"]}=i,t=[],s=o.join(" and ");t.push("/**"),t.push(` * Type Augmentation for ${s}`),t.push(" *"),t.push(` * This file augments the ${s} packages with union types`),t.push(" * specific to your environment configuration."),t.push(" *"),t.push(" * Types are automatically inferred from your blimu.config.ts file."),t.push(" * No regeneration needed when you update your config!"),t.push(" *"),t.push(" * Make sure to include this file in your tsconfig.json:"),t.push(" * {"),t.push(' * "include": ["blimu-types.d.ts"]'),t.push(" * }"),t.push(" */"),t.push("");let a=h.dirname(n),f=h.isAbsolute(e)?h.resolve(e):h.resolve(a,e),D=h.relative(a,f).replace(/\.(ts|mjs|js)$/,""),W=D.startsWith(".")?D:`./${D}`;t.push(`import type config from '${W}';`),t.push("import type {"),t.push(" InferResourceTypes,"),t.push(" InferEntitlementTypes,"),t.push(" InferPlanTypes,"),t.push(" InferLimitTypes,"),t.push(" InferUsageLimitTypes,"),t.push("} from 'blimu';"),t.push("");for(let z of o)t.push(`declare module '${z}' {`),t.push(" /**"),t.push(" * Resource types inferred from your Blimu configuration."),t.push(" */"),t.push(" type ResourceType = InferResourceTypes<typeof config>;"),t.push(""),t.push(" /**"),t.push(" * Entitlement types inferred from your Blimu configuration."),t.push(" */"),t.push(" type EntitlementType = InferEntitlementTypes<typeof config>;"),t.push(""),t.push(" /**"),t.push(" * Plan types inferred from your Blimu configuration."),t.push(" */"),t.push(" type PlanType = InferPlanTypes<typeof config>;"),t.push(""),t.push(" /**"),t.push(" * Limit types inferred from your Blimu configuration."),t.push(" */"),t.push(" type LimitType = InferLimitTypes<typeof config>;"),t.push(""),t.push(" /**"),t.push(" * Usage limit types inferred from your Blimu configuration."),t.push(" */"),t.push(" type UsageLimitType = InferUsageLimitTypes<typeof config>;"),t.push("}"),t.push("");l.existsSync(a)||l.mkdirSync(a,{recursive:!0}),l.writeFileSync(n,t.join(`
3
- `),"utf-8")}var m=d(require("path")),g=d(require("fs"));function y(){let i=[m.join(process.cwd(),"blimu.config.ts"),m.join(process.cwd(),"blimu.config.mjs"),m.join(process.cwd(),"blimu.config.js"),m.join(process.cwd(),"blimu.config.json")];for(let e of i)if(g.existsSync(e))return e;return null}async function _(i){let e=m.isAbsolute(i)?i:m.resolve(process.cwd(),i);if(!g.existsSync(e))throw new Error(`Config file not found: ${e}`);if(m.extname(e).toLowerCase()===".json"){let t=g.readFileSync(e,"utf-8");return JSON.parse(t)}let o=await import(e);return o.default||o}function A(i,e){let o=m.relative(i,e).replace(/\.(ts|mjs|js)$/,"");return o.startsWith(".")?o:`./${o}`}function L(i){i.command("codegen").description("Generate type augmentation file from Blimu config").option("--config <path>","Path to Blimu config file (defaults to blimu.config.ts in project root)").option("--output <path>","Output path for generated type augmentation file (defaults to blimu-types.d.ts in project root)").action(async e=>{let n=p.spinner();try{let o=e.config||y();o||(p.cancel("No config file found. Please provide --config or ensure blimu.config.ts exists in project root."),process.exit(1));let t=u.isAbsolute(o)?o:u.resolve(process.cwd(),o);F.existsSync(t)||(p.cancel(`Config file not found: ${t}`),process.exit(1)),p.log.step(`Using config file: ${t}`);let s=e.output?u.isAbsolute(e.output)?e.output:u.resolve(process.cwd(),e.output):u.join(process.cwd(),"blimu-types.d.ts");p.log.step(`Output: ${s}`);let a=u.dirname(s),f=A(a,t);n.start("Generating type augmentation file with type inference..."),x({configPath:f,outputPath:s}),n.stop("\u26A1\uFE0F Successfully generated type augmentation file"),p.log.success(`Generated at: ${s}`),p.log.info("\u{1F4A1} Tip: Types are automatically inferred from your config."),p.log.info(" No regeneration needed when you update blimu.config.ts!")}catch(o){n.stop("\u274C Failed to generate type augmentation"),p.log.error(`Failed to generate type augmentation: ${o instanceof Error?o.message:String(o)}`),o instanceof Error&&o.stack&&p.log.error(o.stack),process.exit(1)}})}var c=d(require("@clack/prompts"));var T=require("@blimu/fetch");function j(i){let e=[...i?.authStrategies??[]];return i.bearer&&e.push({type:"bearer",token:i.bearer}),i.apiKey&&e.push({type:"apiKey",key:i.apiKey,location:"header",name:"X-API-KEY"}),e}var R=class{constructor(e){this.core=e}list(e,n){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/api-keys`,...n??{}})}create(e,n,o){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/api-keys`,body:n,...o??{}})}delete(e,n,o){return this.core.request({method:"DELETE",path:`/v1/workspace/${encodeURIComponent(e)}/api-keys/${encodeURIComponent(n)}`,...o??{}})}get(e,n,o){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/api-keys/${encodeURIComponent(n)}`,...o??{}})}reveal(e,n,o){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/api-keys/${encodeURIComponent(n)}/reveal`,...o??{}})}};var C=class{constructor(e){this.core=e}get(e,n,o){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/definitions`,...o??{}})}update(e,n,o,t){return this.core.request({method:"PUT",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/definitions`,body:o,...t??{}})}validate(e,n,o,t){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/definitions/validate`,body:o,...t??{}})}};var v=class{constructor(e){this.core=e}getRecords(e,n,o){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/dns/records`,...o??{}})}validate(e,n,o){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/dns/validate`,...o??{}})}};var I=class{constructor(e){this.core=e}list(e,n,o){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments`,query:n,...o??{}})}create(e,n,o){return this.core.request({method:"POST",path:`/v1/workspace/${encodeURIComponent(e)}/environments`,body:n,...o??{}})}delete(e,n,o){return this.core.request({method:"DELETE",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}`,...o??{}})}read(e,n,o){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}`,...o??{}})}update(e,n,o,t){return this.core.request({method:"PUT",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}`,body:o,...t??{}})}getAuthConfig(e,n,o){return this.core.request({method:"GET",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/auth-config`,...o??{}})}updateAuthConfig(e,n,o,t){return this.core.request({method:"PUT",path:`/v1/workspace/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/auth-config`,body:o,...t??{}})}};var S=class{constructor(e){this.core=e}getAccess(e){return this.core.request({method:"GET",path:"/v1/me/access",...e??{}})}};var k=class{constructor(e){this.core=e}list(e,n,o,t){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources`,query:o,...t??{}})}create(e,n,o,t){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources`,body:o,...t??{}})}delete(e,n,o,t,s){return this.core.request({method:"DELETE",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources/${encodeURIComponent(o)}/${encodeURIComponent(t)}`,...s??{}})}get(e,n,o,t,s){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources/${encodeURIComponent(o)}/${encodeURIComponent(t)}`,...s??{}})}update(e,n,o,t,s,a){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources/${encodeURIComponent(o)}/${encodeURIComponent(t)}`,body:s,...a??{}})}listChildren(e,n,o,t,s,a){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources/${encodeURIComponent(o)}/${encodeURIComponent(t)}/children`,query:s,...a??{}})}getResourceUsers(e,n,o,t,s,a){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/resources/${encodeURIComponent(o)}/${encodeURIComponent(t)}/users`,query:s,...a??{}})}};var b=class{constructor(e){this.core=e}provision(e,n,o){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/ssl/provision`,...o??{}})}getStatus(e,n,o){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/ssl/status`,...o??{}})}};var U=class{constructor(e){this.core=e}list(e,n,o,t){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/users`,query:o,...t??{}})}get(e,n,o,t){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/users/${encodeURIComponent(o)}`,...t??{}})}getUserResources(e,n,o,t){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/environments/${encodeURIComponent(n)}/users/${encodeURIComponent(o)}/resources`,...t??{}})}};var P=class{constructor(e){this.core=e}list(e,n,o){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}/members`,query:n,...o??{}})}remove(e,n,o){return this.core.request({method:"DELETE",path:`/v1/workspaces/${encodeURIComponent(e)}/members/${encodeURIComponent(n)}`,...o??{}})}updateRole(e,n,o,t){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}/members/${encodeURIComponent(n)}/role`,body:o,...t??{}})}invite(e,n,o){return this.core.request({method:"POST",path:`/v1/workspaces/${encodeURIComponent(e)}/members/invite`,body:n,...o??{}})}};var $=class{constructor(e){this.core=e}list(e){return this.core.request({method:"GET",path:"/v1/workspaces",...e??{}})}create(e,n){return this.core.request({method:"POST",path:"/v1/workspaces",body:e,...n??{}})}getCurrent(e,n){return this.core.request({method:"GET",path:`/v1/workspaces/${encodeURIComponent(e)}`,...n??{}})}update(e,n,o){return this.core.request({method:"PUT",path:`/v1/workspaces/${encodeURIComponent(e)}`,body:n,...o??{}})}};var w=class{apiKeys;definitions;dns;environments;me;resources;ssl;users;workspaceMembers;workspaces;constructor(e){let n={...e??{}};delete n.apiKey,delete n.bearer;let o=j(e??{}),t=new T.FetchClient({...n,baseURL:e?.baseURL??"https://runtime.blimu.dev",...o.length>0?{authStrategies:o}:{}});this.apiKeys=new R(t),this.definitions=new C(t),this.dns=new v(t),this.environments=new I(t),this.me=new S(t),this.resources=new k(t),this.ssl=new b(t),this.users=new U(t),this.workspaceMembers=new P(t),this.workspaces=new $(t)}};var r=require("zod"),X=r.z.object({is_tenant:r.z.boolean().optional(),roles:r.z.array(r.z.string()).min(1,"At least one role must be defined"),parents:r.z.record(r.z.string(),r.z.object({required:r.z.boolean()})).optional(),roles_inheritance:r.z.record(r.z.string().min(1),r.z.array(r.z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1)).optional()}),Y=r.z.object({roles:r.z.array(r.z.string()).min(1).optional(),plans:r.z.array(r.z.string()).optional(),limit:r.z.string().optional()}),Z=r.z.object({name:r.z.string(),summary:r.z.string().optional(),entitlements:r.z.array(r.z.string()).optional(),plans:r.z.array(r.z.string()).optional(),default_enabled:r.z.boolean().optional()}),ee=r.z.object({name:r.z.string().min(1,"Plan name is required"),summary:r.z.string().optional(),description:r.z.string().min(1,"Plan description is required").optional(),resource_limits:r.z.record(r.z.string(),r.z.number().int().min(0)).optional(),usage_based_limits:r.z.record(r.z.string(),r.z.object({value:r.z.number().int().min(0),period:r.z.enum(["monthly","yearly","lifetime"])})).optional()}),G=r.z.object({resources:r.z.record(r.z.string().min(1),X),entitlements:r.z.record(r.z.string().min(1),Y).optional(),features:r.z.record(r.z.string().min(1),Z).optional(),plans:r.z.record(r.z.string().min(1),ee).optional()});function B(i){i.command("push").description("Push definitions to Blimu API").option("--config <path>","Path to Blimu config file (defaults to blimu.config.ts in project root)").option("--workspace-id <id>","Workspace ID (required)").option("--environment-id <id>","Environment ID (required)").option("--api-key <key>","API key for authentication").option("--bearer <token>","Bearer token for authentication").option("--base-url <url>","Base URL for the API","https://runtime.blimu.dev").action(async e=>{let n=c.spinner();try{e.workspaceId||(c.cancel("Workspace ID is required. Use --workspace-id <id>"),process.exit(1)),e.environmentId||(c.cancel("Environment ID is required. Use --environment-id <id>"),process.exit(1)),!e.apiKey&&!e.bearer&&(c.cancel("Authentication required. Provide either --api-key <key> or --bearer <token>"),process.exit(1));let o=e.config||y();o||(c.cancel("No config file found. Please provide --config or ensure blimu.config.ts exists in project root."),process.exit(1)),c.log.step(`Loading config from: ${o}`),n.start("Loading and validating config file...");let t=await _(o);n.stop("\u2713 Config loaded"),n.start("Validating config structure...");let s=G.safeParse(t);s.success||(n.stop("\u274C Config validation failed"),c.log.error("Config validation errors:"),s.error.issues.forEach(q=>{c.log.error(` - ${q.path.join(".")}: ${q.message}`)}),process.exit(1));let a=s.data;n.stop("\u2713 Config validated"),n.start("Connecting to Blimu API...");let f=new w({baseURL:e.baseUrl,...e.apiKey?{apiKey:e.apiKey}:{},...e.bearer?{bearer:e.bearer}:{}});n.stop("\u2713 Connected"),n.start("Pushing definitions to Blimu..."),await f.definitions.update(e.workspaceId,e.environmentId,{resources:a.resources,...a.entitlements?{entitlements:a.entitlements}:{},...a.features?{features:a.features}:{},...a.plans?{plans:a.plans}:{}}),n.stop("\u2713 Definitions pushed successfully"),c.log.success(`Successfully pushed definitions to workspace ${e.workspaceId}, environment ${e.environmentId}`)}catch(o){n.stop("\u274C Failed to push definitions"),c.log.error(`Failed to push definitions: ${o instanceof Error?o.message:String(o)}`),o instanceof Error&&o.stack&&c.log.error(o.stack),process.exit(1)}})}var O=new K.Command;O.name("blimu").description("Blimu - Authorization as a Service CLI").version(process.env.npm_package_version??"0.0.0");L(O);B(O);O.parse();
4
- //# sourceMappingURL=main.cjs.map
package/dist/main.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/main.ts","../src/commands/codegen.ts","../src/utils/type-augmentation-generator.ts","../src/utils/config-loader.ts","../src/commands/push.ts","../src/api-sdk/client.ts","../src/api-sdk/auth-strategies.ts","../src/api-sdk/services/api_keys.ts","../src/api-sdk/services/definitions.ts","../src/api-sdk/services/dns.ts","../src/api-sdk/services/environments.ts","../src/api-sdk/services/me.ts","../src/api-sdk/services/resources.ts","../src/api-sdk/services/ssl.ts","../src/api-sdk/services/users.ts","../src/api-sdk/services/workspace_members.ts","../src/api-sdk/services/workspaces.ts","../src/config/schema.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { codegenCommand } from './commands/codegen';\nimport { pushCommand } from './commands/push';\n\nconst program = new Command();\n\nprogram\n .name('blimu')\n .description('Blimu - Authorization as a Service CLI')\n .version(process.env['npm_package_version'] ?? '0.0.0');\n\n// Register commands\ncodegenCommand(program);\npushCommand(program);\n\n// Parse arguments\nprogram.parse();\n","import { Command } from 'commander';\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as clack from '@clack/prompts';\nimport { generateTypeAugmentationFile } from '../utils/type-augmentation-generator';\nimport {\n findDefaultConfig,\n getRelativeImportPath,\n} from '../utils/config-loader';\n\n/**\n * Register the codegen command\n */\nexport function codegenCommand(program: Command): void {\n program\n .command('codegen')\n .description('Generate type augmentation file from Blimu config')\n .option(\n '--config <path>',\n 'Path to Blimu config file (defaults to blimu.config.ts in project root)'\n )\n .option(\n '--output <path>',\n 'Output path for generated type augmentation file (defaults to blimu-types.d.ts in project root)'\n )\n .action(async (options) => {\n const spinner = clack.spinner();\n\n try {\n // Find config file\n const configPath = options.config || findDefaultConfig();\n if (!configPath) {\n clack.cancel(\n 'No config file found. Please provide --config or ensure blimu.config.ts exists in project root.'\n );\n process.exit(1);\n }\n\n // Resolve to absolute path\n const absoluteConfigPath = path.isAbsolute(configPath)\n ? configPath\n : path.resolve(process.cwd(), configPath);\n\n if (!fs.existsSync(absoluteConfigPath)) {\n clack.cancel(`Config file not found: ${absoluteConfigPath}`);\n process.exit(1);\n }\n\n clack.log.step(`Using config file: ${absoluteConfigPath}`);\n\n // Determine output path\n const outputPath = options.output\n ? path.isAbsolute(options.output)\n ? options.output\n : path.resolve(process.cwd(), options.output)\n : path.join(process.cwd(), 'blimu-types.d.ts');\n\n clack.log.step(`Output: ${outputPath}`);\n\n // Calculate relative path from output to config for import statement\n const outputDir = path.dirname(outputPath);\n const relativeConfigPath = getRelativeImportPath(\n outputDir,\n absoluteConfigPath\n );\n\n // Generate type augmentation file\n spinner.start(\n 'Generating type augmentation file with type inference...'\n );\n\n generateTypeAugmentationFile({\n configPath: relativeConfigPath,\n outputPath,\n // Always augment both @blimu/types and @blimu/backend\n // This is an internal implementation detail, not user-configurable\n });\n\n spinner.stop('⚡️ Successfully generated type augmentation file');\n\n clack.log.success(`Generated at: ${outputPath}`);\n clack.log.info(\n '💡 Tip: Types are automatically inferred from your config.'\n );\n clack.log.info(\n ' No regeneration needed when you update blimu.config.ts!'\n );\n } catch (error) {\n spinner.stop('❌ Failed to generate type augmentation');\n clack.log.error(\n `Failed to generate type augmentation: ${error instanceof Error ? error.message : String(error)}`\n );\n if (error instanceof Error && error.stack) {\n clack.log.error(error.stack);\n }\n process.exit(1);\n }\n });\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Options for generating type augmentation file\n */\nexport interface GenerateTypeAugmentationOptions {\n /** Path to the config file (relative to output directory or absolute) */\n configPath: string;\n /** Output path for the generated type augmentation file */\n outputPath: string;\n /** Types package names to augment (defaults to ['@blimu/types', '@blimu/backend']) */\n typesPackages?: string[];\n}\n\n/**\n * Generate type augmentation file for @blimu/types and @blimu/backend using type inference utilities.\n *\n * This generates a .d.ts file that imports the config and uses type inference\n * utilities to automatically extract types from the config structure.\n *\n * @param options - Generation options\n */\nexport function generateTypeAugmentationFile(options: GenerateTypeAugmentationOptions): void {\n const { configPath, outputPath, typesPackages = ['@blimu/types', '@blimu/backend'] } = options;\n\n const lines: string[] = [];\n\n // Header\n const packageNames = typesPackages.join(' and ');\n lines.push('/**');\n lines.push(` * Type Augmentation for ${packageNames}`);\n lines.push(' *');\n lines.push(` * This file augments the ${packageNames} packages with union types`);\n lines.push(' * specific to your environment configuration.');\n lines.push(' *');\n lines.push(' * Types are automatically inferred from your blimu.config.ts file.');\n lines.push(' * No regeneration needed when you update your config!');\n lines.push(' *');\n lines.push(' * Make sure to include this file in your tsconfig.json:');\n lines.push(' * {');\n lines.push(' * \"include\": [\"blimu-types.d.ts\"]');\n lines.push(' * }');\n lines.push(' */');\n lines.push('');\n\n // Calculate output directory and relative import path\n const outputDir = path.dirname(outputPath);\n const resolvedConfigPath = path.isAbsolute(configPath)\n ? path.resolve(configPath)\n : path.resolve(outputDir, configPath);\n const relativeConfigPath = path.relative(outputDir, resolvedConfigPath);\n // Remove .ts/.mjs/.js extension and ensure it starts with ./\n const importPath = relativeConfigPath.replace(/\\.(ts|mjs|js)$/, '');\n const finalImportPath = importPath.startsWith('.') ? importPath : `./${importPath}`;\n\n // Import config and type utilities\n lines.push(`import type config from '${finalImportPath}';`);\n lines.push('import type {');\n lines.push(' InferResourceTypes,');\n lines.push(' InferEntitlementTypes,');\n lines.push(' InferPlanTypes,');\n lines.push(' InferLimitTypes,');\n lines.push(' InferUsageLimitTypes,');\n lines.push(\"} from 'blimu';\");\n lines.push('');\n\n // Generate module augmentation for each package\n for (const typesPackage of typesPackages) {\n lines.push(`declare module '${typesPackage}' {`);\n lines.push(' /**');\n lines.push(' * Resource types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type ResourceType = InferResourceTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Entitlement types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type EntitlementType = InferEntitlementTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Plan types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type PlanType = InferPlanTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Limit types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type LimitType = InferLimitTypes<typeof config>;');\n lines.push('');\n lines.push(' /**');\n lines.push(' * Usage limit types inferred from your Blimu configuration.');\n lines.push(' */');\n lines.push(' type UsageLimitType = InferUsageLimitTypes<typeof config>;');\n lines.push('}');\n lines.push('');\n }\n\n // Ensure output directory exists\n if (!fs.existsSync(outputDir)) {\n fs.mkdirSync(outputDir, { recursive: true });\n }\n\n // Write file\n fs.writeFileSync(outputPath, lines.join('\\n'), 'utf-8');\n}\n","import * as path from 'path';\nimport * as fs from 'fs';\n\n/**\n * Find default config file in project root\n */\nexport function findDefaultConfig(): string | null {\n const possiblePaths = [\n path.join(process.cwd(), 'blimu.config.ts'),\n path.join(process.cwd(), 'blimu.config.mjs'),\n path.join(process.cwd(), 'blimu.config.js'),\n path.join(process.cwd(), 'blimu.config.json'),\n ];\n\n for (const configPath of possiblePaths) {\n if (fs.existsSync(configPath)) {\n return configPath;\n }\n }\n\n return null;\n}\n\n/**\n * Load and parse config file\n */\nexport async function loadConfig(configPath: string): Promise<unknown> {\n const absolutePath = path.isAbsolute(configPath)\n ? configPath\n : path.resolve(process.cwd(), configPath);\n\n if (!fs.existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`);\n }\n\n const ext = path.extname(absolutePath).toLowerCase();\n\n if (ext === '.json') {\n const content = fs.readFileSync(absolutePath, 'utf-8');\n return JSON.parse(content);\n }\n\n // For .ts, .mjs, .js files, use dynamic import\n const module = await import(absolutePath);\n return module.default || module;\n}\n\n/**\n * Get relative import path from output directory to config file\n * Handles both relative paths and ensures proper extension handling\n */\nexport function getRelativeImportPath(fromDir: string, toFile: string): string {\n const relative = path.relative(fromDir, toFile);\n // Remove .ts/.mjs/.js extension for import\n const withoutExt = relative.replace(/\\.(ts|mjs|js)$/, '');\n // Ensure it starts with ./ or ../\n if (!withoutExt.startsWith('.')) {\n return `./${withoutExt}`;\n }\n return withoutExt;\n}\n","import { Command } from 'commander';\nimport * as clack from '@clack/prompts';\nimport { BlimuCli } from '../api-sdk/client';\nimport { BlimuConfigSchema } from '../config/schema';\nimport { findDefaultConfig, loadConfig } from '../utils/config-loader';\n\n/**\n * Register the push command\n */\nexport function pushCommand(program: Command): void {\n program\n .command('push')\n .description('Push definitions to Blimu API')\n .option(\n '--config <path>',\n 'Path to Blimu config file (defaults to blimu.config.ts in project root)'\n )\n .option('--workspace-id <id>', 'Workspace ID (required)')\n .option('--environment-id <id>', 'Environment ID (required)')\n .option('--api-key <key>', 'API key for authentication')\n .option('--bearer <token>', 'Bearer token for authentication')\n .option('--base-url <url>', 'Base URL for the API', 'https://runtime.blimu.dev')\n .action(async (options) => {\n const spinner = clack.spinner();\n\n try {\n // Validate required options\n if (!options.workspaceId) {\n clack.cancel('Workspace ID is required. Use --workspace-id <id>');\n process.exit(1);\n }\n\n if (!options.environmentId) {\n clack.cancel('Environment ID is required. Use --environment-id <id>');\n process.exit(1);\n }\n\n // Check authentication\n if (!options.apiKey && !options.bearer) {\n clack.cancel(\n 'Authentication required. Provide either --api-key <key> or --bearer <token>'\n );\n process.exit(1);\n }\n\n // Find and load config file\n const configPath = options.config || findDefaultConfig();\n if (!configPath) {\n clack.cancel(\n 'No config file found. Please provide --config or ensure blimu.config.ts exists in project root.'\n );\n process.exit(1);\n }\n\n clack.log.step(`Loading config from: ${configPath}`);\n\n spinner.start('Loading and validating config file...');\n const rawConfig = await loadConfig(configPath);\n spinner.stop('✓ Config loaded');\n\n // Validate config structure\n spinner.start('Validating config structure...');\n const validationResult = BlimuConfigSchema.safeParse(rawConfig);\n if (!validationResult.success) {\n spinner.stop('❌ Config validation failed');\n clack.log.error('Config validation errors:');\n validationResult.error.issues.forEach((err) => {\n clack.log.error(` - ${err.path.join('.')}: ${err.message}`);\n });\n process.exit(1);\n }\n const config = validationResult.data;\n spinner.stop('✓ Config validated');\n\n // Create API client\n spinner.start('Connecting to Blimu API...');\n const client = new BlimuCli({\n baseURL: options.baseUrl,\n ...(options.apiKey ? { apiKey: options.apiKey } : {}),\n ...(options.bearer ? { bearer: options.bearer } : {}),\n });\n spinner.stop('✓ Connected');\n\n // Push definitions\n spinner.start('Pushing definitions to Blimu...');\n await client.definitions.update(options.workspaceId, options.environmentId, {\n resources: config.resources,\n ...(config.entitlements ? { entitlements: config.entitlements } : {}),\n ...(config.features ? { features: config.features } : {}),\n ...(config.plans ? { plans: config.plans } : {}),\n });\n spinner.stop('✓ Definitions pushed successfully');\n\n clack.log.success(\n `Successfully pushed definitions to workspace ${options.workspaceId}, environment ${options.environmentId}`\n );\n } catch (error) {\n spinner.stop('❌ Failed to push definitions');\n clack.log.error(\n `Failed to push definitions: ${error instanceof Error ? error.message : String(error)}`\n );\n if (error instanceof Error && error.stack) {\n clack.log.error(error.stack);\n }\n process.exit(1);\n }\n });\n}\n","import { FetchClient, FetchError } from '@blimu/fetch';\nimport {\n type FetchClientConfig,\n type BearerAuthStrategy,\n type ApiKeyAuthStrategy,\n} from '@blimu/fetch';\nimport { buildAuthStrategies } from './auth-strategies';\nimport { ApiKeysService } from './services/api_keys';\nimport { DefinitionsService } from './services/definitions';\nimport { DnsService } from './services/dns';\nimport { EnvironmentsService } from './services/environments';\nimport { MeService } from './services/me';\nimport { ResourcesService } from './services/resources';\nimport { SslService } from './services/ssl';\nimport { UsersService } from './services/users';\nimport { WorkspaceMembersService } from './services/workspace_members';\nimport { WorkspacesService } from './services/workspaces';\n\nexport type ClientOption = FetchClientConfig & {\n apiKey?: ApiKeyAuthStrategy['key'];\n bearer?: BearerAuthStrategy['token'];\n};\n\nexport class BlimuCli {\n readonly apiKeys: ApiKeysService;\n readonly definitions: DefinitionsService;\n readonly dns: DnsService;\n readonly environments: EnvironmentsService;\n readonly me: MeService;\n readonly resources: ResourcesService;\n readonly ssl: SslService;\n readonly users: UsersService;\n readonly workspaceMembers: WorkspaceMembersService;\n readonly workspaces: WorkspacesService;\n\n constructor(options?: ClientOption) {\n const restCfg = { ...(options ?? {}) };\n delete restCfg.apiKey;\n delete restCfg.bearer;\n\n const authStrategies = buildAuthStrategies(options ?? {});\n\n const core = new FetchClient({\n ...restCfg,\n baseURL: options?.baseURL ?? 'https://runtime.blimu.dev',\n ...(authStrategies.length > 0 ? { authStrategies } : {}),\n });\n\n this.apiKeys = new ApiKeysService(core);\n this.definitions = new DefinitionsService(core);\n this.dns = new DnsService(core);\n this.environments = new EnvironmentsService(core);\n this.me = new MeService(core);\n this.resources = new ResourcesService(core);\n this.ssl = new SslService(core);\n this.users = new UsersService(core);\n this.workspaceMembers = new WorkspaceMembersService(core);\n this.workspaces = new WorkspacesService(core);\n }\n}\n\n// Re-export FetchError for backward compatibility\nexport { FetchError };\nexport const BlimuCliError = FetchError;\n","import type { AuthStrategy } from '@blimu/fetch';\nimport type { ClientOption } from './client';\n\nexport function buildAuthStrategies(cfg: ClientOption): AuthStrategy[] {\n const authStrategies: AuthStrategy[] = [...(cfg?.authStrategies ?? [])];\n\n if (cfg.bearer) {\n authStrategies.push({\n type: 'bearer',\n token: cfg.bearer,\n });\n }\n if (cfg.apiKey) {\n authStrategies.push({\n type: 'apiKey',\n key: cfg.apiKey,\n location: 'header',\n name: 'X-API-KEY',\n });\n }\n return authStrategies;\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class ApiKeysService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspace/{workspaceId}/api-keys*\n * @returns List API keys*/\n list(\n workspaceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/api-keys`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/api-keys*\n * @returns Create API key*/\n create(\n workspaceId: string,\n body: Schema.ApiKeyCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/api-keys`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspace/{workspaceId}/api-keys/{id}*\n * @returns Delete API key*/\n delete(\n workspaceId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/api-keys/${encodeURIComponent(id)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspace/{workspaceId}/api-keys/{id}*\n * @returns Get API key*/\n get(\n workspaceId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/api-keys/${encodeURIComponent(id)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/api-keys/{id}/reveal*\n * @returns Reveal API key*/\n reveal(\n workspaceId: string,\n id: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ApiKeyRevealDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/api-keys/${encodeURIComponent(id)}/reveal`,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class DefinitionsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}/definitions*\n * @summary Get environment definitions*/\n get(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DefinitionDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/definitions`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspace/{workspaceId}/environments/{environmentId}/definitions*\n * @summary Update environment definitions*/\n update(\n workspaceId: string,\n environmentId: string,\n body: Schema.DefinitionUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/definitions`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/environments/{environmentId}/definitions/validate*\n * @summary Validate Blimu configuration*\n * @description Validates a complete Blimu configuration including resources, entitlements, features, and plans. Returns validation errors and optionally generates an OpenAPI spec if valid.*/\n validate(\n workspaceId: string,\n environmentId: string,\n body: Schema.DefinitionValidateRequestDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DefinitionValidateResponseDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/definitions/validate`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class DnsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/dns/records*\n * @summary Get DNS records for an environment*/\n getRecords(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DnsRecordListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/dns/records`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/dns/validate*\n * @summary Validate DNS records for an environment*/\n validate(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.DnsRecordListDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/dns/validate`,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class EnvironmentsService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspace/{workspaceId}/environments*\n * @summary List environments*/\n list(\n workspaceId: string,\n query?: Schema.EnvironmentsListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspace/{workspaceId}/environments*\n * @summary Create a new environment*/\n create(\n workspaceId: string,\n body: Schema.EnvironmentCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspace/{workspaceId}/environments/{environmentId}*\n * @summary Delete an environment*/\n delete(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}*\n * @summary Read an environment by ID*/\n read(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentWithDefinitionDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspace/{workspaceId}/environments/{environmentId}*\n * @summary Update an environment*/\n update(\n workspaceId: string,\n environmentId: string,\n body: Schema.EnvironmentUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspace/{workspaceId}/environments/{environmentId}/auth-config*\n * @summary Get authentication configuration for environment*/\n getAuthConfig(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentAuthConfigDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/auth-config`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspace/{workspaceId}/environments/{environmentId}/auth-config*\n * @summary Update authentication configuration for environment*/\n updateAuthConfig(\n workspaceId: string,\n environmentId: string,\n body: Schema.EnvironmentAuthConfigUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.EnvironmentAuthConfigDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspace/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/auth-config`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class MeService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/me/access*\n * @summary Get active resources for current user*/\n getAccess(init?: Omit<RequestInit, 'method' | 'body'>): Promise<Schema.UserAccessDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/me/access`,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class ResourcesService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources*\n * @summary List resources for an environment*/\n list(\n workspaceId: string,\n environmentId: string,\n query?: Schema.ResourcesListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/resources*\n * @summary Create a new resource*/\n create(\n workspaceId: string,\n environmentId: string,\n body: Schema.ResourceCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}*\n * @summary Delete a resource*/\n delete(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}*\n * @summary Get a specific resource*/\n get(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}*\n * @summary Update a resource*/\n update(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n body: Schema.ResourceUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}/children*\n * @summary List children resources for a specific resource*/\n listChildren(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n query?: Schema.ResourcesListChildrenQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}/children`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/resources/{resourceType}/{resourceId}/users*\n * @summary Get users with roles on a resource*/\n getResourceUsers(\n workspaceId: string,\n environmentId: string,\n resourceType: string,\n resourceId: string,\n query?: Schema.ResourcesGetResourceUsersQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.ResourceUserListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/resources/${encodeURIComponent(resourceType)}/${encodeURIComponent(resourceId)}/users`,\n query,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class SslService {\n constructor(private core: FetchClient) {}\n\n /**\n * POST /v1/workspaces/{workspaceId}/environments/{environmentId}/ssl/provision*\n * @summary Provision custom domains and SSL certificates for an environment*/\n provision(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.CustomHostnameListDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/ssl/provision`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/ssl/status*\n * @summary Get SSL certificate status for an environment*/\n getStatus(\n workspaceId: string,\n environmentId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.SslStatusResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/ssl/status`,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class UsersService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/users*\n * @summary List users for an environment*/\n list(\n workspaceId: string,\n environmentId: string,\n query?: Schema.UsersListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.UserListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/users`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/users/{userId}*\n * @summary Get user details by ID*/\n get(\n workspaceId: string,\n environmentId: string,\n userId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.UserDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/users/${encodeURIComponent(userId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}/environments/{environmentId}/users/{userId}/resources*\n * @summary Get user resource relationships*/\n getUserResources(\n workspaceId: string,\n environmentId: string,\n userId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.UserResourceDto_Output[]> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/environments/${encodeURIComponent(environmentId)}/users/${encodeURIComponent(userId)}/resources`,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class WorkspaceMembersService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces/{workspaceId}/members*\n * @summary List workspace members with pagination and search*/\n list(\n workspaceId: string,\n query?: Schema.WorkspaceMembersListQuery,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.MemberListResponseDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members`,\n query,\n ...(init ?? {}),\n });\n }\n\n /**\n * DELETE /v1/workspaces/{workspaceId}/members/{userId}*\n * @summary Remove member from workspace*/\n remove(\n workspaceId: string,\n userId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'DELETE',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(userId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}/members/{userId}/role*\n * @summary Update member role*/\n updateRole(\n workspaceId: string,\n userId: string,\n body: Schema.UpdateRoleDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<unknown> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members/${encodeURIComponent(userId)}/role`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces/{workspaceId}/members/invite*\n * @summary Invite a member to the workspace*/\n invite(\n workspaceId: string,\n body: Schema.InviteMemberDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.InviteMemberResponseDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}/members/invite`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import { FetchClient } from '@blimu/fetch';\nimport * as Schema from '../schema';\n\nexport class WorkspacesService {\n constructor(private core: FetchClient) {}\n\n /**\n * GET /v1/workspaces*\n * @summary Get all workspaces*/\n list(init?: Omit<RequestInit, 'method' | 'body'>): Promise<Schema.WorkspaceListDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces`,\n ...(init ?? {}),\n });\n }\n\n /**\n * POST /v1/workspaces*\n * @summary Create a new workspace*/\n create(\n body: Schema.WorkspaceCreateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.WorkspaceCreateResponseDto_Output> {\n return this.core.request({\n method: 'POST',\n path: `/v1/workspaces`,\n body,\n ...(init ?? {}),\n });\n }\n\n /**\n * GET /v1/workspaces/{workspaceId}*\n * @summary Get current authenticated workspace*/\n getCurrent(\n workspaceId: string,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.WorkspaceDto_Output> {\n return this.core.request({\n method: 'GET',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}`,\n ...(init ?? {}),\n });\n }\n\n /**\n * PUT /v1/workspaces/{workspaceId}*\n * @summary Update authenticated workspace*/\n update(\n workspaceId: string,\n body: Schema.WorkspaceUpdateDto,\n init?: Omit<RequestInit, 'method' | 'body'>\n ): Promise<Schema.WorkspaceDto_Output> {\n return this.core.request({\n method: 'PUT',\n path: `/v1/workspaces/${encodeURIComponent(workspaceId)}`,\n body,\n ...(init ?? {}),\n });\n }\n}\n","import { z } from 'zod';\n\n/**\n * Zod schema for resource definition\n */\nexport const ResourceDefinitionSchema = z.object({\n is_tenant: z.boolean().optional(),\n roles: z.array(z.string()).min(1, 'At least one role must be defined'),\n parents: z.record(z.string(), z.object({ required: z.boolean() })).optional(),\n roles_inheritance: z\n .record(\n z.string().min(1), // local role\n // Allow tokens containing letters, numbers, underscores or dashes\n // Examples: parent->editor, organization->admin, workspace_v2->viewer\n z.array(z.string().regex(/^([a-z0-9_-]+->)*[a-z0-9_-]+$/i)).min(1),\n )\n .optional(),\n});\n\n/**\n * Zod schema for entitlement definition\n */\nexport const EntitlementDefinitionSchema = z.object({\n roles: z.array(z.string()).min(1).optional(),\n plans: z.array(z.string()).optional(),\n limit: z.string().optional(), // Reference to usage-based limit\n});\n\n/**\n * Zod schema for feature definition\n */\nexport const FeatureDefinitionSchema = z.object({\n name: z.string(),\n summary: z.string().optional(),\n entitlements: z.array(z.string()).optional(),\n plans: z.array(z.string()).optional(),\n default_enabled: z.boolean().optional(),\n});\n\n/**\n * Zod schema for plan definition\n */\nexport const PlanDefinitionSchema = z.object({\n name: z.string().min(1, 'Plan name is required'),\n summary: z.string().optional(),\n description: z.string().min(1, 'Plan description is required').optional(),\n resource_limits: z.record(z.string(), z.number().int().min(0)).optional(),\n usage_based_limits: z\n .record(\n z.string(),\n z.object({\n value: z.number().int().min(0),\n period: z.enum(['monthly', 'yearly', 'lifetime']),\n }),\n )\n .optional(),\n});\n\n/**\n * Zod schema for complete Blimu configuration\n */\nexport const BlimuConfigSchema = z.object({\n resources: z.record(z.string().min(1), ResourceDefinitionSchema),\n entitlements: z.record(z.string().min(1), EntitlementDefinitionSchema).optional(),\n features: z.record(z.string().min(1), FeatureDefinitionSchema).optional(),\n plans: z.record(z.string().min(1), PlanDefinitionSchema).optional(),\n});\n\n/**\n * Type inference from schemas\n */\nexport type ResourceDefinition = z.infer<typeof ResourceDefinitionSchema>;\nexport type EntitlementDefinition = z.infer<typeof EntitlementDefinitionSchema>;\nexport type FeatureDefinition = z.infer<typeof FeatureDefinitionSchema>;\nexport type PlanDefinition = z.infer<typeof PlanDefinitionSchema>;\nexport type BlimuConfig = z.infer<typeof BlimuConfigSchema>;\n"],"mappings":"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","names":["import_commander","path","fs","clack","fs","path","generateTypeAugmentationFile","options","configPath","outputPath","typesPackages","lines","packageNames","outputDir","resolvedConfigPath","importPath","finalImportPath","typesPackage","path","fs","findDefaultConfig","possiblePaths","configPath","loadConfig","absolutePath","content","module","getRelativeImportPath","fromDir","toFile","withoutExt","codegenCommand","program","options","spinner","configPath","findDefaultConfig","absoluteConfigPath","outputPath","outputDir","relativeConfigPath","getRelativeImportPath","generateTypeAugmentationFile","error","clack","import_fetch","buildAuthStrategies","cfg","authStrategies","ApiKeysService","core","workspaceId","init","body","id","DefinitionsService","core","workspaceId","environmentId","init","body","DnsService","core","workspaceId","environmentId","init","EnvironmentsService","core","workspaceId","query","init","body","environmentId","MeService","core","init","ResourcesService","core","workspaceId","environmentId","query","init","body","resourceType","resourceId","SslService","core","workspaceId","environmentId","init","UsersService","core","workspaceId","environmentId","query","init","userId","WorkspaceMembersService","core","workspaceId","query","init","userId","body","WorkspacesService","core","init","body","workspaceId","BlimuCli","options","restCfg","authStrategies","buildAuthStrategies","core","ApiKeysService","DefinitionsService","DnsService","EnvironmentsService","MeService","ResourcesService","SslService","UsersService","WorkspaceMembersService","WorkspacesService","import_zod","ResourceDefinitionSchema","EntitlementDefinitionSchema","FeatureDefinitionSchema","PlanDefinitionSchema","BlimuConfigSchema","pushCommand","program","options","spinner","configPath","findDefaultConfig","rawConfig","loadConfig","validationResult","BlimuConfigSchema","err","config","client","BlimuCli","error","program","codegenCommand","pushCommand"]}