@eide/foir-cli 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1281,6 +1281,7 @@ import {
1281
1281
  FieldSchema as ProtoFieldSchema,
1282
1282
  SharingConfigSchema as ProtoSharingConfigSchema,
1283
1283
  ModelConfigSchema as ProtoModelConfigSchema,
1284
+ LookupDefinitionSchema as ProtoLookupDefinitionSchema,
1284
1285
  CreateModelRequestSchema,
1285
1286
  GetModelRequestSchema,
1286
1287
  GetModelByKeyRequestSchema,
@@ -1328,7 +1329,13 @@ function jsConfigToProto(c) {
1328
1329
  naturalKeyField: c.naturalKeyField,
1329
1330
  systemEntity: c.systemEntity ?? false,
1330
1331
  deletable: c.deletable,
1331
- editable: c.editable
1332
+ editable: c.editable,
1333
+ lookups: c.lookups ? c.lookups.map(
1334
+ (l) => create3(ProtoLookupDefinitionSchema, {
1335
+ keyBy: l.keyBy ?? [],
1336
+ name: l.name
1337
+ })
1338
+ ) : []
1332
1339
  });
1333
1340
  }
1334
1341
  function createModelsMethods(client) {
@@ -1383,7 +1390,8 @@ function createModelsMethods(client) {
1383
1390
  config: params.config ? jsConfigToProto(params.config) : void 0,
1384
1391
  changeDescription: params.changeDescription,
1385
1392
  updatePushSnapshot: params.updatePushSnapshot ?? false,
1386
- snapshotOnly: params.snapshotOnly ?? false
1393
+ snapshotOnly: params.snapshotOnly ?? false,
1394
+ allowLookupRebuild: params.allowLookupRebuild ?? false
1387
1395
  })
1388
1396
  );
1389
1397
  return resp.model ?? null;
@@ -5063,7 +5071,15 @@ async function reconcileConfig(client, configId, manifest, options = {}) {
5063
5071
  const operationBaseUrl = manifest.operationBaseUrl ?? "";
5064
5072
  const modelConflicts = [];
5065
5073
  const mappingConflicts = [];
5066
- await reconcileModels(client, configId, manifest.models ?? [], summary, options.force ?? false, modelConflicts);
5074
+ await reconcileModels(
5075
+ client,
5076
+ configId,
5077
+ manifest.models ?? [],
5078
+ summary,
5079
+ options.force ?? false,
5080
+ options.allowLookupRebuild ?? false,
5081
+ modelConflicts
5082
+ );
5067
5083
  await reconcileOperations(client, configId, manifest.operations ?? [], operationBaseUrl, summary);
5068
5084
  await reconcileHooks(client, configId, manifest.hooks ?? [], summary);
5069
5085
  await reconcileSegments(client, configId, manifest.segments ?? [], summary);
@@ -5094,7 +5110,7 @@ async function reconcileConfig(client, configId, manifest, options = {}) {
5094
5110
  }
5095
5111
  return summary;
5096
5112
  }
