diff --git a/packages/aws/index.ts b/packages/aws/index.ts index cf43297..0a9e1c9 100644 --- a/packages/aws/index.ts +++ b/packages/aws/index.ts @@ -24,11 +24,11 @@ class AWSSourceModule extends SourceModule { get originalKeyInfos(): KeyInfo[] { return [ { - name: 'AWS_ACCESS_KEY_ID', + name: prefix(this.options.prefix, 'AWS_ACCESS_KEY_ID'), value: this.options.key, }, { - name: 'AWS_SECRET_ACCESS_KEY', + name: prefix(this.options.prefix, 'AWS_SECRET_ACCESS_KEY'), value: this.options.secretKey, }, ]; @@ -49,6 +49,10 @@ class AWSSourceModule extends SourceModule { }) ); + // Why the hell do I have to arbitrarily wait? + // What is propagating on Amazon's backend that results in the token not being immediately usable? + await new Promise((resolve) => setTimeout(resolve, 7000)); + this.accessKey = AccessKey; return [ diff --git a/packages/core/@types/source-module.ts b/packages/core/@types/source-module.ts index 089da2d..008ca42 100644 --- a/packages/core/@types/source-module.ts +++ b/packages/core/@types/source-module.ts @@ -42,7 +42,7 @@ export abstract class SourceModule { await Promise.all( this.options.targets.map(async (target) => { Logger.silly(`(${target.name}) Reverting...`); - await target.revert(this.originalKeyInfos); + await target.target(this.originalKeyInfos); Logger.silly(`(${target.name}) Successfully reverted!`); }) ); diff --git a/packages/core/@types/target-module.ts b/packages/core/@types/target-module.ts index 856abc9..102b223 100644 --- a/packages/core/@types/target-module.ts +++ b/packages/core/@types/target-module.ts @@ -4,5 +4,4 @@ export interface ITargetModule { get name(): string; target(keyInfos: KeyInfo[]): Promise; - revert(keyInfos: KeyInfo[]): Promise; } diff --git a/packages/core/fs/index.ts b/packages/core/fs/index.ts new file mode 100644 index 0000000..592009f --- /dev/null +++ b/packages/core/fs/index.ts @@ -0,0 +1,7 @@ +import { FSSourceModule } from './source'; +import { FSTargetModule } from './target'; + +export const FS = { + Source: FSSourceModule, + Target: FSTargetModule, +}; diff --git a/packages/core/fs/source.ts b/packages/core/fs/source.ts new file mode 100644 index 0000000..c5a2190 --- /dev/null +++ b/packages/core/fs/source.ts @@ -0,0 +1,42 @@ +import path from 'node:path'; +import { SourceModule, KeyInfo } from '../@types'; +import { read, readSync } from './utils/dotenv'; + +export class FSSourceModule extends SourceModule { + protected declare options: FSSourceModule.Options; + private keyInfos: KeyInfo[]; + + constructor({ targets, file, ...options }: FSSourceModule.Options) { + super({ targets }); + + this.options = { + ...this.options, + ...options, + file: path.join(process.cwd(), file), + }; + + this.keyInfos = readSync(this.options.file); + } + + get name(): string { + return 'fs'; + } + + get originalKeyInfos(): KeyInfo[] { + return this.keyInfos; + } + + async source(): Promise { + return await read(this.options.file); + } + + async revert(): Promise {} + + async cleanup(): Promise {} +} + +namespace FSSourceModule { + export type Options = { + file: string; + } & SourceModule.Options; +} diff --git a/packages/core/fs/target.ts b/packages/core/fs/target.ts new file mode 100644 index 0000000..32272e3 --- /dev/null +++ b/packages/core/fs/target.ts @@ -0,0 +1,28 @@ +import { ITargetModule, KeyInfo } from '../@types'; +import path from 'node:path'; +import { merge } from './utils/dotenv'; + +export class FSTargetModule implements ITargetModule { + private options: FSTargetModule.Options; + + constructor({ file, ...options }: FSTargetModule.Options) { + this.options = { + ...options, + file: path.join(process.cwd(), file), + }; + } + + get name(): string { + return 'fs'; + } + + async target(keyInfos: KeyInfo[]): Promise { + return await merge(this.options.file, keyInfos); + } +} + +export namespace FSTargetModule { + export interface Options { + file: string; + } +} diff --git a/packages/core/fs/utils/dotenv.ts b/packages/core/fs/utils/dotenv.ts new file mode 100644 index 0000000..3c388cc --- /dev/null +++ b/packages/core/fs/utils/dotenv.ts @@ -0,0 +1,39 @@ +import { KeyInfo } from '../..'; +import * as fs from 'node:fs/promises'; +import { readFileSync } from 'node:fs'; +import { keyInfoToKeyValue, keyValueToKeyInfo } from './keyinfo'; + +export async function read(path: string): Promise { + const content = await fs.readFile(path, { + encoding: 'utf-8', + }); + + return content.split(/\r?\n/).filter(Boolean).map(keyValueToKeyInfo); +} + +export function readSync(path: string): KeyInfo[] { + const content = readFileSync(path, { + encoding: 'utf-8', + }); + + return content.split(/\r?\n/).filter(Boolean).map(keyValueToKeyInfo); +} + +export async function write(path: string, keyInfos: KeyInfo[]): Promise { + await fs.writeFile(path, keyInfos.map(keyInfoToKeyValue).join('\n'), { + encoding: 'utf-8', + }); +} + +export async function merge(path: string, keyInfos: KeyInfo[]): Promise { + const existingKeyInfos = await read(path); + const mergedKeyInfos: KeyInfo[] = [...keyInfos]; + + for (const existingKeyInfo of existingKeyInfos) { + if (mergedKeyInfos.find((keyInfo) => keyInfo.name === existingKeyInfo.name)) continue; + + mergedKeyInfos.push(existingKeyInfo); + } + + await write(path, mergedKeyInfos); +} diff --git a/packages/core/fs/utils/keyinfo.ts b/packages/core/fs/utils/keyinfo.ts new file mode 100644 index 0000000..e7e204d --- /dev/null +++ b/packages/core/fs/utils/keyinfo.ts @@ -0,0 +1,14 @@ +import { KeyInfo } from '../../@types/key-info'; + +export function keyInfoToKeyValue(keyInfo: KeyInfo): string { + return `${keyInfo.name}=${keyInfo.value}`; +} + +export function keyValueToKeyInfo(keyValue: string): KeyInfo { + const [name, value] = keyValue.split('='); + + return { + name, + value, + }; +} diff --git a/packages/core/index.ts b/packages/core/index.ts index d0af2ec..5d9a940 100644 --- a/packages/core/index.ts +++ b/packages/core/index.ts @@ -37,4 +37,5 @@ export function prefix(...values: string[]): string { } export * from './@types'; +export * from './fs'; export { LogLevel, Logger }; diff --git a/packages/github/index.ts b/packages/github/index.ts index 8f9cb05..8ab3c53 100644 --- a/packages/github/index.ts +++ b/packages/github/index.ts @@ -25,7 +25,7 @@ class GitHubTargetModule implements ITargetModule { } get name(): string { - return 'github'; + return `github:${this.options.org}`; } private async getOrgPublicKey(org: string): Promise<{ key_id: string; key: string }> {