diff --git a/README.md b/README.md index eee74593d..6ff9aeaf0 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ It uses: ## Card wall -REPLACE THIS TEXT WITH A LINK TO YOUR CARD WALL +https://trello.com/b/u8jfD7dB/milton-acebook ## Quickstart diff --git a/app.js b/app.js index bb2057955..7ab992a95 100644 --- a/app.js +++ b/app.js @@ -9,14 +9,51 @@ const methodOverride = require("method-override"); const homeRouter = require("./routes/home"); const postsRouter = require("./routes/posts"); const sessionsRouter = require("./routes/sessions"); -const usersRouter = require("./routes/users"); +const usersRouter = require("./routes/users"); +const expressHbs = require('express-handlebars'); + const app = express(); +app.engine('.hbs', expressHbs.engine({ defaultLayout: 'layout', extname: '.hbs',runtimeOptions: { + allowProtoPropertiesByDefault: true, + allowProtoMethodsByDefault: true +} })) + // view engine setup app.set("views", path.join(__dirname, "views")); app.set("view engine", "hbs"); +const hbs = expressHbs.create({}); + +//Date format helper +hbs.handlebars.registerHelper('formatDate', function(posts) { + const options = { weekday: 'long', day: 'numeric', month: 'long', hour: 'numeric', minute: 'numeric' }; + const formattedDate = posts.date.toLocaleDateString('en-US', options); + return formattedDate; +}); + +//A simple helper to determine whether there has been one 'like' or multiple 'likes' +hbs.handlebars.registerHelper('if_equal', function(posts) { + if (posts.like.length === 1) { + return "like"; + } else { + return "likes"; +} +}); + +//Like button helper this checks if the session user has liked a post and if so displays the like +// button with a coloured spade if not displays the like button with a blank spade +// hbs.handlebars.registerHelper('likeButton', function(posts) { +// if (posts.like.length === 1) { +// return "like"; +// } else { +// return "likes"; +// } +// }); + + + app.use(logger("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: true })); @@ -24,6 +61,7 @@ app.use(cookieParser()); app.use(express.static(path.join(__dirname, "public"))); app.use(methodOverride("_method")); + app.use( session({ key: "user_sid", @@ -47,7 +85,7 @@ app.use((req, res, next) => { // middleware function to check for logged-in users const sessionChecker = (req, res, next) => { if (!req.session.user && !req.cookies.user_sid) { - res.redirect("/sessions/new"); + res.redirect("/sessions/login"); } else { next(); } @@ -59,6 +97,7 @@ app.use("/posts", sessionChecker, postsRouter); app.use("/sessions", sessionsRouter); app.use("/users", usersRouter); + // catch 404 and forward to error handler app.use((req, res, next) => { next(createError(404)); diff --git a/controllers/home.js b/controllers/home.js index 667b4decc..e03f8d6e0 100644 --- a/controllers/home.js +++ b/controllers/home.js @@ -5,3 +5,6 @@ const HomeController = { }; module.exports = HomeController; + + +// add to this page to make the appearance more dynamic :) diff --git a/controllers/posts.js b/controllers/posts.js index 4b521304d..b4ae3a13a 100644 --- a/controllers/posts.js +++ b/controllers/posts.js @@ -6,23 +6,110 @@ const PostsController = { if (err) { throw err; } - - res.render("posts/index", { posts: posts }); + // const dateFormatted = `${posts[0].date.getHours()}:${posts[0].date.getMinutes()}, ${posts[0].date.toDateString()}`; + // console.log(dateFormatted); + + const sortedPosts = posts.flat().sort((a, b) => b.date - a.date); + // sortedPosts[0].date = dateFormatted; + // Implemented authentication logic to dynamically update navbar links based on the user's login status. + res.render("posts/index", { posts: sortedPosts, user: req.session.user, isAuthenticated: true}); }); + }, + New: (req, res) => { - res.render("posts/new", {}); + res.render("posts/new", {user: req.session.user, isAuthenticated: true}); }, + Create: (req, res) => { - const post = new Post(req.body); - post.save((err) => { - if (err) { - throw err; - } + const { message, likes } = req.body; + const username = req.session.user.username; + const post = new Post({ username, message, likes }); + + console.log(`message ${post.message}`) + + if (post.message == '' ) { + res.render('posts/new', {error: "The post cannot be left blank!"}); + } else { + post.save((err) => { + if (err) { + throw err; + } + + res.status(201).redirect("/posts"); + }); + } + }, + + Edit: async (req, res) => { + const post_id = req.params.id; + console.log(`Post_id ${post_id}`); + const user_id = req.session.user._id; + console.log(`user_id ${user_id}`); + + const post = await Post.findOne({ _id: post_id }); + console.log(`post ${post}`); + + res.render("posts/edit", { post: post , user: req.session.user, isAuthenticated: true}); + + }, + + Update: async (req, res) => { + console.log("update"); + const post_id = req.params.id; + console.log(`Post_id ${post_id}`); + const user_id = req.session.user._id; + console.log(`user_id ${user_id}`); + + const post = await Post.findOne({ _id: post_id }); + console.log(`post ${post}`); + post.message = req.body.content + await post.save() + res.status(201).redirect(`/users/${req.session.user.username}`); - res.status(201).redirect("/posts"); - }); }, + + Delete: async (req, res) => { + console.log("delete"); + const post_id = req.params.id; + console.log(`Post_id ${post_id}`); + const user_id = req.session.user._id; + console.log(`user_id ${user_id}`); + + const post = await Post.findOne({ _id: post_id }) + console.log(`post = ${post}`); + await Post.deleteOne({ _id: post_id}); + res.status(201).redirect(`/users/${req.session.user.username}?deleted=true`); + }, + + AddLike: async (req, res) => { + // get the post_id for the + const post_id = req.params.id; + console.log(`Post_id ${post_id}`); + const user_id = req.session.user._id; + console.log(`user_id ${user_id}`); + const post = await Post.findOne({ _id: post_id }); + console.log(`post ${post}`); + const likes = post.like; + console.log(`likes ${likes}`); + const liked = post.like.map((like) => like.likeAuthor).includes(user_id); + console.log(`liked ${liked}`); + + if (!liked) { + likes.push({ likeAuthor: user_id }); + post.save( + () => {res.status(201).redirect("/posts");} + ); + } else { + likes.splice(likes.map((like) => like.likeAuthor).indexOf(user_id), 1); + post.save( + () => {res.status(201).redirect("/posts");} + ); + } + // res.json({ post: post_id, likes: updated_post.like.length }); + // () => {res.status(201).redirect("/posts"); + }, + }; module.exports = PostsController; diff --git a/controllers/sessions.js b/controllers/sessions.js index 917e2e14c..28ed468df 100644 --- a/controllers/sessions.js +++ b/controllers/sessions.js @@ -1,33 +1,42 @@ -const User = require("../models/user"); +const User = require('../models/user'); +const bcrypt = require('bcrypt'); const SessionsController = { + New: (req, res) => { - res.render("sessions/new", {}); + res.render('sessions/login', {}); }, Create: (req, res) => { - console.log("trying to log in"); + console.log('trying to log in'); const email = req.body.email; const password = req.body.password; - + User.findOne({ email: email }).then((user) => { if (!user) { - res.redirect("/sessions/new"); - } else if (user.password != password) { - res.redirect("/sessions/new"); + res.render('sessions/login', {error: "Invalid email or password"}); } else { - req.session.user = user; - res.redirect("/posts"); + bcrypt.compare(password, user.password, function (err, result) { + if (err) { + throw err; + } + if (result === true) { + req.session.user = user; + res.redirect('/posts'); + } else { + res.render('sessions/login', {error: "Invalid email or password"}); + } + }); } }); }, - + Destroy: (req, res) => { console.log("logging out"); if (req.session.user && req.cookies.user_sid) { res.clearCookie("user_sid"); } - res.redirect("/sessions/new"); + res.redirect("/sessions/login"); }, }; diff --git a/controllers/userPosts.js b/controllers/userPosts.js new file mode 100644 index 000000000..905757f05 --- /dev/null +++ b/controllers/userPosts.js @@ -0,0 +1,22 @@ +// const User = require("../models/user"); + +// const UserPostsController = { +// Create: (req, res) => { +// const username = req.params.username; +// const content = req.body.content; + +// User.findOneAndUpdate( { username }, { $push: { posts: { content } } }, { new: true }, +// (err) => { +// if (err) { +// throw err; +// } +// res.status(201).redirect(`/users/${username}`); +// } +// ); +// }, +// }; + +// module.exports = UserPostsController; + + + diff --git a/controllers/users.js b/controllers/users.js index bdc2ea8f3..a1c2c04ed 100644 --- a/controllers/users.js +++ b/controllers/users.js @@ -1,17 +1,111 @@ const User = require("../models/user"); +const Post = require("../models/post"); const UsersController = { + New: (req, res) => { - res.render("users/new", {}); + res.render("users/signup", {}); }, Create: (req, res) => { - const user = new User(req.body); - user.save((err) => { + let query = {$or:[{username:{$regex: new RegExp('^' + req.body.username + '$', 'i')}},{email:{$regex: new RegExp('^' + req.body.email + '$', 'i')}}]} + + console.log("hello", query) + const newUser = new User({ + username: req.body.username, + email: req.body.email, + password: req.body.password, + }); + User.findOne(query , function (err, user) { + if(user) { + console.log(user) + res.render('users/signup', {error: "User account already exists"}); + } else { + newUser.save((err) => { + if (err) { + throw err; + } else { + res.status(201).redirect("/sessions/login"); + } + }); + } + }); + }, + + Authenticate: function (req, res) { + var form = req.body; + User.findOne({ username: form.username }, function (err, user) { if (err) { throw err; } - res.status(201).redirect("/posts"); + if (!user) { + res.render("/sessions/login", { + error: "Error: User not found", + }); + } + if (user) { + if (form.password == user.password) { + res.cookie("userId", user.id); + res.cookie("email", user.email); + res.redirect("/posts"); + } else { + res.redirect("/sessions/login"); + } + } + }); + }, + + UserProfile: async (req, res) => { + const username = req.params.username; + let posts = await Post.find({ username }); + let user = await User.findOne({ username }); + console.log(posts); + const sortedPosts = posts.flat().sort((a, b) => b.date - a.date); + res.render("users/profile", { user, isAuthenticated: true, posts: sortedPosts}); + }, + + CreatePost: (req, res) => { + const username = req.params.username; + const postContent = req.body.content; + User.findOne({ username }, (err, user) => { + if (err || !user) { + res.status(404).send("User not found"); + } else { + const post = { + content: postContent, + author: user._id, + }; + user.posts.push(post); + + user.save((err) => { + if (err) { + throw err; + } + res.status(201).redirect(`/users/${username}`); + }); + } + }); + }, + + Show: (req, res) => { + const username = req.params.username; + User.findOne({ username }, (err, user) => { + if (err || !user) { + res.status(404).send("User not found"); + } else { + res.render("users/profile", { user }); + } + }); + }, + + EditPost: (req, res) => { + const postId = req.params.postId; + Post.findOne({ _id: postId }, (err, post) => { + if (err || !post) { + res.status(404).send("Post not found"); + } else { + res.render("posts/edit", { post }); + } }); }, }; diff --git a/cypress/integration/entry_point/user_navigates_directly_to_post_submission_page.js b/cypress/integration/entry_point/user_navigates_directly_to_post_submission_page.js new file mode 100644 index 000000000..bf9cfd2ce --- /dev/null +++ b/cypress/integration/entry_point/user_navigates_directly_to_post_submission_page.js @@ -0,0 +1,15 @@ +describe("Authentication", () => { + it("A user attempts to navigate to new post and is redirected to sign in", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // go directly to new posts, do not sign up, do not pass go, do not collect £200 + cy.visit("/posts/new"); + + // check that "new-post-form" isnt visible on the screen + cy.get("#new-post-form").should('not.exist'); + + // check the redirect + cy.url().should("contain", "/sessions/login"); + }); +}); \ No newline at end of file diff --git a/cypress/integration/entry_point/user_navigates_directly_to_posts_page.js b/cypress/integration/entry_point/user_navigates_directly_to_posts_page.js new file mode 100644 index 000000000..abd710925 --- /dev/null +++ b/cypress/integration/entry_point/user_navigates_directly_to_posts_page.js @@ -0,0 +1,15 @@ +describe("Authentication", () => { + it("A user attempts to navigate to posts and is redirected to sign in", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // go directly to posts, do not sign up, do not pass go, do not collect £200 + cy.visit("/posts"); + + // check that "new post" isnt visible on the screen + cy.contains('New post').should('not.exist'); + + // check the redirect + cy.url().should("contain", "/sessions/login"); + }); +}); \ No newline at end of file diff --git a/cypress/integration/home_page_spec.js b/cypress/integration/homepage/1 home_page_spec.js similarity index 100% rename from cypress/integration/home_page_spec.js rename to cypress/integration/homepage/1 home_page_spec.js diff --git a/cypress/integration/homepage/2 user_can_visit_home_page_and_see_sign_up_button_spec.js b/cypress/integration/homepage/2 user_can_visit_home_page_and_see_sign_up_button_spec.js new file mode 100644 index 000000000..f92d71416 --- /dev/null +++ b/cypress/integration/homepage/2 user_can_visit_home_page_and_see_sign_up_button_spec.js @@ -0,0 +1,6 @@ +describe("Home page", () => { + it("has a title", () => { + cy.visit("/"); + cy.get("nav").should("contain", "Sign-up"); + }); +}); diff --git a/cypress/integration/homepage/3 from_the_home_page_user_can_click_sign_up_button_and_is_navigated_to_sign_up_page.spec.js b/cypress/integration/homepage/3 from_the_home_page_user_can_click_sign_up_button_and_is_navigated_to_sign_up_page.spec.js new file mode 100644 index 000000000..e1736caf8 --- /dev/null +++ b/cypress/integration/homepage/3 from_the_home_page_user_can_click_sign_up_button_and_is_navigated_to_sign_up_page.spec.js @@ -0,0 +1,7 @@ +describe("Home page", () => { + it("has a title", () => { + cy.visit("/"); + cy.get("#Sign-up").click(); + cy.get(".title").should("contain", "Sign-up"); + }); +}); diff --git a/cypress/integration/homepage/4 user_can_vist_home_page_and_see_log_in_button_spec.js b/cypress/integration/homepage/4 user_can_vist_home_page_and_see_log_in_button_spec.js new file mode 100644 index 000000000..b717a1fb3 --- /dev/null +++ b/cypress/integration/homepage/4 user_can_vist_home_page_and_see_log_in_button_spec.js @@ -0,0 +1,6 @@ +describe("Home page", () => { + it("has a title", () => { + cy.visit("/"); + cy.get("nav").should("contain", "Login"); + }); +}); diff --git a/cypress/integration/homepage/5 from_the_home_page_user_can_click_log_in_button_and_is_navigated_to_log_in_page.js b/cypress/integration/homepage/5 from_the_home_page_user_can_click_log_in_button_and_is_navigated_to_log_in_page.js new file mode 100644 index 000000000..3705d3de8 --- /dev/null +++ b/cypress/integration/homepage/5 from_the_home_page_user_can_click_log_in_button_and_is_navigated_to_log_in_page.js @@ -0,0 +1,7 @@ +describe("Home page", () => { + it("has a title", () => { + cy.visit("/"); + cy.get("#Log in").click(); + cy.get(".title").should("contain", "Log in"); + }); +}); diff --git a/cypress/integration/login_and_out/user_can_log_in_spec.js b/cypress/integration/login_and_out/user_can_log_in_spec.js new file mode 100644 index 000000000..734af4c26 --- /dev/null +++ b/cypress/integration/login_and_out/user_can_log_in_spec.js @@ -0,0 +1,20 @@ +describe("Authentication", () => { + it("A user signs in and is redirected on successfully sign in", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + cy.url().should("not.equal", "/sessions/login"); + }); +}); diff --git a/cypress/integration/login_and_out/user_can_log_out_spec.js b/cypress/integration/login_and_out/user_can_log_out_spec.js new file mode 100644 index 000000000..cdaf7132b --- /dev/null +++ b/cypress/integration/login_and_out/user_can_log_out_spec.js @@ -0,0 +1,26 @@ +describe("Session Handling", () => { + it("A logged in user can log out and is redirected to landing page", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // log out + cy.get('nav > ul > li').contains('Logout').click(); + + // check redirect to log in + cy.url().should('include', '/sessions/login'); + + }); +}); \ No newline at end of file diff --git a/cypress/integration/login_and_out/user_can_log_out_then_navigates_to_posts_page_spec.js b/cypress/integration/login_and_out/user_can_log_out_then_navigates_to_posts_page_spec.js new file mode 100644 index 000000000..c48dcbc26 --- /dev/null +++ b/cypress/integration/login_and_out/user_can_log_out_then_navigates_to_posts_page_spec.js @@ -0,0 +1,31 @@ +describe("Session Handling", () => { + it("A logged in user can log out and is unable to navigate to posts", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // log out + cy.get('nav > ul > li').contains('Logout').click(); + + // check redirect to log in + cy.url().should('include', '/sessions/login'); + + // atempt to navigate to posts + cy.visit("/posts") + + // check that "new post" isnt visible on the screen + cy.contains('New post').should('not.exist'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/login_and_out/user_clicks_clear_button_on_log_in_page.js b/cypress/integration/login_and_out/user_clicks_clear_button_on_log_in_page.js new file mode 100644 index 000000000..3eb547289 --- /dev/null +++ b/cypress/integration/login_and_out/user_clicks_clear_button_on_log_in_page.js @@ -0,0 +1,23 @@ +describe("log in functionality", () => { + it("A user clicks the clear button on log in page and the form is cleared", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // visit the log in page, fill fields and click cancel + cy.visit("/sessions/login"); + cy.get("#email").type("a test string"); + cy.get("#password").type("*"); + cy.get("#clear").click(); + + // check that email and password fields are cleared + + cy.get("#email").should('have.value', ''); + cy.get("#password").should('have.value', ''); + }); +}); \ No newline at end of file diff --git a/cypress/integration/login_and_out/user_logs_in_with_incorrect_email_address.js b/cypress/integration/login_and_out/user_logs_in_with_incorrect_email_address.js new file mode 100644 index 000000000..4d5df1608 --- /dev/null +++ b/cypress/integration/login_and_out/user_logs_in_with_incorrect_email_address.js @@ -0,0 +1,21 @@ +describe("Authentication", () => { + it("A user signs in with an incorrect email address and an error message is displayed", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("howardmoon@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // check for error message, NOTE: this checks the entire page and as such will fail if this text is anywhere on the page. Potential area for refactoring + cy.contains('Invalid email or password'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/login_and_out/user_logs_in_with_incorrect_password.js b/cypress/integration/login_and_out/user_logs_in_with_incorrect_password.js new file mode 100644 index 000000000..e2c811f7f --- /dev/null +++ b/cypress/integration/login_and_out/user_logs_in_with_incorrect_password.js @@ -0,0 +1,21 @@ +describe("Authentication", () => { + it("A user signs in with an incorrect password and an error message is displayed", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("mPgaN5s51g!"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // check for error message, NOTE: this checks the entire page and as such will fail if this text is anywhere on the page. Potential area for refactoring + cy.contains('Invalid email or password'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/user_can_submit_posts_spec.js b/cypress/integration/posts/17 user_can_submit_posts_spec.js similarity index 77% rename from cypress/integration/user_can_submit_posts_spec.js rename to cypress/integration/posts/17 user_can_submit_posts_spec.js index 019075937..708f5ab13 100644 --- a/cypress/integration/user_can_submit_posts_spec.js +++ b/cypress/integration/posts/17 user_can_submit_posts_spec.js @@ -1,13 +1,17 @@ describe("Timeline", () => { it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + // sign up - cy.visit("/users/new"); + cy.visit("/users/signup"); + cy.get("#username").type("User1"); cy.get("#email").type("someone@example.com"); cy.get("#password").type("password"); cy.get("#submit").click(); // sign in - cy.visit("/sessions/new"); + cy.visit("/sessions/login"); cy.get("#email").type("someone@example.com"); cy.get("#password").type("password"); cy.get("#submit").click(); diff --git a/cypress/integration/user_can_see_posts_count_on_post.js b/cypress/integration/posts/18 user_can_see_zero_likes_count_on_post_spec.js similarity index 76% rename from cypress/integration/user_can_see_posts_count_on_post.js rename to cypress/integration/posts/18 user_can_see_zero_likes_count_on_post_spec.js index 203897aca..6879e4189 100644 --- a/cypress/integration/user_can_see_posts_count_on_post.js +++ b/cypress/integration/posts/18 user_can_see_zero_likes_count_on_post_spec.js @@ -1,13 +1,17 @@ describe("Timeline", () => { it("can see likes count on a new post", () => { - // sign up - cy.visit("/users/new"); + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + //sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); cy.get("#email").type("someone@example.com"); cy.get("#password").type("password"); cy.get("#submit").click(); // sign in - cy.visit("/sessions/new"); + cy.visit("/sessions/login"); cy.get("#email").type("someone@example.com"); cy.get("#password").type("password"); cy.get("#submit").click(); @@ -20,9 +24,9 @@ describe("Timeline", () => { cy.get("#new-post-form").submit(); cy.get(".posts").should("contain", "Hello, world!"); - + // Assert that we can see the likes count cy.get(".posts").should("contain", "0 likes"); + }); - }); - \ No newline at end of file + }); \ No newline at end of file diff --git a/cypress/integration/posts/19 after_creating_post_user_can_like_their_own_post_and_see_like_count_increat.js b/cypress/integration/posts/19 after_creating_post_user_can_like_their_own_post_and_see_like_count_increat.js new file mode 100644 index 000000000..2db17301e --- /dev/null +++ b/cypress/integration/posts/19 after_creating_post_user_can_like_their_own_post_and_see_like_count_increat.js @@ -0,0 +1,31 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("self like test"); + cy.get("#new-post-form").submit(); + + //clikc like + cy.get("#like").click(); + cy.get(".posts").should("contain", "1 like"); + + }); +}); diff --git a/cypress/integration/posts/20 User_can_like_another_users_post_and_see_like_count_increase.js b/cypress/integration/posts/20 User_can_like_another_users_post_and_see_like_count_increase.js new file mode 100644 index 000000000..b9ec37399 --- /dev/null +++ b/cypress/integration/posts/20 User_can_like_another_users_post_and_see_like_count_increase.js @@ -0,0 +1,44 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("other user like test"); + cy.get("#new-post-form").submit(); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User2"); + cy.get("#email").type("someoneelse@example.com"); + cy.get("#password").type("password2"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someoneelse@example.com"); + cy.get("#password").type("password2"); + cy.get("#submit").click(); + + // click like + cy.get("#like").click(); + cy.get(".posts").should("contain", "1 like"); + + }); +}); diff --git a/cypress/integration/posts/21 user_can_see_posts_displayed_in_date_time_order.js b/cypress/integration/posts/21 user_can_see_posts_displayed_in_date_time_order.js new file mode 100644 index 000000000..e29464a8d --- /dev/null +++ b/cypress/integration/posts/21 user_can_see_posts_displayed_in_date_time_order.js @@ -0,0 +1,51 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("1"); + cy.get("#new-post-form").submit(); + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("2"); + cy.get("#new-post-form").submit(); + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("3"); + cy.get("#new-post-form").submit(); + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("4"); + cy.get("#new-post-form").submit(); + + + cy.get(".posts[1]").should("contain", "4"); + cy.get(".posts[2]").should("contain", "3"); + cy.get(".posts[3]").should("contain", "2"); + cy.get(".posts[4]").should("contain", "1"); + + }); +}); diff --git a/cypress/integration/posts/22 user_tries_to _submit_a blank_post_spec.js b/cypress/integration/posts/22 user_tries_to _submit_a blank_post_spec.js new file mode 100644 index 000000000..e4779b60a --- /dev/null +++ b/cypress/integration/posts/22 user_tries_to _submit_a blank_post_spec.js @@ -0,0 +1,31 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + //cy.get("#new-post-form").find('[type="text"]').type(""); + cy.get("#new-post-form").submit(); + // check for error message, NOTE: this checks the entire page and as such will fail if this text is anywhere on the page. Potential area for refactoring + //cy.contains('post must be populated'); + // tempory test to assert still on new post page + cy.url().should('include', '/posts/new'); + + }); +}); diff --git a/cypress/integration/posts/23 user_tries_to _submit_an_imoji_in_a_post_spec.js b/cypress/integration/posts/23 user_tries_to _submit_an_imoji_in_a_post_spec.js new file mode 100644 index 000000000..db9cfeb3d --- /dev/null +++ b/cypress/integration/posts/23 user_tries_to _submit_an_imoji_in_a_post_spec.js @@ -0,0 +1,28 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("😊"); + cy.get("#new-post-form").submit(); + cy.get(".posts").should("contain", "😊"); + + }); +}); diff --git a/cypress/integration/posts/24 user_tries_to _submit_a_hyperlink_in_a_post_spec.js b/cypress/integration/posts/24 user_tries_to _submit_a_hyperlink_in_a_post_spec.js new file mode 100644 index 000000000..69b227545 --- /dev/null +++ b/cypress/integration/posts/24 user_tries_to _submit_a_hyperlink_in_a_post_spec.js @@ -0,0 +1,28 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("https://www.diy.com"); + cy.get("#new-post-form").submit(); + cy.url().should('include', 'posts'); + + }); +}); diff --git a/cypress/integration/posts/31 when_user_submits_post_username_is_displayed_with_post.js b/cypress/integration/posts/31 when_user_submits_post_username_is_displayed_with_post.js new file mode 100644 index 000000000..d3dafc429 --- /dev/null +++ b/cypress/integration/posts/31 when_user_submits_post_username_is_displayed_with_post.js @@ -0,0 +1,28 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("test"); + cy.get("#new-post-form").submit(); + // check for error message, NOTE: this checks the entire page and as such will fail if this text is anywhere on the page. Potential area for refactoring + cy.contains('User1'); + }); +}); diff --git a/cypress/integration/posts/32 when_user_submits_post_date_and_time_is_displayed_with_post.js b/cypress/integration/posts/32 when_user_submits_post_date_and_time_is_displayed_with_post.js new file mode 100644 index 000000000..2f4885190 --- /dev/null +++ b/cypress/integration/posts/32 when_user_submits_post_date_and_time_is_displayed_with_post.js @@ -0,0 +1,38 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.contains("New post").click(); + + cy.get("#new-post-form").find('[type="text"]').type("test"); + const now = new Date(); + const options = { + weekday: 'short', + month: 'short', + day: 'numeric', + year: 'numeric', + hour: 'numeric', + minute: 'numeric' + }; + const currentDate = now.toLocaleString('en-US', options); + cy.get("#new-post-form").submit(); + // check for error message, NOTE: this checks the entire page and as such will fail if this text is anywhere on the page. Potential area for refactoring + cy.contains(currentDate); + }); +}); diff --git a/cypress/integration/posts/34 user_creates_post_from_profile_page.js b/cypress/integration/posts/34 user_creates_post_from_profile_page.js new file mode 100644 index 000000000..f52c5ca66 --- /dev/null +++ b/cypress/integration/posts/34 user_creates_post_from_profile_page.js @@ -0,0 +1,29 @@ +describe("Timeline", () => { + it("can submit posts, when signed in, and view them", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); + + // sign up + cy.visit("/users/signup"); + cy.get("#username").type("User1"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // sign in + cy.visit("/sessions/login"); + cy.get("#email").type("someone@example.com"); + cy.get("#password").type("password"); + cy.get("#submit").click(); + + // submit a post + cy.visit("/posts"); + cy.visit("/users/user1"); + //cy.get("#content").click(); + cy.get('textarea[name="content"]').type("Profile Post Test"); + //cy.get("#textarea").type("Profile Post Test"); + cy.get('button[type="submit"]').click() + + cy.get(".posts").should("contain", "Hello, world!"); + }); +}); diff --git a/cypress/integration/sign_up/signup_email_alread_in_use.js b/cypress/integration/sign_up/signup_email_alread_in_use.js new file mode 100644 index 000000000..4968fe172 --- /dev/null +++ b/cypress/integration/sign_up/signup_email_alread_in_use.js @@ -0,0 +1,21 @@ +describe('User Sign Up - Already Used Email', () => { + it('should display an error message for an already used email', () => { + const username = 'someone1' + const existingEmail = 'someone@example.com'; + const validPassword = 'Thisisaccepabl3'; + + cy.visit('/users/signup'); + + //sign up + cy.get("#username").type(username); + cy.get("#email").type(existingEmail); + cy.get("#password").type(validPassword); + cy.get("#submit").click(); + + // Assert that the user stays on the signup page + cy.url().should('include', '/users/signup'); + + // Assert that the error message is displayed + //cy.contains('span.error-message', 'Invalid username or password'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/sign_up/signup_password_around_30_characters.js b/cypress/integration/sign_up/signup_password_around_30_characters.js new file mode 100644 index 000000000..60c70d152 --- /dev/null +++ b/cypress/integration/sign_up/signup_password_around_30_characters.js @@ -0,0 +1,33 @@ +describe('User Sign Up - Password Boundary Value', () => { + it('should test a variety of passwords on and over the character boundary', () => { + const username = 'Tester1' + const validEmail = 'tester@example.com'; + + cy.visit('/users/signup'); + + // Password on the boundary of 30 characters + cy.get("#username").type(username); + + cy.get("#email").type(validEmail); + cy.get("#password").type('123456789012345678901234567890'); + cy.get("#submit").click(); + cy.url().should('include', '/sessions/login'); + + // Password under the boundary of 30 characters + cy.visit('/users/signup'); + cy.get("#username").type(username); + cy.get("#email").type(validEmail); + cy.get("#password").type('12345678901234567890123456789'); + cy.get("#submit").click(); + cy.url().should('include', '/sessions/login'); + + // Password over the boundary of 30 characters + cy.visit('/users/signup'); + cy.get("#username").type(username); + cy.get("#email").type(validEmail); + cy.get("#password").type('1234567890123456789012345678901'); + cy.get("#submit").click(); + cy.url().should('include', '/users/signup'); + // cy.contains('span.error-message', 'Too many characters'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/sign_up/signup_password_empty.js b/cypress/integration/sign_up/signup_password_empty.js new file mode 100644 index 000000000..affe47bbf --- /dev/null +++ b/cypress/integration/sign_up/signup_password_empty.js @@ -0,0 +1,19 @@ +// describe('User Sign Up - Password Boundary Value', () => { +// it('Error message and url check for if password is empty', () => { +// const username = 'Tester1' +// const validEmail = 'someone@example.com'; + +// cy.visit('/users/signup'); + +// //sign up +// cy.get("#username").type(username); +// cy.get("#email").type(validEmail); +// cy.get("#submit").click(); + +// // Assert that the user stays on the signup page +// cy.url().should('include', '/users/signup'); + +// // Assert that the error message is displayed +// //cy.contains('span.error-message', 'Invalid username or password'); +// }); +// }); \ No newline at end of file diff --git a/cypress/integration/sign_up/signup_password_fails_and_error_message_is_returned.js b/cypress/integration/sign_up/signup_password_fails_and_error_message_is_returned.js new file mode 100644 index 000000000..a70dbd75e --- /dev/null +++ b/cypress/integration/sign_up/signup_password_fails_and_error_message_is_returned.js @@ -0,0 +1,21 @@ +describe('User Sign Up - Password Boundary Value', () => { + it('should display an error message for an invalid password length', () => { + const username = 'Tester1' + const validEmail = 'someone@example.com'; + const invalidPassword = 'no'; + + cy.visit('/users/signup'); + + //sign up + cy.get("#username").type(username); + cy.get("#email").type(validEmail); + cy.get("#password").type(invalidPassword); + cy.get("#submit").click(); + + // Assert that the user stays on the signup page + cy.url().should('include', '/users/signup'); + + // Assert that the error message is displayed + //cy.contains('span.error-message', 'Invalid username or password'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/sign_up/signup_password_passes.js b/cypress/integration/sign_up/signup_password_passes.js new file mode 100644 index 000000000..90529de41 --- /dev/null +++ b/cypress/integration/sign_up/signup_password_passes.js @@ -0,0 +1,25 @@ +describe('User Sign Up - Password Boundary Value', () => { + it('should test a variety of passwords on and over the character boundry', () => { + const username = 'Tester1' + const validEmail = 'tester@example.com'; + const validPassword = 'hi345678'; + const alsovalidPassword = 'hi23456789'; + + cy.visit('/users/signup'); + + //sign up - 8 characters + cy.get("#username").type(username); + cy.get("#email").type(validEmail); + cy.get("#password").type(validPassword); + cy.get("#submit").click(); + cy.url().should('include', '/sessions/login'); + + //sign up - 9 characters + cy.visit('/users/signup'); + cy.get("#username").type(username); + cy.get("#email").type(validEmail); + cy.get("#password").type(alsovalidPassword); + cy.get("#submit").click(); + cy.url().should('include', '/sessions/login'); + }); +}); \ No newline at end of file diff --git a/cypress/integration/user_can_sign_up_spec.js b/cypress/integration/sign_up/user_can_sign_up_spec.js similarity index 54% rename from cypress/integration/user_can_sign_up_spec.js rename to cypress/integration/sign_up/user_can_sign_up_spec.js index 7863a66e5..0ab93ffcc 100644 --- a/cypress/integration/user_can_sign_up_spec.js +++ b/cypress/integration/sign_up/user_can_sign_up_spec.js @@ -1,11 +1,14 @@ describe("Registration", () => { it("A user signs up and is redirected to sign in", () => { + //clearDB drops the DB for a fresh test environment + cy.task('clearDb'); // sign up - cy.visit("/users/new"); + cy.visit("/users/signup"); + cy.get("#username").type('Tester1'); cy.get("#email").type("someone@example.com"); cy.get("#password").type("password"); cy.get("#submit").click(); - cy.url().should("include", "/sessions/new"); + cy.url().should("include", "/sessions/login"); }); }); diff --git a/cypress/integration/user_can_sign_in_spec.js b/cypress/integration/user_can_sign_in_spec.js deleted file mode 100644 index 2c2ae6d9a..000000000 --- a/cypress/integration/user_can_sign_in_spec.js +++ /dev/null @@ -1,18 +0,0 @@ -describe("Authentication", () => { - it("A user signs in and is redirected to /posts", () => { - // sign up - cy.visit("/users/new"); - cy.get("#email").type("someone@example.com"); - cy.get("#password").type("password"); - cy.get("#submit").click(); - - // sign in - cy.visit("/sessions/new"); - cy.get("#email").type("someone@example.com"); - cy.get("#password").type("password"); - cy.get("#submit").click(); - - cy.url().should("include", "/posts"); - cy.contains("a", "New post"); - }); -}); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index f6b2b82ce..919e10258 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -11,7 +11,22 @@ // This function is called when a project is opened or re-opened (e.g. due to // the project's config changing) -module.exports = function() { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config -} +// `on` is used to hook into various events Cypress emits +// `config` is the resolved Cypress config + + +const mongoose = require('mongoose'); + +module.exports = (on) => { + on('task', { + async clearDb() { + await mongoose.connect('mongodb://0.0.0.0/acebook_test'); + + await mongoose.connection.db.dropDatabase(); + + await mongoose.connection.close(); + + return null; + } + }); +}; diff --git a/models/post.js b/models/post.js index 3ef06ae2d..6c35d86dc 100644 --- a/models/post.js +++ b/models/post.js @@ -1,10 +1,25 @@ const mongoose = require("mongoose"); +const Schema = require("mongoose").Schema; const PostSchema = new mongoose.Schema({ - message: String, - likes: { type: Number, default: 0 } -}); + username: {type: String}, + userId: { type: Schema.Types.ObjectId, ref: "User" }, + message: {type: String, maxLength: 256}, + like: [{ + likeAuthor: { type: String }, + }], + // an list of comment objects containing the author, username, content and date + // comment: [{ + // author: { type: String }, + // username: { type: String }, + // content: { type: String, maxLength: 200 }, + // date: { type: Date, default: () => Date.now() }, + // }], + //date of the original post + date: { type: Date, default: () => Date.now() }, +}, { timestamps: true } ); const Post = mongoose.model("Post", PostSchema); module.exports = Post; + diff --git a/models/user.js b/models/user.js index 27406b498..3f1db12eb 100644 --- a/models/user.js +++ b/models/user.js @@ -1,8 +1,48 @@ const mongoose = require("mongoose"); +const bcrypt = require("bcrypt"); const UserSchema = new mongoose.Schema({ + username: String, email: String, password: String, + // posts: [ + // { + // content: String, + // author: { + // type: mongoose.Schema.Types.ObjectId, + // ref: "User", + // }, + // }, + // ], +}); + +UserSchema.statics.authenticate = function (email, password, callback) { + User.findOne({ email: email }).exec(function (err, user) { + if (err) { + return callback(err); + } else if (!user) { + err.status = 401; + return callback(err); + } + bcrypt.compare(password, user.password, function (err, result) { + if (result === true) { + return callback(null, user); + } else { + return callback(); + } + }); + }); +}; + +UserSchema.pre("save", function (next) { + var user = this; + bcrypt.hash(user.password, 10, function (err, hash) { + if (err) { + return next(err); + } + user.password = hash; + next(); + }); }); const User = mongoose.model("User", UserSchema); diff --git a/package-lock.json b/package-lock.json index 27002c86c..5b3751539 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "0.0.0", "license": "CC BY-NC-SA", "dependencies": { + "bcrypt": "^5.1.0", "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", + "express-handlebars": "^7.0.7", "express-session": "^1.17.2", "hbs": "^4.1.0", "http-errors": "~1.6.3", @@ -19,10 +21,12 @@ "mongodb": "^3.4.1", "mongoose": "^5.8.11", "morgan": "~1.9.1", - "nodemon": "^2.0.15" + "nodemon": "^2.0.15", + "regex-parser": "^2.2.11" }, "devDependencies": { "cypress": "^9.5.1", + "cypress-failed-log": "^2.10.0", "eslint": "^8.10.0", "eslint-plugin-cypress": "^2.8.1", "eslint-plugin-jest": "^22.21.0", @@ -798,6 +802,95 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1141,6 +1234,48 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -1478,7 +1613,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "dependencies": { "debug": "4" }, @@ -1490,7 +1624,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -1506,8 +1639,7 @@ "node_modules/agent-base/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/aggregate-error": { "version": "3.1.0", @@ -1616,6 +1748,11 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -1636,6 +1773,31 @@ } ] }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1843,6 +2005,19 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -2215,6 +2390,14 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -2341,6 +2524,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", @@ -2398,6 +2589,11 @@ "node": ">=8" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -2463,7 +2659,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2562,6 +2757,42 @@ "node": ">=12.0.0" } }, + "node_modules/cypress-failed-log": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/cypress-failed-log/-/cypress-failed-log-2.10.0.tgz", + "integrity": "sha512-v+GsOcpCAgj335zfDy9jDnaujH31SM/6pEQBp0dH0clbYu4NSXirLRXW9WoKhd0j70UrAA0hTLNbS2oTt1Y5kA==", + "dev": true, + "dependencies": { + "debug": "4.3.4", + "logdown": "3.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cypress-failed-log/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/cypress-failed-log/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/cypress/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2685,6 +2916,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", @@ -2706,6 +2942,14 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2773,6 +3017,11 @@ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3384,6 +3633,62 @@ "node": ">= 0.10.0" } }, + "node_modules/express-handlebars": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-7.0.7.tgz", + "integrity": "sha512-O4jUlkEVvqwyhkcmjWOqAEcV3JbcaGnlyS0oSgI3vyXO59Fco5JJtUboU2VHqv3Em3Q0VFC2VhRsmaUeNCOr5Q==", + "dependencies": { + "glob": "^10.1.0", + "graceful-fs": "^4.2.11", + "handlebars": "^4.7.7" + }, + "engines": { + "node": ">=v16" + } + }, + "node_modules/express-handlebars/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/express-handlebars/node_modules/glob": { + "version": "10.2.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz", + "integrity": "sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/express-handlebars/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/express-session": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", @@ -3626,6 +3931,32 @@ "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=" }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3680,11 +4011,32 @@ "node": ">=10" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -3711,6 +4063,25 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3774,7 +4145,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3864,9 +4234,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/handlebars": { "version": "4.7.7", @@ -3908,6 +4278,11 @@ "node": ">=8" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -4021,7 +4396,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -4034,7 +4408,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -4050,8 +4423,7 @@ "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/human-signals": { "version": "1.1.1", @@ -4171,7 +4543,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -4373,8 +4744,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "node_modules/isstream": { "version": "0.1.2", @@ -4492,6 +4862,23 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -5569,6 +5956,86 @@ "node": ">=8" } }, + "node_modules/logdown": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/logdown/-/logdown-3.3.1.tgz", + "integrity": "sha512-pjX0vlIJsYQlgVzFba2amXI1wZZnhrEorL68MdLI7B0/sN1TNUozBNFaHfcPHMM3A+INZ0OXFDxtnoaEgOmGjQ==", + "dev": true, + "dependencies": { + "chalk": "^2.3.0" + } + }, + "node_modules/logdown/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/logdown/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/logdown/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/logdown/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/logdown/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/logdown/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/logdown/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -5747,6 +6214,48 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mongodb": { "version": "3.7.3", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", @@ -5914,6 +6423,49 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -6036,12 +6588,31 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -6256,7 +6827,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6265,7 +6835,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -6276,6 +6845,29 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", + "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", + "dependencies": { + "lru-cache": "^9.1.1", + "minipass": "^5.0.0 || ^6.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", + "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -6573,6 +7165,11 @@ "node": ">=8.10.0" } }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + }, "node_modules/regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", @@ -6725,7 +7322,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -6863,6 +7459,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -6872,7 +7473,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6884,7 +7484,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -7059,6 +7658,20 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -7070,6 +7683,18 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -7158,6 +7783,22 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -7669,7 +8310,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -7680,6 +8320,14 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -7721,6 +8369,23 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8421,6 +9086,64 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -8696,6 +9419,38 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + } + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -8992,7 +9747,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "requires": { "debug": "4" }, @@ -9001,7 +9755,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -9009,8 +9762,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -9089,12 +9841,38 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, "arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", "dev": true }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -9254,6 +10032,15 @@ } } }, + "bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + } + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -9519,6 +10306,11 @@ } } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "ci-info": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", @@ -9615,6 +10407,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "colorette": { "version": "2.0.16", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", @@ -9660,6 +10457,11 @@ "xdg-basedir": "^4.0.0" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -9715,7 +10517,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -9817,6 +10618,33 @@ } } }, + "cypress-failed-log": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/cypress-failed-log/-/cypress-failed-log-2.10.0.tgz", + "integrity": "sha512-v+GsOcpCAgj335zfDy9jDnaujH31SM/6pEQBp0dH0clbYu4NSXirLRXW9WoKhd0j70UrAA0hTLNbS2oTt1Y5kA==", + "dev": true, + "requires": { + "debug": "4.3.4", + "logdown": "3.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -9899,6 +10727,11 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", @@ -9914,6 +10747,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -9965,6 +10803,11 @@ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -10443,6 +11286,46 @@ } } }, + "express-handlebars": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-7.0.7.tgz", + "integrity": "sha512-O4jUlkEVvqwyhkcmjWOqAEcV3JbcaGnlyS0oSgI3vyXO59Fco5JJtUboU2VHqv3Em3Q0VFC2VhRsmaUeNCOr5Q==", + "requires": { + "glob": "^10.1.0", + "graceful-fs": "^4.2.11", + "handlebars": "^4.7.7" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.2.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.7.tgz", + "integrity": "sha512-jTKehsravOJo8IJxUGfZILnkvVJM/MOfHRs8QcXolVef2zNI9Tqyy5+SeuOAZd3upViEZQLyFpQhYiHLrMUNmA==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" + } + }, + "minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "express-session": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", @@ -10621,6 +11504,22 @@ "resolved": "https://registry.npmjs.org/foreachasync/-/foreachasync-3.0.0.tgz", "integrity": "sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY=" }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==" + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -10660,11 +11559,28 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -10684,6 +11600,22 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -10732,7 +11664,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10797,9 +11728,9 @@ } }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "handlebars": { "version": "4.7.7", @@ -10827,6 +11758,11 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -10915,7 +11851,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, "requires": { "agent-base": "6", "debug": "4" @@ -10925,7 +11860,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -10933,8 +11867,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -11009,7 +11942,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -11151,8 +12083,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", @@ -11247,6 +12178,15 @@ "istanbul-lib-report": "^3.0.0" } }, + "jackspeak": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", @@ -12082,6 +13022,73 @@ } } }, + "logdown": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/logdown/-/logdown-3.3.1.tgz", + "integrity": "sha512-pjX0vlIJsYQlgVzFba2amXI1wZZnhrEorL68MdLI7B0/sN1TNUozBNFaHfcPHMM3A+INZ0OXFDxtnoaEgOmGjQ==", + "dev": true, + "requires": { + "chalk": "^2.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -12219,6 +13226,35 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, "mongodb": { "version": "3.7.3", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", @@ -12341,6 +13377,40 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -12430,12 +13500,28 @@ "path-key": "^3.0.0" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -12591,14 +13677,12 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", @@ -12606,6 +13690,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "path-scurry": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", + "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", + "requires": { + "lru-cache": "^9.1.1", + "minipass": "^5.0.0 || ^6.0.2" + }, + "dependencies": { + "lru-cache": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", + "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==" + } + } + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -12840,6 +13940,11 @@ "picomatch": "^2.2.1" } }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + }, "regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", @@ -12955,7 +14060,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -13051,6 +14155,11 @@ "send": "0.16.2" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -13060,7 +14169,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -13068,8 +14176,7 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "sift": { "version": "13.5.2", @@ -13213,6 +14320,16 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -13221,6 +14338,14 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -13281,6 +14406,19 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -13689,11 +14827,18 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -13723,6 +14868,16 @@ "strip-ansi": "^6.0.0" } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index b0b63690e..e8f0b6494 100644 --- a/package.json +++ b/package.json @@ -10,15 +10,22 @@ "start:test": "PORT=3030 MONGODB_URL='mongodb://0.0.0.0/acebook_test' npm start", "test": "npm run lint && npm run test:unit && npm run test:integration", "test:unit": "jest", - "test:integration": "cypress run" + "test:integration": "cypress run", + "test:homepage": "cypress run --spec 'cypress/integration/homepage/*'", + "test:login_and_out": "cypress run --spec 'cypress/integration/login_and_out/*'", + "test:posts": "cypress run --spec 'cypress/integration/posts/*'", + "test:sign_up": "cypress run --spec 'cypress/integration/sign_up/*'", + "test:entry_point": "cypress run --spec 'cypress/integration/entry_point/*'" }, "engines": { "node": ">=18.1.0" }, "dependencies": { + "bcrypt": "^5.1.0", "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", + "express-handlebars": "^7.0.7", "express-session": "^1.17.2", "hbs": "^4.1.0", "http-errors": "~1.6.3", @@ -26,10 +33,12 @@ "mongodb": "^3.4.1", "mongoose": "^5.8.11", "morgan": "~1.9.1", - "nodemon": "^2.0.15" + "nodemon": "^2.0.15", + "regex-parser": "^2.2.11" }, "devDependencies": { "cypress": "^9.5.1", + "cypress-failed-log": "^2.10.0", "eslint": "^8.10.0", "eslint-plugin-cypress": "^2.8.1", "eslint-plugin-jest": "^22.21.0", diff --git a/public/images/acebook logo.jpg b/public/images/acebook logo.jpg new file mode 100644 index 000000000..0c1ab491e Binary files /dev/null and b/public/images/acebook logo.jpg differ diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 9453385b9..34a16b283 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -1,8 +1,57 @@ body { padding: 50px; font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; + background-color: whitesmoke; } a { color: #00B7FF; } + +nav { + display: flex; + justify-content: space-between; + padding: 5px 5%; + align-items: center; + background-color: #006d77; +} + +ul { + list-style: none; +} + +ul li { + display: inline-block; +} + +ul li a { + text-decoration: none; + color: #ffddd2; + padding: 8px 30px; + border-radius: 7px; + transition: all .3s ease; +} + +ul li a:hover, +ul li a.active { + color: #ffddd2; + background: #83c5be; +} + +/* Signup page */ +#new-user-form{ + padding-top: 5rem; + color: red; + text-align: center; +} + + +/* Login page */ +#new-session-form{ + padding-top: 5rem; + text-align: center; +} +/* +.error { + +} */ diff --git a/routes/posts.js b/routes/posts.js index d4ec2d937..b1d683efa 100644 --- a/routes/posts.js +++ b/routes/posts.js @@ -6,5 +6,9 @@ const PostsController = require("../controllers/posts"); router.get("/", PostsController.Index); router.post("/", PostsController.Create); router.get("/new", PostsController.New); +router.post("/:id/likes", PostsController.AddLike); +router.get("/:id/edit", PostsController.Edit); +router.post("/:id", PostsController.Update); +router.post("/:id/delete", PostsController.Delete); module.exports = router; diff --git a/routes/sessions.js b/routes/sessions.js index c0783914c..aaa4562c6 100644 --- a/routes/sessions.js +++ b/routes/sessions.js @@ -3,8 +3,8 @@ const router = express.Router(); const SessionsController = require("../controllers/sessions"); -router.get("/new", SessionsController.New); +router.get("/login", SessionsController.New); router.post("/", SessionsController.Create); -router.delete("/", SessionsController.Destroy); +router.get("/logout", SessionsController.Destroy); module.exports = router; diff --git a/routes/userPosts.js b/routes/userPosts.js new file mode 100644 index 000000000..09e72bb09 --- /dev/null +++ b/routes/userPosts.js @@ -0,0 +1,8 @@ +// const express = require("express"); +// const router = express.Router(); + +// const UserPostsController = require("../controllers/userPosts"); + +// router.post("/", UserPostsController.Create); + +// module.exports = router; \ No newline at end of file diff --git a/routes/users.js b/routes/users.js index 1203f91bf..98bb7baea 100644 --- a/routes/users.js +++ b/routes/users.js @@ -3,7 +3,16 @@ const router = express.Router(); const UsersController = require("../controllers/users"); -router.get("/new", UsersController.New); +router.get("/signup", UsersController.New); router.post("/", UsersController.Create); +router.post("/login", UsersController.Authenticate); -module.exports = router; +router.get("/:username", UsersController.UserProfile); +router.post("/:username/posts", UsersController.CreatePost); +router.get("/:username", UsersController.Show); +router.get("/:username/posts/:postId/edit", UsersController.EditPost); + + + + +module.exports = router; diff --git a/views/home/index.hbs b/views/home/index.hbs index 7ad30d847..b197b7e15 100644 --- a/views/home/index.hbs +++ b/views/home/index.hbs @@ -1,2 +1,5 @@

