UNPKG

manifest

Version:

The backend for AI code editors

263 lines (262 loc) 13.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SeederService = void 0; const types_1 = require("../../../../types/src"); const common_1 = require("@nestjs/common"); const typeorm_1 = require("typeorm"); const entity_service_1 = require("../../entity/services/entity.service"); const faker_1 = require("@faker-js/faker"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const bcryptjs_1 = __importDefault(require("bcryptjs")); const constants_1 = require("../../constants"); const storage_service_1 = require("../../storage/services/storage.service"); const entity_manifest_service_1 = require("../../manifest/services/entity-manifest.service"); let SeederService = class SeederService { constructor(entityService, entityManifestService, storageService, dataSource) { this.entityService = entityService; this.entityManifestService = entityManifestService; this.storageService = storageService; this.dataSource = dataSource; this.seededFiles = {}; this.seededImages = {}; this.records = {}; } async seed(tableName) { let entityMetadatas = this.entityService.getEntityMetadatas(); if (tableName) { entityMetadatas = entityMetadatas.filter((entity) => entity.tableName === tableName); } const queryRunner = this.dataSource.createQueryRunner(); const dbConnection = this.dataSource.options .type; switch (dbConnection) { case 'postgres': await Promise.all(entityMetadatas.map(async (entity) => queryRunner.query(`TRUNCATE TABLE "${entity.tableName}" CASCADE`))); await Promise.all(entityMetadatas.map(async (entity) => queryRunner .query(`ALTER SEQUENCE "${entity.tableName}_id_seq" RESTART WITH 1`) .catch(() => { }))); break; case 'mysql': await queryRunner.query('SET FOREIGN_KEY_CHECKS = 0'); await Promise.all(entityMetadatas.map(async (entity) => queryRunner.query(`TRUNCATE TABLE \`${entity.tableName}\``))); break; case 'sqlite': await queryRunner.query('PRAGMA foreign_keys = OFF'); await Promise.all(entityMetadatas.map(async (entity) => queryRunner.query(`DELETE FROM [${entity.tableName}]`))); await queryRunner.query('PRAGMA foreign_keys = ON'); break; } entityMetadatas = entityMetadatas.filter((entity) => entity.tableType === 'regular'); for (const entityMetadata of entityMetadatas) { const repository = this.entityService.getEntityRepository({ entityMetadata }); if (entityMetadata.name === constants_1.ADMIN_ENTITY_MANIFEST.className) { await this.seedAdmin(repository); continue; } const entityManifest = this.entityManifestService.getEntityManifest({ className: entityMetadata.name, fullVersion: true }); console.log(`✅ Seeding ${entityManifest.seedCount} ${entityManifest.seedCount > 1 ? entityManifest.namePlural : entityManifest.nameSingular}...`); for (let i = 0; i < entityManifest.seedCount; i++) { const newRecord = repository.create(); if (entityManifest.authenticable) { entityManifest.properties.push(...constants_1.AUTHENTICABLE_PROPS); } for (const propertyManifest of entityManifest.properties) { newRecord[propertyManifest.name] = await this.seedProperty(propertyManifest, entityManifest); } const manyToOneRelationships = entityManifest.relationships.filter((relationship) => relationship.type === 'many-to-one'); for (const relationship of manyToOneRelationships) { newRecord[relationship.name] = await this.seedRelationships(relationship); } await repository.save(newRecord); } } const manyToManyPromises = []; for (const entityMetadata of entityMetadatas) { const entityManifest = this.entityManifestService.getEntityManifest({ className: entityMetadata.name, fullVersion: true }); const repository = this.entityService.getEntityRepository({ entityMetadata }); const allRecords = await repository.find(); const manyToManyRelationships = entityManifest.relationships.filter((relationship) => relationship.type === 'many-to-many' && relationship.owningSide); for (const relationshipManifest of manyToManyRelationships) { for (const record of allRecords) { record[relationshipManifest.name] = await this.seedRelationships(relationshipManifest); manyToManyPromises.push(repository.save(record)); } } } await Promise.all(manyToManyPromises); return; } async seedProperty(propertyManifest, entityManifest) { const typeHandlers = { [types_1.PropType.String]: () => Promise.resolve(faker_1.faker.commerce.product()), [types_1.PropType.Number]: () => Promise.resolve(faker_1.faker.number.int({ max: 50 })), [types_1.PropType.Link]: () => Promise.resolve('https://manifest.build'), [types_1.PropType.Text]: () => Promise.resolve(faker_1.faker.commerce.productDescription()), [types_1.PropType.RichText]: () => Promise.resolve(this.seedRichText()), [types_1.PropType.Money]: () => Promise.resolve(faker_1.faker.finance.amount({ min: 1, max: 500, dec: 2 })), [types_1.PropType.Date]: () => Promise.resolve(faker_1.faker.date.past()), [types_1.PropType.Timestamp]: () => Promise.resolve(faker_1.faker.date.recent()), [types_1.PropType.Email]: () => Promise.resolve(faker_1.faker.internet.email()), [types_1.PropType.Boolean]: () => Promise.resolve(faker_1.faker.datatype.boolean()), [types_1.PropType.Password]: () => Promise.resolve(bcryptjs_1.default.hashSync('manifest', 1)), [types_1.PropType.Choice]: () => Promise.resolve(this.seedChoice(propertyManifest)), [types_1.PropType.Location]: () => Promise.resolve(this.seedLocation()), [types_1.PropType.File]: () => this.seedFile(propertyManifest, entityManifest), [types_1.PropType.Image]: () => this.seedImage(propertyManifest, entityManifest) }; const handler = typeHandlers[propertyManifest.type]; if (handler) { return handler(); } return Promise.reject(new Error(`Unsupported property type: ${propertyManifest.type}`)); } seedRichText() { return ` <h1>${faker_1.faker.commerce.productName()}</h1> <p>This is a dummy HTML content with <a href="https://manifest.build">links</a> and <strong>bold text</strong></p> <ul> <li>${faker_1.faker.commerce.productAdjective()}</li> <li>${faker_1.faker.commerce.productAdjective()}</li> <li>${faker_1.faker.commerce.productAdjective()}</li> </ul> <h2>${faker_1.faker.commerce.productName()}</h2> <p>${faker_1.faker.commerce.productDescription()}<p> `; } seedChoice(propertyManifest) { return faker_1.faker.helpers.arrayElement(propertyManifest.options.values); } async seedFile(propertyManifest, entityManifest) { const fileKey = `${entityManifest.slug}.${propertyManifest.name}`; if (this.seededFiles[fileKey]) { return this.seededFiles[fileKey]; } const dummyFileContent = fs.readFileSync(path.join(__dirname, '..', '..', '..', '..', 'assets', constants_1.DUMMY_FILE_NAME)); const filePath = await this.storageService.store(entityManifest.slug, propertyManifest.name, { originalname: constants_1.DUMMY_FILE_NAME, buffer: dummyFileContent }); this.seededFiles[fileKey] = filePath; return filePath; } async seedImage(propertyManifest, entityManifest) { const imageKey = `${entityManifest.slug}.${propertyManifest.name}`; if (this.seededImages[imageKey]) { return this.seededImages[imageKey]; } const dummyImageContent = fs.readFileSync(path.join(__dirname, '..', '..', '..', '..', 'assets', constants_1.DUMMY_IMAGE_NAME)); const images = await this.storageService.storeImage(entityManifest.slug, propertyManifest.name, { originalname: constants_1.DUMMY_FILE_NAME, buffer: dummyImageContent }, propertyManifest.options?.['sizes']); this.seededImages[imageKey] = images; return images; } seedLocation() { return { lat: faker_1.faker.location.latitude(), lng: faker_1.faker.location.longitude() }; } async seedAdmin(repository) { console.log(`✅ Seeding default admin ${constants_1.DEFAULT_ADMIN_CREDENTIALS.email} with password "${constants_1.DEFAULT_ADMIN_CREDENTIALS.password}"...`); const admin = repository.create(); admin.email = constants_1.DEFAULT_ADMIN_CREDENTIALS.email; admin.password = bcryptjs_1.default.hashSync(constants_1.DEFAULT_ADMIN_CREDENTIALS.password, 1); await repository.save(admin); } async seedRelationships(relationshipManifest) { const relatedEntityRepository = this.entityService.getEntityRepository({ entityMetadata: this.entityService.getEntityMetadata({ className: relationshipManifest.entity }) }); if (!this.records[relationshipManifest.entity]) { this.records[relationshipManifest.entity] = await relatedEntityRepository.find({ select: ['id'] }); } if (relationshipManifest.type === 'many-to-one') { return this.getRandomUniqueIds(this.records[relationshipManifest.entity].map((item) => item.id), 1)[0]; } else if (relationshipManifest.type === 'many-to-many') { const max = Math.min(constants_1.DEFAULT_MAX_MANY_TO_MANY_RELATIONS, this.records[relationshipManifest.entity].length); const numberOfRelations = faker_1.faker.number.int({ min: 0, max }); return this.getRandomUniqueIds(this.records[relationshipManifest.entity].map((item) => item.id), numberOfRelations).map((id) => ({ id })); } } getRandomUniqueIds(ids, count) { const shuffled = [...ids].sort(() => Math.random() - 0.5); return shuffled.slice(0, Math.min(count, ids.length)); } }; exports.SeederService = SeederService; exports.SeederService = SeederService = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [entity_service_1.EntityService, entity_manifest_service_1.EntityManifestService, storage_service_1.StorageService, typeorm_1.DataSource]) ], SeederService);