2023-12-19 16:59:23 +01:00
|
|
|
#!/bin/node
|
2023-12-22 11:46:49 +01:00
|
|
|
const {
|
|
|
|
createApp,
|
|
|
|
getTable,
|
|
|
|
createRow,
|
|
|
|
createTable,
|
|
|
|
getApp,
|
|
|
|
} = require("./utils")
|
2023-12-19 16:59:23 +01:00
|
|
|
|
2023-12-20 11:51:35 +01:00
|
|
|
const Chance = require("chance")
|
2023-12-22 10:05:49 +01:00
|
|
|
|
2023-12-20 11:51:35 +01:00
|
|
|
const generator = new Chance()
|
|
|
|
|
2023-12-20 13:04:16 +01:00
|
|
|
const STUDENT_COUNT = 500
|
2023-12-20 12:18:29 +01:00
|
|
|
const SUBJECT_COUNT = 10
|
2023-12-19 16:59:23 +01:00
|
|
|
|
2023-12-22 11:46:49 +01:00
|
|
|
let { apiKey, appId } = require("yargs")
|
2023-12-22 11:36:29 +01:00
|
|
|
.demandOption(["apiKey"])
|
|
|
|
.option("appId").argv
|
2023-12-19 16:59:23 +01:00
|
|
|
|
2023-12-20 13:04:16 +01:00
|
|
|
const start = Date.now()
|
2023-12-22 11:46:49 +01:00
|
|
|
async function batchCreate(apiKey, appId, table, items, batchSize = 100) {
|
2023-12-21 17:39:14 +01:00
|
|
|
let i = 0
|
2023-12-21 18:29:57 +01:00
|
|
|
let errors = 0
|
2023-12-21 19:06:26 +01:00
|
|
|
|
2023-12-21 17:48:39 +01:00
|
|
|
async function createSingleRow(item) {
|
2023-12-21 18:28:10 +01:00
|
|
|
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 {
|
2023-12-21 18:29:57 +01:00
|
|
|
errors++
|
2023-12-21 18:28:10 +01:00
|
|
|
}
|
2023-12-21 17:39:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const rows = []
|
2023-12-21 19:06:26 +01:00
|
|
|
const maxConcurrency = Math.min(batchSize, items.length)
|
|
|
|
const inFlight = {}
|
|
|
|
|
|
|
|
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
|
|
|
const item = items[itemIndex]
|
2023-12-22 11:52:48 +01:00
|
|
|
const promise = createSingleRow(item)
|
|
|
|
.then(result => {
|
|
|
|
rows.push(result)
|
|
|
|
})
|
|
|
|
.finally(() => {
|
|
|
|
delete inFlight[itemIndex]
|
|
|
|
})
|
2023-12-21 19:06:26 +01:00
|
|
|
|
|
|
|
inFlight[itemIndex] = promise
|
|
|
|
|
|
|
|
if (Object.keys(inFlight).length >= maxConcurrency) {
|
|
|
|
await Promise.race(Object.values(inFlight))
|
|
|
|
}
|
2023-12-21 18:29:57 +01:00
|
|
|
}
|
2023-12-21 19:06:26 +01:00
|
|
|
|
|
|
|
await Promise.all(Object.values(inFlight))
|
|
|
|
|
2023-12-22 10:05:49 +01:00
|
|
|
if (errors) {
|
|
|
|
console.error(
|
|
|
|
`${table.name} - ${errors} creation errored (${
|
|
|
|
(Date.now() - start) / 1000
|
|
|
|
}s)`
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-12-21 17:39:14 +01:00
|
|
|
return rows
|
|
|
|
}
|
|
|
|
|
2023-12-22 11:46:49 +01:00
|
|
|
const useExistingApp = !!appId
|
2023-12-20 12:30:35 +01:00
|
|
|
|
2023-12-22 11:46:49 +01:00
|
|
|
async function upsertTable(appId, tableName, tableData) {
|
|
|
|
if (useExistingApp) {
|
|
|
|
return await getTable(apiKey, appId, tableName)
|
2023-12-20 12:18:29 +01:00
|
|
|
}
|
2023-12-22 11:46:49 +01:00
|
|
|
|
|
|
|
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: http://localhost:10000/builder/app/${appId}`)
|
|
|
|
|
|
|
|
const studentsTable = await getTable(apiKey, appId, "Students")
|
2023-12-19 16:59:23 +01:00
|
|
|
|
2023-12-20 12:52:25 +01:00
|
|
|
let studentNumber = studentsTable.schema["Auto ID"].lastID
|
2023-12-21 17:39:14 +01:00
|
|
|
const students = await batchCreate(
|
|
|
|
apiKey,
|
2023-12-22 11:46:49 +01:00
|
|
|
appId,
|
2023-12-21 17:39:14 +01:00
|
|
|
studentsTable,
|
2023-12-21 17:52:04 +01:00
|
|
|
Array.from({ length: STUDENT_COUNT }).map(() => ({
|
2023-12-21 17:39:14 +01:00
|
|
|
"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 }),
|
2023-12-21 17:48:39 +01:00
|
|
|
}))
|
2023-12-21 17:24:48 +01:00
|
|
|
)
|
2023-12-20 15:02:21 +01:00
|
|
|
|
2023-12-22 11:46:49 +01:00
|
|
|
const subjectTable = await upsertTable(appId, "Subjects", {
|
2023-12-19 16:59:23 +01:00
|
|
|
schema: {
|
2023-12-20 11:51:35 +01:00
|
|
|
Name: {
|
2023-12-19 16:59:23 +01:00
|
|
|
name: "Name",
|
|
|
|
type: "string",
|
|
|
|
},
|
|
|
|
},
|
2023-12-20 12:52:25 +01:00
|
|
|
primaryDisplay: "Name",
|
2023-12-19 16:59:23 +01:00
|
|
|
})
|
2023-12-20 11:51:35 +01:00
|
|
|
|
2023-12-21 17:39:14 +01:00
|
|
|
const subjects = await batchCreate(
|
|
|
|
apiKey,
|
2023-12-22 11:46:49 +01:00
|
|
|
appId,
|
2023-12-21 17:39:14 +01:00
|
|
|
subjectTable,
|
2023-12-21 17:48:39 +01:00
|
|
|
Array.from({ length: SUBJECT_COUNT }).map(() => ({
|
2023-12-21 17:39:14 +01:00
|
|
|
Name: generator.profession(),
|
2023-12-21 17:48:39 +01:00
|
|
|
}))
|
2023-12-21 17:24:48 +01:00
|
|
|
)
|
2023-12-20 15:02:21 +01:00
|
|
|
|
2023-12-22 11:46:49 +01:00
|
|
|
const gradesTable = await upsertTable(appId, "Grades", {
|
2023-12-20 12:52:25 +01:00
|
|
|
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",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2023-12-21 17:48:39 +01:00
|
|
|
await batchCreate(
|
|
|
|
apiKey,
|
2023-12-22 11:46:49 +01:00
|
|
|
appId,
|
2023-12-21 17:48:39 +01:00
|
|
|
gradesTable,
|
|
|
|
students.flatMap(student =>
|
|
|
|
subjects.map(subject => ({
|
2023-12-20 12:52:25 +01:00
|
|
|
Score: generator.integer({ min: 0, max: 100 }),
|
|
|
|
Student: [student],
|
|
|
|
Subject: [subject],
|
2023-12-21 17:48:39 +01:00
|
|
|
}))
|
|
|
|
)
|
|
|
|
)
|
2023-12-21 18:02:44 +01:00
|
|
|
|
|
|
|
console.log(
|
2023-12-22 11:46:49 +01:00
|
|
|
`Access the app here: http://localhost:10000/builder/app/${appId}`
|
2023-12-21 18:02:44 +01:00
|
|
|
)
|
2023-12-19 16:59:23 +01:00
|
|
|
}
|
|
|
|
|
2023-12-20 13:04:16 +01:00
|
|
|
run()
|
|
|
|
.then(() => {
|
2023-12-20 15:02:21 +01:00
|
|
|
console.log(`Done in ${(Date.now() - start) / 1000} seconds`)
|
2023-12-20 13:04:16 +01:00
|
|
|
})
|
|
|
|
.catch(err => {
|
|
|
|
console.error(err)
|
|
|
|
})
|