├── .dockerignore ├── .env.template ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ads-java.yml │ ├── ads.yml │ ├── backend.yml │ ├── dbm.yml │ ├── discounts.yml │ ├── frontend.yml │ ├── nginx.yml │ ├── postgres.yml │ └── release.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── docker-compose.yml ├── ecs ├── README.md ├── ecs-cluster.json ├── ecs-infrastructure.json └── tasks │ └── storedog-task-definition.json ├── scripts ├── backup-db.sh └── prepend_db_statements.sql └── services ├── ads ├── README.md ├── java │ ├── Dockerfile │ ├── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── src │ │ ├── main │ │ ├── java │ │ │ └── adsjava │ │ │ │ └── AdsJavaApplication.java │ │ └── resources │ │ │ ├── application.yml │ │ │ ├── logback-spring.xml │ │ │ └── static │ │ │ ├── ads │ │ │ ├── ad1.jpg │ │ │ ├── ad2.jpg │ │ │ └── ad3.jpg │ │ │ └── banner-list.json │ │ └── test │ │ └── java │ │ └── adsjava │ │ └── AdsJavaApplicationTests.java └── python │ ├── .dockerignore │ ├── Dockerfile │ ├── ads.py │ ├── ads │ ├── 1.jpg │ ├── 2.jpg │ └── 3.jpg │ ├── bootstrap.py │ ├── models.py │ └── requirements.txt ├── backend ├── .nvmrc ├── .rspec ├── .rubocop.yml ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── app.json ├── app │ ├── assets │ │ ├── builds │ │ │ ├── .keep │ │ │ ├── application.js │ │ │ ├── application.js.map │ │ │ ├── spree-dashboard.js │ │ │ └── spree-dashboard.js.map │ │ ├── config │ │ │ └── manifest.js │ │ ├── images │ │ │ ├── .keep │ │ │ └── tshirt1.webp │ │ └── stylesheets │ │ │ └── spree │ │ │ └── frontend │ │ │ └── variables │ │ │ └── variables.scss │ ├── controllers │ │ ├── application_controller.rb │ │ └── concerns │ │ │ └── .keep │ ├── helpers │ │ └── application_helper.rb │ ├── javascript │ │ ├── application.js │ │ └── spree-dashboard.js │ ├── jobs │ │ ├── application_job.rb │ │ └── sentry_job.rb │ ├── mailers │ │ └── .keep │ ├── models │ │ ├── .keep │ │ ├── application_record.rb │ │ └── concerns │ │ │ └── .keep │ ├── services │ │ └── .keep │ └── views │ │ └── .keep ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ ├── render-build.sh │ ├── setup │ ├── setup-no-docker │ ├── spring │ ├── start │ ├── update │ └── wait-for-services ├── config.ru ├── config │ ├── application.rb │ ├── aws.rb │ ├── boot.rb │ ├── cable.yml │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── active_storage.rb │ │ ├── application_controller_renderer.rb │ │ ├── assets.rb │ │ ├── backtrace_silencers.rb │ │ ├── content_security_policy.rb │ │ ├── cookies_serializer.rb │ │ ├── cors.rb │ │ ├── datadog-tracer.rb │ │ ├── devise.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ ├── oj.rb │ │ ├── raven.rb │ │ ├── redis.rb │ │ ├── session_store.rb │ │ ├── spree.rb │ │ └── wrap_parameters.rb │ ├── locales │ │ └── en.yml │ ├── puma.rb │ ├── routes.rb │ ├── secrets.yml │ ├── sidekiq.yml │ ├── spring.rb │ └── storage.yml ├── db │ ├── migrate │ │ ├── 20211203185331_create_active_storage_tables.active_storage.rb │ │ ├── 20211203185340_create_action_mailbox_tables.action_mailbox.rb │ │ ├── 20211203185341_create_action_text_tables.action_text.rb │ │ ├── 20211203185342_spree_four_three.spree.rb │ │ ├── 20211203185343_add_metadata_to_spree_orders.spree.rb │ │ ├── 20211203185344_add_metadata_to_spree_products.spree.rb │ │ ├── 20211203185345_add_metadata_to_spree_variants.spree.rb │ │ ├── 20211203185346_add_metadata_to_spree_line_items.spree.rb │ │ ├── 20211203185347_add_metadata_to_spree_shipments.spree.rb │ │ ├── 20211203185348_add_metadata_to_spree_payments.spree.rb │ │ ├── 20211203185349_add_metadata_to_spree_taxons_and_taxonomies.spree.rb │ │ ├── 20211203185350_add_metadata_to_spree_stock_transfers.spree.rb │ │ ├── 20211203185351_add_metadata_to_spree_multiple_tables.spree.rb │ │ ├── 20211203185352_add_deleted_at_to_spree_stores.spree.rb │ │ ├── 20211203185353_rename_column_access_hash_to_token.spree.rb │ │ ├── 20211203185354_create_spree_wishlists.spree.rb │ │ ├── 20211203185355_create_spree_wished_products.spree.rb │ │ ├── 20211203185356_rename_spree_wished_products_to_spree_wished_items.spree.rb │ │ ├── 20211203185357_add_unique_stock_item_stock_location_variant_deleted_at_index.spree.rb │ │ ├── 20211203185358_create_stock_item_stock_location_id_variant_id_coalesce_deleted_at_unique_index.spree.rb │ │ ├── 20211203185359_create_spree_digital_links.spree.rb │ │ ├── 20211203185360_create_spree_digitals.spree.rb │ │ ├── 20211203185361_rename_secret_to_token_on_spree_digital_links.spree.rb │ │ ├── 20211203185362_add_settings_to_spree_stores.spree.rb │ │ ├── 20211203185363_add_api_key_to_spree_users.spree_api.rb │ │ ├── 20211203185364_resize_api_key_field.spree_api.rb │ │ ├── 20211203185365_rename_api_key_to_spree_api_key.spree_api.rb │ │ ├── 20211203185366_add_index_to_user_spree_api_key.spree_api.rb │ │ ├── 20211203185367_create_doorkeeper_tables.spree_api.rb │ │ ├── 20211203185368_change_integer_id_columns_type.spree_api.rb │ │ ├── 20211203185369_create_spree_webhooks_tables.spree_api.rb │ │ ├── 20211203185370_enable_polymorphic_resource_owner.spree_api.rb │ │ ├── 20211203185371_create_spree_webhooks_events.spree_api.rb │ │ ├── 20211203185372_update_braintree_payment_method_type.spree_gateway.rb │ │ ├── 20211203185373_update_stripe_payment_method_type.spree_gateway.rb │ │ ├── 20211203185374_update_balanced_payment_method_type.spree_gateway.rb │ │ ├── 20211203185375_update_paypal_payment_method_type.spree_gateway.rb │ │ ├── 20211203185376_migrate_stripe_preferences.spree_gateway.rb │ │ ├── 20211203185377_add_spree_check_payment_source.spree_gateway.rb │ │ ├── 20211203185378_add_intent_key_to_payment.spree_gateway.rb │ │ ├── 20211203185379_create_users.spree_auth.rb │ │ ├── 20211203185380_rename_columns_for_devise.spree_auth.rb │ │ ├── 20211203185381_convert_user_remember_field.spree_auth.rb │ │ ├── 20211203185382_add_reset_password_sent_at_to_spree_users.spree_auth.rb │ │ ├── 20211203185383_make_users_email_index_unique.spree_auth.rb │ │ ├── 20211203185384_add_deleted_at_to_users.spree_auth.rb │ │ ├── 20211203185385_add_confirmable_to_users.spree_auth.rb │ │ ├── 20211203185386_add_missing_indices_on_user.spree_auth.rb │ │ └── 20211203185387_change_type_of_ship_address_id_and_bill_address_id_for_spree_users.spree_auth.rb │ ├── schema.rb │ ├── seeds.rb │ └── seeds │ │ └── 001_spree.rb ├── entrypoint.sh ├── lib │ ├── assets │ │ └── .keep │ ├── cloud_flare_middleware.rb │ └── tasks │ │ ├── .keep │ │ ├── clear_cache.rake │ │ └── custom_seed.rake ├── package-lock.json ├── package.json ├── public │ ├── 404.html │ ├── 422.html │ ├── 500.html │ ├── favicon.ico │ └── robots.txt ├── render.yaml ├── spec │ ├── rails_helper.rb │ ├── spec_helper.rb │ └── support │ │ └── vcr.rb ├── storage │ ├── 14 │ │ └── zj │ │ │ └── 14zj5sb9no7mevm8vtzjcym71vy1 │ ├── 16 │ │ └── 9t │ │ │ └── 169tp3memt7id57sh22o8ejtcblg │ ├── 41 │ │ └── wp │ │ │ └── 41wprtxdhsy40nh2h3igvhpdh982 │ ├── 62 │ │ └── xk │ │ │ └── 62xky8otdpnd1lm3zr07z7udt2bx │ ├── 75 │ │ └── n1 │ │ │ └── 75n1re2ozjbz45a88irjss1pu9e6 │ ├── 77 │ │ └── of │ │ │ └── 77of4hptz6t0rf0gn04v0kqjt4dm │ ├── 86 │ │ └── fg │ │ │ └── 86fgtuga925kaa17km9eamshazgr │ ├── 88 │ │ ├── 44 │ │ │ └── 8844gxgfc9ul1djle5kf8sqmgiyc │ │ └── he │ │ │ └── 88hekent0qoefm8b69builrth0xv │ ├── 89 │ │ └── to │ │ │ └── 89to0ymiqabe72nctvgrgqzyrk0o │ ├── 97 │ │ └── xe │ │ │ └── 97xen0j7t6ketkwt4l8vobq14qq9 │ ├── 00 │ │ └── 6g │ │ │ └── 006gnisak94ytqimt378gbad2hf9 │ ├── 0i │ │ └── zg │ │ │ └── 0izgp4zdrg4bxwvji5e0598oa8mp │ ├── 0k │ │ └── 8u │ │ │ └── 0k8uufd4279o44gzgz5efagsqteu │ ├── 0r │ │ ├── 42 │ │ │ └── 0r42dufnbi6rctn4vap71d1urqk9 │ │ └── r1 │ │ │ └── 0rr1qtiq705h498m2e65y04aa1fb │ ├── 1c │ │ └── n3 │ │ │ └── 1cn3v98qnmqwts7m6l5xkbhzvffn │ ├── 1j │ │ └── z1 │ │ │ └── 1jz13ploviow14epdbc68db9fslw │ ├── 1k │ │ └── s2 │ │ │ └── 1ks2veug3cveel5c0eeyaq0m647s │ ├── 2f │ │ └── y5 │ │ │ └── 2fy5a3t0idckqt117wqp88l1haj8 │ ├── 2o │ │ └── or │ │ │ └── 2ooru1xgcss6d2qeg4iwmjjgz2c9 │ ├── 2q │ │ └── zh │ │ │ └── 2qzh6w5ugc805s50nivs2k1xxfvi │ ├── 3l │ │ └── sq │ │ │ └── 3lsqhzqyca5o90l7ek5lcic5ge8z │ ├── 3o │ │ └── i8 │ │ │ └── 3oi8wwgyay2a5vsted2felpry3yw │ ├── 3p │ │ └── nu │ │ │ └── 3pnujzkcnksw26a0cu1vtyp1uviz │ ├── 5b │ │ └── ea │ │ │ └── 5beayoc679qsbk1udyydvujp3tuv │ ├── 6f │ │ └── 85 │ │ │ └── 6f852pkntrw16c0w9wzpdx2rnmud │ ├── 6m │ │ └── b7 │ │ │ └── 6mb7uh60to9dg7fvpjljjmqdnyfw │ ├── 7u │ │ └── pj │ │ │ └── 7upjjhp3sbp38un5ii23l5bm1tf8 │ ├── 7v │ │ └── xz │ │ │ └── 7vxzmrg3zgfub67kf82hb5vifqzu │ ├── 8c │ │ └── kn │ │ │ └── 8cknyjfznqw5id8jzny40hewyyrm │ ├── 8d │ │ └── rw │ │ │ └── 8drwmhakoag0ra8a1myjdr80mt57 │ ├── 8i │ │ └── vj │ │ │ └── 8ivjybuoo1jtnknvptho0ia2ysvl │ ├── 9l │ │ ├── c4 │ │ │ └── 9lc4lfmxvou7mvwqsl8g2fm27wfm │ │ └── ev │ │ │ └── 9levi783acolroehz6wn0cm0mzwa │ ├── az │ │ └── ws │ │ │ └── azwswza6kecyh2bmfnlpr7besvvb │ ├── b0 │ │ ├── 72 │ │ │ └── b0726xe61gdgxgmjki58njnwsivr │ │ └── 95 │ │ │ └── b095fsshrfwmoexn8czq2m3aiqbe │ ├── b5 │ │ └── 31 │ │ │ └── b531yunrur87esye2s4cwavym6te │ ├── bb │ │ ├── 45 │ │ │ └── bb45cs77n8gzn4ps91exl1cxuyft │ │ └── xn │ │ │ └── bbxn5vhfqpqdykae8z2cdf5x3dgs │ ├── bf │ │ └── kg │ │ │ └── bfkgrq99dea00vq7i74ludx4q31l │ ├── bl │ │ └── xp │ │ │ └── blxpqifldxzmb0nby4czkfn4u9q6 │ ├── bp │ │ └── 08 │ │ │ └── bp08j2pskt6xgz9ah0714mqdjwz7 │ ├── bz │ │ └── 2a │ │ │ └── bz2awto4gfx6t6udd7k5gjvke8i7 │ ├── c9 │ │ └── cj │ │ │ └── c9cjtgt3p7hdujcaxt41t08u1kux │ ├── cb │ │ └── kx │ │ │ └── cbkxlh6px78ymmakilgwygcm0qn5 │ ├── cj │ │ └── 1d │ │ │ └── cj1dxfmw44hktr8lhbwzpw7aoxz5 │ ├── d7 │ │ └── k8 │ │ │ └── d7k8l52o2ji9tkor07sqd25wpxdk │ ├── db │ │ └── ag │ │ │ └── dbagqumqgq1z6319o338j7bmt5pq │ ├── dq │ │ └── c7 │ │ │ └── dqc7t23uxsm5axhesoap039wqjeb │ ├── e3 │ │ └── lt │ │ │ └── e3ltmq2g8mfvj4wifyzt7uj3w5ns │ ├── eb │ │ └── 2a │ │ │ └── eb2a2zd73ok9x0rlw0o164mduamd │ ├── f1 │ │ ├── 6r │ │ │ └── f16rwfhvanpxrwgn2ct48cgfp326 │ │ └── f6 │ │ │ └── f1f6rz6nuf57ryix259yxq7j3tje │ ├── f3 │ │ └── dt │ │ │ └── f3dtrvou5azxky00y68u7qbjgaqn │ ├── f5 │ │ └── xr │ │ │ └── f5xr4qy5dtulhpe8kgazjo2x7ubz │ ├── f7 │ │ └── tg │ │ │ └── f7tg9iqtd0i6tqxzkf15010kl9xq │ ├── fj │ │ └── gx │ │ │ └── fjgxeszqvcbrc0v0u2n7i70yd956 │ ├── fk │ │ └── 0o │ │ │ └── fk0o9nsutjpswot205kna7pdoj02 │ ├── fs │ │ └── ip │ │ │ └── fsipi7gdrjs2mxhgop0etbuwsfu2 │ ├── fy │ │ └── au │ │ │ └── fyau0gplpld5a6c12gvncp18ravq │ ├── gq │ │ └── x4 │ │ │ └── gqx496zj9ao0ce2y69s8ebcdt76c │ ├── gs │ │ └── 1o │ │ │ └── gs1oqg4v74c76h2f8zsqj0p91yjc │ ├── h3 │ │ └── um │ │ │ └── h3ump7vjqudll390ky1rdss0xdb4 │ ├── h8 │ │ └── 3c │ │ │ └── h83cdk6x8kd1amwvte8aavqnxii3 │ ├── hm │ │ └── nd │ │ │ └── hmndfefa02esgzpaqksemkf51q88 │ ├── hp │ │ └── sk │ │ │ └── hpskdx8sfybt0o39s4e2veuqv6nd │ ├── hv │ │ └── lm │ │ │ └── hvlm8gb3nktx69eteqqt7atj9qrs │ ├── ir │ │ └── 5t │ │ │ └── ir5thn1x7rn9legliqvjh23qg1bl │ ├── j4 │ │ └── j2 │ │ │ └── j4j2wb67ekv1hle6t5z2aq19gstf │ ├── jl │ │ └── mg │ │ │ └── jlmgno906bkhwsytjqiyns2hqut8 │ ├── jo │ │ └── ru │ │ │ └── joru4prw3skdtc8i4ia5dwq5874k │ ├── jr │ │ └── qt │ │ │ └── jrqti00rfi88kdgvjnw4s0tdv7xc │ ├── k7 │ │ └── hr │ │ │ └── k7hrw0msrvsspxi698amx5kmh2wg │ ├── kr │ │ └── u2 │ │ │ └── kru2kfqkml3mwkuhmc2w0uvtp4x1 │ ├── kw │ │ └── ch │ │ │ └── kwchc38i5j2uqyrfui13h914doju │ ├── l0 │ │ └── id │ │ │ └── l0idqd59oxu5iz00z9m3iep48pjm │ ├── l8 │ │ └── 1g │ │ │ └── l81gft3rnuphlp36xw4q33p4r1cs │ ├── lp │ │ └── lr │ │ │ └── lplrh3v056du1izagk5o76sfu98p │ ├── lt │ │ └── mc │ │ │ └── ltmc7z2yt5ozwpuqmoz2uw98xylf │ ├── m6 │ │ └── sb │ │ │ └── m6sbj199y5b8id0eg6dvktm1nbyu │ ├── ms │ │ └── m8 │ │ │ └── msm81dgmxk4ggqiud2bv4j9waoie │ ├── n1 │ │ └── m4 │ │ │ └── n1m4ol3mo2fbg77imv5qn156swi4 │ ├── n8 │ │ └── aa │ │ │ └── n8aao8d8v8ene7vn4d14zdqxntna │ ├── nd │ │ └── mb │ │ │ └── ndmbmj2or9w5lgnwmyyexp34n509 │ ├── ni │ │ └── yw │ │ │ └── niywd6phcjdfuxw97lxi1y8t1sya │ ├── nx │ │ └── 9d │ │ │ └── nx9dapm2zhd2kh991ompea29775m │ ├── o5 │ │ └── d9 │ │ │ └── o5d9h8s1hih1gihezeeu73fgwa88 │ ├── o7 │ │ └── 2a │ │ │ └── o72a5s5ye01ie6mtx8h7olnldvko │ ├── oi │ │ └── fp │ │ │ └── oifpdmfenjck5p39s91m8ij5ya5a │ ├── op │ │ └── a2 │ │ │ └── opa2g8bl3tpm0ecip3f4yun9hcd8 │ ├── os │ │ └── vh │ │ │ └── osvherjecbdx3ezy3jvar6vvfwrk │ ├── ox │ │ └── 4i │ │ │ └── ox4iruasiwuftdu71u98l5t4rpgm │ ├── p7 │ │ └── d5 │ │ │ └── p7d5guboq24b265ytl0u5w20hzjl │ ├── p8 │ │ └── 0j │ │ │ └── p80jyh6ws8gqmfrp8kcjcgctdieh │ ├── pi │ │ └── co │ │ │ └── picolufbbcsybadgh89nutlhun53 │ ├── pk │ │ └── 18 │ │ │ └── pk18k7l7xvz7fcz9ecz20m01mbg1 │ ├── q5 │ │ └── 90 │ │ │ └── q590wag6b1vszjszc3mfd23192sj │ ├── q8 │ │ └── 69 │ │ │ └── q869nghoropy7vm31r30cgs85x0d │ ├── r0 │ │ └── l3 │ │ │ └── r0l3vmf800tdhnaha8ipdutspb1e │ ├── rc │ │ └── p1 │ │ │ └── rcp1c0ffcrahrxl6ddwdj502lrzh │ ├── rp │ │ └── 62 │ │ │ └── rp62efuo0c81qrdzczbw9vbu1eih │ ├── rw │ │ └── st │ │ │ └── rwst4dkl9wdsmq13w2fwj04ha284 │ ├── rx │ │ └── 4i │ │ │ └── rx4ig9xw7h5y1y2sqqmawsq1x17p │ ├── ss │ │ └── kb │ │ │ └── sskbwu2e4lqf6vdd9po2ozhnfm6d │ ├── t2 │ │ └── gb │ │ │ └── t2gbiuwefu2cu69nx6ef7mxvlkyf │ ├── t8 │ │ └── sf │ │ │ └── t8sfq5w9vte2byg1ql3vrf6erjz6 │ ├── ta │ │ └── su │ │ │ └── tasu842mlz829y8ps7va67ttq7my │ ├── tc │ │ └── uy │ │ │ └── tcuywtfa5bo7iswkbmocinkv4obn │ ├── tq │ │ └── 3q │ │ │ └── tq3q5lsbdzh1hfwfto2ub0dwuuul │ ├── u5 │ │ └── m8 │ │ │ └── u5m8nx87ih2y01eoc5y0og5exoga │ ├── un │ │ └── 6x │ │ │ └── un6xvbm6l3ecxwxwuxffc6b6pksy │ ├── v2 │ │ └── d6 │ │ │ └── v2d6kiibpmi2n5wei0zvfmgcrcp6 │ ├── vd │ │ └── hf │ │ │ └── vdhfjqfz88rsidepmoygmvmzuory │ ├── vk │ │ ├── 66 │ │ │ └── vk66376ys3oh94khxr2gyaqe718p │ │ └── qt │ │ │ └── vkqtro308bcx9nauolzjgfsdjiaj │ ├── vn │ │ └── 91 │ │ │ └── vn912gigj022zdj21b018id2vb0h │ ├── w7 │ │ └── h1 │ │ │ └── w7h15x1uh9994su68lm16er6p8fj │ ├── wp │ │ └── ik │ │ │ └── wpik6q4kgdlnd8zy9vxfayze9bxl │ ├── wt │ │ └── zf │ │ │ └── wtzfa794b5vpax1qrbegb7xnioi2 │ ├── x0 │ │ └── j5 │ │ │ └── x0j50n6qwk4g0p72hy9h9gmz9l41 │ ├── xp │ │ └── 7a │ │ │ └── xp7a6l2hhtrp4ow3oo2e8ozqzuz1 │ ├── yu │ │ └── 65 │ │ │ └── yu65ul5ekff3gdub9ot599wbqq5t │ ├── z8 │ │ └── lp │ │ │ └── z8lp9oe5quoqzkewjtvj14rubeg0 │ └── zi │ │ └── ae │ │ └── ziae3tzvaen6pm7pdzsya7rv46l3 └── vendor │ └── assets │ ├── javascripts │ ├── .keep │ └── spree │ │ ├── backend │ │ └── all.js │ │ └── frontend │ │ └── all.js │ └── stylesheets │ ├── .keep │ └── spree │ ├── backend │ └── all.css │ └── frontend │ └── all.css ├── datadog-agent └── postgres │ └── dd-agent-conf.yaml ├── dbm ├── .dockerignore ├── Dockerfile ├── README.md ├── bootstrap.py ├── dbm.py ├── dbm_exec.sh ├── dbm_setup.sql ├── models.py └── requirements.txt ├── discounts ├── .dockerignore ├── Dockerfile ├── README.md ├── bootstrap.py ├── discounts.py ├── models.py ├── requirements.txt ├── test.py ├── words.json └── words.py ├── frontend ├── .eslintrc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── Dockerfile ├── README.md ├── assets │ ├── base.css │ ├── chrome-bug.css │ ├── components.css │ └── main.css ├── components │ ├── ErrorBoundary.tsx │ ├── cart │ │ ├── CartItem │ │ │ ├── CartItem.module.css │ │ │ ├── CartItem.tsx │ │ │ └── index.ts │ │ ├── CartSidebarView │ │ │ ├── CartSidebarView.module.css │ │ │ ├── CartSidebarView.tsx │ │ │ └── index.ts │ │ └── index.ts │ ├── checkout │ │ ├── CheckoutSidebarView │ │ │ ├── CheckoutSidebarView.module.css │ │ │ ├── CheckoutSidebarView.tsx │ │ │ └── index.ts │ │ ├── OrderConfirmView │ │ │ ├── OrderConfirmView.module.css │ │ │ ├── OrderConfirmView.tsx │ │ │ └── index.ts │ │ ├── PaymentMethodView │ │ │ ├── PaymentMethodView.module.css │ │ │ ├── PaymentMethodView.tsx │ │ │ └── index.ts │ │ ├── PaymentWidget │ │ │ ├── PaymentWidget.module.css │ │ │ ├── PaymentWidget.tsx │ │ │ └── index.ts │ │ ├── ShippingView │ │ │ ├── ShippingView.module.css │ │ │ ├── ShippingView.tsx │ │ │ └── index.ts │ │ ├── ShippingWidget │ │ │ ├── ShippingWidget.module.css │ │ │ ├── ShippingWidget.tsx │ │ │ └── index.ts │ │ └── context.tsx │ ├── common │ │ ├── Ad │ │ │ ├── Ad.tsx │ │ │ └── index.ts │ │ ├── Avatar │ │ │ ├── Avatar.tsx │ │ │ └── index.ts │ │ ├── Discount │ │ │ ├── Discount.tsx │ │ │ └── index.ts │ │ ├── FeatureBar │ │ │ ├── FeatureBar.module.css │ │ │ ├── FeatureBar.tsx │ │ │ └── index.ts │ │ ├── Footer │ │ │ ├── Footer.module.css │ │ │ ├── Footer.tsx │ │ │ └── index.ts │ │ ├── Head │ │ │ ├── Head.tsx │ │ │ └── index.ts │ │ ├── HomeAllProductsGrid │ │ │ ├── HomeAllProductsGrid.module.css │ │ │ ├── HomeAllProductsGrid.tsx │ │ │ └── index.ts │ │ ├── Layout │ │ │ ├── Layout.module.css │ │ │ ├── Layout.tsx │ │ │ └── index.ts │ │ ├── Navbar │ │ │ ├── Navbar.module.css │ │ │ ├── Navbar.tsx │ │ │ ├── NavbarRoot.tsx │ │ │ └── index.ts │ │ ├── SEO │ │ │ ├── SEO.tsx │ │ │ └── index.ts │ │ ├── Searchbar │ │ │ ├── Searchbar.module.css │ │ │ ├── Searchbar.tsx │ │ │ └── index.ts │ │ ├── SidebarLayout │ │ │ ├── SidebarLayout.module.css │ │ │ ├── SidebarLayout.tsx │ │ │ └── index.ts │ │ ├── UserNav │ │ │ ├── MenuSidebarView │ │ │ │ ├── MenuSidebarView.module.css │ │ │ │ ├── MenuSidebarView.tsx │ │ │ │ └── index.ts │ │ │ ├── UserNav.module.css │ │ │ ├── UserNav.tsx │ │ │ └── index.ts │ │ └── index.ts │ ├── icons │ │ ├── ArrowLeft.tsx │ │ ├── ArrowRight.tsx │ │ ├── Bag.tsx │ │ ├── Check.tsx │ │ ├── ChevronDown.tsx │ │ ├── ChevronLeft.tsx │ │ ├── ChevronRight.tsx │ │ ├── ChevronUp.tsx │ │ ├── CreditCard.tsx │ │ ├── Cross.tsx │ │ ├── DoubleChevron.tsx │ │ ├── Github.tsx │ │ ├── Heart.tsx │ │ ├── Info.tsx │ │ ├── MapPin.tsx │ │ ├── Menu.tsx │ │ ├── Minus.tsx │ │ ├── Moon.tsx │ │ ├── Plus.tsx │ │ ├── Star.tsx │ │ ├── Sun.tsx │ │ ├── Trash.tsx │ │ ├── Vercel.tsx │ │ └── index.ts │ ├── product │ │ ├── ProductCard │ │ │ ├── ProductCard-v2.tsx │ │ │ ├── ProductCard.module.css │ │ │ ├── ProductCard.tsx │ │ │ └── index.ts │ │ ├── ProductList.tsx │ │ ├── ProductOptions │ │ │ ├── ProductOptions.tsx │ │ │ └── index.ts │ │ ├── ProductSidebar │ │ │ ├── ProductSidebar.module.css │ │ │ ├── ProductSidebar.tsx │ │ │ └── index.ts │ │ ├── ProductSlider │ │ │ ├── ProductSlider.module.css │ │ │ ├── ProductSlider.tsx │ │ │ └── index.ts │ │ ├── ProductSliderControl │ │ │ ├── ProductSliderControl.module.css │ │ │ ├── ProductSliderControl.tsx │ │ │ └── index.ts │ │ ├── ProductTag │ │ │ ├── ProductTag.module.css │ │ │ ├── ProductTag.tsx │ │ │ └── index.ts │ │ ├── ProductView │ │ │ ├── ProductView.module.css │ │ │ ├── ProductView.tsx │ │ │ └── index.ts │ │ ├── Swatch │ │ │ ├── Swatch.module.css │ │ │ ├── Swatch.tsx │ │ │ └── index.ts │ │ ├── helpers.ts │ │ └── index.ts │ └── ui │ │ ├── Button │ │ ├── Button.module.css │ │ ├── Button.tsx │ │ └── index.ts │ │ ├── Collapse │ │ ├── Collapse.module.css │ │ ├── Collapse.tsx │ │ └── index.ts │ │ ├── Container │ │ ├── Container.tsx │ │ └── index.ts │ │ ├── Dropdown │ │ ├── Dropdown.module.css │ │ └── Dropdown.tsx │ │ ├── Grid │ │ ├── Grid.module.css │ │ ├── Grid.tsx │ │ └── index.ts │ │ ├── Hero │ │ ├── Hero.module.css │ │ ├── Hero.tsx │ │ └── index.ts │ │ ├── Input │ │ ├── Input.module.css │ │ ├── Input.tsx │ │ └── index.ts │ │ ├── Link │ │ ├── Link.tsx │ │ └── index.ts │ │ ├── LoadingDots │ │ ├── LoadingDots.module.css │ │ ├── LoadingDots.tsx │ │ └── index.ts │ │ ├── Logo │ │ ├── Logo.tsx │ │ └── index.ts │ │ ├── Marquee │ │ ├── Marquee.module.css │ │ ├── Marquee.tsx │ │ └── index.ts │ │ ├── Modal │ │ ├── Modal.module.css │ │ ├── Modal.tsx │ │ └── index.ts │ │ ├── Quantity │ │ ├── Quantity.module.css │ │ ├── Quantity.tsx │ │ └── index.ts │ │ ├── README.md │ │ ├── Rating │ │ ├── Rating.module.css │ │ ├── Rating.tsx │ │ └── index.ts │ │ ├── Sidebar │ │ ├── Sidebar.module.css │ │ ├── Sidebar.tsx │ │ └── index.ts │ │ ├── Skeleton │ │ ├── Skeleton.module.css │ │ ├── Skeleton.tsx │ │ └── index.ts │ │ ├── Text │ │ ├── Text.module.css │ │ ├── Text.tsx │ │ └── index.ts │ │ ├── context.tsx │ │ └── index.ts ├── config │ ├── country_iso_codes.json │ ├── seo_meta.json │ └── user_data.json ├── featureFlags.config.json ├── global.d.ts ├── lib │ ├── CartContext.tsx │ ├── api │ │ ├── cart.ts │ │ ├── checkout.ts │ │ ├── pages.ts │ │ ├── products.ts │ │ └── taxons.ts │ ├── colors.ts │ ├── focus-trap.tsx │ ├── hooks │ │ ├── usePrice.tsx │ │ └── useUserAvatar.ts │ ├── range-map.ts │ └── to-pixels.ts ├── next-env.d.ts ├── next-logger.config.js ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ ├── 404.tsx │ ├── [...pages].tsx │ ├── _app.tsx │ ├── _document.tsx │ ├── api │ │ ├── pages │ │ │ ├── [slug].ts │ │ │ └── index.ts │ │ ├── products │ │ │ ├── [slug].ts │ │ │ └── index.ts │ │ └── taxonomies │ │ │ ├── [taxonomy] │ │ │ ├── [slug].ts │ │ │ └── index.ts │ │ │ └── index.ts │ ├── index.tsx │ ├── products │ │ ├── [slug].tsx │ │ └── index.tsx │ └── taxonomies │ │ └── [taxonomy] │ │ ├── [...slug].tsx │ │ └── index.tsx ├── postcss.config.js ├── public │ ├── assets │ │ ├── drop-shirt-0.png │ │ ├── drop-shirt-1.png │ │ ├── drop-shirt-2.png │ │ ├── drop-shirt.png │ │ ├── lightweight-jacket-0.png │ │ ├── lightweight-jacket-1.png │ │ ├── lightweight-jacket-2.png │ │ ├── t-shirt-0.png │ │ ├── t-shirt-1.png │ │ ├── t-shirt-2.png │ │ ├── t-shirt-3.png │ │ └── t-shirt-4.png │ ├── bg-products.svg │ ├── card.png │ ├── cursor-left.png │ ├── cursor-right.png │ ├── favicon-32x32.png │ ├── favicon.ico │ ├── flag-en-us.svg │ ├── flag-es-ar.svg │ ├── flag-es-co.svg │ ├── flag-es.svg │ ├── icon-144x144.png │ ├── icon-192x192.png │ ├── icon-512x512.png │ ├── icon.png │ ├── product-img-placeholder.svg │ ├── site.webmanifest │ ├── slider-arrows.png │ └── vercel.svg ├── tailwind.config.js ├── tsconfig.json └── types │ ├── cart.ts │ ├── checkout.ts │ ├── page.ts │ ├── product.ts │ └── taxons.ts ├── nginx ├── Dockerfile ├── default.conf ├── nginx.conf └── status.conf ├── postgres ├── Dockerfile ├── db │ └── restore.sql ├── postgresql.conf └── scripts │ ├── cleanup-cron │ └── start-services.sh ├── puppeteer ├── Dockerfile └── scripts │ ├── puppeteer.js │ └── puppeteer.sh └── worker └── config └── initializers └── datadog-tracer.rb /.dockerignore: -------------------------------------------------------------------------------- 1 | tmp/* 2 | log/* 3 | .git 4 | node_modules 5 | coverage 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Any future lines will overwrite this default. The last pattern 3 | # that matches, will be the final pattern. 4 | # See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners 5 | 6 | * @DataDog/training @DataDog/corpweb -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | ## How to test 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/workflows/ads-java.yml: -------------------------------------------------------------------------------- 1 | name: Ads - Java 2 | 3 | permissions: {} 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - services/ads/java/** 10 | workflow_dispatch: 11 | 12 | defaults: 13 | run: 14 | working-directory: ads 15 | 16 | jobs: 17 | 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | permissions: 22 | packages: write 23 | contents: read 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Set up Docker Buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Login to GHCR 33 | id: login-ghcr 34 | uses: docker/login-action@v3 35 | with: 36 | registry: ghcr.io 37 | username: ${{ github.actor }} 38 | password: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | - name: Build and push 41 | uses: docker/build-push-action@v5 42 | with: 43 | context: ./services/ads/java 44 | platforms: linux/amd64,linux/arm64 45 | push: true 46 | tags: ghcr.io/datadog/storedog/ads-java:latest 47 | 48 | -------------------------------------------------------------------------------- /.github/workflows/ads.yml: -------------------------------------------------------------------------------- 1 | name: Ads - Python 2 | 3 | permissions: {} 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - services/ads/python/** 10 | workflow_dispatch: 11 | 12 | defaults: 13 | run: 14 | working-directory: ads 15 | 16 | jobs: 17 | 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | permissions: 22 | packages: write 23 | contents: read 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Set up Docker Buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Login to GHCR 33 | id: login-ghcr 34 | uses: docker/login-action@v3 35 | with: 36 | registry: ghcr.io 37 | username: ${{ github.actor }} 38 | password: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | - name: Build and push 41 | uses: docker/build-push-action@v5 42 | with: 43 | context: ./services/ads/python 44 | platforms: linux/amd64,linux/arm64 45 | push: true 46 | tags: ghcr.io/datadog/storedog/ads:latest 47 | 48 | -------------------------------------------------------------------------------- /.github/workflows/backend.yml: -------------------------------------------------------------------------------- 1 | name: Backend 2 | 3 | permissions: {} 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - services/backend/** 10 | workflow_dispatch: 11 | 12 | defaults: 13 | run: 14 | working-directory: backend 15 | 16 | jobs: 17 | 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | permissions: 22 | packages: write 23 | contents: read 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Set up Docker Buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Login to GHCR 33 | id: login-ghcr 34 | uses: docker/login-action@v3 35 | with: 36 | registry: ghcr.io 37 | username: ${{ github.actor }} 38 | password: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | - name: Build and push 41 | uses: docker/build-push-action@v5 42 | with: 43 | context: ./services/backend 44 | platforms: linux/amd64,linux/arm64 45 | push: true 46 | tags: ghcr.io/datadog/storedog/backend:latest 47 | 48 | -------------------------------------------------------------------------------- /.github/workflows/dbm.yml: -------------------------------------------------------------------------------- 1 | name: DBM 2 | 3 | permissions: {} 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - services/dbm/** 10 | workflow_dispatch: 11 | 12 | defaults: 13 | run: 14 | working-directory: dbm 15 | 16 | 17 | jobs: 18 | 19 | build: 20 | 21 | runs-on: ubuntu-latest 22 | permissions: 23 | packages: write 24 | contents: read 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | 30 | - name: Set up Docker Buildx 31 | uses: docker/setup-buildx-action@v3 32 | 33 | - name: Login to GHCR 34 | id: login-ghcr 35 | uses: docker/login-action@v3 36 | with: 37 | registry: ghcr.io 38 | username: ${{ github.actor }} 39 | password: ${{ secrets.GITHUB_TOKEN }} 40 | 41 | - name: Build and push 42 | uses: docker/build-push-action@v5 43 | with: 44 | context: ./services/dbm 45 | platforms: linux/amd64,linux/arm64 46 | push: true 47 | tags: ghcr.io/datadog/storedog/dbm:latest 48 | 49 | -------------------------------------------------------------------------------- /.github/workflows/discounts.yml: -------------------------------------------------------------------------------- 1 | name: Discounts 2 | 3 | permissions: {} 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - services/discounts/** 10 | workflow_dispatch: 11 | 12 | defaults: 13 | run: 14 | working-directory: discounts 15 | 16 | jobs: 17 | 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | permissions: 22 | packages: write 23 | contents: read 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Set up Docker Buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Login to GHCR 33 | id: login-ghcr 34 | uses: docker/login-action@v3 35 | with: 36 | registry: ghcr.io 37 | username: ${{ github.actor }} 38 | password: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | - name: Build and push 41 | uses: docker/build-push-action@v5 42 | with: 43 | context: ./services/discounts 44 | platforms: linux/amd64,linux/arm64 45 | push: true 46 | tags: ghcr.io/datadog/storedog/discounts:latest 47 | -------------------------------------------------------------------------------- /.github/workflows/frontend.yml: -------------------------------------------------------------------------------- 1 | name: Frontend 2 | 3 | permissions: {} 4 | 5 | on: 6 | push: 7 | branches: [ main ] 8 | paths: 9 | - services/frontend/** 10 | workflow_dispatch: 11 | 12 | defaults: 13 | run: 14 | working-directory: frontend 15 | 16 | jobs: 17 | 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | permissions: 22 | packages: write 23 | contents: read 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v3 28 | 29 | - name: Set up Docker Buildx 30 | uses: docker/setup-buildx-action@v3 31 | 32 | - name: Login to GHCR 33 | id: login-ghcr 34 | uses: docker/login-action@v3 35 | with: 36 | registry: ghcr.io 37 | username: ${{ github.actor }} 38 | password: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | - name: Build and push 41 | uses: docker/build-push-action@v5 42 | with: 43 | context: ./services/frontend 44 | platforms: linux/arm64, linux/amd64 45 | push: true 46 | tags: ghcr.io/datadog/storedog/frontend:latest 47 | 48 | -------------------------------------------------------------------------------- /ecs/README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | > [!NOTE] This is a work in progress. The contents of this directory need to be updated to reflect the latest changes in the Storedog app. 4 | 5 | This directory holds the infrastrucutre templates to run Storedog on AWS ECS via EC2. EC2 is the preferred hosting engine due to the `bridge` network mode, which is not available in Fargate. This allows our containers to inter-communicate. 6 | 7 | The memory and CPU settings defined in the `storedog-task-definition.json` assume you are running at least one `m3.xlarge` instance. Note that these settings have not yet been optimized so there is an opportunity to downsize. -------------------------------------------------------------------------------- /scripts/backup-db.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # exec dump on postgres container 4 | 5 | # get root of repository 6 | root=$(git rev-parse --show-toplevel) 7 | prependstatements=$root/scripts/prepend_db_statements.sql 8 | destination=$root/services/postgres/db/restore.sql 9 | 10 | # remove old backups in the restore folder 11 | rm -f $root/services/postgres/db/*.sql 12 | 13 | # exec dump 14 | docker compose exec postgres pg_dump -U postgres storedog_db > $destination 15 | 16 | echo "Backup created at $destination" 17 | 18 | # prepend statements to the dump 19 | cat $prependstatements $destination > $destination.tmp 20 | mv $destination.tmp $destination 21 | -------------------------------------------------------------------------------- /services/ads/java/Dockerfile: -------------------------------------------------------------------------------- 1 | # compile via gradle 2 | FROM gradle:jdk11 AS TEMP_BUILD_IMAGE 3 | ENV APP_HOME=/usr/app/ 4 | WORKDIR $APP_HOME 5 | COPY build.gradle settings.gradle $APP_HOME 6 | 7 | COPY gradle $APP_HOME/gradle 8 | COPY --chown=gradle:gradle . /home/gradle/src 9 | USER root 10 | RUN chown -R gradle /home/gradle/src 11 | 12 | COPY . . 13 | RUN gradle clean build 14 | 15 | # app container 16 | FROM alpine:latest 17 | RUN apk --update add openjdk11-jre 18 | ENV ARTIFACT_NAME=ads-java-0.0.1-SNAPSHOT.jar 19 | ENV APP_HOME=/usr/app/ 20 | ENV ADS_SERVER_PORT=3030 21 | 22 | WORKDIR $APP_HOME 23 | COPY --from=TEMP_BUILD_IMAGE $APP_HOME/build/libs/$ARTIFACT_NAME . 24 | 25 | RUN wget -O dd-java-agent.jar 'https://dtdg.co/latest-java-tracer' 26 | 27 | ENTRYPOINT exec java -javaagent:/usr/app/dd-java-agent.jar -jar ${ARTIFACT_NAME} -------------------------------------------------------------------------------- /services/ads/java/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.springframework.boot' version '2.7.5' 3 | id 'io.spring.dependency-management' version '1.0.15.RELEASE' 4 | id 'java' 5 | } 6 | 7 | group = 'com.example' 8 | version = '0.0.1-SNAPSHOT' 9 | sourceCompatibility = '11' 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation ( 17 | 'commons-io:commons-io:2.4', 18 | 'org.springframework.boot:spring-boot-starter-web' 19 | ) 20 | implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' 21 | implementation 'net.logstash.logback:logstash-logback-encoder:7.0' 22 | testImplementation 'org.springframework.boot:spring-boot-starter-test' 23 | } 24 | 25 | tasks.named('test') { 26 | useJUnitPlatform() 27 | } 28 | -------------------------------------------------------------------------------- /services/ads/java/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/java/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /services/ads/java/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /services/ads/java/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ads-java' 2 | -------------------------------------------------------------------------------- /services/ads/java/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${ADS_SERVER_PORT:3030} 3 | -------------------------------------------------------------------------------- /services/ads/java/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /services/ads/java/src/main/resources/static/ads/ad1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/java/src/main/resources/static/ads/ad1.jpg -------------------------------------------------------------------------------- /services/ads/java/src/main/resources/static/ads/ad2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/java/src/main/resources/static/ads/ad2.jpg -------------------------------------------------------------------------------- /services/ads/java/src/main/resources/static/ads/ad3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/java/src/main/resources/static/ads/ad3.jpg -------------------------------------------------------------------------------- /services/ads/java/src/main/resources/static/banner-list.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Discount Clothing", 5 | "path": "ad1.jpg", 6 | "url": "/t/clothing", 7 | "weight": 15.1 8 | }, 9 | { 10 | "id": 2, 11 | "name": "Cool Hats", 12 | "path": "ad2.jpg", 13 | "url": "/products/datadog-ringer-t-shirt", 14 | "weight": 300.1 15 | }, 16 | { 17 | "id": 3, 18 | "name": "Nice Bags", 19 | "path": "ad3.jpg", 20 | "url": "/t/bags", 21 | "weight": 5242.1 22 | } 23 | ] 24 | -------------------------------------------------------------------------------- /services/ads/java/src/test/java/adsjava/AdsJavaApplicationTests.java: -------------------------------------------------------------------------------- 1 | package adsjava; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class AdsJavaApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /services/ads/python/.dockerignore: -------------------------------------------------------------------------------- 1 | # Version control 2 | .git 3 | 4 | # Compiled Python bytecode 5 | **/__pycache__ 6 | **/*.pyc 7 | **/*.pyo 8 | 9 | # Compiled extensions 10 | **/*.pyd 11 | **/*.so 12 | 13 | # coverage.py 14 | .coverage 15 | .coverage.* 16 | htmlcov 17 | 18 | # Cached files 19 | .cache 20 | .mypy_cache 21 | .hypothesis 22 | .pytest_cache 23 | 24 | # Virtualenvs and builds 25 | build/ 26 | dist/ 27 | .env 28 | .venv 29 | env/ 30 | venv/ 31 | ENV/ 32 | env.bak/ 33 | venv.bak/ 34 | 35 | # Docker 36 | Dockerfile* 37 | .dockerignore 38 | -------------------------------------------------------------------------------- /services/ads/python/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.2 2 | # ^ This enables the new BuildKit stable syntax which can be 3 | # run with the DOCKER_BUILDKIT=1 environment variable in your 4 | # docker build command (see build.sh) 5 | FROM python:3.9.6-slim-buster 6 | # Update, upgrade, and cleanup debian packages 7 | RUN export DEBIAN_FRONTEND=noninteractive && \ 8 | apt-get update && \ 9 | apt-get upgrade --yes && \ 10 | apt-get install --yes build-essential libpq-dev wait-for-it && \ 11 | apt-get clean && \ 12 | rm -rf /var/lib/apt/lists/* 13 | 14 | # Copy over app 15 | WORKDIR /app 16 | COPY . . 17 | 18 | # Install dependencies via pip and avoid caching build artifacts 19 | RUN pip install --no-cache-dir -r requirements.txt 20 | 21 | # Set default Flask app and development environment 22 | ENV FLASK_APP=ads.py 23 | 24 | # Start the app using ddtrace so we have profiling and tracing 25 | ENTRYPOINT ["ddtrace-run"] 26 | CMD flask run --port=3030 --host=0.0.0.0 27 | -------------------------------------------------------------------------------- /services/ads/python/ads/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/python/ads/1.jpg -------------------------------------------------------------------------------- /services/ads/python/ads/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/python/ads/2.jpg -------------------------------------------------------------------------------- /services/ads/python/ads/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/ads/python/ads/3.jpg -------------------------------------------------------------------------------- /services/ads/python/models.py: -------------------------------------------------------------------------------- 1 | from flask_sqlalchemy import SQLAlchemy 2 | import datetime 3 | 4 | db = SQLAlchemy() 5 | 6 | class Advertisement(db.Model): 7 | id = db.Column(db.Integer, primary_key=True) 8 | name = db.Column(db.String(128)) 9 | url = db.Column(db.String(64)) 10 | weight = db.Column(db.Float()) 11 | path = db.Column(db.String(128)) 12 | 13 | def __init__(self, name, url, weight, path): 14 | self.name = name 15 | self.url = url 16 | self.weight = weight 17 | self.path = path 18 | 19 | def serialize(self): 20 | return { 21 | 'id': self.id, 22 | 'name': self.name, 23 | 'url': self.url, 24 | 'weight': self.weight, 25 | 'path': self.path 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /services/ads/python/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2020.11.8 2 | chardet==3.0.4 3 | click==7.1.2 4 | ddtrace==2.16.0 5 | Flask==1.1.2 6 | Flask-Cors==3.0.10 7 | Flask-SQLAlchemy==2.4.4 8 | idna==2.10 9 | intervaltree==3.1.0 10 | itsdangerous==1.1.0 11 | Jinja2==2.11.3 12 | MarkupSafe==1.1.1 13 | nose==1.3.7 14 | protobuf==3.14.0 15 | psycopg2==2.8.6 16 | requests==2.25.1 17 | six==1.15.0 18 | sortedcontainers==2.3.0 19 | SQLAlchemy==1.3.23 20 | tenacity==6.2.0 21 | urllib3==1.26.5 22 | Werkzeug==1.0.1 23 | JSON-log-formatter==0.5.2 -------------------------------------------------------------------------------- /services/backend/.nvmrc: -------------------------------------------------------------------------------- 1 | v16 2 | -------------------------------------------------------------------------------- /services/backend/.rspec: -------------------------------------------------------------------------------- 1 | --require spec_helper -f documentation 2 | -------------------------------------------------------------------------------- /services/backend/README.md: -------------------------------------------------------------------------------- 1 | # Backend service (product management) 2 | 3 | ## Overview 4 | 5 | This service manages the products in the store. It is a Ruby on Rails application built using the Spree framework. The service is packaged as a Docker image and typically used in a Docker Compose file (see the root of this repo). 6 | 7 | -------------------------------------------------------------------------------- /services/backend/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /services/backend/app/assets/builds/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/assets/builds/.keep -------------------------------------------------------------------------------- /services/backend/app/assets/builds/application.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | })(); 3 | //# sourceMappingURL=application.js.map 4 | -------------------------------------------------------------------------------- /services/backend/app/assets/builds/application.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": [], 4 | "sourcesContent": [], 5 | "mappings": "", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /services/backend/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | //= link_tree ../builds 4 | -------------------------------------------------------------------------------- /services/backend/app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/assets/images/.keep -------------------------------------------------------------------------------- /services/backend/app/assets/images/tshirt1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/assets/images/tshirt1.webp -------------------------------------------------------------------------------- /services/backend/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | end 6 | -------------------------------------------------------------------------------- /services/backend/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /services/backend/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper; end 2 | -------------------------------------------------------------------------------- /services/backend/app/javascript/application.js: -------------------------------------------------------------------------------- 1 | // Entry point for the build script in your package.json 2 | -------------------------------------------------------------------------------- /services/backend/app/javascript/spree-dashboard.js: -------------------------------------------------------------------------------- 1 | // Entry point for the build script in your package.json 2 | 3 | import "@spree/dashboard" 4 | 5 | new SpreeDashboard.Dashboard() 6 | 7 | // window.Turbo = SpreeDashboard.Turbo 8 | -------------------------------------------------------------------------------- /services/backend/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /services/backend/app/jobs/sentry_job.rb: -------------------------------------------------------------------------------- 1 | class SentryJob < ApplicationJob 2 | queue_as :sentry 3 | 4 | def perform(event) 5 | Raven.send_event(event) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /services/backend/app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/mailers/.keep -------------------------------------------------------------------------------- /services/backend/app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/models/.keep -------------------------------------------------------------------------------- /services/backend/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /services/backend/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/models/concerns/.keep -------------------------------------------------------------------------------- /services/backend/app/services/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/services/.keep -------------------------------------------------------------------------------- /services/backend/app/views/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/app/views/.keep -------------------------------------------------------------------------------- /services/backend/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /services/backend/bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if ! command -v foreman &> /dev/null 4 | then 5 | echo "Installing foreman..." 6 | gem install foreman 7 | fi 8 | 9 | foreman start -f Procfile.dev 10 | -------------------------------------------------------------------------------- /services/backend/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /services/backend/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /services/backend/bin/render-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # exit on error 3 | set -o errexit 4 | 5 | bundle install 6 | bundle exec rails assets:precompile 7 | bundle exec rails assets:clean 8 | bundle exec rails db:migrate 9 | bundle exec rails db:seed 10 | bundle exec rake spree_sample:load 11 | -------------------------------------------------------------------------------- /services/backend/bin/setup: -------------------------------------------------------------------------------- 1 | 2 | rm -rf .env && cp -f .env.sample .env && 3 | docker-compose build backend && 4 | docker-compose run --rm backend bash -c ' 5 | bin/wait-for-services && 6 | (bundle check || bundle install) && 7 | bundle exec rails db:drop && 8 | bundle exec rails db:create && 9 | bundle exec rails db:migrate && 10 | bundle exec rails db:seed && 11 | rm -rf tmp/latest.dump 12 | ' && 13 | docker-compose up 14 | -------------------------------------------------------------------------------- /services/backend/bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m)) 11 | Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq } 12 | gem 'spring', match[1] 13 | require 'spring/binstub' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /services/backend/bin/start: -------------------------------------------------------------------------------- 1 | docker compose up 2 | -------------------------------------------------------------------------------- /services/backend/bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a way to update your development environment automatically. 14 | # Add necessary update steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies if using Yarn 21 | # system('bin/yarn') 22 | 23 | puts "\n== Updating database ==" 24 | system! 'bin/rails db:migrate' 25 | 26 | puts "\n== Removing old logs and tempfiles ==" 27 | system! 'bin/rails log:clear tmp:clear' 28 | 29 | puts "\n== Restarting application server ==" 30 | system! 'bin/rails restart' 31 | end 32 | -------------------------------------------------------------------------------- /services/backend/bin/wait-for-services: -------------------------------------------------------------------------------- 1 | until nc -z -v -w30 $DB_HOST $DB_PORT; do 2 | echo 'Waiting for PostgreSQL...' 3 | sleep 1 4 | done 5 | echo "PostgreSQL is up and running!" 6 | -------------------------------------------------------------------------------- /services/backend/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /services/backend/config/aws.rb: -------------------------------------------------------------------------------- 1 | Aws::VERSION = Gem.loaded_specs["aws-sdk"].version 2 | -------------------------------------------------------------------------------- /services/backend/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /services/backend/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: spark_starter_kit_production 11 | -------------------------------------------------------------------------------- /services/backend/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /services/backend/config/initializers/active_storage.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy 2 | -------------------------------------------------------------------------------- /services/backend/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /services/backend/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | # Add Yarn node_modules folder to the asset load path. 9 | if defined?(Webpacker) 10 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 11 | end 12 | 13 | # Precompile additional assets. 14 | # application.js, application.css, and all non-JS/CSS in the app/assets 15 | # folder are already added. 16 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 17 | -------------------------------------------------------------------------------- /services/backend/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /services/backend/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /services/backend/config/initializers/cors.rb: -------------------------------------------------------------------------------- 1 | # Avoid CORS issues when API is called from the frontend app. 2 | # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests. 3 | 4 | # Read more: https://github.com/cyu/rack-cors 5 | 6 | Rails.application.config.middleware.insert_before 0, Rack::Cors, debug: ENV.fetch('RACK_CORS_DEBUG', false), logger: (-> { Rails.logger }) do 7 | allow do 8 | origins ENV.fetch('ALLOWED_ORIGIN_HOSTS', '*').split(',') 9 | 10 | resource '*', 11 | headers: :any, 12 | methods: %i[get post delete put patch options head], 13 | max_age: 0 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /services/backend/config/initializers/datadog-tracer.rb: -------------------------------------------------------------------------------- 1 | Datadog.configure do |c| 2 | c.service = ENV['DD_SERVICE'] || 'store-backend' 3 | # Activates and configures an integration 4 | c.tracing.instrument :pg, service_name: 'postgres' 5 | c.tracing.instrument :aws, service_name: 'store-backend-aws' 6 | c.tracing.instrument :dalli, service_name: 'store-backend-memcached' 7 | c.tracing.instrument :active_support, cache_service: 'store-backend-cache' 8 | end -------------------------------------------------------------------------------- /services/backend/config/initializers/devise.rb: -------------------------------------------------------------------------------- 1 | Devise.secret_key = Rails.application.secrets.secret_key_base 2 | if defined?(Spree::Auth) 3 | Spree::Auth::Config.signout_after_password_change = false 4 | end 5 | -------------------------------------------------------------------------------- /services/backend/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /services/backend/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /services/backend/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /services/backend/config/initializers/oj.rb: -------------------------------------------------------------------------------- 1 | require 'oj' 2 | 3 | Oj.optimize_rails 4 | -------------------------------------------------------------------------------- /services/backend/config/initializers/raven.rb: -------------------------------------------------------------------------------- 1 | Raven.configure do |config| 2 | config.async = lambda { |event| SentryJob.perform_later(event) } 3 | config.environments = %w[ production ] 4 | config.excluded_exceptions += ['ActionController::RoutingError', 'ActiveRecord::RecordNotFound', 5 | 'Rack::Timeout::RequestExpiryError', 'Rack::Timeout::RequestTimeoutException'] 6 | config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s) 7 | end 8 | -------------------------------------------------------------------------------- /services/backend/config/initializers/redis.rb: -------------------------------------------------------------------------------- 1 | # fix for Redis config on Heroku 2 | if ENV['REDISCLOUD_URL'].present? && ENV['REDIS_URL'].blank? 3 | ENV['REDIS_URL'] = ENV['REDISCLOUD_URL'] 4 | end 5 | -------------------------------------------------------------------------------- /services/backend/config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | cookie_domain = ENV['COOKIE_DOMAIN'] == 'all' ? :all : ENV['COOKIE_DOMAIN'] 4 | 5 | Rails.application.config.session_store :cookie_store, 6 | key: '_spree_starter_session', 7 | domain: cookie_domain, 8 | expire_after: 12.hours, 9 | secure: Rails.env.production?, 10 | httponly: true, 11 | same_site: :lax 12 | -------------------------------------------------------------------------------- /services/backend/config/initializers/spree.rb: -------------------------------------------------------------------------------- 1 | # Configure Spree Preferences 2 | # 3 | # Note: Initializing preferences available within the Admin will overwrite any changes that were made through the user interface when you restart. 4 | # If you would like users to be able to update a setting with the Admin it should NOT be set here. 5 | # 6 | # Note: If a preference is set here it will be stored within the cache & database upon initialization. 7 | # Just removing an entry from this initializer will not make the preference value go away. 8 | # Instead you must either set a new value or remove entry, clear cache, and remove database entry. 9 | # 10 | # In order to initialize a setting do: 11 | # config.setting_name = 'new value' 12 | Spree.config do |config| 13 | # Example: 14 | # Uncomment to stop tracking inventory levels in the application 15 | # config.track_inventory_levels = false 16 | end 17 | 18 | Spree.user_class = 'Spree::User' 19 | -------------------------------------------------------------------------------- /services/backend/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /services/backend/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /services/backend/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # Spree routes 3 | mount Spree::Core::Engine, at: '/' 4 | 5 | # sidekiq web UI 6 | require 'sidekiq/web' 7 | Sidekiq::Web.use Rack::Auth::Basic do |username, password| 8 | username == Rails.application.secrets.sidekiq_username && 9 | password == Rails.application.secrets.sidekiq_password 10 | end 11 | mount Sidekiq::Web, at: '/sidekiq' 12 | end 13 | -------------------------------------------------------------------------------- /services/backend/config/sidekiq.yml: -------------------------------------------------------------------------------- 1 | --- 2 | :concurrency: 5 3 | :max_memory: 512 # MB 4 | :gc_interval: 10 # GC every 10 jobs 5 | :queues: 6 | - default 7 | - mailers 8 | - sentry 9 | - active_storage_analysis 10 | - spree_stock_location_stock_items 11 | - spree_webhooks 12 | -------------------------------------------------------------------------------- /services/backend/config/spring.rb: -------------------------------------------------------------------------------- 1 | %w( 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ).each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185340_create_action_mailbox_tables.action_mailbox.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from action_mailbox (originally 20180917164000) 2 | class CreateActionMailboxTables < ActiveRecord::Migration[6.0] 3 | def change 4 | create_table :action_mailbox_inbound_emails do |t| 5 | t.integer :status, default: 0, null: false 6 | t.string :message_id, null: false 7 | t.string :message_checksum, null: false 8 | 9 | t.timestamps 10 | 11 | t.index [ :message_id, :message_checksum ], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185341_create_action_text_tables.action_text.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from action_text (originally 20180528164100) 2 | class CreateActionTextTables < ActiveRecord::Migration[6.0] 3 | def change 4 | create_table :action_text_rich_texts do |t| 5 | t.string :name, null: false 6 | t.text :body, size: :long 7 | t.references :record, null: false, polymorphic: true, index: false 8 | 9 | t.timestamps 10 | 11 | t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185343_add_metadata_to_spree_orders.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064321) 2 | class AddMetadataToSpreeOrders < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_orders do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_orders, :public_metadata, :jsonb 7 | add_column :spree_orders, :private_metadata, :jsonb 8 | else 9 | add_column :spree_orders, :public_metadata, :json 10 | add_column :spree_orders, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185344_add_metadata_to_spree_products.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064322) 2 | class AddMetadataToSpreeProducts < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_products do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_products, :public_metadata, :jsonb 7 | add_column :spree_products, :private_metadata, :jsonb 8 | else 9 | add_column :spree_products, :public_metadata, :json 10 | add_column :spree_products, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185345_add_metadata_to_spree_variants.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064323) 2 | class AddMetadataToSpreeVariants < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_variants do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_variants, :public_metadata, :jsonb 7 | add_column :spree_variants, :private_metadata, :jsonb 8 | else 9 | add_column :spree_variants, :public_metadata, :json 10 | add_column :spree_variants, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185346_add_metadata_to_spree_line_items.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064324) 2 | class AddMetadataToSpreeLineItems < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_line_items do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_line_items, :public_metadata, :jsonb 7 | add_column :spree_line_items, :private_metadata, :jsonb 8 | else 9 | add_column :spree_line_items, :public_metadata, :json 10 | add_column :spree_line_items, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185347_add_metadata_to_spree_shipments.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064325) 2 | class AddMetadataToSpreeShipments < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_shipments do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_shipments, :public_metadata, :jsonb 7 | add_column :spree_shipments, :private_metadata, :jsonb 8 | else 9 | add_column :spree_shipments, :public_metadata, :json 10 | add_column :spree_shipments, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185348_add_metadata_to_spree_payments.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064326) 2 | class AddMetadataToSpreePayments < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_payments do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_payments, :public_metadata, :jsonb 7 | add_column :spree_payments, :private_metadata, :jsonb 8 | else 9 | add_column :spree_payments, :public_metadata, :json 10 | add_column :spree_payments, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185349_add_metadata_to_spree_taxons_and_taxonomies.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064327) 2 | class AddMetadataToSpreeTaxonsAndTaxonomies < ActiveRecord::Migration[5.2] 3 | def change 4 | %i[ 5 | spree_taxons 6 | spree_taxonomies 7 | ].each do |table_name| 8 | change_table table_name do |t| 9 | if t.respond_to? :jsonb 10 | add_column table_name, :public_metadata, :jsonb 11 | add_column table_name, :private_metadata, :jsonb 12 | else 13 | add_column table_name, :public_metadata, :json 14 | add_column table_name, :private_metadata, :json 15 | end 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185350_add_metadata_to_spree_stock_transfers.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064328) 2 | class AddMetadataToSpreeStockTransfers < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_stock_transfers do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_stock_transfers, :public_metadata, :jsonb 7 | add_column :spree_stock_transfers, :private_metadata, :jsonb 8 | else 9 | add_column :spree_stock_transfers, :public_metadata, :json 10 | add_column :spree_stock_transfers, :private_metadata, :json 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185351_add_metadata_to_spree_multiple_tables.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210915064329) 2 | class AddMetadataToSpreeMultipleTables < ActiveRecord::Migration[5.2] 3 | def change 4 | %i[ 5 | spree_assets 6 | spree_option_types 7 | spree_option_values 8 | spree_properties 9 | spree_promotions 10 | spree_payment_methods 11 | spree_shipping_methods 12 | spree_prototypes 13 | spree_refunds 14 | spree_customer_returns 15 | spree_users 16 | spree_addresses 17 | spree_credit_cards 18 | spree_store_credits 19 | ].each do |table_name| 20 | change_table table_name do |t| 21 | if t.respond_to? :jsonb 22 | add_column table_name, :public_metadata, :jsonb 23 | add_column table_name, :private_metadata, :jsonb 24 | else 25 | add_column table_name, :public_metadata, :json 26 | add_column table_name, :private_metadata, :json 27 | end 28 | end 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185352_add_deleted_at_to_spree_stores.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210920090344) 2 | class AddDeletedAtToSpreeStores < ActiveRecord::Migration[5.2] 3 | def change 4 | unless column_exists?(:spree_stores, :deleted_at) 5 | add_column :spree_stores, :deleted_at, :datetime 6 | add_index :spree_stores, :deleted_at 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185353_rename_column_access_hash_to_token.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210921070812) 2 | class RenameColumnAccessHashToToken < ActiveRecord::Migration[5.2] 3 | def change 4 | if table_exists?(:spree_wishlists) 5 | rename_column(:spree_wishlists, :access_hash, :token) if column_exists?(:spree_wishlists, :access_hash) 6 | add_reference(:spree_wishlists, :store, index: true) unless column_exists?(:spree_wishlists, :store_id) 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185354_create_spree_wishlists.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210921070813) 2 | class CreateSpreeWishlists < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :spree_wishlists, if_not_exists: true do |t| 5 | t.belongs_to :user 6 | t.belongs_to :store 7 | 8 | t.column :name, :string 9 | t.column :token, :string, null: false 10 | t.column :is_private, :boolean, default: true, null: false 11 | t.column :is_default, :boolean, default: false, null: false 12 | 13 | t.timestamps 14 | end 15 | 16 | add_index :spree_wishlists, :token, unique: true 17 | add_index :spree_wishlists, [:user_id, :is_default] unless index_exists?(:spree_wishlists, [:user_id, :is_default]) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185355_create_spree_wished_products.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210921070814) 2 | class CreateSpreeWishedProducts < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :spree_wished_products, if_not_exists: true do |t| 5 | t.references :variant 6 | t.belongs_to :wishlist 7 | 8 | t.column :quantity, :integer, default: 1, null: false 9 | 10 | t.timestamps 11 | end 12 | 13 | add_index :spree_wished_products, [:variant_id, :wishlist_id], unique: true unless index_exists?(:spree_wished_products, [:variant_id, :wishlist_id]) 14 | add_index :spree_wished_products, :variant_id unless index_exists?(:spree_wished_products, :variant_id) 15 | add_index :spree_wished_products, :wishlist_id unless index_exists?(:spree_wished_products, :wishlist_id) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185356_rename_spree_wished_products_to_spree_wished_items.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210921070815) 2 | class RenameSpreeWishedProductsToSpreeWishedItems < ActiveRecord::Migration[5.2] 3 | def change 4 | rename_table :spree_wished_products, :spree_wished_items 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185357_add_unique_stock_item_stock_location_variant_deleted_at_index.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210921090344) 2 | class AddUniqueStockItemStockLocationVariantDeletedAtIndex < ActiveRecord::Migration[5.2] 3 | def change 4 | add_index :spree_stock_items, [:stock_location_id, :variant_id, :deleted_at], name: 'stock_item_by_loc_var_id_deleted_at', unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185359_create_spree_digital_links.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210929091444) 2 | class CreateSpreeDigitalLinks < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :spree_digital_links, if_not_exists: true do |t| 5 | t.belongs_to :digital 6 | t.belongs_to :line_item 7 | t.string :secret 8 | t.integer :access_counter 9 | 10 | t.timestamps 11 | end 12 | add_index :spree_digital_links, :secret, unique: true unless index_exists?(:spree_digital_links, :secret) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185360_create_spree_digitals.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210929093238) 2 | class CreateSpreeDigitals < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :spree_digitals, if_not_exists: true do |t| 5 | t.belongs_to :variant 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185361_rename_secret_to_token_on_spree_digital_links.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210930143043) 2 | class RenameSecretToTokenOnSpreeDigitalLinks < ActiveRecord::Migration[5.2] 3 | def change 4 | rename_column :spree_digital_links, :secret, :token 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185362_add_settings_to_spree_stores.spree.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree (originally 20210930155649) 2 | class AddSettingsToSpreeStores < ActiveRecord::Migration[5.2] 3 | def change 4 | change_table :spree_stores do |t| 5 | if t.respond_to? :jsonb 6 | add_column :spree_stores, :settings, :jsonb 7 | else 8 | add_column :spree_stores, :settings, :json 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185363_add_api_key_to_spree_users.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20100107141738) 2 | class AddApiKeyToSpreeUsers < ActiveRecord::Migration[4.2] 3 | def change 4 | unless defined?(User) 5 | add_column :spree_users, :api_key, :string, limit: 40 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185364_resize_api_key_field.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20120411123334) 2 | class ResizeApiKeyField < ActiveRecord::Migration[4.2] 3 | def change 4 | unless defined?(User) 5 | change_column :spree_users, :api_key, :string, limit: 48 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185365_rename_api_key_to_spree_api_key.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20120530054546) 2 | class RenameApiKeyToSpreeApiKey < ActiveRecord::Migration[4.2] 3 | def change 4 | unless defined?(User) 5 | rename_column :spree_users, :api_key, :spree_api_key 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185366_add_index_to_user_spree_api_key.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20131017162334) 2 | class AddIndexToUserSpreeApiKey < ActiveRecord::Migration[4.2] 3 | def change 4 | unless defined?(User) 5 | add_index :spree_users, :spree_api_key 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185368_change_integer_id_columns_type.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20210727102516) 2 | class ChangeIntegerIdColumnsType < ActiveRecord::Migration[5.2] 3 | def change 4 | change_column :spree_oauth_access_grants, :resource_owner_id, :bigint 5 | change_column :spree_oauth_access_grants, :application_id, :bigint 6 | 7 | change_column :spree_oauth_access_tokens, :resource_owner_id, :bigint 8 | change_column :spree_oauth_access_tokens, :application_id, :bigint 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185369_create_spree_webhooks_tables.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20210902162826) 2 | class CreateSpreeWebhooksTables < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :spree_webhooks_subscribers do |t| 5 | t.string :url, null: false 6 | t.boolean :active, default: false, index: true 7 | 8 | if t.respond_to? :jsonb 9 | t.jsonb :subscriptions 10 | else 11 | t.json :subscriptions 12 | end 13 | 14 | t.timestamps 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185371_create_spree_webhooks_events.spree_api.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_api (originally 20211025162826) 2 | class CreateSpreeWebhooksEvents < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :spree_webhooks_events do |t| 5 | t.integer "execution_time" 6 | t.string "name", null: false 7 | t.string "request_errors" 8 | t.string "response_code", index: true 9 | t.belongs_to "subscriber", null: false, index: true 10 | t.boolean "success", index: true 11 | t.string "url", null: false 12 | t.timestamps 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185372_update_braintree_payment_method_type.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20121017004102) 2 | class UpdateBraintreePaymentMethodType < SpreeExtension::Migration[4.2] 3 | def up 4 | Spree::PaymentMethod.where(:type => "Spree::Gateway::Braintree").update_all(:type => "Spree::Gateway::BraintreeGateway") 5 | end 6 | 7 | def down 8 | Spree::PaymentMethod.where(:type => "Spree::Gateway::BraintreeGateway").update_all(:type => "Spree::Gateway::Braintree") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185373_update_stripe_payment_method_type.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20130213222555) 2 | class UpdateStripePaymentMethodType < SpreeExtension::Migration[4.2] 3 | def up 4 | Spree::PaymentMethod.where(:type => "Spree::Gateway::Stripe").update_all(:type => "Spree::Gateway::StripeGateway") 5 | end 6 | 7 | def down 8 | Spree::PaymentMethod.where(:type => "Spree::Gateway::StripeGateway").update_all(:type => "Spree::Gateway::Stripe") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185374_update_balanced_payment_method_type.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20130415222802) 2 | class UpdateBalancedPaymentMethodType < SpreeExtension::Migration[4.2] 3 | def up 4 | Spree::PaymentMethod.where(:type => "Spree::Gateway::Balanced").update_all(:type => "Spree::Gateway::BalancedGateway") 5 | end 6 | 7 | def down 8 | Spree::PaymentMethod.where(:type => "Spree::Gateway::BalancedGateway").update_all(:type => "Spree::Gateway::Balanced") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185375_update_paypal_payment_method_type.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20131008221012) 2 | class UpdatePaypalPaymentMethodType < SpreeExtension::Migration[4.2] 3 | def up 4 | Spree::PaymentMethod.where(:type => "Spree::Gateway::PayPal").update_all(:type => "Spree::Gateway::PayPalGateway") 5 | end 6 | 7 | def down 8 | Spree::PaymentMethod.where(:type => "Spree::Gateway::PayPalGateway").update_all(:type => "Spree::Gateway::PayPal") 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185376_migrate_stripe_preferences.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20131112133401) 2 | class MigrateStripePreferences < SpreeExtension::Migration[4.2] 3 | def up 4 | Spree::Preference.where("#{ActiveRecord::Base.connection.quote_column_name("key")} LIKE 'spree/gateway/stripe_gateway/login%'").each do |pref| 5 | pref.key = pref.key.gsub('login', 'secret_key') 6 | pref.save 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185377_add_spree_check_payment_source.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20200317135551) 2 | class AddSpreeCheckPaymentSource < ActiveRecord::Migration[5.1] 3 | def change 4 | create_table :spree_checks do |t| 5 | t.references :payment_method 6 | t.references :user 7 | t.string "account_holder_name" 8 | t.string "account_holder_type" 9 | t.string "routing_number" 10 | t.string "account_number" 11 | t.string "account_type", default: 'checking' 12 | t.string "status" 13 | t.string "last_digits" 14 | t.string "gateway_customer_profile_id" 15 | t.string "gateway_payment_profile_id" 16 | 17 | t.datetime "created_at", null: false 18 | t.datetime "updated_at", null: false 19 | t.datetime "deleted_at" 20 | end 21 | add_index :spree_payment_methods, :id 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185378_add_intent_key_to_payment.spree_gateway.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_gateway (originally 20200422114908) 2 | class AddIntentKeyToPayment < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :spree_payments, :intent_client_key, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185381_convert_user_remember_field.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20101214150824) 2 | class ConvertUserRememberField < SpreeExtension::Migration[4.2] 3 | def up 4 | remove_column :spree_users, :remember_created_at 5 | add_column :spree_users, :remember_created_at, :datetime 6 | end 7 | 8 | def down 9 | remove_column :spree_users, :remember_created_at 10 | add_column :spree_users, :remember_created_at, :string 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185382_add_reset_password_sent_at_to_spree_users.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20120203010234) 2 | class AddResetPasswordSentAtToSpreeUsers < SpreeExtension::Migration[4.2] 3 | def change 4 | Spree.user_class.reset_column_information 5 | unless Spree.user_class.column_names.include?("reset_password_sent_at") 6 | add_column :spree_users, :reset_password_sent_at, :datetime 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185383_make_users_email_index_unique.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20120605211305) 2 | class MakeUsersEmailIndexUnique < SpreeExtension::Migration[4.2] 3 | def up 4 | add_index "spree_users", ["email"], name: "email_idx_unique", unique: true 5 | end 6 | 7 | def down 8 | remove_index "spree_users", name: "email_idx_unique" 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185384_add_deleted_at_to_users.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20140904000425) 2 | class AddDeletedAtToUsers < SpreeExtension::Migration[4.2] 3 | def change 4 | add_column :spree_users, :deleted_at, :datetime 5 | add_index :spree_users, :deleted_at 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185385_add_confirmable_to_users.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20141002154641) 2 | class AddConfirmableToUsers < SpreeExtension::Migration[4.2] 3 | def change 4 | add_column :spree_users, :confirmation_token, :string 5 | add_column :spree_users, :confirmed_at, :datetime 6 | add_column :spree_users, :confirmation_sent_at, :datetime 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185386_add_missing_indices_on_user.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20150416152553) 2 | class AddMissingIndicesOnUser < SpreeExtension::Migration[4.2] 3 | def change 4 | unless index_exists?(:spree_users, :bill_address_id) 5 | add_index :spree_users, :bill_address_id 6 | end 7 | unless index_exists?(:spree_users, :ship_address_id) 8 | add_index :spree_users, :ship_address_id 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /services/backend/db/migrate/20211203185387_change_type_of_ship_address_id_and_bill_address_id_for_spree_users.spree_auth.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from spree_auth (originally 20210728103922) 2 | class ChangeTypeOfShipAddressIdAndBillAddressIdForSpreeUsers < ActiveRecord::Migration[4.2] 3 | def change 4 | change_table(:spree_users) do |t| 5 | t.change :ship_address_id, :bigint 6 | t.change :bill_address_id, :bigint 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /services/backend/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Place all seeds in /seeds/ folder. 3 | # 4 | 5 | Spree::Webhooks.disable_webhooks do 6 | Dir[File.dirname(__FILE__) + '/seeds/*.rb'].sort.each do |file| 7 | puts "Seeds #{file} ..." 8 | require file 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/db/seeds/001_spree.rb: -------------------------------------------------------------------------------- 1 | Spree::Core::Engine.load_seed if defined?(Spree::Core) 2 | Spree::Auth::Engine.load_seed if defined?(Spree::Auth) 3 | -------------------------------------------------------------------------------- /services/backend/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | bundle exec rails db:migrate 4 | exec "$@" 5 | -------------------------------------------------------------------------------- /services/backend/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/lib/assets/.keep -------------------------------------------------------------------------------- /services/backend/lib/cloud_flare_middleware.rb: -------------------------------------------------------------------------------- 1 | # CloudFlare masks the true IP 2 | # This middleware ensures the Rails stack obtains the correct IP when using request.remote_ip 3 | # See https://support.cloudflare.com/hc/en-us/articles/200170786 4 | 5 | module Rack 6 | class CloudFlareMiddleware 7 | def initialize(app) 8 | @app = app 9 | end 10 | 11 | def call(env) 12 | if env['HTTP_CF_CONNECTING_IP'] 13 | env['HTTP_REMOTE_ADDR_BEFORE_CF'] = env['REMOTE_ADDR'] 14 | env['HTTP_X_FORWARDED_FOR_BEFORE_CF'] = env['HTTP_X_FORWARDED_FOR'] 15 | env['REMOTE_ADDR'] = env['HTTP_CF_CONNECTING_IP'] 16 | env['HTTP_X_FORWARDED_FOR'] = env['HTTP_CF_CONNECTING_IP'] 17 | end 18 | @app.call(env) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /services/backend/lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/lib/tasks/.keep -------------------------------------------------------------------------------- /services/backend/lib/tasks/clear_cache.rake: -------------------------------------------------------------------------------- 1 | namespace :cache do 2 | desc 'Clears Rails cache' 3 | task clear: :environment do 4 | Rails.cache.clear 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /services/backend/lib/tasks/custom_seed.rake: -------------------------------------------------------------------------------- 1 | namespace :db do 2 | namespace :seed do 3 | Dir[File.join(Rails.root, 'db', 'seeds', '*.rb')].each do |filename| 4 | task_name = File.basename(filename, '.rb').intern 5 | task task_name => :environment do 6 | load(filename) if File.exist?(filename) 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /services/backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@spree/dashboard": "^0.1.0", 4 | "esbuild": "^0.14.1" 5 | }, 6 | "scripts": { 7 | "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /services/backend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/public/favicon.ico -------------------------------------------------------------------------------- /services/backend/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | User-agent: * 7 | Disallow: /checkout 8 | Disallow: /cart 9 | Disallow: /orders 10 | Disallow: /user 11 | Disallow: /account 12 | Disallow: /api 13 | Disallow: /password 14 | -------------------------------------------------------------------------------- /services/backend/render.yaml: -------------------------------------------------------------------------------- 1 | databases: 2 | - name: spree 3 | databaseName: spree 4 | user: spree 5 | 6 | services: 7 | - type: web 8 | name: spree 9 | env: ruby 10 | buildCommand: "./bin/render-build.sh" 11 | startCommand: "bundle exec puma -C config/puma.rb" 12 | envVars: 13 | - key: DATABASE_URL 14 | fromDatabase: 15 | name: spree 16 | property: connectionString 17 | - key: SECRET_KEY_BASE 18 | generateValue: true 19 | - key: ADMIN_EMAIL 20 | value: 'spree@example.com' 21 | - key: ADMIN_PASSWORD 22 | value: 'spree123' 23 | -------------------------------------------------------------------------------- /services/backend/spec/support/vcr.rb: -------------------------------------------------------------------------------- 1 | require 'vcr' 2 | require 'webmock/rspec' 3 | require 'uri' 4 | require 'webdrivers' 5 | 6 | driver_hosts = Webdrivers::Common.subclasses.map { |driver| URI(driver.base_url).host } 7 | driver_hosts << 'codeclimate.com' 8 | driver_urls = Webdrivers::Common.subclasses.map(&:base_url) 9 | 10 | WebMock.disable_net_connect!(allow_localhost: true, allow: driver_urls) 11 | 12 | VCR.configure do |c| 13 | c.allow_http_connections_when_no_cassette = false 14 | c.cassette_library_dir = Rails.root.join('spec', 'vcr') 15 | c.hook_into :webmock 16 | c.ignore_localhost = true 17 | c.ignore_hosts(*driver_hosts) 18 | c.configure_rspec_metadata! 19 | c.default_cassette_options = { record: :new_episodes } 20 | end 21 | -------------------------------------------------------------------------------- /services/backend/storage/00/6g/006gnisak94ytqimt378gbad2hf9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/00/6g/006gnisak94ytqimt378gbad2hf9 -------------------------------------------------------------------------------- /services/backend/storage/0i/zg/0izgp4zdrg4bxwvji5e0598oa8mp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/0i/zg/0izgp4zdrg4bxwvji5e0598oa8mp -------------------------------------------------------------------------------- /services/backend/storage/0k/8u/0k8uufd4279o44gzgz5efagsqteu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/0k/8u/0k8uufd4279o44gzgz5efagsqteu -------------------------------------------------------------------------------- /services/backend/storage/0r/42/0r42dufnbi6rctn4vap71d1urqk9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/0r/42/0r42dufnbi6rctn4vap71d1urqk9 -------------------------------------------------------------------------------- /services/backend/storage/0r/r1/0rr1qtiq705h498m2e65y04aa1fb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/0r/r1/0rr1qtiq705h498m2e65y04aa1fb -------------------------------------------------------------------------------- /services/backend/storage/14/zj/14zj5sb9no7mevm8vtzjcym71vy1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/14/zj/14zj5sb9no7mevm8vtzjcym71vy1 -------------------------------------------------------------------------------- /services/backend/storage/16/9t/169tp3memt7id57sh22o8ejtcblg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/16/9t/169tp3memt7id57sh22o8ejtcblg -------------------------------------------------------------------------------- /services/backend/storage/1c/n3/1cn3v98qnmqwts7m6l5xkbhzvffn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/1c/n3/1cn3v98qnmqwts7m6l5xkbhzvffn -------------------------------------------------------------------------------- /services/backend/storage/1j/z1/1jz13ploviow14epdbc68db9fslw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/1j/z1/1jz13ploviow14epdbc68db9fslw -------------------------------------------------------------------------------- /services/backend/storage/1k/s2/1ks2veug3cveel5c0eeyaq0m647s: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/1k/s2/1ks2veug3cveel5c0eeyaq0m647s -------------------------------------------------------------------------------- /services/backend/storage/2f/y5/2fy5a3t0idckqt117wqp88l1haj8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/2f/y5/2fy5a3t0idckqt117wqp88l1haj8 -------------------------------------------------------------------------------- /services/backend/storage/2o/or/2ooru1xgcss6d2qeg4iwmjjgz2c9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/2o/or/2ooru1xgcss6d2qeg4iwmjjgz2c9 -------------------------------------------------------------------------------- /services/backend/storage/2q/zh/2qzh6w5ugc805s50nivs2k1xxfvi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/2q/zh/2qzh6w5ugc805s50nivs2k1xxfvi -------------------------------------------------------------------------------- /services/backend/storage/3l/sq/3lsqhzqyca5o90l7ek5lcic5ge8z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/3l/sq/3lsqhzqyca5o90l7ek5lcic5ge8z -------------------------------------------------------------------------------- /services/backend/storage/3o/i8/3oi8wwgyay2a5vsted2felpry3yw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/3o/i8/3oi8wwgyay2a5vsted2felpry3yw -------------------------------------------------------------------------------- /services/backend/storage/3p/nu/3pnujzkcnksw26a0cu1vtyp1uviz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/3p/nu/3pnujzkcnksw26a0cu1vtyp1uviz -------------------------------------------------------------------------------- /services/backend/storage/41/wp/41wprtxdhsy40nh2h3igvhpdh982: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/41/wp/41wprtxdhsy40nh2h3igvhpdh982 -------------------------------------------------------------------------------- /services/backend/storage/5b/ea/5beayoc679qsbk1udyydvujp3tuv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/5b/ea/5beayoc679qsbk1udyydvujp3tuv -------------------------------------------------------------------------------- /services/backend/storage/62/xk/62xky8otdpnd1lm3zr07z7udt2bx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/62/xk/62xky8otdpnd1lm3zr07z7udt2bx -------------------------------------------------------------------------------- /services/backend/storage/6f/85/6f852pkntrw16c0w9wzpdx2rnmud: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/6f/85/6f852pkntrw16c0w9wzpdx2rnmud -------------------------------------------------------------------------------- /services/backend/storage/6m/b7/6mb7uh60to9dg7fvpjljjmqdnyfw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/6m/b7/6mb7uh60to9dg7fvpjljjmqdnyfw -------------------------------------------------------------------------------- /services/backend/storage/75/n1/75n1re2ozjbz45a88irjss1pu9e6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/75/n1/75n1re2ozjbz45a88irjss1pu9e6 -------------------------------------------------------------------------------- /services/backend/storage/77/of/77of4hptz6t0rf0gn04v0kqjt4dm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/77/of/77of4hptz6t0rf0gn04v0kqjt4dm -------------------------------------------------------------------------------- /services/backend/storage/7u/pj/7upjjhp3sbp38un5ii23l5bm1tf8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/7u/pj/7upjjhp3sbp38un5ii23l5bm1tf8 -------------------------------------------------------------------------------- /services/backend/storage/7v/xz/7vxzmrg3zgfub67kf82hb5vifqzu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/7v/xz/7vxzmrg3zgfub67kf82hb5vifqzu -------------------------------------------------------------------------------- /services/backend/storage/86/fg/86fgtuga925kaa17km9eamshazgr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/86/fg/86fgtuga925kaa17km9eamshazgr -------------------------------------------------------------------------------- /services/backend/storage/88/44/8844gxgfc9ul1djle5kf8sqmgiyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/88/44/8844gxgfc9ul1djle5kf8sqmgiyc -------------------------------------------------------------------------------- /services/backend/storage/88/he/88hekent0qoefm8b69builrth0xv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/88/he/88hekent0qoefm8b69builrth0xv -------------------------------------------------------------------------------- /services/backend/storage/89/to/89to0ymiqabe72nctvgrgqzyrk0o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/89/to/89to0ymiqabe72nctvgrgqzyrk0o -------------------------------------------------------------------------------- /services/backend/storage/8c/kn/8cknyjfznqw5id8jzny40hewyyrm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/8c/kn/8cknyjfznqw5id8jzny40hewyyrm -------------------------------------------------------------------------------- /services/backend/storage/8d/rw/8drwmhakoag0ra8a1myjdr80mt57: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/8d/rw/8drwmhakoag0ra8a1myjdr80mt57 -------------------------------------------------------------------------------- /services/backend/storage/8i/vj/8ivjybuoo1jtnknvptho0ia2ysvl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/8i/vj/8ivjybuoo1jtnknvptho0ia2ysvl -------------------------------------------------------------------------------- /services/backend/storage/97/xe/97xen0j7t6ketkwt4l8vobq14qq9: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/97/xe/97xen0j7t6ketkwt4l8vobq14qq9 -------------------------------------------------------------------------------- /services/backend/storage/9l/c4/9lc4lfmxvou7mvwqsl8g2fm27wfm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/9l/c4/9lc4lfmxvou7mvwqsl8g2fm27wfm -------------------------------------------------------------------------------- /services/backend/storage/9l/ev/9levi783acolroehz6wn0cm0mzwa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/9l/ev/9levi783acolroehz6wn0cm0mzwa -------------------------------------------------------------------------------- /services/backend/storage/az/ws/azwswza6kecyh2bmfnlpr7besvvb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/az/ws/azwswza6kecyh2bmfnlpr7besvvb -------------------------------------------------------------------------------- /services/backend/storage/b0/72/b0726xe61gdgxgmjki58njnwsivr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/b0/72/b0726xe61gdgxgmjki58njnwsivr -------------------------------------------------------------------------------- /services/backend/storage/b0/95/b095fsshrfwmoexn8czq2m3aiqbe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/b0/95/b095fsshrfwmoexn8czq2m3aiqbe -------------------------------------------------------------------------------- /services/backend/storage/b5/31/b531yunrur87esye2s4cwavym6te: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/b5/31/b531yunrur87esye2s4cwavym6te -------------------------------------------------------------------------------- /services/backend/storage/bb/45/bb45cs77n8gzn4ps91exl1cxuyft: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/bb/45/bb45cs77n8gzn4ps91exl1cxuyft -------------------------------------------------------------------------------- /services/backend/storage/bb/xn/bbxn5vhfqpqdykae8z2cdf5x3dgs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/bb/xn/bbxn5vhfqpqdykae8z2cdf5x3dgs -------------------------------------------------------------------------------- /services/backend/storage/bf/kg/bfkgrq99dea00vq7i74ludx4q31l: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/bf/kg/bfkgrq99dea00vq7i74ludx4q31l -------------------------------------------------------------------------------- /services/backend/storage/bl/xp/blxpqifldxzmb0nby4czkfn4u9q6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/bl/xp/blxpqifldxzmb0nby4czkfn4u9q6 -------------------------------------------------------------------------------- /services/backend/storage/bp/08/bp08j2pskt6xgz9ah0714mqdjwz7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/bp/08/bp08j2pskt6xgz9ah0714mqdjwz7 -------------------------------------------------------------------------------- /services/backend/storage/bz/2a/bz2awto4gfx6t6udd7k5gjvke8i7: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/bz/2a/bz2awto4gfx6t6udd7k5gjvke8i7 -------------------------------------------------------------------------------- /services/backend/storage/c9/cj/c9cjtgt3p7hdujcaxt41t08u1kux: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/c9/cj/c9cjtgt3p7hdujcaxt41t08u1kux -------------------------------------------------------------------------------- /services/backend/storage/cb/kx/cbkxlh6px78ymmakilgwygcm0qn5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/cb/kx/cbkxlh6px78ymmakilgwygcm0qn5 -------------------------------------------------------------------------------- /services/backend/storage/cj/1d/cj1dxfmw44hktr8lhbwzpw7aoxz5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/cj/1d/cj1dxfmw44hktr8lhbwzpw7aoxz5 -------------------------------------------------------------------------------- /services/backend/storage/d7/k8/d7k8l52o2ji9tkor07sqd25wpxdk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/d7/k8/d7k8l52o2ji9tkor07sqd25wpxdk -------------------------------------------------------------------------------- /services/backend/storage/db/ag/dbagqumqgq1z6319o338j7bmt5pq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/db/ag/dbagqumqgq1z6319o338j7bmt5pq -------------------------------------------------------------------------------- /services/backend/storage/dq/c7/dqc7t23uxsm5axhesoap039wqjeb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/dq/c7/dqc7t23uxsm5axhesoap039wqjeb -------------------------------------------------------------------------------- /services/backend/storage/e3/lt/e3ltmq2g8mfvj4wifyzt7uj3w5ns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/e3/lt/e3ltmq2g8mfvj4wifyzt7uj3w5ns -------------------------------------------------------------------------------- /services/backend/storage/eb/2a/eb2a2zd73ok9x0rlw0o164mduamd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/eb/2a/eb2a2zd73ok9x0rlw0o164mduamd -------------------------------------------------------------------------------- /services/backend/storage/f1/6r/f16rwfhvanpxrwgn2ct48cgfp326: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/f1/6r/f16rwfhvanpxrwgn2ct48cgfp326 -------------------------------------------------------------------------------- /services/backend/storage/f1/f6/f1f6rz6nuf57ryix259yxq7j3tje: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/f1/f6/f1f6rz6nuf57ryix259yxq7j3tje -------------------------------------------------------------------------------- /services/backend/storage/f3/dt/f3dtrvou5azxky00y68u7qbjgaqn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/f3/dt/f3dtrvou5azxky00y68u7qbjgaqn -------------------------------------------------------------------------------- /services/backend/storage/f5/xr/f5xr4qy5dtulhpe8kgazjo2x7ubz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/f5/xr/f5xr4qy5dtulhpe8kgazjo2x7ubz -------------------------------------------------------------------------------- /services/backend/storage/f7/tg/f7tg9iqtd0i6tqxzkf15010kl9xq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/f7/tg/f7tg9iqtd0i6tqxzkf15010kl9xq -------------------------------------------------------------------------------- /services/backend/storage/fj/gx/fjgxeszqvcbrc0v0u2n7i70yd956: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/fj/gx/fjgxeszqvcbrc0v0u2n7i70yd956 -------------------------------------------------------------------------------- /services/backend/storage/fk/0o/fk0o9nsutjpswot205kna7pdoj02: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/fk/0o/fk0o9nsutjpswot205kna7pdoj02 -------------------------------------------------------------------------------- /services/backend/storage/fs/ip/fsipi7gdrjs2mxhgop0etbuwsfu2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/fs/ip/fsipi7gdrjs2mxhgop0etbuwsfu2 -------------------------------------------------------------------------------- /services/backend/storage/fy/au/fyau0gplpld5a6c12gvncp18ravq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/fy/au/fyau0gplpld5a6c12gvncp18ravq -------------------------------------------------------------------------------- /services/backend/storage/gq/x4/gqx496zj9ao0ce2y69s8ebcdt76c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/gq/x4/gqx496zj9ao0ce2y69s8ebcdt76c -------------------------------------------------------------------------------- /services/backend/storage/gs/1o/gs1oqg4v74c76h2f8zsqj0p91yjc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/gs/1o/gs1oqg4v74c76h2f8zsqj0p91yjc -------------------------------------------------------------------------------- /services/backend/storage/h3/um/h3ump7vjqudll390ky1rdss0xdb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/h3/um/h3ump7vjqudll390ky1rdss0xdb4 -------------------------------------------------------------------------------- /services/backend/storage/h8/3c/h83cdk6x8kd1amwvte8aavqnxii3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/h8/3c/h83cdk6x8kd1amwvte8aavqnxii3 -------------------------------------------------------------------------------- /services/backend/storage/hm/nd/hmndfefa02esgzpaqksemkf51q88: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/hm/nd/hmndfefa02esgzpaqksemkf51q88 -------------------------------------------------------------------------------- /services/backend/storage/hp/sk/hpskdx8sfybt0o39s4e2veuqv6nd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/hp/sk/hpskdx8sfybt0o39s4e2veuqv6nd -------------------------------------------------------------------------------- /services/backend/storage/hv/lm/hvlm8gb3nktx69eteqqt7atj9qrs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/hv/lm/hvlm8gb3nktx69eteqqt7atj9qrs -------------------------------------------------------------------------------- /services/backend/storage/ir/5t/ir5thn1x7rn9legliqvjh23qg1bl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/ir/5t/ir5thn1x7rn9legliqvjh23qg1bl -------------------------------------------------------------------------------- /services/backend/storage/j4/j2/j4j2wb67ekv1hle6t5z2aq19gstf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/j4/j2/j4j2wb67ekv1hle6t5z2aq19gstf -------------------------------------------------------------------------------- /services/backend/storage/jl/mg/jlmgno906bkhwsytjqiyns2hqut8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/jl/mg/jlmgno906bkhwsytjqiyns2hqut8 -------------------------------------------------------------------------------- /services/backend/storage/jo/ru/joru4prw3skdtc8i4ia5dwq5874k: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/jo/ru/joru4prw3skdtc8i4ia5dwq5874k -------------------------------------------------------------------------------- /services/backend/storage/jr/qt/jrqti00rfi88kdgvjnw4s0tdv7xc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/jr/qt/jrqti00rfi88kdgvjnw4s0tdv7xc -------------------------------------------------------------------------------- /services/backend/storage/k7/hr/k7hrw0msrvsspxi698amx5kmh2wg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/k7/hr/k7hrw0msrvsspxi698amx5kmh2wg -------------------------------------------------------------------------------- /services/backend/storage/kr/u2/kru2kfqkml3mwkuhmc2w0uvtp4x1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/kr/u2/kru2kfqkml3mwkuhmc2w0uvtp4x1 -------------------------------------------------------------------------------- /services/backend/storage/kw/ch/kwchc38i5j2uqyrfui13h914doju: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/kw/ch/kwchc38i5j2uqyrfui13h914doju -------------------------------------------------------------------------------- /services/backend/storage/l0/id/l0idqd59oxu5iz00z9m3iep48pjm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/l0/id/l0idqd59oxu5iz00z9m3iep48pjm -------------------------------------------------------------------------------- /services/backend/storage/l8/1g/l81gft3rnuphlp36xw4q33p4r1cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/l8/1g/l81gft3rnuphlp36xw4q33p4r1cs -------------------------------------------------------------------------------- /services/backend/storage/lp/lr/lplrh3v056du1izagk5o76sfu98p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/lp/lr/lplrh3v056du1izagk5o76sfu98p -------------------------------------------------------------------------------- /services/backend/storage/lt/mc/ltmc7z2yt5ozwpuqmoz2uw98xylf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/lt/mc/ltmc7z2yt5ozwpuqmoz2uw98xylf -------------------------------------------------------------------------------- /services/backend/storage/m6/sb/m6sbj199y5b8id0eg6dvktm1nbyu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/m6/sb/m6sbj199y5b8id0eg6dvktm1nbyu -------------------------------------------------------------------------------- /services/backend/storage/ms/m8/msm81dgmxk4ggqiud2bv4j9waoie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/ms/m8/msm81dgmxk4ggqiud2bv4j9waoie -------------------------------------------------------------------------------- /services/backend/storage/n1/m4/n1m4ol3mo2fbg77imv5qn156swi4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/n1/m4/n1m4ol3mo2fbg77imv5qn156swi4 -------------------------------------------------------------------------------- /services/backend/storage/n8/aa/n8aao8d8v8ene7vn4d14zdqxntna: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/n8/aa/n8aao8d8v8ene7vn4d14zdqxntna -------------------------------------------------------------------------------- /services/backend/storage/nd/mb/ndmbmj2or9w5lgnwmyyexp34n509: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/nd/mb/ndmbmj2or9w5lgnwmyyexp34n509 -------------------------------------------------------------------------------- /services/backend/storage/ni/yw/niywd6phcjdfuxw97lxi1y8t1sya: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/ni/yw/niywd6phcjdfuxw97lxi1y8t1sya -------------------------------------------------------------------------------- /services/backend/storage/nx/9d/nx9dapm2zhd2kh991ompea29775m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/nx/9d/nx9dapm2zhd2kh991ompea29775m -------------------------------------------------------------------------------- /services/backend/storage/o5/d9/o5d9h8s1hih1gihezeeu73fgwa88: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/o5/d9/o5d9h8s1hih1gihezeeu73fgwa88 -------------------------------------------------------------------------------- /services/backend/storage/o7/2a/o72a5s5ye01ie6mtx8h7olnldvko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/o7/2a/o72a5s5ye01ie6mtx8h7olnldvko -------------------------------------------------------------------------------- /services/backend/storage/oi/fp/oifpdmfenjck5p39s91m8ij5ya5a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/oi/fp/oifpdmfenjck5p39s91m8ij5ya5a -------------------------------------------------------------------------------- /services/backend/storage/op/a2/opa2g8bl3tpm0ecip3f4yun9hcd8: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/op/a2/opa2g8bl3tpm0ecip3f4yun9hcd8 -------------------------------------------------------------------------------- /services/backend/storage/os/vh/osvherjecbdx3ezy3jvar6vvfwrk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/os/vh/osvherjecbdx3ezy3jvar6vvfwrk -------------------------------------------------------------------------------- /services/backend/storage/ox/4i/ox4iruasiwuftdu71u98l5t4rpgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/ox/4i/ox4iruasiwuftdu71u98l5t4rpgm -------------------------------------------------------------------------------- /services/backend/storage/p7/d5/p7d5guboq24b265ytl0u5w20hzjl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/p7/d5/p7d5guboq24b265ytl0u5w20hzjl -------------------------------------------------------------------------------- /services/backend/storage/p8/0j/p80jyh6ws8gqmfrp8kcjcgctdieh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/p8/0j/p80jyh6ws8gqmfrp8kcjcgctdieh -------------------------------------------------------------------------------- /services/backend/storage/pi/co/picolufbbcsybadgh89nutlhun53: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/pi/co/picolufbbcsybadgh89nutlhun53 -------------------------------------------------------------------------------- /services/backend/storage/pk/18/pk18k7l7xvz7fcz9ecz20m01mbg1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/pk/18/pk18k7l7xvz7fcz9ecz20m01mbg1 -------------------------------------------------------------------------------- /services/backend/storage/q5/90/q590wag6b1vszjszc3mfd23192sj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/q5/90/q590wag6b1vszjszc3mfd23192sj -------------------------------------------------------------------------------- /services/backend/storage/q8/69/q869nghoropy7vm31r30cgs85x0d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/q8/69/q869nghoropy7vm31r30cgs85x0d -------------------------------------------------------------------------------- /services/backend/storage/r0/l3/r0l3vmf800tdhnaha8ipdutspb1e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/r0/l3/r0l3vmf800tdhnaha8ipdutspb1e -------------------------------------------------------------------------------- /services/backend/storage/rc/p1/rcp1c0ffcrahrxl6ddwdj502lrzh: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/rc/p1/rcp1c0ffcrahrxl6ddwdj502lrzh -------------------------------------------------------------------------------- /services/backend/storage/rp/62/rp62efuo0c81qrdzczbw9vbu1eih: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/rp/62/rp62efuo0c81qrdzczbw9vbu1eih -------------------------------------------------------------------------------- /services/backend/storage/rw/st/rwst4dkl9wdsmq13w2fwj04ha284: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/rw/st/rwst4dkl9wdsmq13w2fwj04ha284 -------------------------------------------------------------------------------- /services/backend/storage/rx/4i/rx4ig9xw7h5y1y2sqqmawsq1x17p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/rx/4i/rx4ig9xw7h5y1y2sqqmawsq1x17p -------------------------------------------------------------------------------- /services/backend/storage/ss/kb/sskbwu2e4lqf6vdd9po2ozhnfm6d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/ss/kb/sskbwu2e4lqf6vdd9po2ozhnfm6d -------------------------------------------------------------------------------- /services/backend/storage/t2/gb/t2gbiuwefu2cu69nx6ef7mxvlkyf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/t2/gb/t2gbiuwefu2cu69nx6ef7mxvlkyf -------------------------------------------------------------------------------- /services/backend/storage/t8/sf/t8sfq5w9vte2byg1ql3vrf6erjz6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/t8/sf/t8sfq5w9vte2byg1ql3vrf6erjz6 -------------------------------------------------------------------------------- /services/backend/storage/ta/su/tasu842mlz829y8ps7va67ttq7my: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/ta/su/tasu842mlz829y8ps7va67ttq7my -------------------------------------------------------------------------------- /services/backend/storage/tc/uy/tcuywtfa5bo7iswkbmocinkv4obn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/tc/uy/tcuywtfa5bo7iswkbmocinkv4obn -------------------------------------------------------------------------------- /services/backend/storage/tq/3q/tq3q5lsbdzh1hfwfto2ub0dwuuul: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/tq/3q/tq3q5lsbdzh1hfwfto2ub0dwuuul -------------------------------------------------------------------------------- /services/backend/storage/u5/m8/u5m8nx87ih2y01eoc5y0og5exoga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/u5/m8/u5m8nx87ih2y01eoc5y0og5exoga -------------------------------------------------------------------------------- /services/backend/storage/un/6x/un6xvbm6l3ecxwxwuxffc6b6pksy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/un/6x/un6xvbm6l3ecxwxwuxffc6b6pksy -------------------------------------------------------------------------------- /services/backend/storage/v2/d6/v2d6kiibpmi2n5wei0zvfmgcrcp6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/v2/d6/v2d6kiibpmi2n5wei0zvfmgcrcp6 -------------------------------------------------------------------------------- /services/backend/storage/vd/hf/vdhfjqfz88rsidepmoygmvmzuory: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/vd/hf/vdhfjqfz88rsidepmoygmvmzuory -------------------------------------------------------------------------------- /services/backend/storage/vk/66/vk66376ys3oh94khxr2gyaqe718p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/vk/66/vk66376ys3oh94khxr2gyaqe718p -------------------------------------------------------------------------------- /services/backend/storage/vk/qt/vkqtro308bcx9nauolzjgfsdjiaj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/vk/qt/vkqtro308bcx9nauolzjgfsdjiaj -------------------------------------------------------------------------------- /services/backend/storage/vn/91/vn912gigj022zdj21b018id2vb0h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/vn/91/vn912gigj022zdj21b018id2vb0h -------------------------------------------------------------------------------- /services/backend/storage/w7/h1/w7h15x1uh9994su68lm16er6p8fj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/w7/h1/w7h15x1uh9994su68lm16er6p8fj -------------------------------------------------------------------------------- /services/backend/storage/wp/ik/wpik6q4kgdlnd8zy9vxfayze9bxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/wp/ik/wpik6q4kgdlnd8zy9vxfayze9bxl -------------------------------------------------------------------------------- /services/backend/storage/wt/zf/wtzfa794b5vpax1qrbegb7xnioi2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/wt/zf/wtzfa794b5vpax1qrbegb7xnioi2 -------------------------------------------------------------------------------- /services/backend/storage/x0/j5/x0j50n6qwk4g0p72hy9h9gmz9l41: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/x0/j5/x0j50n6qwk4g0p72hy9h9gmz9l41 -------------------------------------------------------------------------------- /services/backend/storage/xp/7a/xp7a6l2hhtrp4ow3oo2e8ozqzuz1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/xp/7a/xp7a6l2hhtrp4ow3oo2e8ozqzuz1 -------------------------------------------------------------------------------- /services/backend/storage/yu/65/yu65ul5ekff3gdub9ot599wbqq5t: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/yu/65/yu65ul5ekff3gdub9ot599wbqq5t -------------------------------------------------------------------------------- /services/backend/storage/z8/lp/z8lp9oe5quoqzkewjtvj14rubeg0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/z8/lp/z8lp9oe5quoqzkewjtvj14rubeg0 -------------------------------------------------------------------------------- /services/backend/storage/zi/ae/ziae3tzvaen6pm7pdzsya7rv46l3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/storage/zi/ae/ziae3tzvaen6pm7pdzsya7rv46l3 -------------------------------------------------------------------------------- /services/backend/vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /services/backend/vendor/assets/javascripts/spree/backend/all.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into including all the files listed below. 2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically 3 | // be included in the compiled file accessible from http://example.com/assets/application.js 4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 5 | // the compiled file. 6 | // 7 | //= require spree/backend 8 | //= require_tree . 9 | -------------------------------------------------------------------------------- /services/backend/vendor/assets/javascripts/spree/frontend/all.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into including all the files listed below. 2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically 3 | // be included in the compiled file accessible from http://example.com/assets/application.js 4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 5 | // the compiled file. 6 | // 7 | //= require spree/frontend 8 | 9 | //= require_tree . 10 | -------------------------------------------------------------------------------- /services/backend/vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/backend/vendor/assets/stylesheets/.keep -------------------------------------------------------------------------------- /services/backend/vendor/assets/stylesheets/spree/backend/all.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll automatically include all the stylesheets available in this directory 3 | * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at 4 | * the top of the compiled file, but it's generally better to create a new file per style scope. 5 | * 6 | *= require spree/backend 7 | *= require_self 8 | *= require_tree . 9 | */ 10 | -------------------------------------------------------------------------------- /services/backend/vendor/assets/stylesheets/spree/frontend/all.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll automatically include all the stylesheets available in this directory 3 | * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at 4 | * the top of the compiled file, but it's generally better to create a new file per style scope. 5 | * 6 | *= require spree/frontend 7 | 8 | *= require_self 9 | *= require_tree . 10 | */ 11 | -------------------------------------------------------------------------------- /services/dbm/.dockerignore: -------------------------------------------------------------------------------- 1 | # Version control 2 | .git 3 | 4 | # Compiled Python bytecode 5 | **/__pycache__ 6 | **/*.pyc 7 | **/*.pyo 8 | 9 | # Compiled extensions 10 | **/*.pyd 11 | **/*.so 12 | 13 | # coverage.py 14 | .coverage 15 | .coverage.* 16 | htmlcov 17 | 18 | # Cached files 19 | .cache 20 | .mypy_cache 21 | .hypothesis 22 | .pytest_cache 23 | 24 | # Virtualenvs and builds 25 | build/ 26 | dist/ 27 | .env 28 | .venv 29 | env/ 30 | venv/ 31 | ENV/ 32 | env.bak/ 33 | venv.bak/ 34 | 35 | # Docker 36 | Dockerfile* 37 | .dockerignore 38 | -------------------------------------------------------------------------------- /services/dbm/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.2 2 | # ^ This enables the new BuildKit stable syntax which can be 3 | # run with the DOCKER_BUILDKIT=1 environment variable in your 4 | # docker build command (see build.sh) 5 | FROM python:3.9.6-slim-buster 6 | 7 | # Update, upgrade, and cleanup debian packages 8 | RUN export DEBIAN_FRONTEND=noninteractive && \ 9 | apt-get update && \ 10 | apt-get upgrade --yes && \ 11 | apt-get install --yes build-essential libpq-dev && \ 12 | apt-get clean && \ 13 | rm -rf /var/lib/apt/lists/* 14 | 15 | # Copy over app 16 | WORKDIR /app 17 | COPY . . 18 | 19 | # Install dependencies via pip and avoid caching build artifacts 20 | RUN pip install --no-cache-dir -r requirements.txt 21 | 22 | # Set default Flask app and development environment 23 | ENV FLASK_APP=dbm.py 24 | 25 | # Start the app using ddtrace so we have profiling and tracing 26 | ENTRYPOINT ["ddtrace-run"] 27 | CMD gunicorn --bind 0.0.0.0:7578 dbm:app 28 | -------------------------------------------------------------------------------- /services/dbm/dbm_exec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | psql -U postgres -d postgres -a -f /etc/postgresql/13/main/dbm_setup.sql -------------------------------------------------------------------------------- /services/dbm/dbm_setup.sql: -------------------------------------------------------------------------------- 1 | create user datadog with password 'datadog'; 2 | GRANT SELECT ON pg_stat_database TO datadog; 3 | CREATE SCHEMA datadog; 4 | GRANT USAGE ON SCHEMA datadog TO datadog; 5 | GRANT USAGE ON SCHEMA public TO datadog; 6 | GRANT pg_monitor TO datadog; 7 | CREATE EXTENSION IF NOT EXISTS pg_stat_statements; 8 | 9 | CREATE OR REPLACE FUNCTION datadog.explain_statement( 10 | l_query TEXT, 11 | OUT explain JSON 12 | ) 13 | RETURNS SETOF JSON AS 14 | $$ 15 | DECLARE 16 | curs REFCURSOR; 17 | plan JSON; 18 | 19 | BEGIN 20 | OPEN curs FOR EXECUTE pg_catalog.concat('EXPLAIN (FORMAT JSON) ', l_query); 21 | FETCH curs INTO plan; 22 | CLOSE curs; 23 | RETURN QUERY SELECT plan; 24 | END; 25 | $$ 26 | LANGUAGE 'plpgsql' 27 | RETURNS NULL ON NULL INPUT 28 | SECURITY DEFINER; -------------------------------------------------------------------------------- /services/dbm/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2020.11.8 2 | chardet==3.0.4 3 | click==8.0 4 | ddtrace==2.16.0 5 | Flask==2.2.2 6 | Flask-Login==0.6.2 7 | Flask-WTF==1.0.1 8 | Flask-Cors==3.0.10 9 | Flask-SQLAlchemy==3.0.2 10 | idna==2.10 11 | intervaltree==3.1.0 12 | itsdangerous==2.0 13 | Jinja2==3.0 14 | MarkupSafe==2.1.1 15 | nose==1.3.7 16 | protobuf==3.14.0 17 | requests==2.25.1 18 | six==1.15.0 19 | sortedcontainers==2.3.0 20 | SQLAlchemy==1.4.42 21 | psycopg2-binary 22 | tenacity==6.2.0 23 | urllib3==1.26.5 24 | gunicorn==20.1.0 25 | Faker==18.3.2 26 | Werkzeug==2.2.2 27 | -------------------------------------------------------------------------------- /services/discounts/.dockerignore: -------------------------------------------------------------------------------- 1 | # Version control 2 | .git 3 | 4 | # Compiled Python bytecode 5 | **/__pycache__ 6 | **/*.pyc 7 | **/*.pyo 8 | 9 | # Compiled extensions 10 | **/*.pyd 11 | **/*.so 12 | 13 | # coverage.py 14 | .coverage 15 | .coverage.* 16 | htmlcov 17 | 18 | # Cached files 19 | .cache 20 | .mypy_cache 21 | .hypothesis 22 | .pytest_cache 23 | 24 | # Virtualenvs and builds 25 | build/ 26 | dist/ 27 | .env 28 | .venv 29 | env/ 30 | venv/ 31 | ENV/ 32 | env.bak/ 33 | venv.bak/ 34 | 35 | # Docker 36 | Dockerfile* 37 | .dockerignore 38 | -------------------------------------------------------------------------------- /services/discounts/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2020.12.5 2 | chardet==4.0.0 3 | click==7.1.2 4 | ddtrace==2.16.0 5 | Flask==1.1.2 6 | Flask-Cors==3.0.10 7 | Flask-SQLAlchemy==2.4.4 8 | idna==2.10 9 | intervaltree==3.1.0 10 | itsdangerous==1.1.0 11 | Jinja2==2.11.3 12 | MarkupSafe==1.1.1 13 | msgpack-python==0.5.6 14 | names==0.3.0 15 | nose==1.3.7 16 | protobuf==3.14.0 17 | psutil==5.8.0 18 | psycopg2==2.8.6 19 | PyDispatcher==2.0.5 20 | PyYAML==5.4.1 21 | requests==2.25.1 22 | six==1.15.0 23 | sortedcontainers==2.3.0 24 | SQLAlchemy==1.3.23 25 | tenacity==6.3.1 26 | urllib3==1.26.5 27 | Werkzeug==1.0.1 28 | wrapt==1.12.1 29 | JSON-log-formatter==0.5.2 -------------------------------------------------------------------------------- /services/frontend/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["next", "prettier"], 3 | "rules": { 4 | "react/no-unescaped-entities": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /services/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | .next/ 13 | out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | .idea 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | 34 | # vercel 35 | .vercel 36 | -------------------------------------------------------------------------------- /services/frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | public -------------------------------------------------------------------------------- /services/frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "useTabs": false 6 | } 7 | -------------------------------------------------------------------------------- /services/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20 AS builder 2 | 3 | # install wait-for-it 4 | RUN apt-get update && apt-get install -y wait-for-it 5 | 6 | WORKDIR /app 7 | COPY package*.json ./ 8 | RUN npm install 9 | COPY . . 10 | EXPOSE 3000 11 | -------------------------------------------------------------------------------- /services/frontend/README.md: -------------------------------------------------------------------------------- 1 | # Frontend service 2 | 3 | ## Description 4 | 5 | The frontend services is a JavaScript application that uses the Next.js React framework. It includes it's own set of API routes, which are used to fetch data from the backend services. 6 | 7 | -------------------------------------------------------------------------------- /services/frontend/assets/chrome-bug.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Chrome has a bug with transitions on load since 2012! 3 | * 4 | * To prevent a "pop" of content, you have to disable all transitions until 5 | * the page is done loading. 6 | * 7 | * https://lab.laukstein.com/bug/input 8 | * https://twitter.com/timer150/status/1345217126680899584 9 | */ 10 | body.loading * { 11 | transition: none !important; 12 | } 13 | -------------------------------------------------------------------------------- /services/frontend/assets/components.css: -------------------------------------------------------------------------------- 1 | .fit { 2 | min-height: calc(100vh - 88px); 3 | } 4 | -------------------------------------------------------------------------------- /services/frontend/assets/main.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @import './base.css'; 3 | 4 | @tailwind components; 5 | @import './components.css'; 6 | 7 | @tailwind utilities; 8 | -------------------------------------------------------------------------------- /services/frontend/components/cart/CartItem/CartItem.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply flex flex-col py-4; 3 | } 4 | 5 | .root:first-child { 6 | padding-top: 0; 7 | } 8 | 9 | .quantity { 10 | appearance: textfield; 11 | @apply w-8 border-accent-2 border mx-3 rounded text-center text-sm text-black; 12 | } 13 | 14 | .quantity::-webkit-outer-spin-button, 15 | .quantity::-webkit-inner-spin-button { 16 | @apply appearance-none m-0; 17 | } 18 | 19 | .productImage { 20 | /* position: absolute; 21 | width: 100%; 22 | height: 100%; 23 | left: 30% !important; 24 | top: 30% !important; */ 25 | transform: scale(1.3); 26 | z-index: 1; 27 | } 28 | 29 | .productName { 30 | @apply font-medium cursor-pointer pb-1; 31 | margin-top: -4px; 32 | } 33 | -------------------------------------------------------------------------------- /services/frontend/components/cart/CartItem/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CartItem' 2 | -------------------------------------------------------------------------------- /services/frontend/components/cart/CartSidebarView/CartSidebarView.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | min-height: 100vh; 3 | } 4 | 5 | .root.empty { 6 | @apply bg-secondary text-secondary; 7 | } 8 | 9 | .lineItemsList { 10 | @apply py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-2 border-accent-2; 11 | } 12 | -------------------------------------------------------------------------------- /services/frontend/components/cart/CartSidebarView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CartSidebarView' 2 | -------------------------------------------------------------------------------- /services/frontend/components/cart/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CartSidebarView } from './CartSidebarView' 2 | export { default as CartItem } from './CartItem' 3 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/CheckoutSidebarView/CheckoutSidebarView.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | min-height: calc(100vh - 322px); 3 | } 4 | 5 | .lineItemsList { 6 | @apply py-4 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-accent-2 border-accent-2; 7 | } 8 | 9 | .fieldset { 10 | @apply flex flex-col my-3; 11 | } 12 | 13 | .fieldset .label { 14 | @apply text-accent-7 uppercase text-xs font-medium mb-2; 15 | } 16 | 17 | .fieldset .input, 18 | .fieldset .select { 19 | @apply p-2 border border-accent-8 w-full text-sm font-normal bg-primary; 20 | } 21 | 22 | .fieldset .input:focus, 23 | .fieldset .select:focus { 24 | @apply outline-none shadow-outline-normal; 25 | } 26 | 27 | .radio { 28 | @apply bg-black; 29 | } 30 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/CheckoutSidebarView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CheckoutSidebarView' 2 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/OrderConfirmView/OrderConfirmView.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply border border-accent-2 px-6 py-5 mb-4 text-center 3 | flex items-center cursor-pointer hover:border-accent-4; 4 | } 5 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/OrderConfirmView/OrderConfirmView.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | import { Text } from '@components/ui'; 3 | import { useUI } from '@components/ui/context'; 4 | import SidebarLayout from '@components/common/SidebarLayout'; 5 | 6 | const OrderConfirmView: FC = () => { 7 | const { setSidebarView } = useUI(); 8 | 9 | return ( 10 |
11 | setSidebarView('CHECKOUT_VIEW')}> 12 |
13 | Thank you for your purchase! 14 |
15 |
16 |
17 | ); 18 | }; 19 | 20 | export default OrderConfirmView; 21 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/OrderConfirmView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './OrderConfirmView' -------------------------------------------------------------------------------- /services/frontend/components/checkout/PaymentMethodView/PaymentMethodView.module.css: -------------------------------------------------------------------------------- 1 | .fieldset { 2 | @apply flex flex-col my-3; 3 | } 4 | 5 | .fieldset .label { 6 | @apply text-accent-7 uppercase text-xs font-medium mb-2; 7 | } 8 | 9 | .fieldset .input, 10 | .fieldset .select { 11 | @apply p-2 border border-accent-8 w-full text-sm font-normal bg-primary; 12 | } 13 | 14 | .fieldset .input:focus, 15 | .fieldset .select:focus { 16 | @apply outline-none shadow-outline-normal; 17 | } 18 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/PaymentMethodView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './PaymentMethodView' 2 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/PaymentWidget/PaymentWidget.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply border border-accent-2 px-6 py-5 mb-4 text-center 3 | flex items-center cursor-pointer hover:border-accent-4; 4 | } 5 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/PaymentWidget/PaymentWidget.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import s from './PaymentWidget.module.css' 3 | import { ChevronRight, CreditCard, Check } from '@components/icons' 4 | 5 | interface ComponentProps { 6 | onClick?: () => any 7 | isValid?: boolean 8 | } 9 | 10 | const PaymentWidget: FC = ({ onClick, isValid }) => { 11 | return ( 12 |
13 |
14 | 15 | 16 | Add Payment Method 17 | 18 | {/* VISA #### #### #### 2345 */} 19 |
20 |
{isValid ? : }
21 | {/*
22 | 23 |
*/} 24 |
25 | ) 26 | } 27 | 28 | export default PaymentWidget 29 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/PaymentWidget/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './PaymentWidget' 2 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/ShippingView/ShippingView.module.css: -------------------------------------------------------------------------------- 1 | .fieldset { 2 | @apply flex flex-col my-3; 3 | } 4 | 5 | .fieldset .label { 6 | @apply text-accent-7 uppercase text-xs font-medium mb-2; 7 | } 8 | 9 | .fieldset .input, 10 | .fieldset .select { 11 | @apply p-2 border border-accent-8 w-full text-sm font-normal bg-primary; 12 | } 13 | 14 | .fieldset .input:focus, 15 | .fieldset .select:focus { 16 | @apply outline-none shadow-outline-normal; 17 | } 18 | 19 | .radio { 20 | @apply bg-black; 21 | } 22 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/ShippingView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ShippingView' 2 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/ShippingWidget/ShippingWidget.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply border border-accent-2 px-6 py-5 mb-4 text-center 3 | flex items-center cursor-pointer hover:border-accent-4; 4 | } 5 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/ShippingWidget/ShippingWidget.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import s from './ShippingWidget.module.css' 3 | import { ChevronRight, MapPin, Check } from '@components/icons' 4 | 5 | interface ComponentProps { 6 | onClick?: () => any 7 | isValid?: boolean 8 | } 9 | 10 | const ShippingWidget: FC = ({ onClick, isValid }) => { 11 | return ( 12 |
13 |
14 | 15 | 16 | Add Shipping Address 17 | 18 |
19 |
{isValid ? : }
20 | {/*
21 | 22 |
*/} 23 |
24 | ) 25 | } 26 | 27 | export default ShippingWidget 28 | -------------------------------------------------------------------------------- /services/frontend/components/checkout/ShippingWidget/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ShippingWidget' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Ad/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Ad' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Avatar/Avatar.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useRef, useEffect } from 'react' 2 | import { useUserAvatar } from '@lib/hooks/useUserAvatar' 3 | 4 | interface Props { 5 | className?: string 6 | children?: any 7 | } 8 | 9 | const Avatar: FC = ({}) => { 10 | let ref = useRef() as React.MutableRefObject 11 | let { userAvatar } = useUserAvatar() 12 | 13 | return ( 14 |
19 | {/* Add an image - We're generating a gradient as placeholder */} 20 |
21 | ) 22 | } 23 | 24 | export default Avatar 25 | -------------------------------------------------------------------------------- /services/frontend/components/common/Avatar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Avatar' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Discount/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Discount' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/FeatureBar/FeatureBar.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply text-center p-6 bg-primary text-sm flex-row 3 | justify-center items-center font-medium fixed bottom-0 4 | w-full z-30 transition-all duration-300 ease-out 5 | md:flex md:text-left; 6 | } 7 | -------------------------------------------------------------------------------- /services/frontend/components/common/FeatureBar/FeatureBar.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import s from './FeatureBar.module.css' 3 | 4 | interface FeatureBarProps { 5 | className?: string 6 | title: string 7 | description?: string 8 | hide?: boolean 9 | action?: React.ReactNode 10 | } 11 | 12 | const FeatureBar: React.FC = ({ 13 | title, 14 | description, 15 | className, 16 | action, 17 | hide, 18 | }) => { 19 | const rootClassName = cn( 20 | s.root, 21 | { 22 | transform: true, 23 | 'translate-y-0 opacity-100': !hide, 24 | 'translate-y-full opacity-0': hide, 25 | }, 26 | className 27 | ) 28 | return ( 29 |
30 | {title} 31 | 32 | {description} 33 | 34 | {action && action} 35 |
36 | ) 37 | } 38 | 39 | export default FeatureBar 40 | -------------------------------------------------------------------------------- /services/frontend/components/common/FeatureBar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './FeatureBar' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Footer/Footer.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply border-t border-accent-2; 3 | } 4 | 5 | .link { 6 | & > svg { 7 | @apply transform duration-75 ease-linear; 8 | } 9 | 10 | &:hover > svg { 11 | @apply scale-110; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /services/frontend/components/common/Footer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Footer' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Head/Head.tsx: -------------------------------------------------------------------------------- 1 | import type { VFC } from 'react' 2 | import { SEO } from '@components/common' 3 | 4 | const Head: VFC = () => { 5 | return ( 6 | 7 | 12 | 13 | 14 | ) 15 | } 16 | 17 | export default Head 18 | -------------------------------------------------------------------------------- /services/frontend/components/common/Head/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Head' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/HomeAllProductsGrid/HomeAllProductsGrid.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply py-12 flex flex-col w-full px-6; 3 | 4 | @screen md { 5 | @apply flex-row; 6 | } 7 | 8 | & .asideWrapper { 9 | @apply pr-3 w-full relative; 10 | 11 | @screen md { 12 | @apply w-48; 13 | } 14 | } 15 | 16 | & .aside { 17 | @apply flex flex-row w-full justify-around mb-12; 18 | 19 | @screen md { 20 | @apply mb-0 block sticky top-32; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /services/frontend/components/common/HomeAllProductsGrid/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './HomeAllProductsGrid' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Layout/Layout.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply h-full bg-primary mx-auto transition-colors duration-150; 3 | max-width: 2460px; 4 | } 5 | -------------------------------------------------------------------------------- /services/frontend/components/common/Layout/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Layout' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Navbar/Navbar.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply sticky top-0 bg-primary z-40 transition-all duration-150; 3 | min-height: 74px; 4 | } 5 | 6 | .nav { 7 | @apply relative flex flex-row justify-between py-4 md:py-4; 8 | } 9 | 10 | .navMenu { 11 | @apply hidden ml-6 space-x-4 lg:block; 12 | } 13 | 14 | .link { 15 | @apply inline-flex items-center leading-6 16 | transition ease-in-out duration-75 cursor-pointer 17 | text-accent-5 text-lg; 18 | } 19 | 20 | .link:hover { 21 | @apply text-accent-9; 22 | } 23 | 24 | .link:focus { 25 | @apply outline-none text-accent-8; 26 | } 27 | 28 | .logo { 29 | @apply cursor-pointer border transform duration-100 ease-in-out px-3 py-2 bg-primary-2 text-white text-2xl; 30 | 31 | &:hover { 32 | @apply shadow-md; 33 | transform: scale(1.05); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /services/frontend/components/common/Navbar/NavbarRoot.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useState, useEffect } from 'react' 2 | import throttle from 'lodash.throttle' 3 | import cn from 'clsx' 4 | import s from './Navbar.module.css' 5 | 6 | const NavbarRoot: FC = ({ children }) => { 7 | const [hasScrolled, setHasScrolled] = useState(false) 8 | 9 | useEffect(() => { 10 | const handleScroll = throttle(() => { 11 | const offset = 0 12 | const { scrollTop } = document.documentElement 13 | const scrolled = scrollTop > offset 14 | 15 | if (hasScrolled !== scrolled) { 16 | setHasScrolled(scrolled) 17 | } 18 | }, 200) 19 | 20 | document.addEventListener('scroll', handleScroll) 21 | return () => { 22 | document.removeEventListener('scroll', handleScroll) 23 | } 24 | }, [hasScrolled]) 25 | 26 | return ( 27 |
28 | {children} 29 |
30 | ) 31 | } 32 | 33 | export default NavbarRoot 34 | -------------------------------------------------------------------------------- /services/frontend/components/common/Navbar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Navbar' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/SEO/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SEO' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/Searchbar/Searchbar.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply relative text-sm bg-accent-0 text-base w-full transition-colors duration-150 border border-accent-2; 3 | } 4 | 5 | .input { 6 | @apply bg-transparent px-3 py-2 appearance-none w-full transition duration-150 ease-in-out pr-10; 7 | } 8 | 9 | .input::placeholder { 10 | @apply text-accent-3; 11 | } 12 | 13 | .input:focus { 14 | @apply outline-none shadow-outline-normal; 15 | } 16 | 17 | .iconContainer { 18 | @apply absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none; 19 | } 20 | 21 | .icon { 22 | @apply h-5 w-5; 23 | } 24 | 25 | @screen sm { 26 | .input { 27 | min-width: 300px; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /services/frontend/components/common/Searchbar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Searchbar' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/SidebarLayout/SidebarLayout.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply relative h-full flex flex-col; 3 | } 4 | 5 | .header { 6 | @apply sticky top-0 pl-4 py-4 pr-6 7 | flex items-center justify-between 8 | bg-accent-0 box-border w-full z-10; 9 | min-height: 66px; 10 | } 11 | 12 | .container { 13 | @apply flex flex-col flex-1 box-border; 14 | } 15 | 16 | @screen lg { 17 | .header { 18 | min-height: 74px; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /services/frontend/components/common/SidebarLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SidebarLayout' 2 | -------------------------------------------------------------------------------- /services/frontend/components/common/UserNav/MenuSidebarView/MenuSidebarView.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply px-4 sm:px-6 sm:w-full flex-1 z-20; 3 | } 4 | 5 | .item { 6 | @apply text-xl font-bold py-2; 7 | } 8 | -------------------------------------------------------------------------------- /services/frontend/components/common/UserNav/MenuSidebarView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MenuSidebarView' 2 | export interface Link { 3 | href: string 4 | label: string 5 | } 6 | -------------------------------------------------------------------------------- /services/frontend/components/common/UserNav/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './UserNav' 2 | export { default as MenuSidebarView } from './MenuSidebarView' 3 | -------------------------------------------------------------------------------- /services/frontend/components/common/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Avatar } from './Avatar' 2 | export { default as FeatureBar } from './FeatureBar' 3 | export { default as Footer } from './Footer' 4 | export { default as Layout } from './Layout' 5 | export { default as Navbar } from './Navbar' 6 | export { default as Searchbar } from './Searchbar' 7 | export { default as UserNav } from './UserNav' 8 | export { default as Head } from './Head' 9 | export { default as SEO } from './SEO' 10 | -------------------------------------------------------------------------------- /services/frontend/components/icons/ArrowLeft.tsx: -------------------------------------------------------------------------------- 1 | const ArrowLeft = ({ ...props }) => { 2 | return ( 3 | 11 | 17 | 23 | 24 | ) 25 | } 26 | 27 | export default ArrowLeft 28 | -------------------------------------------------------------------------------- /services/frontend/components/icons/ArrowRight.tsx: -------------------------------------------------------------------------------- 1 | const ArrowRight = ({ ...props }) => { 2 | return ( 3 | 12 | 18 | 24 | 25 | ) 26 | } 27 | 28 | export default ArrowRight 29 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Bag.tsx: -------------------------------------------------------------------------------- 1 | const Bag = ({ ...props }) => { 2 | return ( 3 | 11 | 17 | 23 | 29 | 30 | ) 31 | } 32 | 33 | export default Bag 34 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Check.tsx: -------------------------------------------------------------------------------- 1 | const Check = ({ ...props }) => { 2 | return ( 3 | 11 | 17 | 18 | ) 19 | } 20 | 21 | export default Check 22 | -------------------------------------------------------------------------------- /services/frontend/components/icons/ChevronDown.tsx: -------------------------------------------------------------------------------- 1 | const ChevronDown = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default ChevronDown 21 | -------------------------------------------------------------------------------- /services/frontend/components/icons/ChevronLeft.tsx: -------------------------------------------------------------------------------- 1 | const ChevronLeft = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default ChevronLeft 21 | -------------------------------------------------------------------------------- /services/frontend/components/icons/ChevronRight.tsx: -------------------------------------------------------------------------------- 1 | const ChevronRight = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default ChevronRight 21 | -------------------------------------------------------------------------------- /services/frontend/components/icons/ChevronUp.tsx: -------------------------------------------------------------------------------- 1 | const ChevronUp = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default ChevronUp 21 | -------------------------------------------------------------------------------- /services/frontend/components/icons/CreditCard.tsx: -------------------------------------------------------------------------------- 1 | const CreditCard = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | 18 | ) 19 | } 20 | 21 | export default CreditCard 22 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Cross.tsx: -------------------------------------------------------------------------------- 1 | const Cross = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | 18 | ) 19 | } 20 | 21 | export default Cross 22 | -------------------------------------------------------------------------------- /services/frontend/components/icons/DoubleChevron.tsx: -------------------------------------------------------------------------------- 1 | const DoubleChevron = ({ ...props }) => { 2 | return ( 3 | 11 | 18 | 19 | ) 20 | } 21 | 22 | export default DoubleChevron 23 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Info.tsx: -------------------------------------------------------------------------------- 1 | const Info = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | 18 | 19 | ) 20 | } 21 | 22 | export default Info 23 | -------------------------------------------------------------------------------- /services/frontend/components/icons/MapPin.tsx: -------------------------------------------------------------------------------- 1 | const MapPin = ({ ...props }) => { 2 | return ( 3 | 14 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default MapPin 21 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Menu.tsx: -------------------------------------------------------------------------------- 1 | const Menu = ({ ...props }) => { 2 | return ( 3 | 11 | 17 | 18 | ) 19 | } 20 | 21 | export default Menu 22 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Minus.tsx: -------------------------------------------------------------------------------- 1 | const Minus = ({ ...props }) => { 2 | return ( 3 | 4 | 11 | 12 | ) 13 | } 14 | 15 | export default Minus 16 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Moon.tsx: -------------------------------------------------------------------------------- 1 | const Moon = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | ) 18 | } 19 | 20 | export default Moon 21 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Plus.tsx: -------------------------------------------------------------------------------- 1 | const Plus = ({ ...props }) => { 2 | return ( 3 | 4 | 11 | 18 | 19 | ) 20 | } 21 | 22 | export default Plus 23 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Star.tsx: -------------------------------------------------------------------------------- 1 | const Star = ({ ...props }) => { 2 | return ( 3 | 11 | 12 | 13 | ) 14 | } 15 | 16 | export default Star 17 | -------------------------------------------------------------------------------- /services/frontend/components/icons/Sun.tsx: -------------------------------------------------------------------------------- 1 | const Sun = ({ ...props }) => { 2 | return ( 3 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ) 26 | } 27 | 28 | export default Sun 29 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductCard' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductOptions/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductOptions' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductSidebar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductSidebar' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductSlider/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductSlider' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductSliderControl/ProductSliderControl.module.css: -------------------------------------------------------------------------------- 1 | .control { 2 | @apply bg-violet absolute bottom-10 right-10 flex flex-row 3 | border-accent-0 border text-accent-0 z-30 shadow-xl select-none; 4 | height: 48px; 5 | } 6 | 7 | .leftControl, 8 | .rightControl { 9 | @apply px-9 cursor-pointer; 10 | transition: background-color 0.2s ease; 11 | } 12 | 13 | .leftControl:hover, 14 | .rightControl:hover { 15 | background-color: var(--violet-dark); 16 | } 17 | 18 | .leftControl:focus, 19 | .rightControl:focus { 20 | @apply outline-none; 21 | } 22 | 23 | .rightControl { 24 | @apply border-l border-accent-0; 25 | } 26 | 27 | .leftControl { 28 | margin-right: -1px; 29 | } 30 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductSliderControl/ProductSliderControl.tsx: -------------------------------------------------------------------------------- 1 | import { FC, MouseEventHandler, memo } from 'react' 2 | import cn from 'clsx' 3 | import s from './ProductSliderControl.module.css' 4 | import { ArrowLeft, ArrowRight } from '@components/icons' 5 | 6 | interface ProductSliderControl { 7 | onPrev: MouseEventHandler 8 | onNext: MouseEventHandler 9 | } 10 | 11 | const ProductSliderControl: FC = ({ onPrev, onNext }) => ( 12 |
13 | 20 | 27 |
28 | ) 29 | 30 | export default memo(ProductSliderControl) 31 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductSliderControl/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductSliderControl' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductTag/ProductTag.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply transition-colors ease-in-out duration-500 3 | absolute top-0 left-0 z-20 pr-16; 4 | } 5 | 6 | .root .name { 7 | @apply pt-0 w-full max-w-3xl leading-10; 8 | font-size: 1.725rem; 9 | letter-spacing: 0.4px; 10 | } 11 | 12 | .root .name span { 13 | @apply py-1 px-3 bg-primary text-primary font-bold; 14 | line-height: 1.4; 15 | min-height: 70px; 16 | font-size: inherit; 17 | letter-spacing: inherit; 18 | box-decoration-break: clone; 19 | -webkit-box-decoration-break: clone; 20 | } 21 | 22 | .root .name span.fontsizing { 23 | display: flex; 24 | padding-top: 1.5rem; 25 | } 26 | 27 | .root .price { 28 | @apply py-2 px-3 text-sm bg-primary text-accent-9 29 | font-semibold inline-block tracking-wide; 30 | margin-top: -1px; 31 | } 32 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductTag/ProductTag.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import s from './ProductTag.module.css' 3 | 4 | interface ProductTagProps { 5 | className?: string 6 | name: string 7 | price: string 8 | fontSize?: number 9 | } 10 | 11 | const ProductTag: React.FC = ({ 12 | name, 13 | price, 14 | className = '', 15 | fontSize = 32, 16 | }) => { 17 | return ( 18 |
19 |