5097
- async function reconcileModels(client, configId, models, summary, force, conflictOut) {
5113
+ async function reconcileModels(client, configId, models, summary, force, allowLookupRebuild, conflictOut) {
5098
5114
  const existing = await client.models.listModels({ limit: 200 });
5099
5115
  const allByKey = new Map(
5100
5116
  existing.items.map((m) => [m.key, m])
@@ -5111,6 +5127,7 @@ async function reconcileModels(client, configId, models, summary, force, conflic
5111
5127
  if (m.pluralName) config2.pluralName = m.pluralName;
5112
5128
  if (m.pluralKey) config2.pluralKey = m.pluralKey;
5113
5129
  if (m.description) config2.description = m.description;
5130
+ if (m.lookups !== void 0) config2.lookups = m.lookups;
5114
5131
  const ex = allByKey.get(m.key);
5115
5132
  if (!ex) {
5116
5133
  plans.push({ kind: "create", model: m, config: config2 });
@@ -5179,7 +5196,8 @@ async function reconcileModels(client, configId, models, summary, force, conflic
5179
5196
  name: p.name,
5180
5197
  fields: fieldsToWrite,
5181
5198
  config: p.config,
5182
- updatePushSnapshot: true
5199
+ updatePushSnapshot: true,
5200
+ allowLookupRebuild
5183
5201
  });
5184
5202
  summary.models.updated++;
5185
5203
  summary.updatedModelIds.push(p.id);
@@ -5802,6 +5820,10 @@ function registerPushCommand(program2, globalOpts) {
5802
5820
  "--publish",
5803
5821
  "Promote updated models, operations, auth providers, profile schema, and design tokens to the published channel after the push. New resources auto-publish; this flag covers updates, which are otherwise left as drafts.",
5804
5822
  false
5823
+ ).option(
5824
+ "--rebuild",
5825
+ "Accept lookup renames. A lookup with the same keyBy and a changed `name` override rebuilds its projection rows (old rows are dropped, new rows are re-emitted from records). Without this flag, the server rejects renames with a pointer here. Pure add / remove on lookups does not require this flag.",
5826
+ false
5805
5827
  ).option("--env <path>", "Path to .env file (default: .env)").action(
5806
5828
  withErrorHandler(
5807
5829
  globalOpts,
@@ -5862,7 +5884,8 @@ function registerPushCommand(program2, globalOpts) {
5862
5884
  tenantId: resolved?.project.tenantId,
5863
5885
  projectId: resolved?.project.id,
5864
5886
  force: opts.force ?? false,
5865
- publishDesignTokens: opts.publish ?? false
5887
+ publishDesignTokens: opts.publish ?? false,
5888
+ allowLookupRebuild: opts.rebuild ?? false
5866
5889
  });
5867
5890
  } catch (e) {
5868
5891
  if (e instanceof PushConflictError) {
@@ -67,6 +67,23 @@ type GenericFieldDefinitionInput = BaseFieldDefinitionInput & {
67
67
  };
68
68
  };
69
69
  type FieldDefinitionInput = SelectFieldDefinitionInput | EnumFieldDefinitionInput | GenericFieldDefinitionInput;
70
+ /**
71
+ * Lookup definition — declares one indexed access path on a model.
72
+ *
73
+ * `keyBy` is the ordered list of top-level scalar field keys that make
74
+ * up the lookup key. Single-field lookups are common; composites are
75
+ * first-class (e.g. `['fromHost', 'fromPath']` for a redirect model).
76
+ * `name` overrides the generated GraphQL query field name; omit it to
77
+ * use `<typeLowerCamel>By<PascalCaseKeyFields>`.
78
+ *
79
+ * Validation runs server-side via the platform's config-write RPC —
80
+ * see RFC §Data model → Constraints. The CLI does no local validation
81
+ * here; the server's structured error surfaces verbatim on failure.
82
+ */
83
+ interface LookupDefinitionInput {
84
+ keyBy: string[];
85
+ name?: string;
86
+ }
70
87
  interface ApplyConfigModelInput {
71
88
  key: string;
72
89
  name: string;
@@ -75,6 +92,12 @@ interface ApplyConfigModelInput {
75
92
  description?: string;
76
93
  fields?: FieldDefinitionInput[];
77
94
  config?: Record<string, unknown>;
95
+ /**
96
+ * Lookup definitions for this model. Server validates: existence /
97
+ * scalar-type / top-level-only / caps (4 lookups, 4 fields) / GraphQL
98
+ * field-name regex for `name`. See RFC §Data model (config surface).
99
+ */
100
+ lookups?: LookupDefinitionInput[];
78
101
  }
79
102
  interface QuotaRule {
80
103
  /** Segment key to target (empty string or omitted = default/fallback). */
@@ -453,4 +476,4 @@ interface FoirSecretsConfig {
453
476
  */
454
477
  declare function defineSecrets(config: FoirSecretsConfig): FoirSecretsConfig;
455
478
 
456
- export { type AppInput, type AppPlacementFieldChoiceInput, type AppSinkMappingInput, type AppSourceMappingInput, type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigDesignTokensInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigProjectInput, type ApplyConfigProjectSettingsInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type EnumFieldConfig, type EnumFieldDefinitionInput, type EnumFieldOption, type ExpressionPrecondition, type FieldDefinitionInput, type FoirSecretsConfig, type Precondition, type QuotaRule, type SecretDeclaration, type SecretOwnerKind, type SegmentPrecondition, type SelectFieldConfig, type SelectFieldDefinitionInput, defineAuthProvider, defineConfig, defineDesignTokens, defineEnumField, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSecrets, defineSegment, defineSelectField };
479
+ export { type AppInput, type AppPlacementFieldChoiceInput, type AppSinkMappingInput, type AppSourceMappingInput, type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigDesignTokensInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigProjectInput, type ApplyConfigProjectSettingsInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type EnumFieldConfig, type EnumFieldDefinitionInput, type EnumFieldOption, type ExpressionPrecondition, type FieldDefinitionInput, type FoirSecretsConfig, type LookupDefinitionInput, type Precondition, type QuotaRule, type SecretDeclaration, type SecretOwnerKind, type SegmentPrecondition, type SelectFieldConfig, type SelectFieldDefinitionInput, defineAuthProvider, defineConfig, defineDesignTokens, defineEnumField, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSecrets, defineSegment, defineSelectField };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eide/foir-cli",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "Universal platform CLI for Foir platform",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -50,7 +50,7 @@
50
50
  "@bufbuild/protovalidate": "^1.1.1",
51
51
  "@connectrpc/connect": "^2.0.0",
52
52
  "@connectrpc/connect-node": "^2.0.0",
53
- "@eide/foir-proto-ts": "^0.59.0",
53
+ "@eide/foir-proto-ts": "^0.66.0",
54
54
  "chalk": "^5.3.0",
55
55
  "commander": "^12.1.0",
56
56
  "dotenv": "^16.4.5",