@joystick.js/node-canary 0.0.0-canary.34 → 0.0.0-canary.340

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/_package.json +2 -3
  2. package/dist/action/class.js +21 -0
  3. package/dist/api/get.js +15 -13
  4. package/dist/api/set.js +15 -13
  5. package/dist/app/accounts/createMetadataTableColumns.js +12 -0
  6. package/dist/app/accounts/deleteUser.js +7 -0
  7. package/dist/app/accounts/generateSession.js +2 -4
  8. package/dist/app/accounts/getBrowserSafeUser.js +5 -2
  9. package/dist/app/accounts/hasLoginTokenExpired.js +1 -2
  10. package/dist/app/accounts/index.js +2 -0
  11. package/dist/app/accounts/login.js +6 -0
  12. package/dist/app/accounts/recoverPassword.js +3 -0
  13. package/dist/app/accounts/resetPassword.js +6 -0
  14. package/dist/app/accounts/signup.js +50 -7
  15. package/dist/app/accounts/verifyEmail.js +3 -0
  16. package/dist/app/cluster.js +26 -0
  17. package/dist/app/databases/generate_sql_from_object.js +60 -0
  18. package/dist/app/databases/mongodb/buildConnectionString.js +1 -1
  19. package/dist/app/databases/mongodb/createAccountsIndexes.js +18 -0
  20. package/dist/app/databases/mongodb/createSessionsIndexes.js +10 -0
  21. package/dist/app/databases/mongodb/index.js +1 -1
  22. package/dist/app/databases/mongodb/queries/accounts.js +8 -1
  23. package/dist/app/databases/mongodb/queries/queues.js +53 -29
  24. package/dist/app/databases/mongodb/queries/sessions.js +26 -0
  25. package/dist/app/databases/postgresql/createSessionsIndexes.js +10 -0
  26. package/dist/app/databases/postgresql/createSessionsTables.js +14 -0
  27. package/dist/app/databases/postgresql/handleCleanupQueues.js +36 -0
  28. package/dist/app/databases/postgresql/index.js +88 -2
  29. package/dist/app/databases/postgresql/queries/accounts.js +5 -2
  30. package/dist/app/databases/postgresql/queries/queues.js +87 -39
  31. package/dist/app/databases/postgresql/queries/sessions.js +43 -0
  32. package/dist/app/databases/queryMap.js +6 -2
  33. package/dist/app/databases/stringToSnakeCase.js +6 -0
  34. package/dist/app/getBrowserSafeRequest.js +3 -3
  35. package/dist/app/index.js +229 -78
  36. package/dist/app/initExpress.js +1 -1
  37. package/dist/app/middleware/csp.js +2 -2
  38. package/dist/app/middleware/getTranslations.js +64 -0
  39. package/dist/app/middleware/get_insecure_landing_page_html.js +71 -0
  40. package/dist/app/middleware/hmr/client.js +13 -9
  41. package/dist/app/middleware/index.js +6 -5
  42. package/dist/app/middleware/insecure.js +3 -4
  43. package/dist/app/middleware/render.js +8 -66
  44. package/dist/app/middleware/session.js +12 -11
  45. package/dist/app/queues/index.js +77 -32
  46. package/dist/app/registerGetters.js +5 -6
  47. package/dist/app/registerSetters.js +5 -6
  48. package/dist/app/runGetter.js +17 -5
  49. package/dist/app/runSessionQuery.js +15 -0
  50. package/dist/app/runSetter.js +17 -5
  51. package/dist/app/sanitizeAPIResponse.js +1 -1
  52. package/dist/app/validateInstanceToken.js +16 -0
  53. package/dist/app/validateSession.js +8 -3
  54. package/dist/app/validateUploaderOptions.js +3 -3
  55. package/dist/app/validateUploads.js +12 -1
  56. package/dist/email/send.js +7 -1
  57. package/dist/email/templates/reset-password.js +0 -1
  58. package/dist/fixture/index.js +40 -0
  59. package/dist/index.js +19 -0
  60. package/dist/lib/escapeKeyValuePair.js +13 -0
  61. package/dist/lib/formatAPIError.js +0 -1
  62. package/dist/lib/getBuildPath.js +1 -1
  63. package/dist/lib/getSSLCertificates.js +3 -3
  64. package/dist/lib/importFile.js +7 -0
  65. package/dist/lib/isValidJSONString.js +1 -1
  66. package/dist/lib/log.js +0 -3
  67. package/dist/lib/objectToSQLKeysString.js +1 -1
  68. package/dist/lib/objectToSQLValuesString.js +1 -1
  69. package/dist/lib/serializeQueryParameters.js +1 -1
  70. package/dist/lib/timestamps.js +47 -0
  71. package/dist/lib/wait.js +8 -0
  72. package/dist/push/logs/index.js +35 -17
  73. package/dist/settings/load.js +3 -5
  74. package/dist/ssr/compileCSS.js +4 -4
  75. package/dist/ssr/findComponentInTree.js +1 -1
  76. package/dist/ssr/getAPIForDataFunctions.js +35 -0
  77. package/dist/ssr/getDataFromComponent.js +15 -0
  78. package/dist/ssr/index.js +19 -45
  79. package/dist/ssr/replaceWhenTags.js +2 -3
  80. package/dist/ssr/setHeadTagsInHTML.js +3 -3
  81. package/dist/test/index.js +9 -0
  82. package/dist/test/trackFunctionCall.js +17 -0
  83. package/dist/validation/inputWithSchema/index.js +3 -3
  84. package/dist/validation/schema/index.js +5 -5
  85. package/dist/websockets/index.js +4 -0
  86. package/getSanitizedContext.js +43 -0
  87. package/package.json +2 -2
  88. package/dist/app/accounts/roles/index.test.js +0 -123
  89. package/dist/app/index.test.js +0 -575
  90. package/dist/app/middleware/sanitizeRequestParameters.js +0 -21
  91. package/dist/email/send.test.js +0 -37
  92. package/dist/validation/index.test.js +0 -463
