mirror of
https://github.com/whyour/qinglong.git
synced 2026-07-01 04:40:38 +08:00
feat: add environment variable labels
This commit is contained in:
@@ -18,6 +18,10 @@ const storage = multer.diskStorage({
|
||||
},
|
||||
});
|
||||
const upload = multer({ storage: storage });
|
||||
const labelSchema = Joi.array()
|
||||
.items(Joi.string().trim().required())
|
||||
.min(1)
|
||||
.required();
|
||||
|
||||
export default (app: Router) => {
|
||||
app.use('/envs', route);
|
||||
@@ -44,6 +48,7 @@ export default (app: Router) => {
|
||||
.required()
|
||||
.pattern(/^[a-zA-Z_][0-9a-zA-Z_]*$/),
|
||||
remarks: Joi.string().optional().allow(''),
|
||||
labels: Joi.array().items(Joi.string().trim()).optional(),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
@@ -70,6 +75,7 @@ export default (app: Router) => {
|
||||
name: Joi.string().required(),
|
||||
remarks: Joi.string().optional().allow('').allow(null),
|
||||
id: Joi.number().required(),
|
||||
labels: Joi.array().items(Joi.string().trim()).optional(),
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -230,6 +236,44 @@ export default (app: Router) => {
|
||||
},
|
||||
);
|
||||
|
||||
route.post(
|
||||
'/labels',
|
||||
celebrate({
|
||||
body: Joi.object({
|
||||
ids: Joi.array().items(Joi.number().required()).min(1).required(),
|
||||
labels: labelSchema,
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const envService = Container.get(EnvService);
|
||||
const data = await envService.addLabels(req.body.ids, req.body.labels);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
route.delete(
|
||||
'/labels',
|
||||
celebrate({
|
||||
body: Joi.object({
|
||||
ids: Joi.array().items(Joi.number().required()).min(1).required(),
|
||||
labels: labelSchema,
|
||||
}),
|
||||
}),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const envService = Container.get(EnvService);
|
||||
const data = await envService.removeLabels(req.body.ids, req.body.labels);
|
||||
return res.send({ code: 200, data });
|
||||
} catch (e) {
|
||||
return next(e);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
route.post(
|
||||
'/upload',
|
||||
upload.single('env'),
|
||||
@@ -248,6 +292,7 @@ export default (app: Router) => {
|
||||
name: x.name,
|
||||
value: x.value,
|
||||
remarks: x.remarks,
|
||||
labels: x.labels,
|
||||
})),
|
||||
);
|
||||
return res.send({ code: 200, data: result });
|
||||
|
||||
@@ -10,6 +10,7 @@ export class Env {
|
||||
name?: string;
|
||||
remarks?: string;
|
||||
isPinned?: 1 | 0;
|
||||
labels?: string[];
|
||||
|
||||
constructor(options: Env) {
|
||||
this.value = options.value;
|
||||
@@ -23,6 +24,7 @@ export class Env {
|
||||
this.name = options.name;
|
||||
this.remarks = options.remarks || '';
|
||||
this.isPinned = options.isPinned || 0;
|
||||
this.labels = options.labels || [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,4 +47,5 @@ export const EnvModel = sequelize.define<EnvInstance>('Env', {
|
||||
name: { type: DataTypes.STRING, unique: 'compositeIndex' },
|
||||
remarks: DataTypes.STRING,
|
||||
isPinned: DataTypes.NUMBER,
|
||||
labels: DataTypes.JSON,
|
||||
});
|
||||
|
||||
@@ -40,6 +40,7 @@ export default async () => {
|
||||
type: 'NUMBER',
|
||||
},
|
||||
{ table: 'Envs', column: 'isPinned', type: 'NUMBER' },
|
||||
{ table: 'Envs', column: 'labels', type: 'JSON' },
|
||||
];
|
||||
|
||||
for (const migration of migrations) {
|
||||
|
||||
@@ -199,6 +199,44 @@ export default class EnvService {
|
||||
await EnvModel.update({ isPinned: 0 }, { where: { id: ids } });
|
||||
}
|
||||
|
||||
public async addLabels(ids: number[], labels: string[]) {
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
const docs = await EnvModel.findAll({
|
||||
where: { id: ids },
|
||||
transaction,
|
||||
});
|
||||
for (const doc of docs) {
|
||||
const env = doc.get({ plain: true });
|
||||
await EnvModel.update(
|
||||
{ labels: Array.from(new Set([...(env.labels || []), ...labels])) },
|
||||
{ where: { id: env.id }, transaction },
|
||||
);
|
||||
}
|
||||
});
|
||||
return await this.find({ id: ids });
|
||||
}
|
||||
|
||||
public async removeLabels(ids: number[], labels: string[]) {
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
const docs = await EnvModel.findAll({
|
||||
where: { id: ids },
|
||||
transaction,
|
||||
});
|
||||
for (const doc of docs) {
|
||||
const env = doc.get({ plain: true });
|
||||
await EnvModel.update(
|
||||
{
|
||||
labels: (env.labels || []).filter(
|
||||
(label: string) => !labels.includes(label),
|
||||
),
|
||||
},
|
||||
{ where: { id: env.id }, transaction },
|
||||
);
|
||||
}
|
||||
});
|
||||
return await this.find({ id: ids });
|
||||
}
|
||||
|
||||
public async set_envs() {
|
||||
const envs = await this.envs('', {
|
||||
name: { [Op.not]: null },
|
||||
|
||||
Reference in New Issue
Block a user