Skip to content

Commit

Permalink
feat: file import (#7219)
Browse files Browse the repository at this point in the history
  • Loading branch information
daveleek authored May 31, 2024
1 parent 6340ecd commit 80ba364
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/lib/__snapshots__/create-config.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ exports[`should create default config 1`] = `
],
"getLogger": [Function],
"import": {
"dropBeforeImport": false,
"environment": "development",
"file": undefined,
"keepExisting": false,
"project": "default",
},
"inlineSegmentConstraints": true,
"isEnterprise": false,
Expand Down
7 changes: 2 additions & 5 deletions src/lib/create-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,8 @@ const defaultAuthentication: IAuthOption = {

const defaultImport: WithOptional<IImportOption, 'file'> = {
file: process.env.IMPORT_FILE,
dropBeforeImport: parseEnvVarBoolean(
process.env.IMPORT_DROP_BEFORE_IMPORT,
false,
),
keepExisting: parseEnvVarBoolean(process.env.IMPORT_KEEP_EXISTING, false),
project: process.env.IMPORT_PROJECT ?? 'default',
environment: process.env.IMPORT_ENVIRONMENT ?? 'development',
};

const defaultEmail: IEmailOption = {
Expand Down
53 changes: 48 additions & 5 deletions src/lib/features/export-import-toggles/export-import-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type { IFeatureStrategiesStore } from '../feature-toggle/types/feature-to
import {
FeaturesExportedEvent,
FeaturesImportedEvent,
SYSTEM_USER,
SYSTEM_USER_AUDIT,
type FeatureToggleDTO,
type IAuditUser,
type IContextFieldStore,
Expand Down Expand Up @@ -55,6 +57,7 @@ import type { IDependentFeaturesReadModel } from '../dependent-features/dependen
import groupBy from 'lodash.groupby';
import { allSettledWithRejection } from '../../util/allSettledWithRejection';
import type { ISegmentReadModel } from '../segment/segment-read-model-type';
import { readFile } from './import-file-reader';

export type IImportService = {
validate(
Expand All @@ -67,6 +70,12 @@ export type IImportService = {
user: IUser,
auditUser: IAuditUser,
): Promise<void>;

importFromFile(
file: string,
project: string,
environment: string,
): Promise<void>;
};

export type IExportService = {
Expand Down Expand Up @@ -264,6 +273,16 @@ export default class ExportImportService
]);
}

async fileImportVerify(dto: ImportTogglesSchema): Promise<void> {
await allSettledWithRejection([
this.verifyStrategies(dto),
this.verifyContextFields(dto),
this.verifyFeatures(dto),
this.verifySegments(dto),
this.verifyDependencies(dto),
]);
}

async importFeatureData(
dto: ImportTogglesSchema,
auditUser: IAuditUser,
Expand All @@ -281,16 +300,40 @@ export default class ExportImportService
auditUser: IAuditUser,
): Promise<void> {
const cleanedDto = await this.cleanData(dto);

await this.importVerify(cleanedDto, user);
await this.processImport(cleanedDto, user, auditUser);
}

async importFromFile(
file: string,
project: string,
environment: string,
): Promise<void> {
const content = await readFile(file);
const data = JSON.parse(content);
const dto = {
project,
environment,
data,
};
const cleanedDto = await this.cleanData(dto);

await this.importFeatureData(cleanedDto, auditUser);
await this.fileImportVerify(cleanedDto);
await this.processImport(cleanedDto, SYSTEM_USER, SYSTEM_USER_AUDIT);
}

private async processImport(
dto: ImportTogglesSchema,
user: IUser,
auditUser: IAuditUser,
) {
await this.importFeatureData(dto, auditUser);

await this.importEnvironmentData(cleanedDto, user, auditUser);
await this.importEnvironmentData(dto, user, auditUser);
await this.eventService.storeEvent(
new FeaturesImportedEvent({
project: cleanedDto.project,
environment: cleanedDto.environment,
project: dto.project,
environment: dto.environment,
auditUser,
}),
);
Expand Down
8 changes: 8 additions & 0 deletions src/lib/features/export-import-toggles/import-file-reader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as fs from 'fs';

export const readFile: (file: string) => Promise<string> = async (file) =>
new Promise((resolve, reject) =>
fs.readFile(file, (err, v) =>
err ? reject(err) : resolve(v.toString('utf-8')),
),
);
6 changes: 5 additions & 1 deletion src/lib/server-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,11 @@ async function createApp(
};

if (config.import.file) {
// TODO: stateservice was here
await services.importService.importFromFile(
config.import.file,
config.import.project,
config.import.environment,
);
}

if (
Expand Down
4 changes: 2 additions & 2 deletions src/lib/types/option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ export interface IAuthOption {

export interface IImportOption {
file: string;
keepExisting: boolean;
dropBeforeImport: boolean;
project: string;
environment: string;
}

export interface IServerOption {
Expand Down

0 comments on commit 80ba364

Please sign in to comment.