#!/bin/node const { createApp, getTable, createRow, createTable, getApp, getRows, } = require("./utils") const Chance = require("chance") const generator = new Chance() const STUDENT_COUNT = 500 const SUBJECT_COUNT = 10 let { apiKey, appId } = require("yargs") .demandOption(["apiKey"]) .option("appId").argv const start = Date.now() async function batchCreate(apiKey, appId, table, items, batchSize = 100) { let i = 0 let errors = 0 async function createSingleRow(item) { try { const row = await createRow(apiKey, appId, table, item) console.log( `${table.name} - ${++i} of ${items.length} created (${ (Date.now() - start) / 1000 }s)` ) return row } catch { errors++ } } const rows = [] const maxConcurrency = Math.min(batchSize, items.length) const inFlight = {} for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { const item = items[itemIndex] const promise = createSingleRow(item) .then(result => { rows.push(result) }) .finally(() => { delete inFlight[itemIndex] }) inFlight[itemIndex] = promise if (Object.keys(inFlight).length >= maxConcurrency) { await Promise.race(Object.values(inFlight)) } } await Promise.all(Object.values(inFlight)) if (errors) { console.error( `${table.name} - ${errors} creation errored (${ (Date.now() - start) / 1000 }s)` ) } return rows } const useExistingApp = !!appId async function upsertTable(appId, tableName, tableData) { if (useExistingApp) { return await getTable(apiKey, appId, tableName) } const table = await createTable(apiKey, appId, { ...tableData, name: tableName, }) return table } async function run() { if (!appId) { const app = appId ? await getApp(apiKey, appId) : await createApp(apiKey) appId = app._id console.log(`App created. Url: http://localhost:10000/builder/app/${appId}`) } else { console.log( `App retrieved. Url: http://localhost:10000/builder/app/${appId}` ) } const studentsTable = await getTable(apiKey, appId, "Students") let studentNumber = studentsTable.schema["Auto ID"].lastID const students = await batchCreate( apiKey, appId, studentsTable, Array.from({ length: STUDENT_COUNT }).map(() => ({ "Student Number": (++studentNumber).toString(), "First Name": generator.first(), "Last Name": generator.last(), Gender: generator.pickone(["M", "F"]), Grade: generator.pickone(["8", "9", "10", "11"]), "Tardiness (Days)": generator.integer({ min: 1, max: 100 }), "Home Number": generator.phone(), "Attendance_(%)": generator.integer({ min: 0, max: 100 }), })) ) const subjectTable = await upsertTable(appId, "Subjects", { schema: { Name: { name: "Name", type: "string", }, }, primaryDisplay: "Name", }) const subjects = useExistingApp ? await getRows(apiKey, appId, subjectTable._id) : await batchCreate( apiKey, appId, subjectTable, Array.from({ length: SUBJECT_COUNT }).map(() => ({ Name: generator.profession(), })) ) const gradesTable = await upsertTable(appId, "Grades", { schema: { Score: { name: "Score", type: "number", }, Student: { name: "Student", tableId: studentsTable._id, constraints: { presence: true, type: "array", }, fieldName: "Grades", relationshipType: "one-to-many", type: "link", }, Subject: { name: "Subject", tableId: subjectTable._id, constraints: { presence: true, type: "array", }, fieldName: "Grades", relationshipType: "one-to-many", type: "link", }, }, }) await batchCreate( apiKey, appId, gradesTable, students.flatMap(student => subjects.map(subject => ({ Score: generator.integer({ min: 0, max: 100 }), Student: [student], Subject: [subject], })) ) ) console.log( `Access the app here: http://localhost:10000/builder/app/${appId}` ) } run() .then(() => { console.log(`Done in ${(Date.now() - start) / 1000} seconds`) }) .catch(err => { console.error(err) })