20 | 27 | {name} 28 | 29 |

30 |
{price}
31 |
32 | ) 33 | } 34 | 35 | export default ProductTag 36 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductTag/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductTag' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/ProductView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProductView' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/Swatch/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Swatch' 2 | -------------------------------------------------------------------------------- /services/frontend/components/product/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Swatch } from './Swatch' 2 | export { default as ProductView } from './ProductView' 3 | export { default as ProductCard } from './ProductCard' 4 | export { default as ProductSlider } from './ProductSlider' 5 | export { default as ProductList } from './ProductList' 6 | export { default as ProductOptions } from './ProductOptions' 7 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Button/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Button' 2 | export * from './Button' 3 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Collapse/Collapse.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply border-b border-accent-2 py-4 flex flex-col outline-none; 3 | } 4 | 5 | .header { 6 | @apply flex flex-row items-center; 7 | } 8 | 9 | .header .label { 10 | @apply text-base font-medium; 11 | } 12 | 13 | .content { 14 | @apply pt-3 overflow-hidden pl-8; 15 | } 16 | 17 | .icon { 18 | @apply mr-3 text-accent-6; 19 | margin-left: -6px; 20 | transition: transform 0.2s ease; 21 | } 22 | 23 | .icon.open { 24 | transform: rotate(90deg); 25 | } 26 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Collapse/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Collapse' 2 | export * from './Collapse' 3 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Container/Container.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import React, { FC } from 'react' 3 | 4 | interface ContainerProps { 5 | className?: string 6 | children?: any 7 | el?: HTMLElement 8 | clean?: boolean 9 | } 10 | 11 | const Container: FC = ({ 12 | children, 13 | className, 14 | el = 'div', 15 | clean = false, // Full Width Screen 16 | }) => { 17 | const rootClassName = cn(className, { 18 | 'mx-auto max-w-7xl px-6 w-full': !clean, 19 | }) 20 | 21 | let Component: React.ComponentType> = 22 | el as any 23 | 24 | return {children} 25 | } 26 | 27 | export default Container 28 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Container/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Container' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Dropdown/Dropdown.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply bg-accent-0; 3 | animation: none; 4 | transition: none; 5 | min-width: 100%; 6 | } 7 | 8 | @media screen(lg) { 9 | .root { 10 | @apply bg-accent-0; 11 | box-shadow: hsl(206 22% 7% / 45%) 0px 10px 38px -10px, 12 | hsl(206 22% 7% / 20%) 0px 10px 20px -15px; 13 | min-width: 14rem; 14 | will-change: transform, opacity; 15 | animation-duration: 600ms; 16 | animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); 17 | animation-fill-mode: forwards; 18 | transform-origin: var(--radix-dropdown-menu-content-transform-origin); 19 | animation-name: slideIn; 20 | } 21 | } 22 | 23 | @keyframes slideIn { 24 | 0% { 25 | opacity: 0; 26 | transform: translateY(2px); 27 | } 28 | 100% { 29 | opacity: 1; 30 | transform: translateY(0px); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Dropdown/Dropdown.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import React from 'react' 3 | import s from './Dropdown.module.css' 4 | import * as DropdownMenu from '@radix-ui/react-dropdown-menu' 5 | 6 | export const Dropdown = DropdownMenu.Root 7 | export const DropdownMenuItem = DropdownMenu.Item 8 | export const DropdownTrigger = DropdownMenu.Trigger 9 | export const DropdownMenuLabel = DropdownMenu.Label 10 | export const DropdownMenuGroup = DropdownMenu.Group 11 | 12 | export const DropdownContent = React.forwardRef< 13 | HTMLDivElement, 14 | { children: React.ReactNode } & DropdownMenu.DropdownMenuContentProps & 15 | React.RefAttributes 16 | >(function DropdownContent({ children, className, ...props }, forwardedRef) { 17 | return ( 18 | 19 |
{children}
20 |
21 | ) 22 | }) 23 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Grid/Grid.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import { FC, ReactNode, Component } from 'react' 3 | import s from './Grid.module.css' 4 | 5 | interface GridProps { 6 | className?: string 7 | children?: ReactNode[] | Component[] | any[] 8 | layout?: 'A' | 'B' | 'C' | 'D' | 'normal' 9 | variant?: 'default' | 'filled' 10 | } 11 | 12 | const Grid: FC = ({ 13 | className, 14 | layout = 'A', 15 | children, 16 | variant = 'default', 17 | }) => { 18 | const rootClassName = cn( 19 | s.root, 20 | { 21 | [s.layoutA]: layout === 'A', 22 | [s.layoutB]: layout === 'B', 23 | [s.layoutC]: layout === 'C', 24 | [s.layoutD]: layout === 'D', 25 | [s.layoutNormal]: layout === 'normal', 26 | [s.default]: variant === 'default', 27 | [s.filled]: variant === 'filled', 28 | }, 29 | className 30 | ) 31 | return
{children}
32 | } 33 | 34 | export default Grid 35 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Grid/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Grid' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Hero/Hero.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply flex flex-col py-16 mx-auto; 3 | } 4 | 5 | .title { 6 | @apply text-accent-0 font-extrabold text-4xl leading-none tracking-tight; 7 | } 8 | 9 | .description { 10 | @apply mt-4 text-xl leading-8 text-accent-2 mb-1 lg:max-w-4xl; 11 | } 12 | 13 | @screen lg { 14 | .root { 15 | @apply flex-row items-start justify-center py-32; 16 | } 17 | .title { 18 | @apply text-5xl max-w-xl text-right leading-10 -mt-3; 19 | line-height: 3.5rem; 20 | } 21 | .description { 22 | @apply mt-0 ml-6; 23 | } 24 | } 25 | 26 | @screen xl { 27 | .title { 28 | @apply text-6xl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Hero/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Hero' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Input/Input.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply bg-primary py-2 px-6 w-full appearance-none transition duration-150 ease-in-out pr-10 border border-accent-3 text-accent-6; 3 | } 4 | 5 | .root:focus { 6 | @apply outline-none shadow-outline-normal; 7 | } 8 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Input/Input.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import s from './Input.module.css' 3 | import React, { InputHTMLAttributes } from 'react' 4 | 5 | export interface InputProps extends InputHTMLAttributes { 6 | className?: string 7 | onChange?: (...args: any[]) => any 8 | } 9 | 10 | const Input: React.FC = (props) => { 11 | const { className, children, onChange, ...rest } = props 12 | 13 | const rootClassName = cn(s.root, {}, className) 14 | 15 | const handleOnChange = (e: any) => { 16 | if (onChange) { 17 | onChange(e.target.value) 18 | } 19 | return null 20 | } 21 | 22 | return ( 23 | 34 | ) 35 | } 36 | 37 | export default Input 38 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Input/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Input' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Link/Link.tsx: -------------------------------------------------------------------------------- 1 | import NextLink, { LinkProps as NextLinkProps } from 'next/link' 2 | 3 | const Link: React.FC = ({ href, children, ...props }) => { 4 | return ( 5 | 6 | {children} 7 | 8 | ) 9 | } 10 | 11 | export default Link 12 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Link/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Link' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/LoadingDots/LoadingDots.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply inline-flex text-center items-center leading-7; 3 | } 4 | 5 | .root .dot { 6 | @apply rounded-full h-2 w-2; 7 | background-color: currentColor; 8 | animation-name: blink; 9 | animation-duration: 1.4s; 10 | animation-iteration-count: infinite; 11 | animation-fill-mode: both; 12 | margin: 0 2px; 13 | } 14 | 15 | .root .dot:nth-of-type(2) { 16 | animation-delay: 0.2s; 17 | } 18 | 19 | .root .dot::nth-of-type(3) { 20 | animation-delay: 0.4s; 21 | } 22 | 23 | @keyframes blink { 24 | 0% { 25 | opacity: 0.2; 26 | } 27 | 20% { 28 | opacity: 1; 29 | } 30 | 100% { 31 | opacity: 0.2; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /services/frontend/components/ui/LoadingDots/LoadingDots.tsx: -------------------------------------------------------------------------------- 1 | import s from './LoadingDots.module.css' 2 | 3 | const LoadingDots: React.FC = () => { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | ) 11 | } 12 | 13 | export default LoadingDots 14 | -------------------------------------------------------------------------------- /services/frontend/components/ui/LoadingDots/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './LoadingDots' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Logo/Logo.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | const Logo: FC = ({ className = '', ...props }) => ( 4 |
5 | Storedog 6 |
7 | ); 8 | 9 | export default Logo; 10 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Logo/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Logo' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Marquee/Marquee.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply w-full min-w-full relative flex flex-row items-center overflow-hidden py-0; 3 | max-height: 320px; 4 | } 5 | 6 | .root > div { 7 | max-height: 320px; 8 | padding: 0; 9 | margin: 0; 10 | } 11 | 12 | .root > div > * > *:nth-child(2) * { 13 | max-height: 100%; 14 | } 15 | 16 | .primary { 17 | @apply bg-accent-0; 18 | } 19 | 20 | .secondary { 21 | @apply bg-accent-9; 22 | } 23 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Marquee/Marquee.tsx: -------------------------------------------------------------------------------- 1 | import cn from 'clsx' 2 | import s from './Marquee.module.css' 3 | import { FC, ReactNode, Component, Children } from 'react' 4 | import { default as FastMarquee } from 'react-fast-marquee' 5 | 6 | interface MarqueeProps { 7 | className?: string 8 | children?: ReactNode[] | Component[] | any[] 9 | variant?: 'primary' | 'secondary' 10 | } 11 | 12 | const Marquee: FC = ({ 13 | className = '', 14 | children, 15 | variant = 'primary', 16 | }) => { 17 | const rootClassName = cn( 18 | s.root, 19 | { 20 | [s.primary]: variant === 'primary', 21 | [s.secondary]: variant === 'secondary', 22 | }, 23 | className 24 | ) 25 | 26 | return ( 27 | 28 | {Children.map(children, (child) => ({ 29 | ...child, 30 | props: { 31 | ...child.props, 32 | className: cn(child.props.className, `${variant}`), 33 | }, 34 | }))} 35 | 36 | ) 37 | } 38 | 39 | export default Marquee 40 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Marquee/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Marquee' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Modal/Modal.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply fixed bg-black bg-opacity-40 flex items-center inset-0 z-50 justify-center; 3 | backdrop-filter: blur(0.8px); 4 | -webkit-backdrop-filter: blur(0.8px); 5 | } 6 | 7 | .modal { 8 | @apply bg-primary p-12 border border-accent-2 relative; 9 | } 10 | 11 | .modal:focus { 12 | @apply outline-none; 13 | } 14 | 15 | .close { 16 | @apply hover:text-accent-5 transition ease-in-out duration-150 focus:outline-none absolute right-0 top-0 m-6; 17 | } 18 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Modal/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Modal' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Quantity/Quantity.module.css: -------------------------------------------------------------------------------- 1 | .actions { 2 | @apply flex p-1 border-accent-2 border items-center justify-center 3 | w-12 text-accent-7; 4 | transition-property: border-color, background, color, transform, box-shadow; 5 | 6 | transition-duration: 0.15s; 7 | transition-timing-function: ease; 8 | user-select: none; 9 | } 10 | 11 | .actions:hover { 12 | @apply border bg-accent-1 border-accent-3 text-accent-9; 13 | transition: border-color; 14 | z-index: 10; 15 | } 16 | 17 | .actions:focus { 18 | @apply outline-none; 19 | } 20 | 21 | .actions:disabled { 22 | @apply cursor-not-allowed; 23 | } 24 | 25 | .input { 26 | @apply bg-transparent px-4 w-full h-full focus:outline-none select-none pointer-events-auto; 27 | } 28 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Quantity/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Quantity' 2 | export * from './Quantity' 3 | -------------------------------------------------------------------------------- /services/frontend/components/ui/README.md: -------------------------------------------------------------------------------- 1 | # UI 2 | 3 | Building blocks to build a rich graphical interfaces. Components should be atomic and pure. Serve one purpose. 4 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Rating/Rating.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/components/ui/Rating/Rating.module.css -------------------------------------------------------------------------------- /services/frontend/components/ui/Rating/Rating.tsx: -------------------------------------------------------------------------------- 1 | import { FC, memo } from 'react' 2 | import rangeMap from '@lib/range-map' 3 | import { Star } from '@components/icons' 4 | import cn from 'clsx' 5 | 6 | export interface RatingProps { 7 | value: number 8 | } 9 | 10 | const Quantity: FC = ({ value = 5 }) => ( 11 |
12 | {rangeMap(5, (i) => ( 13 | = Math.floor(value), 17 | })} 18 | > 19 | 20 | 21 | ))} 22 |
23 | ) 24 | 25 | export default memo(Quantity) 26 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Rating/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Rating' 2 | export * from './Rating' 3 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Sidebar/Sidebar.module.css: -------------------------------------------------------------------------------- 1 | .root { 2 | @apply fixed inset-0 h-full z-50 box-border outline-none; 3 | } 4 | 5 | .sidebar { 6 | @apply h-full flex flex-col text-base bg-accent-0 shadow-xl overflow-y-auto overflow-x-hidden; 7 | -webkit-overflow-scrolling: touch !important; 8 | } 9 | 10 | .backdrop { 11 | @apply absolute inset-0 bg-black bg-opacity-40 duration-100 ease-linear; 12 | backdrop-filter: blur(0.8px); 13 | -webkit-backdrop-filter: blur(0.8px); 14 | } 15 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Sidebar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Sidebar' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Skeleton/Skeleton.module.css: -------------------------------------------------------------------------------- 1 | .skeleton { 2 | @apply block; 3 | background-image: linear-gradient( 4 | 270deg, 5 | var(--accent-0), 6 | var(--accent-2), 7 | var(--accent-0), 8 | var(--accent-1) 9 | ); 10 | background-size: 400% 100%; 11 | animation: loading 8s ease-in-out infinite; 12 | } 13 | 14 | .wrapper { 15 | @apply block relative; 16 | 17 | &:not(.show)::before { 18 | content: none; 19 | } 20 | 21 | &::before { 22 | content: ''; 23 | position: absolute; 24 | top: 0; 25 | left: 0; 26 | right: 0; 27 | bottom: 0; 28 | z-index: 100; 29 | background-image: linear-gradient( 30 | 270deg, 31 | var(--accent-0), 32 | var(--accent-2), 33 | var(--accent-0), 34 | var(--accent-1) 35 | ); 36 | background-size: 400% 100%; 37 | animation: loading 8s ease-in-out infinite; 38 | } 39 | } 40 | 41 | @keyframes loading { 42 | 0% { 43 | background-position: 200% 0; 44 | } 45 | 100% { 46 | background-position: -200% 0; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Skeleton/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Skeleton' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/Text/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Text' 2 | -------------------------------------------------------------------------------- /services/frontend/components/ui/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Hero } from './Hero' 2 | export { default as Logo } from './Logo' 3 | export { default as Grid } from './Grid' 4 | export { default as Button } from './Button' 5 | export { default as Sidebar } from './Sidebar' 6 | export { default as Marquee } from './Marquee' 7 | export { default as Container } from './Container' 8 | export { default as LoadingDots } from './LoadingDots' 9 | export { default as Skeleton } from './Skeleton' 10 | export { default as Modal } from './Modal' 11 | export { default as Text } from './Text' 12 | export { default as Input } from './Input' 13 | export { default as Collapse } from './Collapse' 14 | export { default as Quantity } from './Quantity' 15 | export { default as Rating } from './Rating' 16 | export * from './Dropdown/Dropdown' 17 | export { useUI } from './context' 18 | -------------------------------------------------------------------------------- /services/frontend/config/seo_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Storedog | Datadog Training", 3 | "titleTemplate": "%s - Storedog", 4 | "description": "Storedog, an ecommerce app used for training at https://learn.datadoghq.com", 5 | "openGraph": { 6 | "title": "Storedog | Datadog Training", 7 | "description": "Storedog, an ecommerce app used for training at https://learn.datadoghq.com", 8 | "type": "website", 9 | "url": "https://learn.datadoghq.com", 10 | "site_name": "Storedog", 11 | "images": [ 12 | { 13 | "url": "/card.png", 14 | "width": "800", 15 | "height": "600", 16 | "alt": "Storedog" 17 | } 18 | ] 19 | }, 20 | "twitter": { 21 | "handle": "@datadoghq", 22 | "site": "@datadoghq", 23 | "cardType": "summary_large_image" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /services/frontend/featureFlags.config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "1", 4 | "name": "dbm", 5 | "active": false 6 | }, 7 | { 8 | "id": "2", 9 | "name": "error-tracking", 10 | "active": false 11 | }, 12 | { 13 | "id": "3", 14 | "name": "api-errors", 15 | "active": false 16 | }, 17 | { 18 | "id": "4", 19 | "name": "product-card-frustration", 20 | "active": false 21 | } 22 | ] 23 | -------------------------------------------------------------------------------- /services/frontend/global.d.ts: -------------------------------------------------------------------------------- 1 | // Declarations for modules without types 2 | declare module 'next-themes' 3 | declare module 'code-stash' 4 | -------------------------------------------------------------------------------- /services/frontend/lib/hooks/useUserAvatar.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { useUI } from '@components/ui/context' 3 | import { getRandomPairOfColors } from '@lib/colors' 4 | 5 | export const useUserAvatar = (name = 'userAvatar') => { 6 | const { userAvatar, setUserAvatar } = useUI() 7 | 8 | useEffect(() => { 9 | if (!userAvatar && localStorage.getItem(name)) { 10 | // Get bg from localStorage and push it to the context. 11 | setUserAvatar(localStorage.getItem(name)) 12 | } 13 | if (!localStorage.getItem(name)) { 14 | // bg not set locally, generating one, setting localStorage and context to persist. 15 | const bg = getRandomPairOfColors() 16 | const value = `linear-gradient(140deg, ${bg[0]}, ${bg[1]} 100%)` 17 | localStorage.setItem(name, value) 18 | setUserAvatar(value) 19 | } 20 | }, []) 21 | 22 | return { 23 | userAvatar, 24 | setUserAvatar, 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /services/frontend/lib/range-map.ts: -------------------------------------------------------------------------------- 1 | export default function rangeMap(n: number, fn: (i: number) => any) { 2 | const arr = [] 3 | while (n > arr.length) { 4 | arr.push(fn(arr.length)) 5 | } 6 | return arr 7 | } 8 | -------------------------------------------------------------------------------- /services/frontend/lib/to-pixels.ts: -------------------------------------------------------------------------------- 1 | // Convert numbers or strings to pixel value 2 | // Helpful for styled-jsx when using a prop 3 | // height: ${toPixels(height)}; (supports height={20} and height="20px") 4 | 5 | const toPixels = (value: string | number) => { 6 | if (typeof value === 'number') { 7 | return `${value}px` 8 | } 9 | 10 | return value 11 | } 12 | 13 | export default toPixels 14 | -------------------------------------------------------------------------------- /services/frontend/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /services/frontend/next-logger.config.js: -------------------------------------------------------------------------------- 1 | const pino = require('pino') 2 | 3 | const logger = (defaultConfig) => 4 | pino({ 5 | ...defaultConfig, 6 | errorKey: 'error', 7 | messageKey: 'message', 8 | }) 9 | 10 | module.exports = { logger } 11 | -------------------------------------------------------------------------------- /services/frontend/pages/404.tsx: -------------------------------------------------------------------------------- 1 | import { Layout } from '@components/common' 2 | import { Text } from '@components/ui' 3 | 4 | export default function NotFound() { 5 | return ( 6 |
7 | Not Found 8 | 9 | The requested page doesn't exist or you don't have access to it. 10 | 11 |
12 | ) 13 | } 14 | 15 | NotFound.Layout = Layout 16 | -------------------------------------------------------------------------------- /services/frontend/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document, { Head, Html, Main, NextScript } from 'next/document' 2 | 3 | class MyDocument extends Document { 4 | render() { 5 | return ( 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | ) 14 | } 15 | } 16 | 17 | export default MyDocument 18 | -------------------------------------------------------------------------------- /services/frontend/pages/api/pages/index.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next' 2 | import { getPages } from '@lib/api/pages' 3 | import { codeStash } from 'code-stash' 4 | import config from '../../../featureFlags.config.json' 5 | 6 | export default async function handler( 7 | req: NextApiRequest, 8 | res: NextApiResponse 9 | ) { 10 | if (config && config.length > 0) { 11 | const isError = await codeStash('api-errors', { file: config }) 12 | 13 | if (isError) { 14 | const random = Math.random() 15 | if (random < 0.33) { 16 | return res.status(400).json({ message: 'Bad request' }) 17 | } else if (random < 0.66) { 18 | return res.status(500).json({ message: 'Internal server error' }) 19 | } 20 | } 21 | } 22 | 23 | const pages = await getPages() 24 | res.status(200).json(pages) 25 | } 26 | -------------------------------------------------------------------------------- /services/frontend/pages/api/products/[slug].ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next' 2 | import { getProduct } from '@lib/api/products' 3 | import { Product } from '@customTypes/product' 4 | 5 | export default async function handler( 6 | req: NextApiRequest, 7 | res: NextApiResponse 8 | ) { 9 | try { 10 | const options = { 11 | id: req.query.slug as string, 12 | include: 13 | req.query.include || 14 | 'default_variant,variants,option_types,product_properties,taxons,images,primary_variant', 15 | ...req.query, 16 | } 17 | 18 | const product: Product = await getProduct(options) 19 | 20 | if (!product?.id) { 21 | return res.status(404).json({ error: 'Not Found' }) 22 | } 23 | 24 | res.status(200).json(product) 25 | } catch (error) { 26 | console.error(error) 27 | res.status(500).json({ error: 'Internal Server Error' }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /services/frontend/pages/api/products/index.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next' 2 | import { getProducts } from '@lib/api/products' 3 | import { Product } from '@customTypes/product' 4 | 5 | export default async function handler( 6 | req: NextApiRequest, 7 | res: NextApiResponse 8 | ) { 9 | try { 10 | const options = { 11 | include: 12 | req.query?.includes || 'default_variant,images,primary_variant,taxons', 13 | page: req.query.page || 1, 14 | per_page: req.query.per_page || 25, 15 | ...req.query, 16 | } 17 | 18 | const products: Product[] = await getProducts(options) 19 | 20 | if (products?.length === 0) { 21 | return res.status(404).json({ error: 'No products found' }) 22 | } 23 | 24 | res.status(200).json(products) 25 | } catch (error) { 26 | console.error(error) 27 | res.status(500).json({ error: 'Internal Server Error' }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /services/frontend/pages/api/taxonomies/[taxonomy]/[slug].ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next' 2 | import { getTaxon } from '@lib/api/taxons' 3 | 4 | export default async function handler( 5 | req: NextApiRequest, 6 | res: NextApiResponse 7 | ) { 8 | try { 9 | const options = { 10 | id: `${req.query.taxonomy}/${req.query.slug}`, 11 | include: req.query.include || 'parent,taxonomy,children,image,products', 12 | } 13 | 14 | const taxon = await getTaxon(options) 15 | 16 | if (!taxon?.id) { 17 | return res.status(404).json({ error: 'Not Found' }) 18 | } 19 | 20 | res.status(200).json(taxon) 21 | } catch (error) { 22 | console.error(error) 23 | res.status(500).json({ error: 'Internal Server Error' }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /services/frontend/pages/api/taxonomies/[taxonomy]/index.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next' 2 | import { getTaxon } from '@lib/api/taxons' 3 | 4 | export default async function handler( 5 | req: NextApiRequest, 6 | res: NextApiResponse 7 | ) { 8 | try { 9 | const options = { 10 | id: req.query.taxonomy as string, 11 | include: req.query.include || 'parent,taxonomy,children,image,products', 12 | } 13 | 14 | const taxon = await getTaxon(options) 15 | 16 | if (!taxon?.id) { 17 | return res.status(404).json({ error: 'Not Found' }) 18 | } 19 | 20 | res.status(200).json(taxon) 21 | } catch (error) { 22 | console.error(error) 23 | res.status(500).json({ error: 'Internal Server Error' }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /services/frontend/pages/api/taxonomies/index.ts: -------------------------------------------------------------------------------- 1 | import type { NextApiRequest, NextApiResponse } from 'next' 2 | import { getTaxons } from '@lib/api/taxons' 3 | import { Taxon } from '@customTypes/taxons' 4 | 5 | export default async function handler( 6 | req: NextApiRequest, 7 | res: NextApiResponse 8 | ) { 9 | try { 10 | const options = { 11 | include: req.query?.includes || 'parent,taxonomy,children,image,products', 12 | page: req.query.page || 1, 13 | per_page: req.query.per_page || 25, 14 | } 15 | 16 | const taxons: Taxon[] = await getTaxons(options) 17 | 18 | if (taxons?.length === 0) { 19 | return res.status(404).json({ error: 'Not Found' }) 20 | } 21 | 22 | res.status(200).json(taxons) 23 | } catch (error) { 24 | console.error(error) 25 | res.status(500).json({ error: 'Internal Server Error' }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /services/frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'tailwindcss/nesting', 4 | 'tailwindcss', 5 | 'autoprefixer', 6 | 'postcss-flexbugs-fixes', 7 | [ 8 | 'postcss-preset-env', 9 | { 10 | autoprefixer: { 11 | flexbox: 'no-2009', 12 | }, 13 | stage: 3, 14 | features: { 15 | 'custom-properties': false, 16 | }, 17 | }, 18 | ], 19 | ], 20 | } 21 | -------------------------------------------------------------------------------- /services/frontend/public/assets/drop-shirt-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/drop-shirt-0.png -------------------------------------------------------------------------------- /services/frontend/public/assets/drop-shirt-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/drop-shirt-1.png -------------------------------------------------------------------------------- /services/frontend/public/assets/drop-shirt-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/drop-shirt-2.png -------------------------------------------------------------------------------- /services/frontend/public/assets/drop-shirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/drop-shirt.png -------------------------------------------------------------------------------- /services/frontend/public/assets/lightweight-jacket-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/lightweight-jacket-0.png -------------------------------------------------------------------------------- /services/frontend/public/assets/lightweight-jacket-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/lightweight-jacket-1.png -------------------------------------------------------------------------------- /services/frontend/public/assets/lightweight-jacket-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/lightweight-jacket-2.png -------------------------------------------------------------------------------- /services/frontend/public/assets/t-shirt-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/t-shirt-0.png -------------------------------------------------------------------------------- /services/frontend/public/assets/t-shirt-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/t-shirt-1.png -------------------------------------------------------------------------------- /services/frontend/public/assets/t-shirt-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/t-shirt-2.png -------------------------------------------------------------------------------- /services/frontend/public/assets/t-shirt-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/t-shirt-3.png -------------------------------------------------------------------------------- /services/frontend/public/assets/t-shirt-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/assets/t-shirt-4.png -------------------------------------------------------------------------------- /services/frontend/public/bg-products.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /services/frontend/public/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/card.png -------------------------------------------------------------------------------- /services/frontend/public/cursor-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/cursor-left.png -------------------------------------------------------------------------------- /services/frontend/public/cursor-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/cursor-right.png -------------------------------------------------------------------------------- /services/frontend/public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/favicon-32x32.png -------------------------------------------------------------------------------- /services/frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/favicon.ico -------------------------------------------------------------------------------- /services/frontend/public/flag-es-co.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /services/frontend/public/flag-es.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /services/frontend/public/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/icon-144x144.png -------------------------------------------------------------------------------- /services/frontend/public/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/icon-192x192.png -------------------------------------------------------------------------------- /services/frontend/public/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/icon-512x512.png -------------------------------------------------------------------------------- /services/frontend/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/icon.png -------------------------------------------------------------------------------- /services/frontend/public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Storedog ecommerce", 3 | "short_name": "Storedog", 4 | "description": "Storedog, an ecommerce app used for training at https://learn.datadoghq.com", 5 | "display": "standalone", 6 | "start_url": "/", 7 | "theme_color": "#fff", 8 | "background_color": "#000000", 9 | "orientation": "portrait", 10 | "icons": [ 11 | { 12 | "src": "/icon-192x192.png", 13 | "type": "image/png", 14 | "sizes": "192x192" 15 | }, 16 | { 17 | "src": "/icon-512x512.png", 18 | "type": "image/png", 19 | "sizes": "512x512" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /services/frontend/public/slider-arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DataDog/storedog/b0b3d8a5cc7eae1972e3d9fcc9b36eef472a604f/services/frontend/public/slider-arrows.png -------------------------------------------------------------------------------- /services/frontend/types/cart.ts: -------------------------------------------------------------------------------- 1 | export type CartLineItem = { 2 | id: string 3 | quantity: number 4 | variantId: string 5 | name: string 6 | path: string 7 | productId: string 8 | discounts: [] 9 | variant: { 10 | id: string 11 | sku: string 12 | name: string 13 | price: number 14 | requiresShipping: boolean 15 | availableForSale: boolean 16 | listPrice: number 17 | isInStock: boolean 18 | image: { 19 | url: string 20 | alt: string 21 | } 22 | } 23 | } 24 | 25 | export type Cart = { 26 | createdAt: string 27 | currency: { 28 | code: string 29 | } 30 | customerId: string 31 | discounts: [] 32 | email: string | null 33 | id: string 34 | lineItems: CartLineItem[] | [] 35 | lineItemsSubtotalPrice: number 36 | shipTotal: number 37 | subtotalPrice: number 38 | taxesIncluded: boolean 39 | totalPrice: number 40 | } 41 | -------------------------------------------------------------------------------- /services/frontend/types/page.ts: -------------------------------------------------------------------------------- 1 | export interface Page { 2 | id: string 3 | name: string 4 | url: string 5 | content?: string | null 6 | } 7 | -------------------------------------------------------------------------------- /services/frontend/types/taxons.ts: -------------------------------------------------------------------------------- 1 | export type Taxon = { 2 | id: string 3 | type: string 4 | attributes: { 5 | name: string 6 | pretty_name: string 7 | permalink: string 8 | seo_title?: string 9 | meta_title?: string 10 | meta_description?: string 11 | meta_keywords?: string 12 | } 13 | children?: any[] 14 | parent?: string 15 | products?: any[] 16 | image?: any 17 | } 18 | -------------------------------------------------------------------------------- /services/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG NGINX_VERSION=1.26 2 | 3 | FROM nginx:$NGINX_VERSION 4 | 5 | RUN apt-get update \ 6 | && apt-get install -y \ 7 | build-essential \ 8 | libpcre++-dev \ 9 | zlib1g-dev \ 10 | wget \ 11 | git 12 | 13 | FROM nginx:$NGINX_VERSION 14 | 15 | COPY nginx.conf /etc/nginx/nginx.conf 16 | COPY default.conf /etc/nginx/conf.d/default.conf 17 | COPY status.conf /etc/nginx/conf.d/status.conf 18 | -------------------------------------------------------------------------------- /services/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | events { 3 | worker_connections 1024; 4 | # other event-related settings can go here 5 | } 6 | 7 | http { 8 | include /etc/nginx/conf.d/*.conf; 9 | 10 | log_format main '$remote_addr - $remote_user [$time_local] ' 11 | '"$request" $status $body_bytes_sent ' 12 | '"$http_referer" "$http_user_agent" '; 13 | 14 | access_log /var/log/nginx/access.log main; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /services/nginx/status.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 81; 3 | server_name localhost; 4 | 5 | access_log off; 6 | allow 0.0.0.0/0; 7 | deny all; 8 | 9 | location /nginx_status { 10 | # Choose your status module 11 | 12 | # freely available with open source NGINX 13 | stub_status; 14 | 15 | # for open source NGINX < version 1.7.5 16 | # stub_status on; 17 | 18 | # available only with NGINX Plus 19 | # status; 20 | 21 | # ensures the version information can be retrieved 22 | server_tokens on; 23 | } 24 | } -------------------------------------------------------------------------------- /services/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:15-alpine 2 | 3 | # Install dcron and su-exec for user switching 4 | RUN apk update && apk add --no-cache dcron su-exec 5 | 6 | # Copy SQL dump and PostgreSQL configuration 7 | COPY ./db/restore.sql /docker-entrypoint-initdb.d/ 8 | COPY ./postgresql.conf /postgresql.conf 9 | 10 | # Create log directory and set permissions 11 | RUN mkdir -p /var/log/pg_log && \ 12 | chown -R postgres:postgres /var/log/pg_log && \ 13 | chmod -R 755 /var/log/pg_log 14 | 15 | # Copy the cron job file 16 | COPY ./scripts/cleanup-cron /etc/crontabs/root 17 | 18 | # Copy and set the entrypoint script 19 | COPY ./scripts/start-services.sh /usr/local/bin/start-services.sh 20 | RUN chmod +x /usr/local/bin/start-services.sh 21 | 22 | # Use the custom entrypoint script 23 | ENTRYPOINT ["/usr/local/bin/start-services.sh"] 24 | 25 | # Default command 26 | CMD ["postgres", "-c", "config_file=/postgresql.conf"] 27 | -------------------------------------------------------------------------------- /services/postgres/scripts/cleanup-cron: -------------------------------------------------------------------------------- 1 | */1 * * * * /usr/bin/find /var/log/pg_log/ -type f -name "*" -mmin +5 -delete >> /var/log/cron.log 2>&1 2 | -------------------------------------------------------------------------------- /services/postgres/scripts/start-services.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Start cron as root 4 | crond -f & 5 | 6 | # Ensure data directory has correct permissions 7 | chown -R postgres:postgres /var/lib/postgresql/data 8 | chmod -R 0700 /var/lib/postgresql/data 9 | 10 | # Switch to the postgres user and start PostgreSQL using the original entrypoint 11 | exec su-exec postgres docker-entrypoint.sh "$@" 12 | -------------------------------------------------------------------------------- /services/puppeteer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/puppeteer/puppeteer:20.0.0 2 | 3 | USER pptruser 4 | WORKDIR /home/pptruser 5 | 6 | COPY ./scripts/puppeteer.sh . 7 | COPY ./scripts/puppeteer.js . 8 | 9 | CMD ["bash", "puppeteer.sh"] -------------------------------------------------------------------------------- /services/puppeteer/scripts/puppeteer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | checkStoredog() { 4 | wget --quiet -O - $STOREDOG_URL |grep -qi storedog 5 | } 6 | 7 | printf "\nWaiting for Storedog" 8 | 9 | until checkStoredog; do 10 | printf . 11 | sleep 2 12 | done 13 | 14 | printf "\nBrowser replay starting.\n\n" 15 | 16 | while : 17 | do 18 | node puppeteer.js $STOREDOG_URL 19 | done 20 | -------------------------------------------------------------------------------- /services/worker/config/initializers/datadog-tracer.rb: -------------------------------------------------------------------------------- 1 | Datadog.configure do |c| 2 | c.service = ENV['DD_SERVICE'] || 'store-worker' 3 | # Activates and configures an integration 4 | c.tracing.instrument :sidekiq, tag_args: true 5 | c.tracing.instrument :pg, service_name: 'postgres' 6 | c.tracing.instrument :active_support, cache_service: 'store-worker-cache' 7 | c.tracing.instrument :redis, service_name: 'store-worker-redis' 8 | end --------------------------------------------------------------------------------