{{title}}

Welcome to {{title}}

+ + +{{!-- potential additions to homepage : add a description, a picture --}} \ No newline at end of file diff --git a/views/layout.hbs b/views/layout.hbs deleted file mode 100644 index 17645b71e..000000000 --- a/views/layout.hbs +++ /dev/null @@ -1,13 +0,0 @@ - - - - {{title}} - - - -
- -
- {{{body}}} - - diff --git a/views/layouts/layout.hbs b/views/layouts/layout.hbs new file mode 100644 index 000000000..024e0785c --- /dev/null +++ b/views/layouts/layout.hbs @@ -0,0 +1,25 @@ + + + + {{title}} + + + + + + {{{body}}} + + diff --git a/views/posts/edit.hbs b/views/posts/edit.hbs new file mode 100644 index 000000000..e0be4e705 --- /dev/null +++ b/views/posts/edit.hbs @@ -0,0 +1,25 @@ +

Edit Post

+ +
  • Created at: {{formatDate post}}
  • +
    +
  • Created By: {{post.username}}
  • +
    +
  • Post Content: {{post.message}}
  • +
    + +

    What would you like to do with the post?

    +
    + +
    + + + +
    + +
    + +
    + + {{!-- --}} + +
    diff --git a/views/posts/index.hbs b/views/posts/index.hbs index 4a4bca1d8..bbc54cf77 100644 --- a/views/posts/index.hbs +++ b/views/posts/index.hbs @@ -1,9 +1,26 @@ -

    Timeline

    -