@graphql-hive/cli
Version:
A CLI util to manage and control your GraphQL Hive
171 lines • 5.38 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Config = exports.allowedKeys = exports.graphqlEndpoint = void 0;
const tslib_1 = require("tslib");
const fs_1 = tslib_1.__importDefault(require("fs"));
const path_1 = tslib_1.__importDefault(require("path"));
const mkdirp_1 = require("mkdirp");
const zod_1 = require("zod");
const LegacyConfigModel = zod_1.z.object({
registry: zod_1.z.string().optional(),
token: zod_1.z.string().optional(),
});
const ConfigModel = zod_1.z.object({
registry: zod_1.z
.object({
endpoint: zod_1.z.string().url().optional(),
accessToken: zod_1.z.string().optional(),
})
.optional(),
cdn: zod_1.z
.object({
endpoint: zod_1.z.string().url().optional(),
accessToken: zod_1.z.string().optional(),
})
.optional(),
});
const getAllowedConfigKeys = (config) => {
const keys = new Set();
const traverse = (obj, path = []) => {
if (obj instanceof zod_1.z.ZodObject) {
const shape = obj.shape;
for (const [key, value] of Object.entries(shape)) {
traverse(value, [...path, key]);
}
}
else {
keys.add(path.join('.'));
}
return path.join('.');
};
traverse(config);
return keys;
};
exports.graphqlEndpoint = 'https://app.graphql-hive.com/graphql';
exports.allowedKeys = Array.from(getAllowedConfigKeys(ConfigModel));
class Config {
constructor({ filepath, rootDir }) {
if (filepath) {
this.filepath = filepath;
}
else {
this.filepath = path_1.default.join(rootDir, 'hive.json');
}
}
get(key) {
const map = this.read();
const parts = key.split('.');
let current = map;
for (const part of parts) {
if (current == null) {
return null;
}
current = current[part];
}
return current;
}
set(key, value) {
if (getAllowedConfigKeys(ConfigModel).has(key) === false) {
throw new Error(`Invalid configuration key: ${key}`);
}
const map = this.read();
const parts = key.split('.');
let current = map;
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
if (!current[part]) {
current[part] = {};
}
if (i === parts.length - 1) {
current[part] = value;
}
current = current[part];
}
this.write(map);
}
delete(key) {
const map = this.read();
const parts = key.split('.');
let current = map;
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
if (!current[part]) {
current[part] = {};
}
if (i === parts.length - 1) {
current[part] = undefined;
}
current = current[part];
}
this.write(map);
}
clear() {
try {
(0, mkdirp_1.sync)(path_1.default.dirname(this.filepath));
}
catch (_a) { }
fs_1.default.writeFileSync(this.filepath, JSON.stringify({}), 'utf8');
}
readSpace(content) {
// eslint-disable-next-line no-process-env
const space = process.env.HIVE_SPACE;
if (space) {
return content[space];
}
if ('default' in content) {
return content['default'];
}
return content;
}
read() {
try {
if (!this.cache) {
const space = this.readSpace(JSON.parse(fs_1.default.readFileSync(this.filepath, 'utf-8')));
const legacyConfig = LegacyConfigModel.safeParse(space);
if (legacyConfig.success) {
this.cache = {
registry: {
endpoint: legacyConfig.data.registry,
accessToken: legacyConfig.data.token,
},
cdn: {
endpoint: undefined,
accessToken: undefined,
},
};
}
const config = ConfigModel.safeParse(space);
// TODO: we should probably print a warning/error in case of an invalid config.
if (config.success) {
this.cache = config.data;
}
else {
throw new Error('Invalid config.');
}
}
}
catch (error) {
this.cache = {
registry: {
endpoint: undefined,
accessToken: undefined,
},
cdn: {
endpoint: undefined,
accessToken: undefined,
},
};
}
return this.cache;
}
write(map) {
this.cache = map;
try {
(0, mkdirp_1.sync)(path_1.default.dirname(this.filepath));
}
catch (e) { }
fs_1.default.writeFileSync(this.filepath, JSON.stringify(this.cache));
}
}
exports.Config = Config;
//# sourceMappingURL=config.js.map