diff --git a/app/__init__.py b/app/__init__.py index 2764c4cc8..b31dfb911 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -30,5 +30,8 @@ def create_app(test_config=None): migrate.init_app(app, db) # Register Blueprints here - + from .routes import tasks_bp, goals_bp + app.register_blueprint(tasks_bp) + app.register_blueprint(goals_bp) return app + diff --git a/app/helper.py b/app/helper.py new file mode 100644 index 000000000..11ac205a1 --- /dev/null +++ b/app/helper.py @@ -0,0 +1,28 @@ +from flask import abort, make_response +from app.models.task import Task +from app.models.goal import Goal + + +def validate_id(id): + try: + id = int(id) + except: + abort(make_response({"message":f"this is not a valid id: {id}"}, 400)) + + task = Task.query.get(id) + if not task: + abort(make_response({"message":f"id {id} not found!"}, 404)) + return task + +def validate_goal(id): + try: + id = int(id) + except: + abort(make_response({"message":f"this is not a valid id: {id}"}, 400)) + + goal = Goal.query.get(id) + if not goal: + abort(make_response({"message":f"id {id} not found!"}, 404)) + return goal + + diff --git a/app/models/goal.py b/app/models/goal.py index b0ed11dd8..0a0338d86 100644 --- a/app/models/goal.py +++ b/app/models/goal.py @@ -2,4 +2,26 @@ class Goal(db.Model): - goal_id = db.Column(db.Integer, primary_key=True) + goal_id = db.Column(db.Integer, primary_key=True, autoincrement=True) + title = db.Column(db.String, nullable=False) + tasks = db.relationship("Task", back_populates="goal", lazy=True) + + + def to_dict(self): + return{ + "id":self.goal_id, + "title":self.title + } + + #create function for title + @classmethod + def create(cls, request_body): + return cls( + title = request_body["title"] + ) + + +#update function for title + def update(self, request_body): + self.title=request_body["title"] + diff --git a/app/models/task.py b/app/models/task.py index c91ab281f..2149ac32b 100644 --- a/app/models/task.py +++ b/app/models/task.py @@ -1,5 +1,48 @@ from app import db +from datetime import datetime class Task(db.Model): - task_id = db.Column(db.Integer, primary_key=True) + task_id = db.Column(db.Integer, primary_key=True, autoincrement=True ) + title = db.Column(db.String, nullable=False) + description = db.Column(db.String, nullable=False) + completed_at = db.Column(db.DateTime, nullable=True, default=None) + goal = db.relationship("Goal", back_populates="tasks") + goals_id = db.Column(db.Integer, db.ForeignKey("goal.goal_id")) + + def to_dict(self): + is_complete=True if self.completed_at else False + + task_dict = { + "id":self.task_id, + "title":self.title, + "description":self.description, + "is_complete":is_complete + } + if self.goals_id: + task_dict["goal_id"] = self.goals_id + + return task_dict + +#create function for title & description + @classmethod + def create(cls, request_body): + return cls( + title = request_body["title"], + description = request_body["description"] + ) + +#update function for title & description + def update(self, request_body): + self.title=request_body["title"] + self.description=request_body["description"] + + +#patch function for is_completed + def patch_complete(self): + self.completed_at=datetime.utcnow() + +#patch function for is_completed when incomplete + def patch_incomplete(self): + self.completed_at=None + \ No newline at end of file diff --git a/app/routes.py b/app/routes.py index 3aae38d49..4e828cc19 100644 --- a/app/routes.py +++ b/app/routes.py @@ -1 +1,234 @@ -from flask import Blueprint \ No newline at end of file +from flask import Blueprint, jsonify, make_response, request +import os, requests +from app import db +from app.models.task import Task +from app.models.goal import Goal +from app.helper import validate_id, validate_goal + +tasks_bp = Blueprint("tasks", __name__, url_prefix="/tasks") +goals_bp = Blueprint("goals", __name__, url_prefix="/goals") + + +#get all tasks-"/tasks"-GET(read) +@tasks_bp.route("", methods=["GET"]) +def get_all_tasks(): + if request.args.get("sort") == "asc": + tasks = Task.query.order_by(Task.title.asc()) + elif request.args.get("sort") == "desc": + tasks = Task.query.order_by(Task.title.desc()) + else: + tasks = Task.query.all() + tasks_response = [] + for task in tasks: + tasks_response.append(task.to_dict()) + return jsonify(tasks_response), 200 + + +#get one tasks-"/tasks/1"-GET(read) +@tasks_bp.route("/", methods=["GET"]) +def get_task(id): + task = validate_id(id) + return jsonify({"task":task.to_dict()}), 200 + + +#create task-"/tasks"-POST(create) +@tasks_bp.route("", methods=["POST"]) +def create_task(): + request_body = request.get_json() + try: + new_task = Task.create(request_body) + except KeyError: + return make_response({"details": "Invalid data"}), 400 + + db.session.add(new_task) + db.session.commit() + return jsonify({"task":new_task.to_dict()}), 201 + + +#update task-"tasks/1"-PUT(update) +@tasks_bp.route("/", methods=["PUT"]) +def update_task(id): + task = validate_id(id) + request_body = request.get_json() + task.update(request_body) + db.session.commit() + return jsonify({"task":task.to_dict()}), 200 + + +#delete task-"tasks/1"-DELETE(delete) +@tasks_bp.route("/", methods=["DELETE"]) +def delete_task(id): + task = validate_id(id) + db.session.delete(task) + db.session.commit() + return jsonify({"details": f'Task {id} "{task.to_dict()["title"]}" successfully deleted'}), 200 + + +#patch task-"tasks/1/mark_complete"-PATCH(update) +@tasks_bp.route("//mark_complete", methods=["PATCH"]) +def mark_complete(id): + task = validate_id(id) + request_body = request.get_json() + task.patch_complete() + db.session.commit() + + SLACK_API_URL = "https://slack.com/api/chat.postMessage" + if "SLACKBOT_TOKEN" is None: + return jsonify({'error': 'Slackbot token not set'}), 500 + headers = {"Authorization": os.environ.get("SLACKBOT_TOKEN")} + params = { + 'channel': 'task-notification', + 'text': f"Someone just completed the task {task.title}", + } + response = requests.post(SLACK_API_URL, headers=headers, json=params) + if not response.ok: + return jsonify({'error': 'Failed to send Slack message'}), 500 + + return jsonify({"task":task.to_dict()}), 200 + + +#patch task-"tasks/1/mark_incomplete"-PATCH(update) +@tasks_bp.route("//mark_incomplete", methods=["PATCH"]) +def mark_incomplete(id): + task = validate_id(id) + request_body = request.get_json() + task.patch_incomplete() + db.session.commit() + return jsonify({"task":task.to_dict()}), 200 + + + + + + + + + + + + + + + +#==========================WAVE 5 GOALS BELOW========================== + + + + + +#get all goals-"/tasks"-GET(read) +@goals_bp.route("", methods=["GET"]) +def get_all_goals(): + goals = Goal.query.all() + goals_response = [] + for goal in goals: + goals_response.append(goal.to_dict()) + return jsonify(goals_response), 200 + + +#get one goals-"/goals/1"-GET(read) +@goals_bp.route("/", methods=["GET"]) +def get_goal(id): + goal = validate_goal(id) + return jsonify({"goal":goal.to_dict()}), 200 + + +#create goal-"/goals"-POST(create) +@goals_bp.route("", methods=["POST"]) +def create_goal(): + request_body = request.get_json() + try: + new_goal = Goal.create(request_body) + except KeyError: + return make_response({"details": "Invalid data"}), 400 + + db.session.add(new_goal) + db.session.commit() + return jsonify({"goal":new_goal.to_dict()}), 201 + + +#update goal-"goals/1"-PUT(update) +@goals_bp.route("/", methods=["PUT"]) +def update_goal(id): + goal = validate_goal(id) + request_body = request.get_json() + goal.update(request_body) + db.session.commit() + return jsonify({"goal":goal.to_dict()}), 200 + + +#delete goal-"goals/1"-DELETE(delete) +@goals_bp.route("/", methods=["DELETE"]) +def delete_goal(id): + goal = validate_goal(id) + db.session.delete(goal) + db.session.commit() + return jsonify({"details": f'Goal {id} "{goal.to_dict()["title"]}" successfully deleted'}), 200 + + +#patch goal-"goals/1/mark_complete"-PATCH(update) +@goals_bp.route("//mark_complete", methods=["PATCH"]) +def mark_complete(id): + goal = validate_id(id) + request_body = request.get_json() + goal.patch_complete() + db.session.commit() + return jsonify({"goal":goal.to_dict()}), 200 + + +#patch goal-"goals/1/mark_incomplete"-PATCH(update) +@goals_bp.route("//mark_incomplete", methods=["PATCH"]) +def mark_incomplete(id): + goal = validate_id(id) + request_body = request.get_json() + goal.patch_incomplete() + db.session.commit() + return jsonify({"goal":goal.to_dict()}), 200 + + + + + + + + + + + + + +# #=================wave6================== + +#add tasks to goal-"/goal_id/tasks"-POST(create) +@goals_bp.route("//tasks", methods=["POST"]) +def add_tasks_to_goal(goal_id): + goal = validate_goal(goal_id) + request_body = request.get_json() + + for task_id in request_body["task_ids"]: + task = validate_id(task_id) + goal.tasks.append(task) + + db.session.commit() + + task_ids = [task.task_id for task in goal.tasks] + + response_body = { + "id": goal.goal_id, + "task_ids": task_ids + } + return jsonify(response_body), 200 + +#get tasks from goal-"/goal_id/tasks"-GET(read) +@goals_bp.route("//tasks", methods=["GET"]) +def get_tasks_from_goal_id(goal_id): + goal = validate_goal(goal_id) + task_list= [task.to_dict() for task in goal.tasks] + + response_body = { + "id": goal.goal_id, + "title": goal.title, + "tasks": task_list + } + + return jsonify(response_body), 200 diff --git a/migrations/README b/migrations/README new file mode 100644 index 000000000..98e4f9c44 --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/migrations/alembic.ini b/migrations/alembic.ini new file mode 100644 index 000000000..f8ed4801f --- /dev/null +++ b/migrations/alembic.ini @@ -0,0 +1,45 @@ +# A generic, single database configuration. + +[alembic] +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/migrations/env.py b/migrations/env.py new file mode 100644 index 000000000..8b3fb3353 --- /dev/null +++ b/migrations/env.py @@ -0,0 +1,96 @@ +from __future__ import with_statement + +import logging +from logging.config import fileConfig + +from sqlalchemy import engine_from_config +from sqlalchemy import pool +from flask import current_app + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) +logger = logging.getLogger('alembic.env') + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +config.set_main_option( + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, 'autogenerate', False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info('No changes in schema detected.') + + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool, + ) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions['migrate'].configure_args + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako new file mode 100644 index 000000000..2c0156303 --- /dev/null +++ b/migrations/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/88ae0e6b8cba_.py b/migrations/versions/88ae0e6b8cba_.py new file mode 100644 index 000000000..0bc6d06f2 --- /dev/null +++ b/migrations/versions/88ae0e6b8cba_.py @@ -0,0 +1,38 @@ +"""empty message + +Revision ID: 88ae0e6b8cba +Revises: d40787e04fa4 +Create Date: 2023-05-12 04:57:14.611896 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '88ae0e6b8cba' +down_revision = 'd40787e04fa4' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('task', 'description', + existing_type=sa.VARCHAR(), + nullable=False) + op.alter_column('task', 'title', + existing_type=sa.VARCHAR(), + nullable=False) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('task', 'title', + existing_type=sa.VARCHAR(), + nullable=True) + op.alter_column('task', 'description', + existing_type=sa.VARCHAR(), + nullable=True) + # ### end Alembic commands ### diff --git a/migrations/versions/d40787e04fa4_.py b/migrations/versions/d40787e04fa4_.py new file mode 100644 index 000000000..b45bf74c4 --- /dev/null +++ b/migrations/versions/d40787e04fa4_.py @@ -0,0 +1,30 @@ +"""empty message + +Revision ID: d40787e04fa4 +Revises: f30dbe623280 +Create Date: 2023-05-12 04:47:50.516943 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd40787e04fa4' +down_revision = 'f30dbe623280' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('task', sa.Column('goals_id', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'task', 'goal', ['goals_id'], ['goal_id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'task', type_='foreignkey') + op.drop_column('task', 'goals_id') + # ### end Alembic commands ### diff --git a/migrations/versions/ea22a74f4756_.py b/migrations/versions/ea22a74f4756_.py new file mode 100644 index 000000000..c18967d15 --- /dev/null +++ b/migrations/versions/ea22a74f4756_.py @@ -0,0 +1,39 @@ +"""empty message + +Revision ID: ea22a74f4756 +Revises: +Create Date: 2023-05-09 18:04:43.717868 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ea22a74f4756' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('goal', + sa.Column('goal_id', sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint('goal_id') + ) + op.create_table('task', + sa.Column('task_id', sa.Integer(), nullable=False), + sa.Column('title', sa.String(), nullable=True), + sa.Column('description', sa.String(), nullable=True), + sa.Column('completed_at', sa.DateTime(), nullable=True), + sa.PrimaryKeyConstraint('task_id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('task') + op.drop_table('goal') + # ### end Alembic commands ### diff --git a/migrations/versions/ee762152d3ac_.py b/migrations/versions/ee762152d3ac_.py new file mode 100644 index 000000000..9aedd909d --- /dev/null +++ b/migrations/versions/ee762152d3ac_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: ee762152d3ac +Revises: ea22a74f4756 +Create Date: 2023-05-11 21:58:50.553303 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ee762152d3ac' +down_revision = 'ea22a74f4756' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('goal', sa.Column('title', sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('goal', 'title') + # ### end Alembic commands ### diff --git a/migrations/versions/f30dbe623280_.py b/migrations/versions/f30dbe623280_.py new file mode 100644 index 000000000..a9106dfc3 --- /dev/null +++ b/migrations/versions/f30dbe623280_.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: f30dbe623280 +Revises: ee762152d3ac +Create Date: 2023-05-12 04:42:30.337518 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'f30dbe623280' +down_revision = 'ee762152d3ac' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('goal', 'title', + existing_type=sa.VARCHAR(), + nullable=False) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('goal', 'title', + existing_type=sa.VARCHAR(), + nullable=True) + # ### end Alembic commands ### diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 000000000..ea11cf842 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,15 @@ +{ + "name": "task-list-api", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/node_modules/dotenv/CHANGELOG.md b/node_modules/dotenv/CHANGELOG.md new file mode 100644 index 000000000..c8869f22f --- /dev/null +++ b/node_modules/dotenv/CHANGELOG.md @@ -0,0 +1,368 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.0.3...master) + +## [16.0.3](https://github.com/motdotla/dotenv/compare/v16.0.2...v16.0.3) (2022-09-29) + +### Changed + +- Added library version to debug logs ([#682](https://github.com/motdotla/dotenv/pull/682)) + +## [16.0.2](https://github.com/motdotla/dotenv/compare/v16.0.1...v16.0.2) (2022-08-30) + +### Added + +- Export `env-options.js` and `cli-options.js` in package.json for use with downstream [dotenv-expand](https://github.com/motdotla/dotenv-expand) module + +## [16.0.1](https://github.com/motdotla/dotenv/compare/v16.0.0...v16.0.1) (2022-05-10) + +### Changed + +- Minor README clarifications +- Development ONLY: updated devDependencies as recommended for development only security risks ([#658](https://github.com/motdotla/dotenv/pull/658)) + +## [16.0.0](https://github.com/motdotla/dotenv/compare/v15.0.1...v16.0.0) (2022-02-02) + +### Added + +- _Breaking:_ Backtick support πŸŽ‰ ([#615](https://github.com/motdotla/dotenv/pull/615)) + +If you had values containing the backtick character, please quote those values with either single or double quotes. + +## [15.0.1](https://github.com/motdotla/dotenv/compare/v15.0.0...v15.0.1) (2022-02-02) + +### Changed + +- Properly parse empty single or double quoted values 🐞 ([#614](https://github.com/motdotla/dotenv/pull/614)) + +## [15.0.0](https://github.com/motdotla/dotenv/compare/v14.3.2...v15.0.0) (2022-01-31) + +`v15.0.0` is a major new release with some important breaking changes. + +### Added + +- _Breaking:_ Multiline parsing support (just works. no need for the flag.) + +### Changed + +- _Breaking:_ `#` marks the beginning of a comment (UNLESS the value is wrapped in quotes. Please update your `.env` files to wrap in quotes any values containing `#`. For example: `SECRET_HASH="something-with-a-#-hash"`). + +..Understandably, (as some teams have noted) this is tedious to do across the entire team. To make it less tedious, we recommend using [dotenv cli](https://github.com/dotenv-org/cli) going forward. It's an optional plugin that will keep your `.env` files in sync between machines, environments, or team members. + +### Removed + +- _Breaking:_ Remove multiline option (just works out of the box now. no need for the flag.) + +## [14.3.2](https://github.com/motdotla/dotenv/compare/v14.3.1...v14.3.2) (2022-01-25) + +### Changed + +- Preserve backwards compatibility on values containing `#` 🐞 ([#603](https://github.com/motdotla/dotenv/pull/603)) + +## [14.3.1](https://github.com/motdotla/dotenv/compare/v14.3.0...v14.3.1) (2022-01-25) + +### Changed + +- Preserve backwards compatibility on exports by re-introducing the prior in-place exports 🐞 ([#606](https://github.com/motdotla/dotenv/pull/606)) + +## [14.3.0](https://github.com/motdotla/dotenv/compare/v14.2.0...v14.3.0) (2022-01-24) + +### Added + +- Add `multiline` option πŸŽ‰ ([#486](https://github.com/motdotla/dotenv/pull/486)) + +## [14.2.0](https://github.com/motdotla/dotenv/compare/v14.1.1...v14.2.0) (2022-01-17) + +### Added + +- Add `dotenv_config_override` cli option +- Add `DOTENV_CONFIG_OVERRIDE` command line env option + +## [14.1.1](https://github.com/motdotla/dotenv/compare/v14.1.0...v14.1.1) (2022-01-17) + +### Added + +- Add React gotcha to FAQ on README + +## [14.1.0](https://github.com/motdotla/dotenv/compare/v14.0.1...v14.1.0) (2022-01-17) + +### Added + +- Add `override` option πŸŽ‰ ([#595](https://github.com/motdotla/dotenv/pull/595)) + +## [14.0.1](https://github.com/motdotla/dotenv/compare/v14.0.0...v14.0.1) (2022-01-16) + +### Added + +- Log error on failure to load `.env` file ([#594](https://github.com/motdotla/dotenv/pull/594)) + +## [14.0.0](https://github.com/motdotla/dotenv/compare/v13.0.1...v14.0.0) (2022-01-16) + +### Added + +- _Breaking:_ Support inline comments for the parser πŸŽ‰ ([#568](https://github.com/motdotla/dotenv/pull/568)) + +## [13.0.1](https://github.com/motdotla/dotenv/compare/v13.0.0...v13.0.1) (2022-01-16) + +### Changed + +* Hide comments and newlines from debug output ([#404](https://github.com/motdotla/dotenv/pull/404)) + +## [13.0.0](https://github.com/motdotla/dotenv/compare/v12.0.4...v13.0.0) (2022-01-16) + +### Added + +* _Breaking:_ Add type file for `config.js` ([#539](https://github.com/motdotla/dotenv/pull/539)) + +## [12.0.4](https://github.com/motdotla/dotenv/compare/v12.0.3...v12.0.4) (2022-01-16) + +### Changed + +* README updates +* Minor order adjustment to package json format + +## [12.0.3](https://github.com/motdotla/dotenv/compare/v12.0.2...v12.0.3) (2022-01-15) + +### Changed + +* Simplified jsdoc for consistency across editors + +## [12.0.2](https://github.com/motdotla/dotenv/compare/v12.0.1...v12.0.2) (2022-01-15) + +### Changed + +* Improve embedded jsdoc type documentation + +## [12.0.1](https://github.com/motdotla/dotenv/compare/v12.0.0...v12.0.1) (2022-01-15) + +### Changed + +* README updates and clarifications + +## [12.0.0](https://github.com/motdotla/dotenv/compare/v11.0.0...v12.0.0) (2022-01-15) + +### Removed + +- _Breaking:_ drop support for Flow static type checker ([#584](https://github.com/motdotla/dotenv/pull/584)) + +### Changed + +- Move types/index.d.ts to lib/main.d.ts ([#585](https://github.com/motdotla/dotenv/pull/585)) +- Typescript cleanup ([#587](https://github.com/motdotla/dotenv/pull/587)) +- Explicit typescript inclusion in package.json ([#566](https://github.com/motdotla/dotenv/pull/566)) + +## [11.0.0](https://github.com/motdotla/dotenv/compare/v10.0.0...v11.0.0) (2022-01-11) + +### Changed + +- _Breaking:_ drop support for Node v10 ([#558](https://github.com/motdotla/dotenv/pull/558)) +- Patch debug option ([#550](https://github.com/motdotla/dotenv/pull/550)) + +## [10.0.0](https://github.com/motdotla/dotenv/compare/v9.0.2...v10.0.0) (2021-05-20) + +### Added + +- Add generic support to parse function +- Allow for import "dotenv/config.js" +- Add support to resolve home directory in path via ~ + +## [9.0.2](https://github.com/motdotla/dotenv/compare/v9.0.1...v9.0.2) (2021-05-10) + +### Changed + +- Support windows newlines with debug mode + +## [9.0.1](https://github.com/motdotla/dotenv/compare/v9.0.0...v9.0.1) (2021-05-08) + +### Changed + +- Updates to README + +## [9.0.0](https://github.com/motdotla/dotenv/compare/v8.6.0...v9.0.0) (2021-05-05) + +### Changed + +- _Breaking:_ drop support for Node v8 + +## [8.6.0](https://github.com/motdotla/dotenv/compare/v8.5.1...v8.6.0) (2021-05-05) + +### Added + +- define package.json in exports + +## [8.5.1](https://github.com/motdotla/dotenv/compare/v8.5.0...v8.5.1) (2021-05-05) + +### Changed + +- updated dev dependencies via npm audit + +## [8.5.0](https://github.com/motdotla/dotenv/compare/v8.4.0...v8.5.0) (2021-05-05) + +### Added + +- allow for `import "dotenv/config"` + +## [8.4.0](https://github.com/motdotla/dotenv/compare/v8.3.0...v8.4.0) (2021-05-05) + +### Changed + +- point to exact types file to work with VS Code + +## [8.3.0](https://github.com/motdotla/dotenv/compare/v8.2.0...v8.3.0) (2021-05-05) + +### Changed + +- _Breaking:_ drop support for Node v8 (mistake to be released as minor bump. later bumped to 9.0.0. see above.) + +## [8.2.0](https://github.com/motdotla/dotenv/compare/v8.1.0...v8.2.0) (2019-10-16) + +### Added + +- TypeScript types + +## [8.1.0](https://github.com/motdotla/dotenv/compare/v8.0.0...v8.1.0) (2019-08-18) + +### Changed + +- _Breaking:_ drop support for Node v6 ([#392](https://github.com/motdotla/dotenv/issues/392)) + +# [8.0.0](https://github.com/motdotla/dotenv/compare/v7.0.0...v8.0.0) (2019-05-02) + +### Changed + +- _Breaking:_ drop support for Node v6 ([#302](https://github.com/motdotla/dotenv/issues/392)) + +## [7.0.0] - 2019-03-12 + +### Fixed + +- Fix removing unbalanced quotes ([#376](https://github.com/motdotla/dotenv/pull/376)) + +### Removed + +- Removed `load` alias for `config` for consistency throughout code and documentation. + +## [6.2.0] - 2018-12-03 + +### Added + +- Support preload configuration via environment variables ([#351](https://github.com/motdotla/dotenv/issues/351)) + +## [6.1.0] - 2018-10-08 + +### Added + +- `debug` option for `config` and `parse` methods will turn on logging + +## [6.0.0] - 2018-06-02 + +### Changed + +- _Breaking:_ drop support for Node v4 ([#304](https://github.com/motdotla/dotenv/pull/304)) + +## [5.0.0] - 2018-01-29 + +### Added + +- Testing against Node v8 and v9 +- Documentation on trim behavior of values +- Documentation on how to use with `import` + +### Changed + +- _Breaking_: default `path` is now `path.resolve(process.cwd(), '.env')` +- _Breaking_: does not write over keys already in `process.env` if the key has a falsy value +- using `const` and `let` instead of `var` + +### Removed + +- Testing against Node v7 + +## [4.0.0] - 2016-12-23 + +### Changed + +- Return Object with parsed content or error instead of false ([#165](https://github.com/motdotla/dotenv/pull/165)). + +### Removed + +- `verbose` option removed in favor of returning result. + +## [3.0.0] - 2016-12-20 + +### Added + +- `verbose` option will log any error messages. Off by default. +- parses email addresses correctly +- allow importing config method directly in ES6 + +### Changed + +- Suppress error messages by default ([#154](https://github.com/motdotla/dotenv/pull/154)) +- Ignoring more files for NPM to make package download smaller + +### Fixed + +- False positive test due to case-sensitive variable ([#124](https://github.com/motdotla/dotenv/pull/124)) + +### Removed + +- `silent` option removed in favor of `verbose` + +## [2.0.0] - 2016-01-20 + +### Added + +- CHANGELOG to ["make it easier for users and contributors to see precisely what notable changes have been made between each release"](http://keepachangelog.com/). Linked to from README +- LICENSE to be more explicit about what was defined in `package.json`. Linked to from README +- Testing nodejs v4 on travis-ci +- added examples of how to use dotenv in different ways +- return parsed object on success rather than boolean true + +### Changed + +- README has shorter description not referencing ruby gem since we don't have or want feature parity + +### Removed + +- Variable expansion and escaping so environment variables are encouraged to be fully orthogonal + +## [1.2.0] - 2015-06-20 + +### Added + +- Preload hook to require dotenv without including it in your code + +### Changed + +- clarified license to be "BSD-2-Clause" in `package.json` + +### Fixed + +- retain spaces in string vars + +## [1.1.0] - 2015-03-31 + +### Added + +- Silent option to silence `console.log` when `.env` missing + +## [1.0.0] - 2015-03-13 + +### Removed + +- support for multiple `.env` files. should always use one `.env` file for the current environment + +[7.0.0]: https://github.com/motdotla/dotenv/compare/v6.2.0...v7.0.0 +[6.2.0]: https://github.com/motdotla/dotenv/compare/v6.1.0...v6.2.0 +[6.1.0]: https://github.com/motdotla/dotenv/compare/v6.0.0...v6.1.0 +[6.0.0]: https://github.com/motdotla/dotenv/compare/v5.0.0...v6.0.0 +[5.0.0]: https://github.com/motdotla/dotenv/compare/v4.0.0...v5.0.0 +[4.0.0]: https://github.com/motdotla/dotenv/compare/v3.0.0...v4.0.0 +[3.0.0]: https://github.com/motdotla/dotenv/compare/v2.0.0...v3.0.0 +[2.0.0]: https://github.com/motdotla/dotenv/compare/v1.2.0...v2.0.0 +[1.2.0]: https://github.com/motdotla/dotenv/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/motdotla/dotenv/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/motdotla/dotenv/compare/v0.4.0...v1.0.0 diff --git a/node_modules/dotenv/LICENSE b/node_modules/dotenv/LICENSE new file mode 100644 index 000000000..c430ad8bd --- /dev/null +++ b/node_modules/dotenv/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Scott Motte +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/node_modules/dotenv/README.md b/node_modules/dotenv/README.md new file mode 100644 index 000000000..bef76307a --- /dev/null +++ b/node_modules/dotenv/README.md @@ -0,0 +1,446 @@ + + +[![dotenv-vault](https://badge.dotenv.org/works-with.svg?r=1)](https://www.dotenv.org/r/github.com/dotenv-org/dotenv-vault?r=1) + +# dotenv + +dotenv + +Dotenv is a zero-dependency module that loads environment variables from a `.env` file into [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). Storing configuration in the environment separate from code is based on [The Twelve-Factor App](http://12factor.net/config) methodology. + +[![BuildStatus](https://img.shields.io/travis/motdotla/dotenv/master.svg?style=flat-square)](https://travis-ci.org/motdotla/dotenv) +[![Build status](https://ci.appveyor.com/api/projects/status/github/motdotla/dotenv?svg=true)](https://ci.appveyor.com/project/motdotla/dotenv/branch/master) +[![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) +[![Coverage Status](https://img.shields.io/coveralls/motdotla/dotenv/master.svg?style=flat-square)](https://coveralls.io/github/motdotla/dotenv?branch=coverall-intergration) +[![LICENSE](https://img.shields.io/github/license/motdotla/dotenv.svg)](LICENSE) +[![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) +[![Featured on Openbase](https://badges.openbase.com/js/featured/dotenv.svg?token=eE0hWPkhC2JGSD4G9hwg5C54EBxjJAyvurGfQsYoKiQ=)](https://openbase.com/js/dotenv?utm_source=embedded&utm_medium=badge&utm_campaign=featured-badge&utm_term=js/dotenv) +[![Limited Edition Tee Original](https://img.shields.io/badge/Limited%20Edition%20Tee%20%F0%9F%91%95-Original-yellow?labelColor=black&style=plastic)](https://dotenv.gumroad.com/l/original) +[![Limited Edition Tee Redacted](https://img.shields.io/badge/Limited%20Edition%20Tee%20%F0%9F%91%95-Redacted-gray?labelColor=black&style=plastic)](https://dotenv.gumroad.com/l/redacted) + +## Install + +```bash +# install locally (recommended) +npm install dotenv --save +``` + +Or installing with yarn? `yarn add dotenv` + +## Usage + +Create a `.env` file in the root of your project: + +```dosini +S3_BUCKET="YOURS3BUCKET" +SECRET_KEY="YOURSECRETKEYGOESHERE" +``` + +As early as possible in your application, import and configure dotenv: + +```javascript +require('dotenv').config() +console.log(process.env) // remove this after you've confirmed it is working +``` + +.. or using ES6? + +```javascript +import * as dotenv from 'dotenv' // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import +dotenv.config() +import express from 'express' +``` + +That's it. `process.env` now has the keys and values you defined in your `.env` file: + +```javascript +require('dotenv').config() + +... + +s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {}) +``` + +### Multiline values + +If you need multiline variables, for example private keys, those are now supported (`>= v15.0.0`) with line breaks: + +```dosini +PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- +... +Kh9NV... +... +-----END RSA PRIVATE KEY-----" +``` + +Alternatively, you can double quote strings and use the `\n` character: + +```dosini +PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n" +``` + +### Comments + +Comments may be added to your file on their own line or inline: + +```dosini +# This is a comment +SECRET_KEY=YOURSECRETKEYGOESHERE # comment +SECRET_HASH="something-with-a-#-hash" +``` + +Comments begin where a `#` exists, so if your value contains a `#` please wrap it in quotes. This is a breaking change from `>= v15.0.0` and on. + +### Parsing + +The engine which parses the contents of your file containing environment variables is available to use. It accepts a String or Buffer and will return an Object with the parsed keys and values. + +```javascript +const dotenv = require('dotenv') +const buf = Buffer.from('BASIC=basic') +const config = dotenv.parse(buf) // will return an object +console.log(typeof config, config) // object { BASIC : 'basic' } +``` + +### Preload + +You can use the `--require` (`-r`) [command line option](https://nodejs.org/api/cli.html#-r---require-module) to preload dotenv. By doing this, you do not need to require and load dotenv in your application code. + +```bash +$ node -r dotenv/config your_script.js +``` + +The configuration options below are supported as command line arguments in the format `dotenv_config_