@joystick.js/node-canary 0.0.0-canary.384 → 0.0.0-canary.385

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.
@@ -1 +1 @@
1
- import i from"../../../databases/queries/accounts.js";import u from"../../../accounts/default_user_output_fields.js";import _ from"../../format_api_error.js";import d from"../../handle_api_error.js";import p from"../../validate_input.js";import m from"../../../accounts/signup.js";const c=async(t={},s={})=>{try{const a=await i("user",{email_address:t?.body?.emailAddress||t?.body?.email_address});a&&await i("delete_user",{user_id:a?._id||a?.user_id});const e=process.joystick?.app_options?.accounts?.signup?.metadata,r=e?await p(t?.body?.metadata,e):[];if(r?.length>0)return d("accounts.signup",{errors:r.map(n=>_(new Error(n),"accounts.signup.metadata",401))},s);const o=await m({email_address:t?.body?.emailAddress||t?.body?.email_address,password:t?.body?.password,metadata:t?.body?.metadata,output:t?.body?.output||u});s.status(200).send(JSON.stringify({...o?.user||{},joystick_login_token:o?.token,joystick_login_token_expires_at:o?.token_expires_at}))}catch(a){d("test.accounts.signup",a,s)}};var w=c;export{w as default};
1
+ import r from"../../../databases/queries/accounts.js";import m from"../../../accounts/default_user_output_fields.js";import p from"../../format_api_error.js";import d from"../../handle_api_error.js";import c from"../../validate_input.js";import y from"../../../accounts/signup.js";const l=async(t={},s={})=>{try{const a=await r("user",{email_address:t?.body?.emailAddress||t?.body?.email_address}),u=await r("user",{username:t?.body?.username}),e=a||u;e&&await r("delete_user",{user_id:e?._id||e?.user_id});const i=process.joystick?.app_options?.accounts?.signup?.metadata,n=i?await c(t?.body?.metadata,i):[];if(n?.length>0)return d("accounts.signup",{errors:n.map(_=>p(new Error(_),"accounts.signup.metadata",401))},s);const o=await y({email_address:t?.body?.emailAddress||t?.body?.email_address,username:t?.body?.username,password:t?.body?.password,metadata:t?.body?.metadata,output:t?.body?.output||m});s.status(200).send(JSON.stringify({...o?.user||{},joystick_login_token:o?.token,joystick_login_token_expires_at:o?.token_expires_at}))}catch(a){d("test.accounts.signup",a,s)}};var x=l;export{x as default};
@@ -1 +1 @@
1
- import _ from"chalk";import{htmlToText as d}from"html-to-text";import g from"juice";import v from"nodemailer";import w from"../../lib/dynamic_import.js";import b from"../../lib/get_joystick_build_path.js";import j from"../../lib/get_translations.js";import x from"../settings/load.js";import y from"../../lib/path_exists.js";import T from"../ssr/index.js";import $ from"../../test/track_function_call.js";import k from"./validate_smtp_settings.js";const e=x(),E=async(t={})=>{if(process.env.NODE_ENV==="test"){$("node.email.send",[t]);return}const s=k(e?.config?.email?.smtp);if(!s)return console.warn(_.redBright("Invalid SMTP settings. Cannot send email.")),Promise.resolve(null);const r=parseInt(e?.config?.email?.smtp?.port,10),n=r===465||![25,587].includes(r),l=s?v.createTransport({host:e?.config?.email?.smtp?.host,port:r,secure:n,auth:{user:e?.config?.email?.smtp?.username,pass:e?.config?.email?.smtp?.password}}):null,m=b(),a=`${m}email/${t?.template}.js`,p=t?.template&&await y(a),o={from:e?.config?.email?.from,...t};if(p){const c=await w(`${a}?v=${new Date().getTime()}`),u=await j({is_email:!0,email_template_name:t?.template,joystick_build_path:m,req:{context:{user:t?.user}}}),i=await T({is_email:!0,component_options:{props:t?.props,translations:u},component_to_render:c,email_options:{base_html_name:t?.base,subject:t?.subject,preheader:t?.preheader}}),f=d(i),h=g(i,{preserveMediaQueries:!0,preserveImportant:!0,removeStyleTags:!1});return o.html=h,o.text=f,l.sendMail(o)}return console.warn(`Email template at /email/${t?.template}.js could not be found.`),Promise.resolve()};var z=E;export{z as default};
1
+ import d from"chalk";import{htmlToText as _}from"html-to-text";import w from"juice";import b from"nodemailer";import j from"../../lib/dynamic_import.js";import x from"../../lib/get_joystick_build_path.js";import y from"../../lib/get_translations.js";import T from"../settings/load.js";import v from"../../lib/path_exists.js";import $ from"../ssr/index.js";import k from"../../test/track_function_call.js";import E from"./validate_smtp_settings.js";const r=T(),I=async(t={},e={})=>{if(process.env.NODE_ENV==="test"){k("node.email.send",[t]);return}const a=E(r?.config?.email?.smtp);if(!a)return console.warn(d.redBright("Invalid SMTP settings. Cannot send email.")),Promise.resolve(null);const s=parseInt(e?.port||r?.config?.email?.smtp?.port,10),l=s===465||![25,587].includes(s),p=a?b.createTransport({host:e?.host||r?.config?.email?.smtp?.host,port:s,secure:l,auth:{user:e?.username||r?.config?.email?.smtp?.username,pass:e?.password||r?.config?.email?.smtp?.password}}):null,m=x(),n=`${m}email/${t?.template}.js`,c=t?.template&&await v(n),o={from:r?.config?.email?.from,...t};if(e?.headers&&(o.headers=e?.headers),c){const u=await j(`${n}?v=${new Date().getTime()}`),f=await y({is_email:!0,email_template_name:t?.template,joystick_build_path:m,req:{context:{user:t?.user}}}),i=await $({is_email:!0,component_options:{props:t?.props,translations:f},component_to_render:u,email_options:{base_html_name:t?.base,subject:t?.subject,preheader:t?.preheader}}),h=_(i),g=w(i,{preserveMediaQueries:!0,preserveImportant:!0,removeStyleTags:!1});return o.html=g,o.text=h,p.sendMail(o)}return console.warn(`Email template at /email/${t?.template}.js could not be found.`),Promise.resolve()};var A=I;export{A as default};
@@ -1 +1 @@
1
- const u=async(n,o,r)=>{n.context={...n?.context||{},ifLoggedIn:(t="",e=null)=>{if(n?.context?.user&&t)return o.redirect(t);if(e)return e()},ifNotLoggedIn:(t="",e=null)=>{if(!n?.context?.user&&t)return o.redirect(t);if(e)return e()},...process.databases||{}},r()};var f=u;export{f as default};
1
+ const t=(e="",n=null)=>{if(req?.context?.user&&e)return res.redirect(e);if(n)return n()},r=(e="",n=null)=>{if(!req?.context?.user&&e)return res.redirect(e);if(n)return n()},s=async(e,n,o)=>{e.context={...e?.context||{},if_logged_in:t,ifLoggedIn:t,if_not_logged_in:r,ifNotLoggedIn:r,...process.databases||{}},o()};var i=s;export{i as default};
@@ -1 +1 @@
1
- import d from"chalk";import h from"fs";import c from"os";import b from"../../lib/generate_id.js";import f from"../databases/get_target_database_connection.js";import l from"../databases/queries/map.js";import _ from"../../lib/timestamps.js";import i from"../../lib/types.js";import p from"../../test/track_function_call.js";class m{constructor(e="",t={}){this.init_database=this.init_database.bind(this),this.machine_id=h.readFileSync(`${c.homedir()}/.cheatcode/MACHINE_ID`,"utf-8")?.trim().replace(/\n/g,""),this.name=e,this.options={concurrent_jobs:1,...t},this.init_database(this?.options?.external,this?.options?.database?.provider)}async init_database(e=!1,t=null){const n=t||f("queues")?.provider,s=l[n]?.queues,o=this._get_database_connection();i.is_object(o)&&i.is_object(s)&&(this.db=Object.entries(s||{})?.reduce((a={},[r,u])=>(a[r]=u.bind({db:o,machine_id:this.machine_id,queue:{name:this.name,options:this.options}}),a),{_connection:o}),e||(await this.db.initialize_database(n),(this?.options?.runOnStartup||this?.options?.run_on_startup)&&this.run()))}_get_database_connection(){if(this?.options?.database){const{provider:e,name:t}=this?.options?.database,n=process.databases&&process.databases[e]&&process.databases[e][t];return n||console.warn(d.red(`Connection to database ${e}.${t} not found on process. Cannot start queue.`)),n||null}return process.databases._queues}async add(e={}){const t=(e?.next_run_at||e?.next_run_at)==="now"||!e?.next_run_at&&!e?.next_run_at?_.get_future_time():e?.next_run_at||e?.next_run_at,n={_id:b(16),status:"pending",environment:process.env.NODE_ENV,next_run_at:t,job:e?.job,payload:e?.payload},s=this?.options?.jobs&&this?.options?.jobs[e?.job];if(s&&(i.is_function(s?.preflight?.onBeforeAdd)||i.is_function(s?.preflight?.on_before_add))&&!await(s?.preflight?.onBeforeAdd||s?.preflight?.on_before_add)(n,this.db._connection,`queue_${this.name}`))return null;this.db.add_job(n)}async _check_if_okay_to_run_jobs(){return await this._get_number_of_jobs_running()<(this.options.concurrent_jobs||this.options.concurrent_jobs)}_get_number_of_jobs_running(){return this.db.count_jobs("running")}_handle_requeue_jobs_running_before_restart(){if(this.db)return!this.options.retryJobsRunningBeforeRestart&&!this.options.retry_jobs_running_before_restart?this.db.delete_incomplete_jobs_for_machine():this.db.set_jobs_for_machine_pending()}run(){this.db&&(process.env.NODE_ENV!=="test"&&console.log(`Starting ${this.name} queue...`),this._handle_requeue_jobs_running_before_restart().then(()=>{setInterval(async()=>{if(await this._check_if_okay_to_run_jobs()&&!process.env.HALT_QUEUES){const t=await this.db.get_next_job_to_run();this.handle_next_job(t)}},300)}))}async handle_next_job(e={}){const t=this.options.jobs[e?.job];if(e&&e?.job&&t&&i.is_function(t?.run))try{if((i.is_function(t?.preflight?.okayToRun)||i.is_function(t?.preflight?.okay_to_run))&&!await(t?.preflight?.okayToRun||t?.preflight?.okay_to_run)(e?.payload,e))return this._handle_requeue_job(e,_.get_future_time("seconds",t?.preflight?.requeueDelayInSeconds||t?.preflight?.requeue_delay_in_seconds||10));if((i.is_number(t?.maxAttempts)||i.is_number(t?.max_attempts))&&e?.attempts>=parseInt(t?.maxAttempts||t?.max_attempts,10))return(i.is_function(t?.onMaxAttemptsExhausted)||i.is_function(t?.on_max_attempts_exhausted))&&await(t.onMaxAttemptsExhausted||t.on_max_attempts_exhausted)(e),this._handle_delete_job(e?._id);await this._log_attempt(e?._id),p(`node.queues.${this?.name}.jobs.${e?.job}`,[e?.payload]),await t.run(e?.payload,{...e,queue:this,completed:()=>this._handle_job_completed(e?._id),failed:n=>this._handle_job_failed(e,t,n),delete:()=>this._handle_delete_job(e?._id),requeue:(n="")=>this._handle_requeue_job(e,n)})}catch(n){console.warn(n),this._handle_job_failed(e,t,n)}}_log_attempt(e=""){return this.db.log_attempt(e)}_handle_job_completed(e=""){return this.db.set_job_completed(e)}_handle_job_failed(e={},t={},n=""){return t?.requeueOnFailure||t?.requeue_on_failure?this._handle_requeue_job(e,_.get_future_time("seconds",10)):this.db.set_job_failed(e?._id,n)}_handle_delete_job(e=""){return this.db.delete_job(e)}_handle_requeue_job(e={},t=null){return this.db.requeue_job(e?._id,t||_.get_future_time())}list(e=""){const t={};return e&&(t.status=e),this.db.get_jobs(t)}}var $=m;export{$ as default};
1
+ import d from"chalk";import h from"fs";import c from"os";import b from"../../lib/generate_id.js";import f from"../databases/get_target_database_connection.js";import l from"../databases/queries/map.js";import _ from"../../lib/timestamps.js";import i from"../../lib/types.js";import p from"../../test/track_function_call.js";class m{constructor(e="",t={}){this.init_database=this.init_database.bind(this),this.machine_id=h.readFileSync(`${c.homedir()}/.cheatcode/MACHINE_ID`,"utf-8")?.trim().replace(/\n/g,""),this.name=e,this.options={concurrent_jobs:1,...t},this.init_database(this?.options?.external,this?.options?.database?.provider)}async init_database(e=!1,t=null){const n=t||f("queues")?.provider,s=l[n]?.queues,o=this._get_database_connection();i.is_object(o)&&i.is_object(s)&&(this.db=Object.entries(s||{})?.reduce((a={},[r,u])=>(a[r]=u.bind({db:o,machine_id:this.machine_id,queue:{name:this.name,options:this.options}}),a),{_connection:o}),e||(await this.db.initialize_database(n),(this?.options?.runOnStartup||this?.options?.run_on_startup)&&this.run()))}_get_database_connection(){if(this?.options?.database){const{provider:e,name:t}=this?.options?.database,n=process.databases&&process.databases[e]&&process.databases[e][t];return n||console.warn(d.red(`Connection to database ${e}.${t} not found on process. Cannot start queue.`)),n||null}return process.databases._queues}async add(e={}){const t=(e?.next_run_at||e?.next_run_at)==="now"||!e?.next_run_at&&!e?.next_run_at?_.get_future_time():e?.next_run_at||e?.next_run_at,n={_id:b(16),status:"pending",environment:process.env.NODE_ENV,next_run_at:t,job:e?.job,payload:e?.payload},s=this?.options?.jobs&&this?.options?.jobs[e?.job];if(s&&(i.is_function(s?.preflight?.onBeforeAdd)||i.is_function(s?.preflight?.on_before_add))&&!await(s?.preflight?.onBeforeAdd||s?.preflight?.on_before_add)(n,this.db._connection,`queue_${this.name}`))return null;this.db.add_job(n)}async _check_if_okay_to_run_jobs(){return await this._get_number_of_jobs_running()<(this.options.concurrent_jobs||this.options.concurrent_jobs||1)}_get_number_of_jobs_running(){return this.db.count_jobs("running")}_handle_requeue_jobs_running_before_restart(){if(this.db)return!this.options.retryJobsRunningBeforeRestart&&!this.options.retry_jobs_running_before_restart?this.db.delete_incomplete_jobs_for_machine():this.db.set_jobs_for_machine_pending()}run(){this.db&&(process.env.NODE_ENV!=="test"&&console.log(`Starting ${this.name} queue...`),this._handle_requeue_jobs_running_before_restart().then(()=>{setInterval(async()=>{if(await this._check_if_okay_to_run_jobs()&&!process.env.HALT_QUEUES){const t=await this.db.get_next_job_to_run();this.handle_next_job(t)}},300)}))}async handle_next_job(e={}){const t=this.options.jobs[e?.job];if(e&&e?.job&&t&&i.is_function(t?.run))try{if((i.is_function(t?.preflight?.okayToRun)||i.is_function(t?.preflight?.okay_to_run))&&!await(t?.preflight?.okayToRun||t?.preflight?.okay_to_run)(e?.payload,e))return this._handle_requeue_job(e,_.get_future_time("seconds",t?.preflight?.requeueDelayInSeconds||t?.preflight?.requeue_delay_in_seconds||10));if((i.is_number(t?.maxAttempts)||i.is_number(t?.max_attempts))&&e?.attempts>=parseInt(t?.maxAttempts||t?.max_attempts,10))return(i.is_function(t?.onMaxAttemptsExhausted)||i.is_function(t?.on_max_attempts_exhausted))&&await(t.onMaxAttemptsExhausted||t.on_max_attempts_exhausted)(e),this._handle_delete_job(e?._id);await this._log_attempt(e?._id),p(`node.queues.${this?.name}.jobs.${e?.job}`,[e?.payload]),await t.run(e?.payload,{...e,queue:this,completed:()=>this._handle_job_completed(e?._id),failed:n=>this._handle_job_failed(e,t,n),delete:()=>this._handle_delete_job(e?._id),requeue:(n="")=>this._handle_requeue_job(e,n)})}catch(n){console.warn(n),this._handle_job_failed(e,t,n)}}_log_attempt(e=""){return this.db.log_attempt(e)}_handle_job_completed(e=""){return this.db.set_job_completed(e)}_handle_job_failed(e={},t={},n=""){return t?.requeueOnFailure||t?.requeue_on_failure?this._handle_requeue_job(e,_.get_future_time("seconds",10)):this.db.set_job_failed(e?._id,n)}_handle_delete_job(e=""){return this.db.delete_job(e)}_handle_requeue_job(e={},t=null){return this.db.requeue_job(e?._id,t||_.get_future_time())}list(e=""){const t={};return e&&(t.status=e),this.db.get_jobs(t)}}var $=m;export{$ as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@joystick.js/node-canary",
3
3
  "type": "module",
4
- "version": "0.0.0-canary.384",
4
+ "version": "0.0.0-canary.385",
5
5
  "description": "The Node.js framework for Joystick.",
6
6
  "main": "./dist/index.js",
7
7
  "scripts": {
@@ -10,7 +10,9 @@ const test_accounts_signup = async (req = {}, res = {}) => {
10
10
  // NOTE: Assume accounts created in tests are ephemeral on a per-run basis.
11
11
  // When signing up, automatically delete an existing user to avoid fragile
12
12
  // tests and conflicts between runs.
13
- const existing_user = await accounts_query('user', { email_address: req?.body?.emailAddress || req?.body?.email_address });
13
+ const existing_user_with_email = await accounts_query('user', { email_address: req?.body?.emailAddress || req?.body?.email_address });
14
+ const existing_user_with_username = await accounts_query('user', { username: req?.body?.username });
15
+ const existing_user = existing_user_with_email || existing_user_with_username;
14
16
 
15
17
  if (existing_user) {
16
18
  await accounts_query('delete_user', { user_id: existing_user?._id || existing_user?.user_id });
@@ -29,6 +31,7 @@ const test_accounts_signup = async (req = {}, res = {}) => {
29
31
 
30
32
  const signup_response = await signup({
31
33
  email_address: req?.body?.emailAddress || req?.body?.email_address,
34
+ username: req?.body?.username,
32
35
  password: req?.body?.password,
33
36
  metadata: req?.body?.metadata,
34
37
  output: req?.body?.output || default_user_output_fields,
@@ -13,7 +13,7 @@ import validate_smtp_settings from "./validate_smtp_settings.js";
13
13
 
14
14
  const settings = load_settings();
15
15
 
16
- const send_email = async (send_email_options = {}) => {
16
+ const send_email = async (send_email_options = {}, smtp_overrides = {}) => {
17
17
  if (process.env.NODE_ENV === 'test') {
18
18
  // NOTE: In a test environment, we do not actually want to send an email. Instead,
19
19
  // track the call and then return.
@@ -31,17 +31,17 @@ const send_email = async (send_email_options = {}) => {
31
31
  // NOTE: Check the port number as nodemailer notes most SMTP providers required a plaintext
32
32
  // connection *first* before upgrading the connection via STARTTLS. This prevents an SSL error
33
33
  // when sending emails via SMTP port 587 or 25. See: https://nodemailer.com/smtp/#tls-options.
34
- const smtp_port = parseInt(settings?.config?.email?.smtp?.port, 10);
34
+ const smtp_port = parseInt(smtp_overrides?.port || settings?.config?.email?.smtp?.port, 10);
35
35
  const should_use_secure = smtp_port === 465 || ![25, 587].includes(smtp_port);
36
36
 
37
37
  const smtp = valid_smtp_settings
38
38
  ? nodemailer.createTransport({
39
- host: settings?.config?.email?.smtp?.host,
39
+ host: smtp_overrides?.host || settings?.config?.email?.smtp?.host,
40
40
  port: smtp_port,
41
41
  secure: should_use_secure,
42
42
  auth: {
43
- user: settings?.config?.email?.smtp?.username,
44
- pass: settings?.config?.email?.smtp?.password,
43
+ user: smtp_overrides?.username || settings?.config?.email?.smtp?.username,
44
+ pass: smtp_overrides?.password || settings?.config?.email?.smtp?.password,
45
45
  },
46
46
  })
47
47
  : null;
@@ -55,6 +55,10 @@ const send_email = async (send_email_options = {}) => {
55
55
  ...send_email_options,
56
56
  };
57
57
 
58
+ if (smtp_overrides?.headers) {
59
+ nodemailer_options.headers = smtp_overrides?.headers;
60
+ }
61
+
58
62
  if (template_exists) {
59
63
  const email_template_component = await dynamic_import(`${template_path}?v=${new Date().getTime()}`);
60
64
 
@@ -1,24 +1,30 @@
1
+ const if_logged_in = (redirect_path = "", callback = null) => {
2
+ if (!!req?.context?.user && redirect_path) {
3
+ return res.redirect(redirect_path);
4
+ }
5
+
6
+ if (callback) {
7
+ return callback();
8
+ }
9
+ };
10
+
11
+ const if_not_logged_in = (redirect_path = "", callback = null) => {
12
+ if (!req?.context?.user && redirect_path) {
13
+ return res.redirect(redirect_path);
14
+ }
15
+
16
+ if (callback) {
17
+ return callback();
18
+ }
19
+ };
20
+
1
21
  const context_middleware = async (req, res, next) => {
2
22
  req.context = {
3
23
  ...(req?.context || {}),
4
- ifLoggedIn: (redirect_path = "", callback = null) => {
5
- if (!!req?.context?.user && redirect_path) {
6
- return res.redirect(redirect_path);
7
- }
8
-
9
- if (callback) {
10
- return callback();
11
- }
12
- },
13
- ifNotLoggedIn: (redirect_path = "", callback = null) => {
14
- if (!req?.context?.user && redirect_path) {
15
- return res.redirect(redirect_path);
16
- }
17
-
18
- if (callback) {
19
- return callback();
20
- }
21
- },
24
+ if_logged_in,
25
+ ifLoggedIn: if_logged_in,
26
+ if_not_logged_in,
27
+ ifNotLoggedIn: if_not_logged_in,
22
28
  ...(process.databases || {}),
23
29
  };
24
30
 
@@ -123,7 +123,7 @@ class Queue {
123
123
 
124
124
  async _check_if_okay_to_run_jobs() {
125
125
  const jobs_running = await this._get_number_of_jobs_running();
126
- return jobs_running < (this.options.concurrent_jobs || this.options.concurrent_jobs);
126
+ return jobs_running < (this.options.concurrent_jobs || this.options.concurrent_jobs || 1);
127
127
  }
128
128
 
129
129
  _get_number_of_jobs_running() {