@@ -1,40 +1,52 @@
1
- import dayjs from "dayjs";
1
+ import getTargetDatabaseProvider from "../../getTargetDatabaseProvider.js";
2
2
  var queues_default = {
3
3
  addJob: function(jobToAdd = {}) {
4
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
5
- return db.insertOne(jobToAdd);
4
+ const db = this.db?.collection(`queue_${this.queue.name}`);
5
+ return db.insertOne({
6
+ ...jobToAdd,
7
+ attempts: 0
8
+ });
6
9
  },
7
10
  countJobs: function(status = "") {
8
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
9
- return db.countDocuments({ status });
11
+ const db = this.db?.collection(`queue_${this.queue.name}`);
12
+ return db.countDocuments({ status, lockedBy: this.machineId });
10
13
  },
11
14
  deleteJob: function(jobId = "") {
12
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
15
+ const db = this.db?.collection(`queue_${this.queue.name}`);
13
16
  return db.deleteOne({ _id: jobId });
14
17
  },
18
+ deleteIncompleteJobsForMachine: function() {
19
+ const db = this.db?.collection(`queue_${this.queue.name}`);
20
+ return db.deleteMany({ status: { $in: ["incomplete", "running"] }, lockedBy: this.machineId });
21
+ },
15
22
  getJobs: function(query = {}) {
16
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
17
- return db.find(query).toArray();
23
+ const db = this.db?.collection(`queue_${this.queue.name}`);
24
+ return db.find({
25
+ ...query,
26
+ environment: process.env.NODE_ENV
27
+ }).toArray();
18
28
  },
19
29
  getNextJobToRun: async function() {
20
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
30
+ const db = this.db?.collection(`queue_${this.queue.name}`);
21
31
  const nextJob = await db.findOneAndUpdate({
22
32
  $or: [
23
33
  {
24
34
  status: "pending",
25
- nextRunAt: { $lte: dayjs().format() },
35
+ environment: process.env.NODE_ENV,
36
+ nextRunAt: { $lte: new Date().toISOString() },
26
37
  lockedBy: { $exists: false }
27
38
  },
28
39
  {
29
40
  status: "pending",
30
- nextRunAt: { $lte: dayjs().format() },
41
+ environment: process.env.NODE_ENV,
42
+ nextRunAt: { $lte: new Date().toISOString() },
31
43
  lockedBy: null
32
44
  }
33
45
  ]
34
46
  }, {
35
47
  $set: {
36
48
  status: "running",
37
- startedAt: dayjs().format(),
49
+ startedAt: new Date().toISOString(),
38
50
  lockedBy: this.machineId
39
51
  }
40
52
  }, {
@@ -44,19 +56,36 @@ var queues_default = {
44
56
  });
45
57
  return nextJob?.value;
46
58
  },
47
- initializeDatabase: function() {
48
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
59
+ initializeDatabase: async function() {
60
+ await this.db.createCollection(`queue_${this.queue.name}`);
61
+ const db = this.db?.collection(`queue_${this.queue.name}`);
62
+ const indexes = await db?.indexes();
49
63
  db.createIndex({ status: 1 });
50
64
  db.createIndex({ status: 1, nextRunAt: 1 });
65
+ db.createIndex({ status: 1, environment: 1, nextRunAt: 1, lockedBy: 1 });
51
66
  if (this.queue.options?.cleanup?.completedAfterSeconds) {
67
+ if (indexes?.find((index) => index?.name === "completedAt_1")) {
68
+ await db.dropIndex({ completedAt: 1 });
69
+ }
52
70
  db.createIndex({ completedAt: 1 }, { expireAfterSeconds: this?.queue?.options?.cleanup?.completedAfterSeconds });
53
71
  }
54
72
  if (this.queue.options?.cleanup?.failedAfterSeconds) {
73
+ if (indexes?.find((index) => index?.name === "failedAt_1")) {
74
+ await db.dropIndex({ failedAt: 1 });
75
+ }
55
76
  db.createIndex({ failedAt: 1 }, { expireAfterSeconds: this?.queue?.options?.cleanup?.failedAfterSeconds });
56
77
  }
57
78
  },
79
+ logAttempt: function(jobId = "") {
80
+ const db = this.db?.collection(`queue_${this.queue.name}`);
81
+ return db.updateOne({ _id: jobId }, {
82
+ $inc: {
83
+ attempts: 1
84
+ }
85
+ });
86
+ },
58
87
  requeueJob: function(jobId = "", nextRunAt = null) {
59
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
88
+ const db = this.db?.collection(`queue_${this.queue.name}`);
60
89
  return db.updateOne({ _id: jobId }, {
61
90
  $set: {
62
91
  status: "pending",
@@ -67,36 +96,31 @@ var queues_default = {
67
96
  }
68
97
  });
69
98
  },
70
- setJobsForMachineIncomplete: function() {
71
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
72
- return db.updateMany({ status: "running", lockedBy: this.machineId }, {
73
- $set: {
74
- status: "incomplete"
75
- }
76
- });
77
- },
78
99
  setJobCompleted: function(jobId = "") {
79
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
100
+ const db = this.db?.collection(`queue_${this.queue.name}`);
80
101
  return db.updateOne({ _id: jobId }, {
81
102
  $set: {
82
103
  status: "completed",
83
- completedAt: dayjs().format()
104
+ completedAt: new Date(new Date().toISOString())
84
105
  }
85
106
  });
86
107
  },
87
108
  setJobFailed: function(jobId = "", error = "") {
88
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
109
+ const db = this.db?.collection(`queue_${this.queue.name}`);
89
110
  return db.updateOne({ _id: jobId }, {
90
111
  $set: {
91
112
  status: "failed",
92
- failedAt: dayjs().format(),
113
+ failedAt: new Date(new Date().toISOString()),
93
114
  error
94
115
  }
95
116
  });
96
117
  },
97
118
  setJobsForMachinePending: function() {
98
- const db = process.databases._queues?.collection(`queue_${this.queue.name}`);
99
- return db.updateMany({ status: { $in: ["pending", "running"] }, lockedBy: this.machineId }, {
119
+ const db = this.db?.collection(`queue_${this.queue.name}`);
120
+ return db.updateMany({
121
+ status: { $in: ["pending", "running"] },
122
+ lockedBy: this.machineId
123
+ }, {
100
124
  $set: {
101
125
  status: "pending"
102
126
  },
@@ -0,0 +1,26 @@
1
+ import dayjs from "dayjs";
2
+ import generateId from "../../../../lib/generateId";
3
+ var sessions_default = {
4
+ create_session: async () => {
5
+ const session_id = generateId();
6
+ await process.databases._sessions?.collection("sessions").insertOne({
7
+ _id: session_id,
8
+ csrf: generateId(32),
9
+ createdAt: new Date().toISOString()
10
+ });
11
+ return session_id;
12
+ },
13
+ get_session: async (input = {}) => {
14
+ return process.databases._sessions?.collection("sessions").findOne({
15
+ _id: input?.session_id
16
+ });
17
+ },
18
+ delete_expired_sessions: async () => {
19
+ return process.databases._sessions?.collection("sessions").deleteMany({
20
+ createdAt: { $lte: dayjs().subtract(1, "hour").format() }
21
+ });
22
+ }
23
+ };
24
+ export {
25
+ sessions_default as default
26
+ };
@@ -0,0 +1,10 @@
1
+ const createIndex = async (indexName = "", tableName = "", tableColumns = []) => {
2
+ return process.databases._sessions?.query(`CREATE INDEX IF NOT EXISTS ${indexName} ON ${tableName}(${tableColumns.join(", ")})`);
3
+ };
4
+ var createSessionsIndexes_default = async () => {
5
+ await createIndex("session_by_id", "sessions", ["session_id"]);
6
+ await createIndex("session_created_at", "sessions", ["created_at"]);
7
+ };
8
+ export {
9
+ createSessionsIndexes_default as default
10
+ };
@@ -0,0 +1,14 @@
1
+ const createTable = async (table = "", tableColumns = []) => {
2
+ return process.databases._sessions?.query(`CREATE TABLE IF NOT EXISTS ${table} (${tableColumns.join(", ")})`);
3
+ };
4
+ var createSessionsTables_default = async () => {
5
+ await createTable("sessions", [
6
+ "id bigserial primary key",
7
+ "session_id text",
8
+ "csrf text",
9
+ "created_at text"
10
+ ]);
11
+ };
12
+ export {
13
+ createSessionsTables_default as default
14
+ };
@@ -0,0 +1,36 @@
1
+ const get_future_timestamp = (timestamp, seconds = 0) => {
2
+ const date = new Date(timestamp);
3
+ date.setSeconds(date.getSeconds() + seconds);
4
+ return date.toISOString();
5
+ };
6
+ var handleCleanupQueues_default = async ({
7
+ database = {},
8
+ table = "",
9
+ seconds = 0
10
+ }) => {
11
+ const jobs_with_status = await database.query(`
12
+ SELECT * FROM ${table} WHERE status = ANY($1) AND environment = $2
13
+ `, [
14
+ ["completed", "failed"],
15
+ process.env.NODE_ENV
16
+ ]);
17
+ const jobs_to_cleanup = jobs_with_status?.filter((job = {}) => {
18
+ if (job?.status === "completed") {
19
+ const completed_at_with_seconds = get_future_timestamp(job?.completed_at, seconds);
20
+ return completed_at_with_seconds <= new Date().toISOString();
21
+ }
22
+ if (job?.status === "failed") {
23
+ const failed_at_with_seconds = get_future_timestamp(job?.failed_at, seconds);
24
+ return failed_at_with_seconds <= new Date().toISOString();
25
+ }
26
+ return false;
27
+ });
28
+ await database.query(`
29
+ DELETE FROM ${table} WHERE _id = ANY($1)
30
+ `, [
31
+ jobs_to_cleanup?.map(({ _id }) => _id)
32
+ ]);
33
+ };
34
+ export {
35
+ handleCleanupQueues_default as default
36
+ };
@@ -1,6 +1,8 @@
1
1
  import postgresql from "pg";
2
2
  import chalk from "chalk";
3
3
  import os from "os";
4
+ import fs from "fs";
5
+ import generate_sql_from_object from "../generate_sql_from_object";
4
6
  const { Pool } = postgresql;
5
7
  var postgresql_default = async (settings = {}, databasePort = 2610) => {
6
8
  const connection = settings?.connection || {
@@ -13,14 +15,20 @@ var postgresql_default = async (settings = {}, databasePort = 2610) => {
13
15
  };
14
16
  try {
15
17
  const host = connection.hosts && connection.hosts[0];
16
- const pool = new Pool({
18
+ const connection_config = {
17
19
  user: connection?.username || "",
18
20
  database: connection?.database,
19
21
  password: connection?.password || "",
20
22
  host: host?.hostname,
21
23
  port: host?.port,
22
24
  ...settings?.options || {}
23
- });
25
+ };
26
+ if (settings?.options?.ssl?.ca) {
27
+ connection_config.ssl = {
28
+ ca: fs.readFileSync(settings?.options?.ssl?.ca)
29
+ };
30
+ }
31
+ const pool = new Pool(connection_config);
24
32
  return {
25
33
  pool,
26
34
  query: (...args) => {
@@ -39,6 +47,84 @@ Failed Values:
39
47
  console.log(args[1]);
40
48
  throw error;
41
49
  });
50
+ },
51
+ add_column: (options = {}) => {
52
+ const column = generate_sql_from_object.add_column(options);
53
+ return pool.query(column.statement).then((response) => {
54
+ return response?.rows || [];
55
+ }).catch((error) => {
56
+ console.log(chalk.redBright(`
57
+ Failed SQL Statement:
58
+ `));
59
+ console.log(column.statement);
60
+ throw error;
61
+ });
62
+ },
63
+ create_table: (options = {}) => {
64
+ const table = generate_sql_from_object.create_table(options);
65
+ return pool.query(table.statement).then((response) => {
66
+ return response?.rows || [];
67
+ }).catch((error) => {
68
+ console.log(chalk.redBright(`
69
+ Failed SQL Statement:
70
+ `));
71
+ console.log(table.statement);
72
+ throw error;
73
+ });
74
+ },
75
+ insert: (options = {}) => {
76
+ const insert = generate_sql_from_object.insert(options);
77
+ return pool.query(insert.statement, insert.values).then((response) => {
78
+ return response?.rows || [];
79
+ }).catch((error) => {
80
+ console.log(chalk.redBright(`
81
+ Failed SQL Statement:
82
+ `));
83
+ console.log(insert.statement);
84
+ console.log(`
85
+ `);
86
+ console.log(chalk.redBright(`
87
+ Failed Values:
88
+ `));
89
+ console.log(insert.values);
90
+ throw error;
91
+ });
92
+ },
93
+ select: (options = {}) => {
94
+ const select = generate_sql_from_object.select(options);
95
+ return pool.query(select.statement, select.values).then((response) => {
96
+ return response?.rows || [];
97
+ }).catch((error) => {
98
+ console.log(chalk.redBright(`
99
+ Failed SQL Statement:
100
+ `));
101
+ console.log(select.statement);
102
+ console.log(`
103
+ `);
104
+ console.log(chalk.redBright(`
105
+ Failed Values:
106
+ `));
107
+ console.log(select.where);
108
+ throw error;
109
+ });
110
+ },
111
+ update: (options = {}) => {
112
+ const update = generate_sql_from_object.update(options);
113
+ return pool.query(update.statement, update.values).then((response) => {
114
+ return response?.rows || [];
115
+ }).catch((error) => {
116
+ console.log(chalk.redBright(`
117
+ Failed SQL Statement:
118
+ `));
119
+ console.log(update.statement);
120
+ console.log(`
121
+ `);
122
+ console.log(chalk.redBright(`
123
+ Failed Values:
124
+ `));
125
+ console.log(update.values);
126
+ throw error;
127
+ });
42
128
  }
43
129
  };
44
130
  } catch (exception) {
@@ -21,7 +21,7 @@ var accounts_default = {
21
21
  },
22
22
  createUser: async (input = {}) => {
23
23
  const userId = generateId();
24
- const keys = ["user_id", ...Object.keys(input) || []]?.map((inputKey) => {
24
+ const keys = ["user_id", ...Object.keys(input || {}) || []]?.map((inputKey) => {
25
25
  return camelPascalToSnake(inputKey);
26
26
  })?.join(",");
27
27
  const values = [userId, ...Object.values(input) || []];
@@ -43,8 +43,11 @@ var accounts_default = {
43
43
  }
44
44
  return null;
45
45
  },
46
+ deleteUser: async (input = {}) => {
47
+ await process.databases._users?.query(`DELETE FROM users WHERE user_id = $1`, [input?.userId]);
48
+ },
46
49
  deleteOldSessions: async (input = {}) => {
47
- await process.databases._users?.query(`DELETE FROM users_sessions WHERE user_id = $1 AND token_expires_at::date < NOW()`, [input?.userId]);
50
+ await process.databases._users?.query(`DELETE FROM users_sessions WHERE user_id = $1 AND token_expires_at::timestamp < NOW()`, [input?.userId]);
48
51
  },
49
52
  addSession: async (input = {}) => {
50
53
  await process.databases._users?.query(`INSERT INTO users_sessions(user_id, token, token_expires_at) VALUES ($1, $2, $3);`, [input?.userId, input?.session?.token, input?.session?.tokenExpiresAt]);
@@ -1,27 +1,32 @@
1
- import dayjs from "dayjs";
1
+ import cron from "node-cron";
2
+ import handleCleanupQueues from "../handleCleanupQueues";
2
3
  var queues_default = {
3
4
  addJob: function(jobToAdd = {}) {
4
- const db = process.databases._queues;
5
+ const db = this?.db;
5
6
  return db?.query(`
6
7
  INSERT INTO queue_${this.queue.name} (
7
8
  _id,
8
9
  status,
10
+ environment,
9
11
  job,
10
12
  payload,
11
- next_run_at
13
+ next_run_at,
14
+ attempts
12
15
  ) VALUES (
13
- $1, $2, $3, $4, $5
16
+ $1, $2, $3, $4, $5, $6, $7
14
17
  )
15
18
  `, [
16
19
  jobToAdd?._id,
17
20
  jobToAdd?.status,
21
+ jobToAdd?.environment,
18
22
  jobToAdd?.job,
19
23
  JSON.stringify(jobToAdd?.payload),
20
- jobToAdd?.nextRunAt
24
+ jobToAdd?.nextRunAt,
25
+ 0
21
26
  ]);
22
27
  },
23
28
  countJobs: async function(status = "") {
24
- const db = process.databases._queues;
29
+ const db = this?.db;
25
30
  const [jobs] = await db?.query(`
26
31
  SELECT
27
32
  count(*)
@@ -29,13 +34,16 @@ var queues_default = {
29
34
  queue_${this.queue.name}
30
35
  WHERE
31
36
  status = $1
37
+ AND
38
+ locked_by = $2
32
39
  `, [
33
- status
40
+ status,
41
+ this.machineId
34
42
  ]);
35
43
  return Promise.resolve(jobs.count);
36
44
  },
37
45
  deleteJob: function(jobId = "") {
38
- const db = process.databases._queues;
46
+ const db = this?.db;
39
47
  return db?.query(`
40
48
  DELETE FROM
41
49
  queue_${this.queue.name}
@@ -45,34 +53,55 @@ var queues_default = {
45
53
  jobId
46
54
  ]);
47
55
  },
56
+ deleteIncompleteJobsForMachine: function() {
57
+ const db = this?.db;
58
+ return db?.query(`
59
+ DELETE FROM
60
+ queue_${this.queue.name}
61
+ WHERE
62
+ status = ANY($1)
63
+ AND
64
+ locked_by = $2
65
+ `, [
66
+ ["incomplete", "running"],
67
+ this.machineId
68
+ ]);
69
+ },
48
70
  getJobs: function(query = {}) {
49
- const db = process.databases._queues;
71
+ const db = this?.db;
50
72
  return db?.query(`
51
73
  SELECT * FROM
52
74
  queue_${this.queue.name}
53
75
  ${query?.status ? `
54
76
  WHERE
55
77
  status = $1
78
+ AND
79
+ environment = $2
56
80
  ` : ""}
57
81
  `, [
58
- query?.status
82
+ query?.status,
83
+ process.env.NODE_ENV
59
84
  ]);
60
85
  },
61
86
  getNextJobToRun: async function() {
62
- const db = process.databases._queues;
87
+ const db = this?.db;
63
88
  const [nextJob] = await db?.query(`
64
89
  SELECT * FROM
65
90
  queue_${this.queue.name}
66
91
  WHERE
67
92
  status = $1
68
93
  AND
69
- next_run_at::date <= NOW()
94
+ environment = $2
95
+ AND
96
+ next_run_at::timestamp <= $3
70
97
  AND
71
98
  locked_by IS NULL
72
99
  ORDER BY
73
100
  next_run_at ASC
74
101
  `, [
75
- "pending"
102
+ "pending",
103
+ process.env.NODE_ENV,
104
+ new Date().toISOString()
76
105
  ]);
77
106
  if (nextJob?._id) {
78
107
  await db?.query(`
@@ -86,7 +115,7 @@ var queues_default = {
86
115
  _id = $4
87
116
  `, [
88
117
  "running",
89
- dayjs().format(),
118
+ new Date().toISOString(),
90
119
  this.machineId,
91
120
  nextJob?._id
92
121
  ]);
@@ -97,11 +126,12 @@ var queues_default = {
97
126
  } : {};
98
127
  },
99
128
  initializeDatabase: async function() {
100
- const db = process.databases._queues;
129
+ const db = this?.db;
101
130
  await db?.query(`
102
131
  CREATE TABLE IF NOT EXISTS queue_${this.queue.name} (
103
132
  _id text PRIMARY KEY,
104
133
  status text,
134
+ environment text,
105
135
  job text,
106
136
  payload text,
107
137
  next_run_at text,
@@ -109,51 +139,69 @@ var queues_default = {
109
139
  started_at text,
110
140
  completed_at text,
111
141
  failed_at text,
112
- error text
142
+ error text,
143
+ attempts smallint
113
144
  )
114
145
  `);
146
+ db?.query(`ALTER TABLE queue_${this.queue.name} ADD COLUMN IF NOT EXISTS attempts smallint`);
147
+ db?.query(`ALTER TABLE queue_${this.queue.name} ADD COLUMN IF NOT EXISTS environment text`);
115
148
  db?.query(`CREATE INDEX IF NOT EXISTS status_index ON queue_${this.queue.name} (status)`);
116
149
  db?.query(`CREATE INDEX IF NOT EXISTS status_nextRunAt_index ON queue_${this.queue.name} (status, next_run_at)`);
150
+ db?.query(`CREATE INDEX IF NOT EXISTS nextJob_index ON queue_${this.queue.name} (status, environment, next_run_at, locked_by)`);
117
151
  db?.query(`CREATE INDEX IF NOT EXISTS completedAt_index ON queue_${this.queue.name} (completed_at)`);
118
152
  db?.query(`CREATE INDEX IF NOT EXISTS failedAt_index ON queue_${this.queue.name} (failed_at)`);
153
+ if (this.queue.options?.cleanup?.completedAfterSeconds) {
154
+ cron.schedule("*/30 * * * * *", () => {
155
+ handleCleanupQueues({
156
+ database: db,
157
+ table: `queue_${this.queue.name}`,
158
+ seconds: this.queue.options?.cleanup?.completedAfterSeconds
159
+ });
160
+ });
161
+ }
162
+ if (this.queue.options?.cleanup?.failedAfterSeconds) {
163
+ cron.schedule("*/30 * * * * *", () => {
164
+ handleCleanupQueues({
165
+ database: db,
166
+ table: `queue_${this.queue.name}`,
167
+ seconds: this.queue.options?.cleanup?.failedAfterSeconds
168
+ });
169
+ });
170
+ }
119
171
  },
120
- requeueJob: function(jobId = "", nextRunAt = null) {
121
- const db = process.databases._queues;
172
+ logAttempt: function(jobId = "") {
173
+ const db = this?.db;
122
174
  return db?.query(`
123
175
  UPDATE
124
176
  queue_${this.queue.name}
125
177
  SET
126
- status = $1,
127
- next_run_at = $2,
128
- locked_by = $3
178
+ attempts = attempts + 1
129
179
  WHERE
130
- _id = $4
180
+ _id = $1
131
181
  `, [
132
- "pending",
133
- nextRunAt,
134
- null,
135
182
  jobId
136
183
  ]);
137
184
  },
138
- setJobsForMachineIncomplete: function() {
139
- const db = process.databases._queues;
185
+ requeueJob: function(jobId = "", nextRunAt = null) {
186
+ const db = this?.db;
140
187
  return db?.query(`
141
188
  UPDATE
142
189
  queue_${this.queue.name}
143
190
  SET
144
- status = $1
145
- WHERE
146
- status = $2
147
- AND
191
+ status = $1,
192
+ next_run_at = $2,
148
193
  locked_by = $3
194
+ WHERE
195
+ _id = $4
149
196
  `, [
150
- "incomplete",
151
- "running",
152
- this.machineId
197
+ "pending",
198
+ nextRunAt,
199
+ null,
200
+ jobId
153
201
  ]);
154
202
  },
155
203
  setJobCompleted: function(jobId = "") {
156
- const db = process.databases._queues;
204
+ const db = this?.db;
157
205
  return db?.query(`
158
206
  UPDATE
159
207
  queue_${this.queue.name}
@@ -164,12 +212,12 @@ var queues_default = {
164
212
  _id = $3
165
213
  `, [
166
214
  "completed",
167
- dayjs().format(),
215
+ new Date().toISOString(),
168
216
  jobId
169
217
  ]);
170
218
  },
171
219
  setJobFailed: function(jobId = "", error = "") {
172
- const db = process.databases._queues;
220
+ const db = this?.db;
173
221
  return db?.query(`
174
222
  UPDATE
175
223
  queue_${this.queue.name}
@@ -181,13 +229,13 @@ var queues_default = {
181
229
  _id = $4
182
230
  `, [
183
231
  "failed",
184
- dayjs().format(),
232
+ new Date().toISOString(),
185
233
  error,
186
234
  jobId
187
235
  ]);
188
236
  },
189
237
  setJobsForMachinePending: function() {
190
- const db = process.databases._queues;
238
+ const db = this?.db;
191
239
  return db?.query(`
192
240
  UPDATE
193
241
  queue_${this.queue.name}
@@ -0,0 +1,43 @@
1
+ import generateId from "../../../../lib/generateId";
2
+ var sessions_default = {
3
+ create_session: async (input = {}) => {
4
+ const session_id = generateId();
5
+ await process.databases._sessions?.query(`
6
+ INSERT INTO
7
+ sessions (
8
+ session_id,
9
+ csrf,
10
+ created_at
11
+ )
12
+ VALUES ($1, $2, $3)
13
+ `, [
14
+ session_id,
15
+ generateId(32),
16
+ new Date().toISOString()
17
+ ]);
18
+ return session_id;
19
+ },
20
+ get_session: async (input = {}) => {
21
+ const [session] = await process.databases._sessions?.query(`
22
+ SELECT * FROM
23
+ sessions
24
+ WHERE
25
+ session_id = $1
26
+ `, [
27
+ input?.session_id
28
+ ]);
29
+ return session;
30
+ },
31
+ delete_expired_sessions: async () => {
32
+ const date = new Date();
33
+ date.setHours(date.getHours() - 1);
34
+ return process.databases.postgresql.query(`
35
+ DELETE FROM sessions WHERE created_at::timestamp < $1
36
+ `, [
37
+ date.toISOString()
38
+ ]);
39
+ }
40
+ };
41
+ export {
42
+ sessions_default as default
43
+ };