@eide/foir-cli 0.4.11 → 0.5.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 +286 -6
- package/dist/lib/config-helpers.d.ts +60 -1
- package/dist/lib/config-helpers.js +8 -0
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -3146,10 +3146,13 @@ async function createPlatformClient(options) {
|
|
|
3146
3146
|
headers["Authorization"] = `Bearer ${credentials.accessToken}`;
|
|
3147
3147
|
}
|
|
3148
3148
|
const resolved = await resolveProjectContext(options);
|
|
3149
|
-
if (resolved) {
|
|
3150
|
-
|
|
3151
|
-
|
|
3149
|
+
if (!resolved) {
|
|
3150
|
+
throw new Error(
|
|
3151
|
+
"No project selected. Run `foir select-project` to choose a project."
|
|
3152
|
+
);
|
|
3152
3153
|
}
|
|
3154
|
+
headers["x-tenant-id"] = resolved.project.tenantId;
|
|
3155
|
+
headers["x-project-id"] = resolved.project.id;
|
|
3153
3156
|
const authInterceptor = (next) => async (req) => {
|
|
3154
3157
|
for (const [key, value] of Object.entries(headers)) {
|
|
3155
3158
|
req.header.set(key, value);
|
|
@@ -3240,10 +3243,13 @@ async function getStorageAuth(options) {
|
|
|
3240
3243
|
baseHeaders["Authorization"] = `Bearer ${credentials.accessToken}`;
|
|
3241
3244
|
}
|
|
3242
3245
|
const resolved = await resolveProjectContext(options);
|
|
3243
|
-
if (resolved) {
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
+
if (!resolved) {
|
|
3247
|
+
throw new Error(
|
|
3248
|
+
"No project selected. Run `foir select-project` to choose a project."
|
|
3249
|
+
);
|
|
3246
3250
|
}
|
|
3251
|
+
baseHeaders["x-tenant-id"] = resolved.project.tenantId;
|
|
3252
|
+
baseHeaders["x-project-id"] = resolved.project.id;
|
|
3247
3253
|
let cachedToken = null;
|
|
3248
3254
|
const getToken = async () => {
|
|
3249
3255
|
if (cachedToken && Date.now() < cachedToken.expiresAt - 3e4) {
|
|
@@ -5105,6 +5111,275 @@ async function reconcileApiKeys(client, apiKeys, summary) {
|
|
|
5105
5111
|
}
|
|
5106
5112
|
}
|
|
5107
5113
|
|
|
5114
|
+
// src/lib/validate-integrations.ts
|
|
5115
|
+
import { fromJson as fromJson3 } from "@bufbuild/protobuf";
|
|
5116
|
+
import { pathToString } from "@bufbuild/protobuf/reflect";
|
|
5117
|
+
import { createValidator } from "@bufbuild/protovalidate";
|
|
5118
|
+
import {
|
|
5119
|
+
IntegrationConfigSchema,
|
|
5120
|
+
ExtensionConfigSchema
|
|
5121
|
+
} from "@eide/foir-proto-ts/integrations/v1/integrations_pb";
|
|
5122
|
+
var IntegrationValidationError = class extends Error {
|
|
5123
|
+
errors;
|
|
5124
|
+
constructor(errors) {
|
|
5125
|
+
super(
|
|
5126
|
+
`foir.config.ts failed validation:
|
|
5127
|
+
${errors.map((e) => ` - ${e}`).join("\n")}`
|
|
5128
|
+
);
|
|
5129
|
+
this.name = "IntegrationValidationError";
|
|
5130
|
+
this.errors = errors;
|
|
5131
|
+
}
|
|
5132
|
+
};
|
|
5133
|
+
var validator = createValidator();
|
|
5134
|
+
function validateIntegrationsAndExtensions(manifest) {
|
|
5135
|
+
const errors = [];
|
|
5136
|
+
const warnings = [];
|
|
5137
|
+
const modelsByKey = /* @__PURE__ */ new Map();
|
|
5138
|
+
for (const model of manifest.models ?? []) {
|
|
5139
|
+
modelsByKey.set(model.key, model);
|
|
5140
|
+
}
|
|
5141
|
+
if (manifest.integrations) {
|
|
5142
|
+
for (const [name, integration] of Object.entries(manifest.integrations)) {
|
|
5143
|
+
validateIntegration(name, integration, modelsByKey, errors, warnings);
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
if (manifest.extensions) {
|
|
5147
|
+
for (const [name, extension] of Object.entries(manifest.extensions)) {
|
|
5148
|
+
validateExtension(name, extension, modelsByKey, errors);
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
return { errors, warnings };
|
|
5152
|
+
}
|
|
5153
|
+
function assertValid(result) {
|
|
5154
|
+
if (result.errors.length > 0) {
|
|
5155
|
+
throw new IntegrationValidationError(result.errors);
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
function validateIntegration(name, integration, modelsByKey, errors, warnings) {
|
|
5159
|
+
const prefix = `integration '${name}'`;
|
|
5160
|
+
const protoJson = toIntegrationProtoJson(name, integration);
|
|
5161
|
+
const structuralErrors = runProtoValidation(
|
|
5162
|
+
prefix,
|
|
5163
|
+
protoJson,
|
|
5164
|
+
(json) => fromJson3(IntegrationConfigSchema, json, { ignoreUnknownFields: true })
|
|
5165
|
+
);
|
|
5166
|
+
errors.push(...structuralErrors);
|
|
5167
|
+
const sync = integration.sync ?? {};
|
|
5168
|
+
for (const [sourceType, mapping] of Object.entries(sync)) {
|
|
5169
|
+
validateSyncMapping(
|
|
5170
|
+
`${prefix} sync.${sourceType}`,
|
|
5171
|
+
mapping,
|
|
5172
|
+
name,
|
|
5173
|
+
modelsByKey,
|
|
5174
|
+
errors,
|
|
5175
|
+
warnings
|
|
5176
|
+
);
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
function validateSyncMapping(prefix, mapping, integrationName, modelsByKey, errors, warnings) {
|
|
5180
|
+
const model = mapping.model ? modelsByKey.get(mapping.model) : void 0;
|
|
5181
|
+
const seed = mapping.modelSeed;
|
|
5182
|
+
if (!mapping.model) {
|
|
5183
|
+
return;
|
|
5184
|
+
}
|
|
5185
|
+
if (!model && !seed) {
|
|
5186
|
+
errors.push(
|
|
5187
|
+
`${prefix}: missing model '${mapping.model}' referenced by integration '${integrationName}' \u2014 declare it under models or provide a modelSeed`
|
|
5188
|
+
);
|
|
5189
|
+
return;
|
|
5190
|
+
}
|
|
5191
|
+
const fieldKeys = model ? new Set((model.fields ?? []).map((f) => f.key)) : new Set(Object.keys(seed?.fields ?? {}));
|
|
5192
|
+
if (mapping.naturalKey && !fieldKeys.has(mapping.naturalKey)) {
|
|
5193
|
+
errors.push(
|
|
5194
|
+
`${prefix}: naturalKey '${mapping.naturalKey}' does not exist on ${model ? `model '${mapping.model}'` : `modelSeed for '${mapping.model}'`}`
|
|
5195
|
+
);
|
|
5196
|
+
}
|
|
5197
|
+
const fields = mapping.fields ?? {};
|
|
5198
|
+
for (const [sourceField, foirField] of Object.entries(fields)) {
|
|
5199
|
+
if (!foirField) continue;
|
|
5200
|
+
if (!fieldKeys.has(foirField)) {
|
|
5201
|
+
errors.push(
|
|
5202
|
+
`${prefix}: field mapping '${sourceField} -> ${foirField}' references field '${foirField}' which does not exist on ${model ? `model '${mapping.model}'` : `modelSeed for '${mapping.model}'`}`
|
|
5203
|
+
);
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
if (seed && model) {
|
|
5207
|
+
detectSeedDrift(prefix, seed, model, warnings);
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
function detectSeedDrift(prefix, seed, model, warnings) {
|
|
5211
|
+
const modelFieldTypes = /* @__PURE__ */ new Map();
|
|
5212
|
+
for (const field of model.fields ?? []) {
|
|
5213
|
+
modelFieldTypes.set(field.key, field.type);
|
|
5214
|
+
}
|
|
5215
|
+
for (const [key, field] of Object.entries(seed.fields ?? {})) {
|
|
5216
|
+
const modelType = modelFieldTypes.get(key);
|
|
5217
|
+
if (!modelType) {
|
|
5218
|
+
warnings.push(
|
|
5219
|
+
`${prefix}: modelSeed.fields.${key} is not present on existing model \u2014 modelSeed is ignored on subsequent pushes`
|
|
5220
|
+
);
|
|
5221
|
+
} else if (field.type && modelType !== field.type) {
|
|
5222
|
+
warnings.push(
|
|
5223
|
+
`${prefix}: modelSeed.fields.${key}.type '${field.type}' disagrees with existing model field type '${modelType}' \u2014 modelSeed is ignored on subsequent pushes`
|
|
5224
|
+
);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
function validateExtension(name, extension, modelsByKey, errors) {
|
|
5229
|
+
const prefix = `extension '${name}'`;
|
|
5230
|
+
const protoJson = toExtensionProtoJson(name, extension);
|
|
5231
|
+
const structuralErrors = runProtoValidation(
|
|
5232
|
+
prefix,
|
|
5233
|
+
protoJson,
|
|
5234
|
+
(json) => fromJson3(ExtensionConfigSchema, json, { ignoreUnknownFields: true })
|
|
5235
|
+
);
|
|
5236
|
+
errors.push(...structuralErrors);
|
|
5237
|
+
const placements = extension.placements ?? [];
|
|
5238
|
+
placements.forEach((placement, index) => {
|
|
5239
|
+
if (placement.model && !modelsByKey.has(placement.model)) {
|
|
5240
|
+
errors.push(
|
|
5241
|
+
`${prefix} placements[${index}]: missing model '${placement.model}' referenced by extension '${name}'`
|
|
5242
|
+
);
|
|
5243
|
+
}
|
|
5244
|
+
});
|
|
5245
|
+
}
|
|
5246
|
+
function runProtoValidation(prefix, json, decode) {
|
|
5247
|
+
let message;
|
|
5248
|
+
try {
|
|
5249
|
+
message = decode(json);
|
|
5250
|
+
} catch (err) {
|
|
5251
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5252
|
+
return [`${prefix}: cannot decode as proto \u2014 ${msg}`];
|
|
5253
|
+
}
|
|
5254
|
+
const result = runValidate(message);
|
|
5255
|
+
if (result.kind === "valid") return [];
|
|
5256
|
+
if (result.kind === "error") {
|
|
5257
|
+
return [`${prefix}: validator error \u2014 ${result.error.message}`];
|
|
5258
|
+
}
|
|
5259
|
+
return result.violations.map((v) => `${prefix}: ${formatViolation(v)}`);
|
|
5260
|
+
}
|
|
5261
|
+
function runValidate(message) {
|
|
5262
|
+
if (!message || typeof message !== "object") {
|
|
5263
|
+
return { kind: "error", error: new Error("message is not an object") };
|
|
5264
|
+
}
|
|
5265
|
+
const anyMsg = message;
|
|
5266
|
+
let schema;
|
|
5267
|
+
if (anyMsg.$typeName === "integrations.v1.IntegrationConfig") {
|
|
5268
|
+
schema = IntegrationConfigSchema;
|
|
5269
|
+
} else if (anyMsg.$typeName === "integrations.v1.ExtensionConfig") {
|
|
5270
|
+
schema = ExtensionConfigSchema;
|
|
5271
|
+
} else {
|
|
5272
|
+
return { kind: "error", error: new Error(`unknown message type ${anyMsg.$typeName ?? "?"}`) };
|
|
5273
|
+
}
|
|
5274
|
+
const result = validator.validate(
|
|
5275
|
+
// Both schema/message casts are safe because we picked schema by $typeName.
|
|
5276
|
+
schema,
|
|
5277
|
+
message
|
|
5278
|
+
);
|
|
5279
|
+
if (result.kind === "valid") return { kind: "valid" };
|
|
5280
|
+
if (result.kind === "error") return { kind: "error", error: result.error };
|
|
5281
|
+
return { kind: "invalid", violations: result.violations };
|
|
5282
|
+
}
|
|
5283
|
+
function formatViolation(v) {
|
|
5284
|
+
let path3 = "";
|
|
5285
|
+
try {
|
|
5286
|
+
path3 = pathToString(v.field);
|
|
5287
|
+
} catch {
|
|
5288
|
+
path3 = "";
|
|
5289
|
+
}
|
|
5290
|
+
const message = v.message ?? "";
|
|
5291
|
+
return path3 ? `${path3}: ${message}` : message;
|
|
5292
|
+
}
|
|
5293
|
+
function compact(obj) {
|
|
5294
|
+
const out = {};
|
|
5295
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
5296
|
+
if (v !== void 0) out[k] = v;
|
|
5297
|
+
}
|
|
5298
|
+
return out;
|
|
5299
|
+
}
|
|
5300
|
+
function toIntegrationProtoJson(name, integration) {
|
|
5301
|
+
return compact({
|
|
5302
|
+
name,
|
|
5303
|
+
enabled: integration.enabled ?? true,
|
|
5304
|
+
middleware: integration.middleware ? { url: integration.middleware.url ?? "" } : void 0,
|
|
5305
|
+
credentials: {
|
|
5306
|
+
strategy: integration.credentials?.strategy ? credentialStrategyToProto(integration.credentials.strategy) : "CREDENTIAL_STRATEGY_UNSPECIFIED"
|
|
5307
|
+
},
|
|
5308
|
+
sync: integration.sync ? Object.fromEntries(
|
|
5309
|
+
Object.entries(integration.sync).map(([k, v]) => [k, syncMappingToProto(v)])
|
|
5310
|
+
) : {},
|
|
5311
|
+
settings: integration.settings,
|
|
5312
|
+
metadata: integration.metadata
|
|
5313
|
+
});
|
|
5314
|
+
}
|
|
5315
|
+
function syncMappingToProto(mapping) {
|
|
5316
|
+
return compact({
|
|
5317
|
+
model: mapping.model ?? "",
|
|
5318
|
+
naturalKey: mapping.naturalKey ?? "",
|
|
5319
|
+
fields: mapping.fields ?? {},
|
|
5320
|
+
modelSeed: mapping.modelSeed ? {
|
|
5321
|
+
fields: Object.fromEntries(
|
|
5322
|
+
Object.entries(mapping.modelSeed.fields ?? {}).map(([k, v]) => [
|
|
5323
|
+
k,
|
|
5324
|
+
compact({
|
|
5325
|
+
type: v.type ?? "",
|
|
5326
|
+
required: v.required ?? false,
|
|
5327
|
+
naturalKey: v.naturalKey ?? false,
|
|
5328
|
+
label: v.label,
|
|
5329
|
+
helpText: v.helpText,
|
|
5330
|
+
config: v.config
|
|
5331
|
+
})
|
|
5332
|
+
])
|
|
5333
|
+
)
|
|
5334
|
+
} : void 0
|
|
5335
|
+
});
|
|
5336
|
+
}
|
|
5337
|
+
function credentialStrategyToProto(strategy) {
|
|
5338
|
+
switch (strategy) {
|
|
5339
|
+
case "oauth":
|
|
5340
|
+
return "CREDENTIAL_STRATEGY_OAUTH";
|
|
5341
|
+
case "api_key":
|
|
5342
|
+
return "CREDENTIAL_STRATEGY_API_KEY";
|
|
5343
|
+
case "shared_secret":
|
|
5344
|
+
return "CREDENTIAL_STRATEGY_SHARED_SECRET";
|
|
5345
|
+
case "ssh_key":
|
|
5346
|
+
return "CREDENTIAL_STRATEGY_SSH_KEY";
|
|
5347
|
+
case "none":
|
|
5348
|
+
return "CREDENTIAL_STRATEGY_NONE";
|
|
5349
|
+
case "managed":
|
|
5350
|
+
return "CREDENTIAL_STRATEGY_MANAGED";
|
|
5351
|
+
default:
|
|
5352
|
+
return "CREDENTIAL_STRATEGY_UNSPECIFIED";
|
|
5353
|
+
}
|
|
5354
|
+
}
|
|
5355
|
+
function toExtensionProtoJson(name, extension) {
|
|
5356
|
+
const placements = (extension.placements ?? []).map(
|
|
5357
|
+
(p) => compact({
|
|
5358
|
+
target: extensionTargetToProto(p.target),
|
|
5359
|
+
model: p.model ?? "",
|
|
5360
|
+
tab: p.tab ?? "",
|
|
5361
|
+
title: p.title ?? "",
|
|
5362
|
+
hints: p.hints
|
|
5363
|
+
})
|
|
5364
|
+
);
|
|
5365
|
+
return compact({
|
|
5366
|
+
name,
|
|
5367
|
+
url: extension.url ?? "",
|
|
5368
|
+
placements,
|
|
5369
|
+
metadata: extension.metadata
|
|
5370
|
+
});
|
|
5371
|
+
}
|
|
5372
|
+
function extensionTargetToProto(target) {
|
|
5373
|
+
switch (target) {
|
|
5374
|
+
case "record":
|
|
5375
|
+
return "EXTENSION_TARGET_RECORD";
|
|
5376
|
+
case "model-list":
|
|
5377
|
+
return "EXTENSION_TARGET_MODEL_LIST";
|
|
5378
|
+
default:
|
|
5379
|
+
return "EXTENSION_TARGET_UNSPECIFIED";
|
|
5380
|
+
}
|
|
5381
|
+
}
|
|
5382
|
+
|
|
5108
5383
|
// src/commands/push.ts
|
|
5109
5384
|
var CONFIG_FILE_NAMES = [
|
|
5110
5385
|
"foir.config.ts",
|
|
@@ -5181,6 +5456,11 @@ function registerPushCommand(program2, globalOpts) {
|
|
|
5181
5456
|
'Config must have at least "key" and "name" fields.'
|
|
5182
5457
|
);
|
|
5183
5458
|
}
|
|
5459
|
+
const validation = validateIntegrationsAndExtensions(config2);
|
|
5460
|
+
for (const warning of validation.warnings) {
|
|
5461
|
+
console.log(chalk6.yellow(`\u26A0 ${warning}`));
|
|
5462
|
+
}
|
|
5463
|
+
assertValid(validation);
|
|
5184
5464
|
const client = await createPlatformClient(globalOpts());
|
|
5185
5465
|
console.log(
|
|
5186
5466
|
chalk6.dim(`Pushing config "${config2.key}" to platform...`)
|
|
@@ -166,6 +166,57 @@ interface ApplyConfigApiKeyInput {
|
|
|
166
166
|
/** Restrict file uploads to specific MIME types (e.g. ["image/*", "video/*"]). */
|
|
167
167
|
allowedFileTypes?: string[];
|
|
168
168
|
}
|
|
169
|
+
type CredentialStrategy = 'oauth' | 'api_key' | 'shared_secret' | 'ssh_key' | 'none' | 'managed';
|
|
170
|
+
interface IntegrationMiddlewareInput {
|
|
171
|
+
/** Full https URL of the middleware handling this integration. */
|
|
172
|
+
url: string;
|
|
173
|
+
}
|
|
174
|
+
interface IntegrationCredentialsInput {
|
|
175
|
+
strategy: CredentialStrategy;
|
|
176
|
+
}
|
|
177
|
+
interface ModelSeedFieldInput {
|
|
178
|
+
type: string;
|
|
179
|
+
required?: boolean;
|
|
180
|
+
naturalKey?: boolean;
|
|
181
|
+
label?: string;
|
|
182
|
+
helpText?: string;
|
|
183
|
+
config?: Record<string, unknown>;
|
|
184
|
+
}
|
|
185
|
+
interface ModelSeedInput {
|
|
186
|
+
fields: Record<string, ModelSeedFieldInput>;
|
|
187
|
+
}
|
|
188
|
+
interface IntegrationSyncMappingInput {
|
|
189
|
+
/** foir model key this source type writes into. */
|
|
190
|
+
model: string;
|
|
191
|
+
/** foir field holding the upstream natural key. UPSERTs are keyed on this. */
|
|
192
|
+
naturalKey: string;
|
|
193
|
+
/** Explicit source field -> foir field mapping. */
|
|
194
|
+
fields: Record<string, string>;
|
|
195
|
+
/** Optional one-time bootstrap schema if the target model is missing. */
|
|
196
|
+
modelSeed?: ModelSeedInput;
|
|
197
|
+
}
|
|
198
|
+
interface IntegrationInput {
|
|
199
|
+
enabled?: boolean;
|
|
200
|
+
middleware: IntegrationMiddlewareInput;
|
|
201
|
+
credentials: IntegrationCredentialsInput;
|
|
202
|
+
sync: Record<string, IntegrationSyncMappingInput>;
|
|
203
|
+
/** Opaque middleware-specific settings — not validated by the CLI. */
|
|
204
|
+
settings?: Record<string, unknown>;
|
|
205
|
+
metadata?: Record<string, unknown>;
|
|
206
|
+
}
|
|
207
|
+
type ExtensionTarget = 'record' | 'model-list';
|
|
208
|
+
interface ExtensionPlacementInput {
|
|
209
|
+
target: ExtensionTarget;
|
|
210
|
+
model: string;
|
|
211
|
+
tab: string;
|
|
212
|
+
title: string;
|
|
213
|
+
hints?: Record<string, unknown>;
|
|
214
|
+
}
|
|
215
|
+
interface ExtensionInput {
|
|
216
|
+
url: string;
|
|
217
|
+
placements: ExtensionPlacementInput[];
|
|
218
|
+
metadata?: Record<string, unknown>;
|
|
219
|
+
}
|
|
169
220
|
interface ApplyConfigInput {
|
|
170
221
|
key: string;
|
|
171
222
|
name: string;
|
|
@@ -181,6 +232,10 @@ interface ApplyConfigInput {
|
|
|
181
232
|
authProviders?: ApplyConfigAuthProviderInput[];
|
|
182
233
|
placements?: ApplyConfigPlacementInput[];
|
|
183
234
|
apiKeys?: ApplyConfigApiKeyInput[];
|
|
235
|
+
/** Per-project integration declarations, keyed by integration name. */
|
|
236
|
+
integrations?: Record<string, IntegrationInput>;
|
|
237
|
+
/** Per-project extension declarations, keyed by extension name. */
|
|
238
|
+
extensions?: Record<string, ExtensionInput>;
|
|
184
239
|
[key: string]: unknown;
|
|
185
240
|
}
|
|
186
241
|
/** Define a complete config manifest. */
|
|
@@ -203,5 +258,9 @@ declare function defineAuthProvider(provider: ApplyConfigAuthProviderInput): App
|
|
|
203
258
|
declare function defineHook(hook: ApplyConfigHookInput): ApplyConfigHookInput;
|
|
204
259
|
/** Define an editor placement (sidebar or main-editor tab). */
|
|
205
260
|
declare function definePlacement(placement: ApplyConfigPlacementInput): ApplyConfigPlacementInput;
|
|
261
|
+
/** Define an integration declaration. */
|
|
262
|
+
declare function defineIntegration(integration: IntegrationInput): IntegrationInput;
|
|
263
|
+
/** Define an extension declaration. */
|
|
264
|
+
declare function defineExtensionDeclaration(extension: ExtensionInput): ExtensionInput;
|
|
206
265
|
|
|
207
|
-
export { type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type ExpressionPrecondition, type FieldDefinitionInput, type Precondition, type QuotaRule, type SegmentPrecondition, defineAuthProvider, defineConfig, defineExtension, defineField, defineHook, defineModel, defineOperation, definePlacement, defineSchedule, defineSegment };
|
|
266
|
+
export { type ApplyConfigApiKeyInput, type ApplyConfigAuthProviderInput, type ApplyConfigHookInput, type ApplyConfigInput, type ApplyConfigModelInput, type ApplyConfigOperationInput, type ApplyConfigPlacementInput, type ApplyConfigScheduleInput, type ApplyConfigSegmentInput, type CredentialStrategy, type ExpressionPrecondition, type ExtensionInput, type ExtensionPlacementInput, type ExtensionTarget, type FieldDefinitionInput, type IntegrationCredentialsInput, type IntegrationInput, type IntegrationMiddlewareInput, type IntegrationSyncMappingInput, type ModelSeedFieldInput, type ModelSeedInput, type Precondition, type QuotaRule, type SegmentPrecondition, defineAuthProvider, defineConfig, defineExtension, defineExtensionDeclaration, defineField, defineHook, defineIntegration, defineModel, defineOperation, definePlacement, defineSchedule, defineSegment };
|
|
@@ -27,12 +27,20 @@ function defineHook(hook) {
|
|
|
27
27
|
function definePlacement(placement) {
|
|
28
28
|
return placement;
|
|
29
29
|
}
|
|
30
|
+
function defineIntegration(integration) {
|
|
31
|
+
return integration;
|
|
32
|
+
}
|
|
33
|
+
function defineExtensionDeclaration(extension) {
|
|
34
|
+
return extension;
|
|
35
|
+
}
|
|
30
36
|
export {
|
|
31
37
|
defineAuthProvider,
|
|
32
38
|
defineConfig,
|
|
33
39
|
defineExtension,
|
|
40
|
+
defineExtensionDeclaration,
|
|
34
41
|
defineField,
|
|
35
42
|
defineHook,
|
|
43
|
+
defineIntegration,
|
|
36
44
|
defineModel,
|
|
37
45
|
defineOperation,
|
|
38
46
|
definePlacement,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eide/foir-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Universal platform CLI for Foir platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -47,9 +47,10 @@
|
|
|
47
47
|
"license": "UNLICENSED",
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@bufbuild/protobuf": "^2.0.0",
|
|
50
|
+
"@bufbuild/protovalidate": "^1.1.1",
|
|
50
51
|
"@connectrpc/connect": "^2.0.0",
|
|
51
52
|
"@connectrpc/connect-node": "^2.0.0",
|
|
52
|
-
"@eide/foir-proto-ts": "^0.
|
|
53
|
+
"@eide/foir-proto-ts": "^0.6.1",
|
|
53
54
|
"chalk": "^5.3.0",
|
|
54
55
|
"commander": "^12.1.0",
|
|
55
56
|
"dotenv": "^16.4.5",
|