├── .gitignore
├── LICENSE
├── README.md
├── chakra-ui
├── .gitignore
├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── README.md
├── client
│ ├── main.html
│ └── main.js
├── imports
│ └── ui
│ │ ├── App.js
│ │ ├── HeroCallToAction.js
│ │ └── Navbar.js
├── package-lock.json
├── package.json
└── server
│ └── main.js
├── complex-todos-svelte
├── .deploy
│ ├── mup.js
│ └── settings.json
├── .gitignore
├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── LICENSE
├── README.md
├── client
│ ├── init.js
│ ├── main.css
│ ├── main.html
│ ├── main.js
│ └── ui
│ │ ├── About.svelte
│ │ ├── App.svelte
│ │ ├── Task.svelte
│ │ ├── TaskAddNewForm.svelte
│ │ └── Tasks.svelte
├── cypress.json
├── cypress
│ ├── fixtures
│ │ └── example.json
│ ├── integration
│ │ ├── constants
│ │ │ └── test.js
│ │ ├── tests
│ │ │ ├── 1.prepareTestEnvironment.test.js
│ │ │ ├── authentication.test.js
│ │ │ ├── navigation.test.js
│ │ │ └── tasks.test.js
│ │ └── utilities
│ │ │ ├── commons.js
│ │ │ ├── doLogin.js
│ │ │ └── doLogout.js
│ ├── plugins
│ │ └── index.js
│ ├── readme.md
│ └── support
│ │ ├── commands.js
│ │ └── index.js
├── imports
│ ├── modules
│ │ ├── eventEmitter
│ │ │ ├── eventEmitterService.js
│ │ │ └── server
│ │ │ │ └── index.js
│ │ ├── tasks
│ │ │ ├── database
│ │ │ │ └── tasks.js
│ │ │ ├── enums
│ │ │ │ ├── methodNames.js
│ │ │ │ ├── publications.js
│ │ │ │ └── rateLimitter.js
│ │ │ ├── server
│ │ │ │ ├── index.js
│ │ │ │ ├── tasks.ensureIndexes.js
│ │ │ │ ├── tasks.events.js
│ │ │ │ ├── tasks.guards.js
│ │ │ │ ├── tasks.publications.js
│ │ │ │ └── tasks.rateLimiter.js
│ │ │ ├── taskRepository.js
│ │ │ ├── taskService.js
│ │ │ ├── tasks.methods.js
│ │ │ └── tasks.methods.test.js
│ │ └── users
│ │ │ ├── enums
│ │ │ └── cacheKey.js
│ │ │ └── server
│ │ │ ├── index.js
│ │ │ └── user.cache.js
│ └── shared
│ │ ├── enums
│ │ └── events.js
│ │ ├── functions
│ │ ├── bound.js
│ │ ├── isDefined.js
│ │ ├── lang.js
│ │ └── user.js
│ │ ├── logger
│ │ └── logger.js
│ │ ├── mixins
│ │ └── LoggedInMixin.js
│ │ ├── repository
│ │ └── baseRepository.js
│ │ └── utilities
│ │ └── dateUtility.js
├── package-lock.json
├── package.json
├── packages
│ ├── logger
│ │ ├── .github
│ │ │ ├── FUNDING.yml
│ │ │ ├── ISSUE_TEMPLATE
│ │ │ └── PULL_REQUEST_TEMPLATE
│ │ ├── .gitignore
│ │ ├── .versions
│ │ ├── CHANGELOG.md
│ │ ├── CODE_OF_CONDUCT.md
│ │ ├── CONTRIBUTING.md
│ │ ├── HISTORY.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── logger-tests.js
│ │ ├── logger.js
│ │ ├── meteor-logger.jpg
│ │ └── package.js
│ └── readme.md
├── screenshot.jpg
├── server
│ ├── init.js
│ ├── main.js
│ ├── modules.js
│ ├── modules
│ │ ├── cache
│ │ │ ├── cacheService.js
│ │ │ └── server
│ │ │ │ └── index.js
│ │ ├── dummies
│ │ │ ├── dummiesService.js
│ │ │ ├── fixtures
│ │ │ │ ├── dummyTasks.js
│ │ │ │ └── dummyUsers.js
│ │ │ ├── readme.md
│ │ │ └── server
│ │ │ │ ├── dummies.methods.js
│ │ │ │ └── index.js
│ │ ├── jobs
│ │ │ └── server
│ │ │ │ ├── index.js
│ │ │ │ └── tasks.expire.js
│ │ └── migrations
│ │ │ ├── database
│ │ │ └── migrations.js
│ │ │ ├── migrationRepository.js
│ │ │ ├── migrationService.js
│ │ │ ├── readme.md
│ │ │ └── server
│ │ │ ├── 1.0.1.js
│ │ │ ├── index.js
│ │ │ └── migrations.guards.js
│ └── shared
│ │ └── enums
│ │ └── job.js
├── settings.json
└── tests
│ ├── enums
│ └── users.js
│ ├── main.js
│ ├── package.json.test.js
│ └── readme.md
├── cordova
├── .gitignore
├── .meteor
│ ├── .gitignore
│ ├── cordova-plugins
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── README.md
├── client
│ ├── main.css
│ ├── main.html
│ └── main.js
├── imports
│ ├── collections
│ │ └── links.js
│ ├── infra
│ │ ├── addPlayerId.js
│ │ ├── apple-app-site-association.js
│ │ ├── constants.js
│ │ ├── database-seed.js
│ │ ├── google-analytics.js
│ │ ├── meta-tags.js
│ │ ├── methodCall.js
│ │ ├── native.js
│ │ ├── one-signal.js
│ │ ├── pwa-json.js
│ │ ├── rest.js
│ │ ├── sendPush.js
│ │ └── serviceWorkerInit.js
│ ├── methods
│ │ └── createUser.js
│ └── ui
│ │ ├── App.js
│ │ ├── Hello.js
│ │ ├── Info.js
│ │ └── User.js
├── mobile-config.js
├── package-lock.json
├── package.json
├── private
│ ├── env
│ │ └── production
│ │ │ └── settings.json
│ ├── jenkins.groovy
│ └── native-app
│ │ └── production
│ │ ├── build.sh
│ │ ├── publish-android.sh
│ │ └── publish-ios.sh
├── public
│ └── sw.js
└── server
│ └── main.js
├── nft-marketplace
├── .gitignore
├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── README.md
├── app
│ └── ui
│ │ ├── AccountPage.jsx
│ │ ├── App.jsx
│ │ ├── ConnectPage.jsx
│ │ ├── DetailsPage.jsx
│ │ ├── HomePage.jsx
│ │ ├── SellNftPage.jsx
│ │ ├── common
│ │ ├── CategoryOptions.jsx
│ │ ├── CheckAccount.jsx
│ │ ├── ConnectAccount.jsx
│ │ ├── CurrentAccount.jsx
│ │ ├── Footer.jsx
│ │ ├── NavBar.jsx
│ │ ├── RoutePaths.jsx
│ │ ├── Routes.jsx
│ │ └── SortOptions.jsx
│ │ ├── components
│ │ ├── Button.jsx
│ │ ├── Card.jsx
│ │ └── Fields
│ │ │ ├── InputField.jsx
│ │ │ ├── Select.jsx
│ │ │ └── useField.jsx
│ │ └── util
│ │ ├── formatPrice.js
│ │ └── usePriceConverter.js
├── client
│ ├── main.css
│ ├── main.html
│ └── main.jsx
├── config.js
├── contracts
│ └── NFTMarketplace.sol
├── hardhat.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│ └── images
│ │ ├── bg-stars.svg
│ │ ├── default-profile-avatar.png
│ │ ├── logo.png
│ │ └── metamask-logo.png
├── scripts
│ └── deploy.js
├── server
│ └── main.js
├── tailwind.config.js
└── tests
│ ├── hardhat.js
│ └── main.js
├── parties
├── .gitignore
├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── client
│ ├── main.css
│ ├── main.html
│ └── main.js
├── imports
│ └── model.js
├── package-lock.json
├── package.json
├── public
│ └── soma.png
├── server
│ └── main.js
└── tests
│ └── main.js
├── tailwindcss
├── .gitignore
├── .meteor
│ ├── .finished-upgraders
│ ├── .gitignore
│ ├── .id
│ ├── packages
│ ├── platforms
│ ├── release
│ └── versions
├── .postcssrc.js
├── README.md
├── client
│ ├── main.css
│ ├── main.html
│ └── main.js
├── imports
│ └── ui
│ │ ├── App.js
│ │ ├── Dashboard.js
│ │ └── List.js
├── package-lock.json
├── package.json
├── public
│ └── logo.svg
├── server
│ └── main.js
└── tailwind.config.js
└── tic-tac-toe
├── .gitignore
├── .meteor
├── .finished-upgraders
├── .gitignore
├── .id
├── packages
├── platforms
├── release
└── versions
├── README.md
├── client
├── main.css
├── main.html
└── main.jsx
├── imports
├── api
│ └── rooms.js
└── ui
│ ├── App.jsx
│ ├── GameScreen.jsx
│ ├── RoomList.jsx
│ └── game.css
├── package-lock.json
├── package.json
├── public
├── circle.png
└── cross.png
└── server
└── main.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | # Intelij IDEs project configuration folder
107 | .idea
108 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Meteor
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chakra-ui/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | yarn.lock
61 |
62 | # next.js build output
63 | .next
64 |
65 | # webstorm
66 | **/.idea/*
67 | !.idea/runConfigurations
68 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 | 1.7-split-underscore-from-meteor-base
19 | 1.8.3-split-jquery-from-blaze
20 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | j3mxcj0j3jfj.pzmhdxgvur2
8 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.5.2-alpha300.19 # Packages every Meteor app needs to have
8 | mobile-experience@1.1.1-alpha300.19 # Packages for a great mobile UX
9 | mongo@2.0.0-alpha300.19 # The database Meteor supports right now
10 | reactive-var@1.0.13-alpha300.19 # Reactive variable for tracker
11 |
12 | standard-minifier-css@1.9.3-alpha300.19 # CSS minifier run for production mode
13 | standard-minifier-js@3.0.0-alpha300.19 # JS minifier run for production mode
14 | es5-shim@4.8.1-alpha300.19 # ECMAScript 5 compatibility for older browsers
15 | ecmascript@0.16.8-alpha300.19 # Enable ECMAScript2015+ syntax in app code
16 | typescript@4.9.5-alpha300.19 # Enable TypeScript syntax in .ts and .tsx modules
17 | shell-server@0.6.0-alpha300.19 # Server-side component of the `meteor shell` command
18 | hot-module-replacement@0.5.4-alpha300.19 # Update client in development without reloading the page
19 |
20 | autopublish@1.0.8-alpha300.19 # Publish all data to the clients (for prototyping)
21 | insecure@1.0.8-alpha300.19 # Allow all DB writes from clients (for prototyping)
22 | static-html@1.3.3-alpha300.19 # Define static page content in .html files
23 | react-meteor-data # React higher-order component for reactively tracking Meteor data
24 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@3.0-alpha.19
2 |
--------------------------------------------------------------------------------
/chakra-ui/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@2.0.0-alpha300.19
2 | autopublish@1.0.8-alpha300.19
3 | autoupdate@2.0.0-alpha300.19
4 | babel-compiler@7.11.0-alpha300.19
5 | babel-runtime@1.5.2-alpha300.19
6 | base64@1.0.13-alpha300.19
7 | binary-heap@1.0.12-alpha300.19
8 | blaze-tools@2.0.0-alpha300.17
9 | boilerplate-generator@2.0.0-alpha300.19
10 | caching-compiler@2.0.0-alpha300.19
11 | caching-html-compiler@2.0.0-alpha300.17
12 | callback-hook@1.6.0-alpha300.19
13 | check@1.3.3-alpha300.19
14 | core-runtime@1.0.0-alpha300.19
15 | ddp@1.4.2-alpha300.19
16 | ddp-client@3.0.0-alpha300.19
17 | ddp-common@1.4.1-alpha300.19
18 | ddp-server@3.0.0-alpha300.19
19 | diff-sequence@1.1.3-alpha300.19
20 | dynamic-import@0.7.4-alpha300.19
21 | ecmascript@0.16.8-alpha300.19
22 | ecmascript-runtime@0.8.2-alpha300.19
23 | ecmascript-runtime-client@0.12.2-alpha300.19
24 | ecmascript-runtime-server@0.11.1-alpha300.19
25 | ejson@1.1.4-alpha300.19
26 | es5-shim@4.8.1-alpha300.19
27 | facts-base@1.0.2-alpha300.19
28 | fetch@0.1.4-alpha300.19
29 | geojson-utils@1.0.12-alpha300.19
30 | hot-code-push@1.0.5-alpha300.19
31 | hot-module-replacement@0.5.4-alpha300.19
32 | html-tools@2.0.0-alpha300.17
33 | htmljs@2.0.0-alpha300.17
34 | id-map@1.2.0-alpha300.19
35 | insecure@1.0.8-alpha300.19
36 | inter-process-messaging@0.1.2-alpha300.19
37 | launch-screen@1.3.1-alpha300.19
38 | logging@1.3.3-alpha300.19
39 | meteor@2.0.0-alpha300.19
40 | meteor-base@1.5.2-alpha300.19
41 | minifier-css@2.0.0-alpha300.19
42 | minifier-js@3.0.0-alpha300.19
43 | minimongo@2.0.0-alpha300.19
44 | mobile-experience@1.1.1-alpha300.19
45 | mobile-status-bar@1.1.1-alpha300.19
46 | modern-browsers@0.1.10-alpha300.19
47 | modules@0.19.1-alpha300.19
48 | modules-runtime@0.13.2-alpha300.19
49 | modules-runtime-hot@0.14.3-alpha300.19
50 | mongo@2.0.0-alpha300.19
51 | mongo-decimal@0.1.4-alpha300.19
52 | mongo-dev-server@1.1.1-alpha300.19
53 | mongo-id@1.0.9-alpha300.19
54 | npm-mongo@4.16.1-alpha300.19
55 | ordered-dict@1.2.0-alpha300.19
56 | promise@1.0.0-alpha300.19
57 | random@1.2.2-alpha300.19
58 | react-fast-refresh@0.2.8-alpha300.19
59 | react-meteor-data@2.7.2
60 | reactive-var@1.0.13-alpha300.19
61 | reload@1.3.2-alpha300.19
62 | retry@1.1.1-alpha300.19
63 | routepolicy@1.1.2-alpha300.19
64 | shell-server@0.6.0-alpha300.19
65 | socket-stream-client@0.5.2-alpha300.19
66 | spacebars-compiler@2.0.0-alpha300.17
67 | standard-minifier-css@1.9.3-alpha300.19
68 | standard-minifier-js@3.0.0-alpha300.19
69 | static-html@1.3.3-alpha300.19
70 | templating-tools@2.0.0-alpha300.17
71 | tracker@1.3.3-alpha300.19
72 | typescript@4.9.5-alpha300.19
73 | underscore@1.0.14-alpha300.19
74 | webapp@2.0.0-alpha300.19
75 | webapp-hashing@1.1.2-alpha300.19
76 |
--------------------------------------------------------------------------------
/chakra-ui/README.md:
--------------------------------------------------------------------------------
1 | # Meteor + Chakra UI + Dark mode example
2 |
3 | Demo deployed on [Galaxy](https://meteor.com/cloud):
4 |
5 | https://chakraui.meteorapp.com/
6 |
7 | ## Chakra UI
8 |
9 | The setup is already done in this project, but if you want to do it in another project you can follow the steps below.
10 |
11 | They are pretty much the same as the recommended on the [installation page](https://chakra-ui.com/docs/getting-started) of Chakra UI.
12 |
13 | ### 1 - Install npm dependencies
14 | ```bash
15 | npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
16 | ```
17 |
18 | ### 2 - Install Chakra UI icons
19 |
20 | ```bash
21 | npm i @chakra-ui/icons
22 | ```
23 |
24 | See [package.json](package.json) as example.
25 |
26 | ### 3 - Setup Chakra UI Provider + Color Mode
27 |
28 | ```js
29 | import React from 'react';
30 | import { ChakraProvider, ColorModeScript, extendTheme } from '@chakra-ui/react';
31 | import { HeroCallToAction } from './HeroCallToAction';
32 | import { Navbar } from './Navbar';
33 |
34 | const theme = extendTheme({ config: {
35 | initialColorMode: 'dark',
36 | useSystemColorMode: false,
37 | } });
38 |
39 | export const App = () => (
40 | <>
41 |
42 |
43 |
44 |
45 |
46 | >
47 | );
48 |
49 | ```
50 |
51 | See [main.js](client/main.js) and [App.js](imports/ui/App.js) as example.
52 |
53 | ## Running the example
54 |
55 | ### Install dependencies
56 |
57 | ```bash
58 | meteor npm install
59 | ```
60 |
61 | ### Running
62 |
63 | ```bash
64 | meteor npm run start
65 | ```
66 |
--------------------------------------------------------------------------------
/chakra-ui/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | Meteor + Chakra UI Example
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/chakra-ui/client/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meteor } from 'meteor/meteor';
3 | import { render } from 'react-dom';
4 | import { App } from '../imports/ui/App';
5 |
6 | Meteor.startup(() => {
7 | render( , document.getElementById('react-target'));
8 | });
9 |
--------------------------------------------------------------------------------
/chakra-ui/imports/ui/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ChakraProvider, ColorModeScript, extendTheme } from '@chakra-ui/react';
3 | import { HeroCallToAction } from './HeroCallToAction';
4 | import { Navbar } from './Navbar';
5 |
6 | const theme = extendTheme({ config: {
7 | initialColorMode: 'dark',
8 | useSystemColorMode: false,
9 | } });
10 |
11 | export const App = () => (
12 | <>
13 |
14 |
15 |
16 |
17 |
18 | >
19 | );
20 |
--------------------------------------------------------------------------------
/chakra-ui/imports/ui/HeroCallToAction.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Box,
4 | Button,
5 | Container,
6 | createIcon,
7 | Heading,
8 | Icon,
9 | Stack,
10 | Text,
11 | useColorModeValue,
12 | } from '@chakra-ui/react';
13 | import { SearchIcon, StarIcon } from '@chakra-ui/icons';
14 |
15 | const Arrow = createIcon({
16 | displayName: 'Arrow',
17 | viewBox: '0 0 72 24',
18 | path: (
19 |
25 | ),
26 | });
27 |
28 | export function HeroCallToAction() {
29 | return (
30 | <>
31 |
32 |
37 |
41 |
42 | Meteor 3.0 {' '}
43 | + {' '}
44 |
45 | Node 20 {' '}
46 |
47 | + Chakra UI
48 |
49 |
50 | Meteor is a framework for building Web, Mobile, and Desktop applications in JS.
51 | Chakra UI is a simple, modular and accessible component library to build your React applications.
52 |
53 |
59 | }
68 | _hover={{
69 | bg: 'green.500',
70 | }}>
71 | Clone this Repository
72 |
73 | }>
74 | Learn More
75 |
76 |
77 |
85 |
92 | Create your app
93 |
94 |
95 |
96 |
97 |
98 | >
99 | );
100 | }
101 |
--------------------------------------------------------------------------------
/chakra-ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chakra-ui-meteor-example",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run",
6 | "eslint": "eslint . --fix"
7 | },
8 | "dependencies": {
9 | "@babel/runtime": "^7.23.5",
10 | "@chakra-ui/icons": "^2.1.1",
11 | "@chakra-ui/react": "^2.8.2",
12 | "@emotion/react": "^11.11.1",
13 | "@emotion/styled": "^11.11.0",
14 | "framer-motion": "^10.16.12",
15 | "meteor-node-stubs": "^1.2.7",
16 | "react": "^18.2.0",
17 | "react-dom": "^18.2.0"
18 | },
19 | "devDependencies": {
20 | "@quave/eslint-config-quave": "^1.0.7",
21 | "@types/meteor": "^2.9.7",
22 | "@types/react": "^18.2.41",
23 | "@types/react-dom": "^18.2.17"
24 | },
25 | "meteor": {
26 | "mainModule": {
27 | "client": "client/main.js",
28 | "server": "server/main.js"
29 | }
30 | },
31 | "eslintConfig": {
32 | "extends": [
33 | "@quave/quave"
34 | ]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/chakra-ui/server/main.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 |
3 | Meteor.startup(() => {
4 | // eslint-disable-next-line no-console
5 | console.info('server ready');
6 | });
7 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.deploy/mup.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | servers: {
3 | one: {
4 | host: '1.2.3.4',
5 | username: 'root',
6 | password: 'password',
7 | opts: {
8 | port: 22
9 | }
10 | }
11 | },
12 |
13 | app: {
14 | name: 'complex-todo-svelte',
15 | path: '../',
16 | docker: {
17 | image: 'abernix/meteord:node-12-base',
18 | },
19 | servers: {
20 | one: {},
21 | },
22 | buildOptions: {
23 | serverOnly: true,
24 | },
25 | env: {
26 | ROOT_URL: 'http://app.com',
27 | },
28 | deployCheckPort: 80,
29 | enableUploadProgressBar: true
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.deploy/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": {
3 | "log": [
4 | "ERROR",
5 | "FATAL",
6 | "WARN",
7 | "INFO",
8 | "TRACE",
9 | ]
10 | },
11 | "monti": {
12 | "appId": "bzuQ34N4GPrwEu6Bo",
13 | "appSecret": "a7343029-4163-4c69-9342-d09b4d515e0c"
14 | }
15 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 | 1.7-split-underscore-from-meteor-base
19 | 1.8.3-split-jquery-from-blaze
20 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | ou78pym2e7kf.kuc1f56r19il
8 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.5.1 # Packages every Meteor app needs to have
8 | mobile-experience@1.1.0 # Packages for a great mobile UX
9 | mongo@1.12.0 # The database Meteor supports right now
10 | jquery # Wrapper package for npm-installed jquery
11 | reactive-var@1.0.11 # Reactive variable for tracker
12 | tracker@1.2.0 # Meteor's client-side reactive programming library
13 |
14 | standard-minifier-css@1.7.3 # CSS minifier run for production mode
15 | standard-minifier-js@2.6.1 # JS minifier run for production mode
16 | es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers
17 | ecmascript@0.15.3 # Enable ECMAScript2015+ syntax in app code
18 | typescript@4.3.5 # Enable TypeScript syntax in .ts and .tsx modules
19 | shell-server@0.5.0 # Server-side component of the `meteor shell` command
20 |
21 | svelte:compiler
22 | rdb:svelte-meteor-data
23 | static-html
24 | svelte:blaze-integration
25 | meteortesting:mocha
26 |
27 | #
28 | # Accounts and roles
29 | #
30 | accounts-ui@1.4.0
31 | accounts-password@2.0.0
32 |
33 | #
34 | # Data layer
35 | #
36 | aldeed:collection2
37 | dburles:mongo-collection-instances
38 |
39 | #
40 | # Validated methods
41 | #
42 | mdg:validated-method
43 | ddp-rate-limiter@1.1.0
44 |
45 | #
46 | # Logging
47 | #
48 | ostrio:logger
49 | ostrio:loggerconsole
50 |
51 | #
52 | # Scheduled jobs
53 | #
54 | msavin:sjobs
55 |
56 | #
57 | # APM
58 | #
59 | montiapm:agent
60 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@2.3.5
2 |
--------------------------------------------------------------------------------
/complex-todos-svelte/.meteor/versions:
--------------------------------------------------------------------------------
1 | accounts-base@2.0.1
2 | accounts-password@2.0.0
3 | accounts-ui@1.4.0
4 | accounts-ui-unstyled@1.5.0
5 | aldeed:collection2@3.4.1
6 | allow-deny@1.1.0
7 | autoupdate@1.7.0
8 | babel-compiler@7.7.0
9 | babel-runtime@1.5.0
10 | base64@1.0.12
11 | binary-heap@1.0.11
12 | blaze@2.5.0
13 | blaze-tools@1.1.2
14 | boilerplate-generator@1.7.1
15 | caching-compiler@1.2.2
16 | caching-html-compiler@1.2.1
17 | callback-hook@1.3.1
18 | check@1.3.1
19 | dburles:mongo-collection-instances@0.3.1
20 | ddp@1.4.0
21 | ddp-client@2.5.0
22 | ddp-common@1.4.0
23 | ddp-rate-limiter@1.1.0
24 | ddp-server@2.4.1
25 | diff-sequence@1.1.1
26 | dynamic-import@0.7.1
27 | ecmascript@0.15.3
28 | ecmascript-runtime@0.7.0
29 | ecmascript-runtime-client@0.11.1
30 | ecmascript-runtime-server@0.10.1
31 | ejson@1.1.1
32 | email@2.1.1
33 | es5-shim@4.8.0
34 | fetch@0.1.1
35 | geojson-utils@1.0.10
36 | hot-code-push@1.0.4
37 | html-tools@1.1.2
38 | htmljs@1.1.1
39 | http@1.4.4
40 | id-map@1.1.1
41 | inter-process-messaging@0.1.1
42 | jquery@3.0.0
43 | launch-screen@1.3.0
44 | less@3.0.2
45 | livedata@1.0.18
46 | localstorage@1.2.0
47 | logging@1.2.0
48 | mdg:validated-method@1.2.0
49 | meteor@1.9.3
50 | meteor-base@1.5.1
51 | meteortesting:browser-tests@1.3.4
52 | meteortesting:mocha@2.0.2
53 | meteortesting:mocha-core@8.1.2
54 | minifier-css@1.5.4
55 | minifier-js@2.6.1
56 | minimongo@1.7.0
57 | mobile-experience@1.1.0
58 | mobile-status-bar@1.1.0
59 | modern-browsers@0.1.5
60 | modules@0.16.0
61 | modules-runtime@0.12.0
62 | mongo@1.12.0
63 | mongo-decimal@0.1.2
64 | mongo-dev-server@1.1.0
65 | mongo-id@1.0.8
66 | mongo-livedata@1.0.12
67 | montiapm:agent@2.44.1
68 | montiapm:meteorx@2.2.0
69 | msavin:sjobs@4.1.0
70 | npm-mongo@3.9.1
71 | observe-sequence@1.0.19
72 | ordered-dict@1.1.0
73 | ostrio:logger@2.0.9
74 | ostrio:loggerconsole@2.0.5
75 | promise@0.12.0
76 | raix:eventemitter@1.0.0
77 | random@1.2.0
78 | rate-limit@1.0.9
79 | rdb:svelte-meteor-data@0.3.0
80 | react-fast-refresh@0.1.1
81 | reactive-dict@1.3.0
82 | reactive-var@1.0.11
83 | reload@1.3.1
84 | retry@1.1.0
85 | routepolicy@1.1.1
86 | service-configuration@1.1.0
87 | session@1.2.0
88 | sha@1.0.9
89 | shell-server@0.5.0
90 | socket-stream-client@0.4.0
91 | spacebars@1.2.0
92 | spacebars-compiler@1.3.0
93 | standard-minifier-css@1.7.3
94 | standard-minifier-js@2.6.1
95 | static-html@1.3.2
96 | svelte:blaze-integration@0.4.0
97 | svelte:compiler@3.31.2
98 | templating@1.4.1
99 | templating-compiler@1.4.1
100 | templating-runtime@1.5.0
101 | templating-tools@1.2.1
102 | tmeasday:check-npm-versions@1.0.2
103 | tracker@1.2.0
104 | typescript@4.3.5
105 | underscore@1.0.10
106 | url@1.3.2
107 | webapp@1.11.1
108 | webapp-hashing@1.1.0
109 | zodern:meteor-package-versions@0.2.1
110 |
--------------------------------------------------------------------------------
/complex-todos-svelte/LICENSE:
--------------------------------------------------------------------------------
1 | ========================================
2 | Meteor is licensed under the MIT License
3 | ========================================
4 |
5 | Copyright (C) 2011--2016 Meteor Development Group
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | this software and associated documentation files (the "Software"), to deal in
9 | the Software without restriction, including without limitation the rights to
10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | the Software, and to permit persons to whom the Software is furnished to do so,
12 | subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/complex-todos-svelte/client/init.js:
--------------------------------------------------------------------------------
1 | import {log} from '../imports/shared/logger/logger.js';
2 | import {Accounts} from 'meteor/accounts-base';
3 | import App from './ui/App.svelte';
4 |
5 | /**
6 | * Initialize client at startup
7 | * @locus server
8 | */
9 | class ClientInit
10 | {
11 | /**
12 | * @constructor
13 | */
14 | constructor()
15 | {
16 | log.info('Client is starting');
17 |
18 | this._accountUIConfig();
19 |
20 | this._renderApp();
21 | }
22 |
23 | _accountUIConfig()
24 | {
25 | log.debug('Configuring accounts user interface');
26 |
27 | Accounts.ui.config({
28 | passwordSignupFields: 'USERNAME_ONLY'
29 | });
30 | }
31 |
32 | _renderApp()
33 | {
34 | log.debug('Rendering app');
35 |
36 | new App({
37 | target: document.getElementById('app')
38 | });
39 | }
40 | }
41 |
42 | /**
43 | * No need to export it
44 | * It will only run once on client initialize
45 | */
46 | Meteor.startup(function()
47 | {
48 | new ClientInit;
49 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/client/main.css:
--------------------------------------------------------------------------------
1 | .nav-login {
2 | padding: 8px;
3 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | Complex Todo List
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/complex-todos-svelte/client/main.js:
--------------------------------------------------------------------------------
1 | import './init.js';
--------------------------------------------------------------------------------
/complex-todos-svelte/client/ui/About.svelte:
--------------------------------------------------------------------------------
1 |
2 |
About
3 |
This is an example app to show how anyone can combine Meteor.js with svelte. The example is like a simple to-do application and it covers lots of things related with the real world
4 |
5 |
--------------------------------------------------------------------------------
/complex-todos-svelte/client/ui/App.svelte:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
Meteor.js & Svelte Example
21 |
22 |
23 |
24 |
25 |
26 |
27 | Tasks
28 |
29 |
30 | About
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/complex-todos-svelte/client/ui/Task.svelte:
--------------------------------------------------------------------------------
1 |
32 |
33 |
36 |
37 |
38 | { task.username } : { task.text }
39 | {#if showButton}
40 |
46 | {/if}
47 |
48 |
49 |
50 |
51 | {#if showButton}
52 |
54 | { task.private ? "Private" : "Public" }
55 |
56 |
58 | Delete
59 |
60 | {/if}
61 |
62 |
63 |
--------------------------------------------------------------------------------
/complex-todos-svelte/client/ui/TaskAddNewForm.svelte:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/complex-todos-svelte/client/ui/Tasks.svelte:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
34 | {#if $currentUser}
35 |
36 | {/if}
37 |
38 |
39 |
40 |
Pending Items ({ $incompleteCount })
41 |
42 |
73 |
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:3000/",
3 | "watchForFileChanges": true,
4 | "defaultCommandTimeout": 15000,
5 | "requestTimeout": 15000,
6 | "pageLoadTimeout": 120000,
7 | "responseTimeout": 60000,
8 | "retries": {
9 | "runMode": 2,
10 | "openMode": 0
11 | },
12 | "projectId": "ctdsm1"
13 | }
14 |
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/constants/test.js:
--------------------------------------------------------------------------------
1 | export const TEST = {
2 | USER: {
3 | DEMO: {
4 | USERNAME: 'gunce',
5 | PASSWORD: 'password'
6 | },
7 | TEST: {
8 | USERNAME: 'username',
9 | PASSWORD: 'password'
10 | }
11 | },
12 | TASK: {
13 | PUBLIC: 'Public test task',
14 | PRIVATE: 'Private test task'
15 | }
16 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/tests/1.prepareTestEnvironment.test.js:
--------------------------------------------------------------------------------
1 | import {visit, wait} from '../utilities/commons.js';
2 |
3 | describe('Prepare Test Environment', function()
4 | {
5 | it('Clear database', function()
6 | {
7 | visit('/');
8 |
9 | cy.window().then((win) =>
10 | {
11 | win.Meteor.call('clear.database');
12 | });
13 |
14 | wait(1000);
15 |
16 | cy.url().should('contain', 'localhost');
17 | });
18 |
19 | it('Insert dummy data', function()
20 | {
21 | visit('/');
22 |
23 | cy.window().then((win) =>
24 | {
25 | win.Meteor.call('insert.dummy.data');
26 | });
27 |
28 | wait(1000);
29 |
30 | cy.url().should('contain', 'localhost');
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/tests/authentication.test.js:
--------------------------------------------------------------------------------
1 | import {visit} from '../utilities/commons.js';
2 | import {TEST} from '../constants/test.js';
3 | import {doLogin} from '../utilities/doLogin.js';
4 | import {doLogout} from '../utilities/doLogout.js';
5 |
6 | describe('Authentication', function()
7 | {
8 | it('Sign up - Fail - Passwords must match', function()
9 | {
10 | visit('/');
11 |
12 | cy.get('#login-sign-in-link').click();
13 |
14 | cy.get('#signup-link').click();
15 |
16 | cy.get('#login-username').clear().type(TEST.USER.TEST.USERNAME);
17 |
18 | cy.get('#login-password').clear().type('password1');
19 |
20 | cy.get('#login-password-again').clear().type('password2');
21 |
22 | cy.get('#login-buttons-password').click();
23 |
24 | cy.get('.message.error-message').should('contain', 'Passwords don\'t match');
25 | });
26 |
27 | it('Sign up - Fail - Password must long', function()
28 | {
29 | visit('/');
30 |
31 | cy.get('#login-sign-in-link').click();
32 |
33 | cy.get('#signup-link').click();
34 |
35 | cy.get('#login-username').clear().type(TEST.USER.TEST.USERNAME);
36 |
37 | cy.get('#login-password').clear().type('pass');
38 |
39 | cy.get('#login-password-again').clear().type('pass');
40 |
41 | cy.get('#login-buttons-password').click();
42 |
43 | cy.get('.message.error-message').should('contain', 'Password must be at least 6 characters long');
44 | });
45 |
46 | it('Sign up - Success', function()
47 | {
48 | visit('/');
49 |
50 | cy.get('#login-sign-in-link').click();
51 |
52 | cy.get('#signup-link').click();
53 |
54 | cy.get('#login-username').clear().type(TEST.USER.TEST.USERNAME);
55 |
56 | cy.get('#login-password').clear().type(TEST.USER.TEST.PASSWORD);
57 |
58 | cy.get('#login-password-again').clear().type(TEST.USER.TEST.PASSWORD);
59 |
60 | cy.get('#login-buttons-password').click();
61 |
62 | cy.get('#login-name-link').should('contain', TEST.USER.TEST.USERNAME);
63 | });
64 |
65 | it('Sign in - Fail - Incorrect password', function()
66 | {
67 | visit('/');
68 |
69 | cy.get('#login-sign-in-link').click();
70 |
71 | cy.get('#login-username').clear().type(TEST.USER.TEST.USERNAME);
72 |
73 | cy.get('#login-password').clear().type('pass');
74 |
75 | cy.get('#login-buttons-password').click();
76 |
77 | cy.get('.message.error-message').should('contain', 'Incorrect password');
78 | });
79 |
80 | it('Sign in - Fail - User not found', function()
81 | {
82 | visit('/');
83 |
84 | cy.get('#login-sign-in-link').click();
85 |
86 | cy.get('#login-username').clear().type('user');
87 |
88 | cy.get('#login-password').clear().type('pass');
89 |
90 | cy.get('#login-buttons-password').click();
91 |
92 | cy.get('.message.error-message').should('contain', 'User not found');
93 | });
94 |
95 | it('Sign in - Success', function()
96 | {
97 | visit('/');
98 |
99 | doLogin();
100 | });
101 |
102 | it('Sign out', function()
103 | {
104 | visit('/');
105 |
106 | doLogout()
107 |
108 | cy.get('#login-sign-in-link').should('contain', 'Sign in');
109 | });
110 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/tests/navigation.test.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/cypress/integration/tests/navigation.test.js
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/tests/tasks.test.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/cypress/integration/tests/tasks.test.js
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/utilities/commons.js:
--------------------------------------------------------------------------------
1 | import {waitForMeteorSubscriptions} from '../../support/commands.js';
2 |
3 | /**
4 | * Wait for provided ms
5 | * @param timeMs {number}
6 | */
7 | export function wait(timeMs = 500)
8 | {
9 | cy.wait(timeMs);
10 | }
11 |
12 | /**
13 | * Subscription aware visit function
14 | * @param url {string}
15 | */
16 | export function visit(url)
17 | {
18 | cy.visit(url);
19 |
20 | waitForMeteorSubscriptions();
21 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/utilities/doLogin.js:
--------------------------------------------------------------------------------
1 | import {TEST} from '../constants/constantsForTests.js';
2 | import {waitForMeteorSubscriptions} from '../../support/commands.js';
3 |
4 | /**
5 | * Login with provided user name and password (subscription aware)
6 | * @param username {string}
7 | * @param password {string}
8 | */
9 | export function doLogin(username = TEST.USER.DEMO.USERNAME, password = TEST.USER.DEMO.PASSWORD)
10 | {
11 | cy.visit('/');
12 |
13 | cy.get('#login-sign-in-link').click();
14 |
15 | cy.get('#login-username').clear().type(TEST.USER.TEST.USERNAME);
16 |
17 | cy.get('#login-password').clear().type(TEST.USER.TEST.PASSWORD);
18 |
19 | cy.get('#login-buttons-password').click();
20 |
21 | cy.get('#login-name-link').should('contain', TEST.USER.TEST.USERNAME);
22 |
23 | cy.window().its('Meteor').invoke('userId').should((userId) =>
24 | {
25 | expect(userId).not.to.be.null;
26 | });
27 |
28 | waitForMeteorSubscriptions();
29 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/integration/utilities/doLogout.js:
--------------------------------------------------------------------------------
1 | export function doLogout()
2 | {
3 | cy.window().then((win) =>
4 | {
5 | win.Meteor.logout();
6 | });
7 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | ///
2 | // ***********************************************************
3 | // This example plugins/index.js can be used to load plugins
4 | //
5 | // You can change the location of this file or turn off loading
6 | // the plugins file with the 'pluginsFile' configuration option.
7 | //
8 | // You can read more here:
9 | // https://on.cypress.io/plugins-guide
10 | // ***********************************************************
11 |
12 | // This function is called when a project is opened or re-opened (e.g. due to
13 | // the project's config changing)
14 |
15 | /**
16 | * @type {Cypress.PluginConfig}
17 | */
18 | module.exports = (on, config) =>
19 | {
20 | // `on` is used to hook into various events Cypress emits
21 | // `config` is the resolved Cypress config
22 | };
23 |
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/readme.md:
--------------------------------------------------------------------------------
1 | # E2E Tests
2 |
3 | This folder contains e2e tests
4 |
5 | ### Test Strategy
6 |
7 | Some test may require dummy data, the responsibility of dummy data should not be on cypress. The test data is different
8 | from dummy data. Test data will be stored and modified by cypress.
9 |
10 | ### Test Plan
11 |
12 | 1. Authentication
13 | - [x] Sign up - Fail - Passwords must match
14 | - [x] Sign up - Fail - Password must long
15 | - [x] Sign up - Success
16 | - [x] Sign in - Fail - Incorrect password
17 | - [x] Sign in - Fail - User not found
18 | - [x] Sign in - Success
19 | - [ ] Sign out
20 |
21 | 1. Navigation
22 | - [ ] Go to tasks page
23 | - [ ] Go to about page
24 |
25 | 1. Task
26 | - [ ] Guest can not see the new task form
27 | - [ ] Insert a new task
28 | - [ ] Update a task as checked
29 | - [ ] Update a task as unchecked
30 | - [ ] Update a task as private
31 | - [ ] Update a task as public
32 | - [ ] Remove a task
33 | - [ ] Check if a task is expired
34 |
35 | ### How to start tests
36 |
37 | Type ```npm run cypress``` into terminal
38 |
39 | ### Location of tests
40 |
41 | If cypress cache exists after file change, delete
42 | ~/Library/Application Support/Cypress/cy
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
27 | Cypress.Commands.add('allSubscriptionsReady', (options = {}) =>
28 | {
29 | const log = {
30 | name: 'allSubscriptionsReady'
31 | };
32 |
33 | const getValue = () =>
34 | {
35 | return cy.state('window').DDP._allSubscriptionsReady();
36 | };
37 |
38 | const resolveValue = () =>
39 | {
40 | return Cypress.Promise.try(getValue).then((value) =>
41 | {
42 | return cy.verifyUpcomingAssertions(value, options, {
43 | onRetry: resolveValue
44 | });
45 | });
46 | };
47 |
48 | return resolveValue().then((value) =>
49 | {
50 | Cypress.log(log);
51 | return value;
52 | });
53 | });
54 |
55 | export function waitForMeteorSubscriptions()
56 | {
57 | cy.window().its('DDP').invoke('_allSubscriptionsReady').should((ready) =>
58 | {
59 | expect(ready).to.be.true;
60 | });
61 | }
62 |
--------------------------------------------------------------------------------
/complex-todos-svelte/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands';
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/eventEmitter/eventEmitterService.js:
--------------------------------------------------------------------------------
1 | const EventEmitter = require('events');
2 |
3 | export const eventEmitter = new EventEmitter();
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/eventEmitter/server/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/imports/modules/eventEmitter/server/index.js
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/database/tasks.js:
--------------------------------------------------------------------------------
1 | import {Mongo} from 'meteor/mongo';
2 | import SimpleSchema from 'simpl-schema';
3 |
4 | const Tasks = new Mongo.Collection('tasks');
5 |
6 | Tasks.attachSchema(new SimpleSchema({
7 | text: {
8 | type: String
9 | },
10 | createdAt: {
11 | type: Date
12 | },
13 | owner: {
14 | type: String
15 | },
16 | username: {
17 | type: String
18 | },
19 | checked: {
20 | type: Boolean,
21 | optional: true
22 | },
23 | expired: {
24 | type: Boolean,
25 | optional: true
26 | },
27 | private: {
28 | type: Boolean,
29 | optional: true
30 | }
31 | }));
32 |
33 | export {Tasks};
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/enums/methodNames.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {{UPDATE_AS_CHECKED: string, UPDATE_AS_PRIVATE: string, REMOVE: string, INSERT: string}}
3 | */
4 | export const TASKS_METHOD = {
5 | INSERT: 'tasks.insert',
6 | REMOVE: 'tasks.remove',
7 | UPDATE_AS_CHECKED: 'tasks.update.asChecked',
8 | UPDATE_AS_PRIVATE: 'tasks.update.asPrivate'
9 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/enums/publications.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {{TASKS: string}}
3 | */
4 | export const TASKS_PUBLICATION = {
5 | TASKS: 'tasks'
6 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/enums/rateLimitter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef RATE_LIMITER
3 | * @type {{TIME_INTERVAL: number, REQUEST_COUNT: number}}
4 | */
5 | export const RATE_LIMITER = {
6 | REQUEST_COUNT: 5,
7 | TIME_INTERVAL: 1000
8 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/server/index.js:
--------------------------------------------------------------------------------
1 | import './tasks.ensureIndexes.js';
2 | import './tasks.events.js';
3 | import './tasks.guards.js';
4 | import './tasks.publications.js';
5 | import './tasks.rateLimiter.js';
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/server/tasks.ensureIndexes.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/imports/modules/tasks/server/tasks.ensureIndexes.js
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/server/tasks.events.js:
--------------------------------------------------------------------------------
1 | import {eventEmitter} from '../../eventEmitter/eventEmitterService.js';
2 | import {EVENT} from '../../../shared/enums/events.js';
3 | import {log} from '../../../shared/logger/logger.js';
4 | import {taskRepository} from '../taskRepository.js';
5 |
6 | eventEmitter.on(EVENT.TASKS.EXPIRE, ({maxDate}) =>
7 | {
8 | log.debug(`Event ${EVENT.TASKS.EXPIRE} triggered`);
9 |
10 | taskRepository.updateMany({createdAt: {$lte: maxDate}}, {$set: {expired: true}});
11 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/server/tasks.guards.js:
--------------------------------------------------------------------------------
1 | import {Tasks} from '../database/tasks.js';
2 |
3 | Tasks.allow({
4 | insert()
5 | {
6 | return false;
7 | },
8 | update()
9 | {
10 | return false;
11 | },
12 | remove()
13 | {
14 | return false;
15 | }
16 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/server/tasks.publications.js:
--------------------------------------------------------------------------------
1 | import {Meteor} from 'meteor/meteor';
2 | import {Tasks} from '../database/tasks.js';
3 | import {TASKS_PUBLICATION} from '../enums/publications.js';
4 |
5 | Meteor.publish(TASKS_PUBLICATION.TASKS, function tasksPublication()
6 | {
7 | return Tasks.find({
8 | $or: [
9 | {private: {$ne: true}},
10 | {owner: this.userId}
11 | ]
12 | });
13 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/server/tasks.rateLimiter.js:
--------------------------------------------------------------------------------
1 | import {_} from 'meteor/underscore';
2 | import {RATE_LIMITER} from '../enums/rateLimitter.js';
3 | import {tasksInsert, tasksRemove, tasksUpdateAsChecked, tasksUpdateAsPrivate} from '../tasks.methods.js';
4 |
5 | const LISTS_METHODS = _.pluck([
6 | tasksInsert,
7 | tasksRemove,
8 | tasksUpdateAsChecked,
9 | tasksUpdateAsPrivate
10 | ], 'name');
11 |
12 | DDPRateLimiter.addRule({
13 | name(name)
14 | {
15 | return _.contains(LISTS_METHODS, name);
16 | },
17 | // Rate limit per connection
18 | connectionId()
19 | {
20 | return true;
21 | }
22 | }, RATE_LIMITER.REQUEST_COUNT, RATE_LIMITER.TIME_INTERVAL);
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/taskRepository.js:
--------------------------------------------------------------------------------
1 | import {BaseRepository} from '../../shared/repository/baseRepository.js';
2 | import {Tasks} from './database/tasks.js';
3 |
4 | class TaskRepository extends BaseRepository
5 | {
6 | /**
7 | * @constructor
8 | */
9 | constructor()
10 | {
11 | super(Tasks);
12 | }
13 | }
14 |
15 | export const taskRepository = new TaskRepository();
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/taskService.js:
--------------------------------------------------------------------------------
1 | import {taskRepository} from './taskRepository.js';
2 | import {Meteor} from 'meteor/meteor';
3 | import {User} from '../../shared/functions/user.js';
4 |
5 | class TaskService
6 | {
7 | /**
8 | * @param taskId {string}
9 | * @returns {*}
10 | */
11 | getTask(taskId)
12 | {
13 | return taskRepository.findOne(taskId);
14 | }
15 |
16 | /**
17 | * @param text {string}
18 | * @returns {string}
19 | */
20 | insert(text)
21 | {
22 | return taskRepository.insert({
23 | text,
24 | createdAt: new Date(),
25 | owner: User._id,
26 | username: User.details.username
27 | });
28 | }
29 |
30 | /**
31 | * @param taskId
32 | */
33 | remove(taskId)
34 | {
35 | const task = this.getTask(taskId);
36 |
37 | if(task.private && task.owner !== User._id)
38 | {
39 | // If the task is private, make sure only the owner can delete it
40 | throw new Meteor.Error('not-authorized');
41 | }
42 |
43 | taskRepository.remove(taskId);
44 | }
45 |
46 | /**
47 | * @param taskId {string}
48 | * @param setChecked
49 | */
50 | updateAsChecked(taskId, setChecked)
51 | {
52 | const task = this.getTask(taskId);
53 |
54 | if(task.private && task.owner !== User._id)
55 | {
56 | // If the task is private, make sure only the owner can check it off
57 | throw new Meteor.Error('not-authorized');
58 | }
59 |
60 | taskRepository.update(taskId, {$set: {checked: setChecked}});
61 | }
62 |
63 | /**
64 | * @param taskId {string}
65 | * @param setPrivate {boolean}
66 | */
67 | updateAsPrivate(taskId, setPrivate)
68 | {
69 | const task = this.getTask(taskId);
70 |
71 | // Make sure only the task owner can make a task private
72 | if(task.owner !== User._id)
73 | {
74 | throw new Meteor.Error('not-authorized');
75 | }
76 |
77 | taskRepository.update(taskId, {$set: {private: setPrivate}});
78 | }
79 | }
80 |
81 | export const taskService = new TaskService();
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/tasks.methods.js:
--------------------------------------------------------------------------------
1 | import {ValidatedMethod} from 'meteor/mdg:validated-method';
2 | import SimpleSchema from 'simpl-schema';
3 | import {taskService} from './taskService.js';
4 | import {LoggedInMixin} from '../../shared/mixins/LoggedInMixin.js';
5 | import {TASKS_METHOD} from './enums/methodNames.js';
6 |
7 | /**
8 | * @type {ValidatedMethod}
9 | */
10 | export const tasksInsert = new ValidatedMethod({
11 | name: TASKS_METHOD.INSERT,
12 | mixins: [LoggedInMixin],
13 | validate: new SimpleSchema({
14 | text: {type: String}
15 | }).validator(),
16 | /**
17 | * @param text {string}
18 | * @returns {string}
19 | */
20 | run({text})
21 | {
22 | return taskService.insert(text);
23 | }
24 | });
25 |
26 | /**
27 | * @type {ValidatedMethod}
28 | */
29 | export const tasksRemove = new ValidatedMethod({
30 | name: TASKS_METHOD.REMOVE,
31 | mixins: [LoggedInMixin],
32 | validate: new SimpleSchema({
33 | taskId: {type: String}
34 | }).validator(),
35 | /**
36 | * @param taskId {string}
37 | */
38 | run({taskId})
39 | {
40 | taskService.remove(taskId);
41 | }
42 | });
43 |
44 | /**
45 | * @type {ValidatedMethod}
46 | */
47 | export const tasksUpdateAsChecked = new ValidatedMethod({
48 | name: TASKS_METHOD.UPDATE_AS_CHECKED,
49 | mixins: [LoggedInMixin],
50 | validate: new SimpleSchema({
51 | taskId: {type: String},
52 | setChecked: {type: Boolean}
53 | }).validator(),
54 | /**
55 | * @param taskId {string}
56 | * @param setChecked {boolean}
57 | */
58 | run({taskId, setChecked})
59 | {
60 | taskService.updateAsChecked(taskId, setChecked);
61 | }
62 | });
63 |
64 | /**
65 | * @type {ValidatedMethod}
66 | */
67 | export const tasksUpdateAsPrivate = new ValidatedMethod({
68 | name: TASKS_METHOD.UPDATE_AS_PRIVATE,
69 | mixins: [LoggedInMixin],
70 | validate: new SimpleSchema({
71 | taskId: {type: String},
72 | setPrivate: {type: Boolean}
73 | }).validator(),
74 | /**
75 | * @param taskId {string}
76 | * @param setPrivate {boolean}
77 | */
78 | run({taskId, setPrivate})
79 | {
80 | taskService.updateAsPrivate(taskId, setPrivate);
81 | }
82 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/tasks/tasks.methods.test.js:
--------------------------------------------------------------------------------
1 | import {assert} from 'chai';
2 | import {taskRepository} from './taskRepository.js';
3 | import {tasksInsert, tasksRemove, tasksUpdateAsChecked} from './tasks.methods.js';
4 | import {UNIT_TEST} from '../../../tests/enums/users.js';
5 |
6 | describe('Tasks methods', () =>
7 | {
8 | const userId = UNIT_TEST.USER_ID;
9 | let taskId;
10 |
11 | beforeEach(function()
12 | {
13 | taskRepository.remove({});
14 | });
15 |
16 | it('tasksInsert', () =>
17 | {
18 | // Set up method arguments and context
19 | const context = {userId};
20 |
21 | const args = {text: 'new task'};
22 |
23 | // Execute the method
24 | tasksInsert._execute(context, args);
25 |
26 | // Verify that the method does what we expected
27 | assert.equal(taskRepository.find().count(), 1);
28 | });
29 |
30 | it('tasksRemove', () =>
31 | {
32 | // Set up method arguments and context
33 | const context = {userId};
34 |
35 | taskId = taskRepository.insert({
36 | text: 'test task',
37 | createdAt: new Date(),
38 | owner: userId,
39 | username: 'john doe'
40 | });
41 |
42 | const args = {taskId};
43 |
44 | // Execute the method
45 | tasksRemove._execute(context, args);
46 |
47 | // Verify that the method does what we expected
48 | assert.equal(taskRepository.find().count(), 0);
49 | });
50 |
51 | it('tasksUpdateAsChecked', () =>
52 | {
53 | // Set up method arguments and context
54 | const context = {userId};
55 |
56 | taskId = taskRepository.insert({
57 | text: 'test task',
58 | createdAt: new Date(),
59 | owner: userId,
60 | username: 'john doe'
61 | });
62 |
63 | const args = {
64 | taskId: taskId,
65 | setChecked: true
66 | };
67 |
68 | // Execute the method
69 | tasksUpdateAsChecked._execute(context, args);
70 |
71 | let task = taskRepository.findOne(taskId);
72 |
73 | // Verify that the method does what we expected
74 | assert.equal(task.checked, true);
75 | });
76 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/users/enums/cacheKey.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {{USER: string}}
3 | */
4 | export const CACHE_KEY = {
5 | USER: 'user'
6 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/users/server/index.js:
--------------------------------------------------------------------------------
1 | import './user.cache.js';
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/modules/users/server/user.cache.js:
--------------------------------------------------------------------------------
1 | import {memcache} from '../../../../server/modules/cache/cacheService.js';
2 | import {CACHE_KEY} from '../enums/cacheKey.js';
3 | import {Meteor} from 'meteor/meteor';
4 |
5 | class UserCache
6 | {
7 | /**
8 | * Returns cached profile info
9 | * @locus server
10 | * @param userId {string}
11 | * @returns {object|null}
12 | */
13 | get(userId)
14 | {
15 | if(memcache.hasKey(`${CACHE_KEY.USER}.${userId}`))
16 | {
17 | return memcache.getValue(`${CACHE_KEY.USER}.${userId}`);
18 | }
19 | else
20 | {
21 | let userFromDB = Meteor.users.findOne(userId);
22 |
23 | if(userFromDB !== null)
24 | {
25 | memcache.setValue(`${CACHE_KEY.USER}.${userId}`, userFromDB);
26 | }
27 |
28 | return userFromDB;
29 | }
30 | }
31 | /**
32 | * Adds provided user to the cache
33 | * @locus server
34 | * @param user {object}
35 | */
36 | cache(user)
37 | {
38 | memcache.setValue(`${CACHE_KEY.USER}.${user._id}`, user);
39 | }
40 | /**
41 | * Removes cache of provided profile
42 | * @locus server
43 | * @param userId {string}
44 | */
45 | remove(userId)
46 | {
47 | memcache.remove(`${CACHE_KEY.USER}.${userId}`);
48 | }
49 | }
50 |
51 | export const userCache = new UserCache();
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/enums/events.js:
--------------------------------------------------------------------------------
1 | export const EVENT = {
2 | TASKS: {
3 | EXPIRE: 'tasks.expire'
4 | }
5 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/functions/bound.js:
--------------------------------------------------------------------------------
1 | import {Meteor} from 'meteor/meteor';
2 |
3 | /**
4 | * Used in callbacks which should be called with Meteor context
5 | */
6 | export const bound = Meteor.bindEnvironment((callback) =>
7 | {
8 | callback();
9 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/functions/isDefined.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param reference {*}
3 | * @return {boolean}
4 | */
5 | export const isUndefined = (reference) =>
6 | {
7 | return reference === void 0;
8 | };
9 |
10 | /**
11 | * @param reference {*}
12 | * @return {boolean}
13 | */
14 | export const isDefined = (reference) =>
15 | {
16 | return !isUndefined(reference);
17 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/functions/lang.js:
--------------------------------------------------------------------------------
1 | import {TAPi18n} from 'meteor/tap:i18n';
2 |
3 | /**
4 | * @param key {string}
5 | * @param options {*}
6 | * @return {*}
7 | */
8 | export const lang = (key, options = '') =>
9 | {
10 | return TAPi18n.__(key, options);
11 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/functions/user.js:
--------------------------------------------------------------------------------
1 | import {Meteor} from 'meteor/meteor';
2 | import {UNIT_TEST} from '../../../tests/enums/users.js';
3 |
4 | /**
5 | * @type {{readonly details: (*), readonly _id: *}}
6 | */
7 | export const User = {
8 | get _id()
9 | {
10 | if(Meteor.isTest)
11 | {
12 | return UNIT_TEST.USER_ID;
13 | }
14 |
15 | return Meteor.userId();
16 | },
17 | get details()
18 | {
19 | if(Meteor.isTest)
20 | {
21 | return {
22 | _id: UNIT_TEST.USER_ID,
23 | username: UNIT_TEST.USERNAME
24 | };
25 | }
26 |
27 | if(Meteor.isClient)
28 | {
29 | return Meteor.users.findOne(this._id);
30 | }
31 | else
32 | {
33 | const {userCache} = require('../../modules/users/server/user.cache.js');
34 | return userCache.get(this._id);
35 | }
36 | }
37 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/mixins/LoggedInMixin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Mixin for validated methods
3 | * @param methodOptions {object}
4 | * @returns {*}
5 | * @constructor
6 | */
7 | export const LoggedInMixin = function(methodOptions)
8 | {
9 | const runFunction = methodOptions.run;
10 |
11 | methodOptions.run = function()
12 | {
13 | if(!this.userId)
14 | {
15 | throw new Meteor.Error(`Only users can run this`);
16 | }
17 |
18 | return runFunction.call(this, ...arguments);
19 | };
20 |
21 | return methodOptions;
22 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/imports/shared/utilities/dateUtility.js:
--------------------------------------------------------------------------------
1 | export class DateUtility
2 | {
3 | /**
4 | * @param day {number}
5 | * @returns {Date}
6 | */
7 | static beforeDays(day = 1)
8 | {
9 | let date = new Date();
10 | date.setDate(date.getDate() - day);
11 |
12 | return date;
13 | }
14 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "complex-todos-svelte",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor -s settings.json --port 3000",
6 | "test": "TEST_WATCH=1 meteor -s settings.json --port 3000 test --driver-package meteortesting:mocha",
7 | "cypress": "cypress open",
8 | "visualize": "meteor -s settings.json --production --extra-packages bundle-visualizer",
9 | "deploy": "cd .deploy && mup deploy"
10 | },
11 | "dependencies": {
12 | "@babel/runtime": "^7.15.3",
13 | "bcrypt": "^5.0.1",
14 | "jquery": "^3.4.1",
15 | "meteor-node-stubs": "^1.0.0",
16 | "node-cache": "^5.1.2",
17 | "simpl-schema": "^1.10.2",
18 | "svelte": "^3.31.2",
19 | "svelte-routing": "^1.6.0"
20 | },
21 | "meteor": {
22 | "mainModule": {
23 | "client": "client/main.js",
24 | "server": "server/main.js"
25 | },
26 | "testModule": "tests/main.js"
27 | },
28 | "devDependencies": {
29 | "chai": "^4.2.0",
30 | "cypress": "^7.3.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | patreon: dr_dimitru
4 | custom: https://paypal.me/veliovgroup
5 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/.github/ISSUE_TEMPLATE:
--------------------------------------------------------------------------------
1 | ### I'm having an issue:
2 | - Give an expressive description of what is went wrong
3 | - Version of `ostrio:logger` you're experiencing this issue
4 | - Version of `Meteor` you're experiencing this issue
5 | - Is it *Server* or *Client* (*Browser*) issue?
6 | - Browser name and its version (Chrome, Firefox, Safari, etc.)?
7 | - Platform name and its version (Win, Mac, Linux)?
8 | - If you're getting an error or exception, please provide its full stack-trace as plain-text or screenshot
9 |
10 | ### I have a suggestion:
11 | - Describe your feature / request
12 | - How you going to use it? Give a usage example(s)
13 |
14 | ### Documentation is missing something or incorrect (have typos, etc.):
15 | - Give an expressive description what you have changed/added and why
16 | - Make sure you're using correct markdown markup
17 | - Make sure all code blocks starts with tripple ``` (*backtick*) and have a syntax tag, for more read [this docs](https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting)
18 | - Post your addition/changes in issue, we will manage it
19 |
20 | ## Thank you, and do not forget to get rid of this default message
21 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/.github/PULL_REQUEST_TEMPLATE:
--------------------------------------------------------------------------------
1 | Thank you for contribution. Before you go:
2 | 1. Make sure you're using `spaces` for indentation
3 | 2. Make sure all new code is documented in-code-docs
4 | 3. Make sure new features, or changes in behavior is documented in README.md and/or other docs materials
5 | 4. Make sure this PR was previously discussed, if not create new issue ticket for your PR
6 | 5. Give an expressive description what you have changed/added and why
7 |
8 | Thank you for making this package better :)
9 |
10 | ## Do not forget to get rid of this default message
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .npm
3 | node_modules
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/.versions:
--------------------------------------------------------------------------------
1 | allow-deny@1.1.0
2 | babel-compiler@7.6.0
3 | babel-runtime@1.3.0
4 | base64@1.0.11
5 | binary-heap@1.0.11
6 | boilerplate-generator@1.6.0
7 | callback-hook@1.1.0
8 | check@1.3.1
9 | ddp@1.4.0
10 | ddp-client@2.3.3
11 | ddp-common@1.4.0
12 | ddp-server@2.2.0
13 | diff-sequence@1.1.1
14 | dynamic-import@0.5.0
15 | ecmascript@0.12.4
16 | ecmascript-runtime@0.7.0
17 | ecmascript-runtime-client@0.8.0
18 | ecmascript-runtime-server@0.7.1
19 | ejson@1.1.0
20 | fetch@0.1.0
21 | geojson-utils@1.0.10
22 | id-map@1.1.0
23 | inter-process-messaging@0.1.0
24 | local-test:ostrio:logger@2.0.8
25 | logging@1.1.20
26 | meteor@1.9.2
27 | minimongo@1.4.5
28 | modern-browsers@0.1.3
29 | modules@0.13.0
30 | modules-runtime@0.10.3
31 | mongo@1.6.0
32 | mongo-decimal@0.1.0
33 | mongo-dev-server@1.1.0
34 | mongo-id@1.0.7
35 | npm-mongo@3.1.1
36 | ordered-dict@1.1.0
37 | ostrio:logger@2.0.8
38 | promise@0.11.2
39 | random@1.1.0
40 | reactive-var@1.0.11
41 | reload@1.2.0
42 | retry@1.1.0
43 | routepolicy@1.1.0
44 | socket-stream-client@0.2.2
45 | tinytest@1.1.0
46 | tracker@1.2.0
47 | underscore@1.0.10
48 | webapp@1.7.1
49 | webapp-hashing@1.0.9
50 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 | For full package history, please see [releases at GitHub](https://github.com/VeliovGroup/Meteor-logger/releases)
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project, and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at info@veliovgroup.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ### I'm having an issue:
2 | 1. Search [issues](https://github.com/VeliovGroup/Meteor-logger/issues?utf8=✓&q=is%3Aissue), maybe your issue is already solved
3 | 2. Before submitting an issue make sure it's only related to `ostrio:logger` package
4 | 3. If your issue is not solved:
5 | - Give an expressive description of what is gone wrong
6 | - Version of `ostrio:logger` you're experiencing this issue
7 | - Version of `Meteor` you're experiencing this issue
8 | - Is it *Server* or *Client* (*Browser*) issue?
9 | - Browser name and its version (Chrome, Firefox, Safari, etc.)?
10 | - Platform name and its version (Win, Mac, Linux)?
11 | - If you're getting an error or exception, please provide its full stack-trace as plain-text or screenshot
12 |
13 | ### I have a suggestion:
14 | 1. PRs are always welcome - [send a PR](https://github.com/VeliovGroup/Meteor-logger/pulls)
15 | 2. If you're can not send a PR for some reason:
16 | - Create a new issue ticket
17 | - Describe your feature / request
18 | - How are you going to use it? Give a usage example(s)
19 |
20 | ### Documentation is missing something or incorrect (have typos, etc.):
21 | 1. PRs are always welcome - [send a PR](https://github.com/VeliovGroup/Meteor-logger/pulls)
22 | 2. If you're can not send a PR to docs for some reason:
23 | - Create a new issue ticket
24 | - Give an expressive description what you have changed/added and why
25 | - Make sure you're using correct markdown markup
26 | - Make sure all code blocks starts with triple ``` (*backtick*) and have a syntax tag, for more read [this docs](https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting)
27 | - Post addition/changes as issue ticket, we will manage it
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/HISTORY.md:
--------------------------------------------------------------------------------
1 | History
2 | =========
3 | For full package history, please see [releases at GitHub](https://github.com/VeliovGroup/Meteor-logger/releases)
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019, dr.dimitru (Dmitry A.; Veliov Group, LLC)
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms,
5 | with or without modification, are permitted provided
6 | that the following conditions are met:
7 |
8 | 1. Redistributions of source code must retain the
9 | above copyright notice, this list of conditions
10 | and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the
13 | above copyright notice, this list of conditions and
14 | the following disclaimer in the documentation and/or
15 | other materials provided with the distribution.
16 |
17 | 3. Neither the name of the copyright holder nor the
18 | names of its contributors may be used to endorse or
19 | promote products derived from this software without
20 | specific prior written permission.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/meteor-logger.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/packages/logger/meteor-logger.jpg
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/logger/package.js:
--------------------------------------------------------------------------------
1 | Package.describe({
2 | name: 'ostrio:logger',
3 | version: '2.0.9', // couldn't change the version because the other dependencies of logger
4 | summary: 'Logging: isomorphic driver with support of MongoDB, File (FS) and Console',
5 | git: 'https://github.com/VeliovGroup/Meteor-logger',
6 | documentation: 'README.md'
7 | });
8 |
9 | Package.onUse((api) => {
10 | api.versionsFrom('1.4');
11 | api.use(['ecmascript', 'reactive-var', 'check'], ['client', 'server']);
12 | api.mainModule('logger.js', ['client', 'server']);
13 | });
14 |
15 | Package.onTest((api) => {
16 | api.use('tinytest');
17 | api.use(['ecmascript', 'underscore', 'ostrio:logger']);
18 | api.addFiles('logger-tests.js');
19 | });
20 |
--------------------------------------------------------------------------------
/complex-todos-svelte/packages/readme.md:
--------------------------------------------------------------------------------
1 | # Custom & Local Packages
2 | If you want you can write your own Meteor packages or change a current one.
3 |
4 | For example, I found a small bug in ```ostrio:logger``` and put that package into the folder.
5 | Then, I fixed it for my own purpose.
6 |
--------------------------------------------------------------------------------
/complex-todos-svelte/screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/screenshot.jpg
--------------------------------------------------------------------------------
/complex-todos-svelte/server/init.js:
--------------------------------------------------------------------------------
1 | import {log} from '../imports/shared/logger/logger.js';
2 | import {Jobs} from 'meteor/msavin:sjobs';
3 | import {JOB} from './shared/enums/job.js';
4 |
5 | /**
6 | * Initialize server at startup
7 | * @locus server
8 | */
9 | class ServerInit
10 | {
11 | /**
12 | * @constructor
13 | */
14 | constructor()
15 | {
16 | log.info('Server is starting');
17 |
18 | this.initializeJobs();
19 | }
20 |
21 | /**
22 | * Run added jobs
23 | */
24 | initializeJobs()
25 | {
26 | Jobs.run(JOB.TASKS.EXPIRE, {
27 | in: {
28 | days: 7
29 | }
30 | }
31 | );
32 | }
33 | }
34 |
35 | /**
36 | * No need to export it
37 | * It will only run once on server initialize
38 | */
39 | Meteor.startup(function()
40 | {
41 | new ServerInit;
42 | });
43 |
--------------------------------------------------------------------------------
/complex-todos-svelte/server/main.js:
--------------------------------------------------------------------------------
1 | import './modules.js';
2 | import './init.js';
3 |
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules.js:
--------------------------------------------------------------------------------
1 | import '../imports/modules/tasks/server';
2 | import '../imports/modules/users/server';
3 |
4 | import './modules/cache/server';
5 | import './modules/dummies/server';
6 | import './modules/jobs/server';
7 | import './modules/migrations/server';
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/cache/server/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/complex-todos-svelte/server/modules/cache/server/index.js
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/dummies/dummiesService.js:
--------------------------------------------------------------------------------
1 | import {log} from '../../../imports/shared/logger/logger.js';
2 | import {DUMMY_USERS} from './fixtures/dummyUsers.js';
3 | import {DUMMY_TASKS} from './fixtures/dummyTasks.js';
4 | import {taskRepository} from '../../../imports/modules/tasks/taskRepository.js';
5 | import {Mongo} from 'meteor/mongo';
6 |
7 | /**
8 | * This service adds dummy data to test all features including franchise and admin actions
9 | * the user which will be added is an admin account. Thus, the tester can check everything
10 | * @development
11 | * @locus server
12 | */
13 | class DummiesService
14 | {
15 | /**
16 | * @constructor
17 | * @development
18 | * @locus server
19 | */
20 | constructor()
21 | {
22 | if(Meteor.isProduction)
23 | {
24 | return true;
25 | }
26 |
27 | this.tasks = DUMMY_TASKS;
28 | this.users = DUMMY_USERS;
29 | }
30 |
31 | /**
32 | * Clears all database
33 | * @development
34 | * @locus server
35 | */
36 | clearDatabase()
37 | {
38 | log.debug(__fn);
39 |
40 | const collections = Mongo.Collection.getAll();
41 |
42 | // Add special collections here to prevent restart to start the tests
43 | const restrictedCollections = ['roles', 'migrations', 'jobs_data', 'jobs_dominator_3'];
44 |
45 | collections.forEach(collection =>
46 | {
47 | if(!restrictedCollections.includes(collection))
48 | {
49 | collection.instance.remove({});
50 | }
51 | });
52 | }
53 |
54 | /**
55 | * Inserts dummy data
56 | * @development
57 | * @locus server
58 | * @returns {boolean}
59 | */
60 | insertDummyData()
61 | {
62 | log.debug(__fn);
63 |
64 | this._insertTasks();
65 | this._insertUsers();
66 | }
67 |
68 | /**
69 | * @development
70 | * @locus server
71 | * @private
72 | */
73 | _insertTasks()
74 | {
75 | log.debug(__fn);
76 |
77 | this.tasks.forEach(task =>
78 | {
79 | taskRepository.insertBulk(task);
80 | });
81 |
82 | taskRepository.executeBulk();
83 | }
84 |
85 | /**
86 | * @development
87 | * @locus server
88 | * @private
89 | */
90 | _insertUsers()
91 | {
92 | log.debug(__fn);
93 |
94 | this.users.forEach(user =>
95 | {
96 | Meteor.users.insert(user);
97 | });
98 | }
99 | }
100 |
101 | export const dummiesService = new DummiesService();
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/dummies/fixtures/dummyTasks.js:
--------------------------------------------------------------------------------
1 | export const DUMMY_TASKS = [{
2 | '_id': 't6xnFenfSrXFkdTek',
3 | 'text': 'expired task',
4 | 'createdAt': new Date('2021-05-05'),
5 | 'owner': 'jtX6xqGj29tq5Nhdh',
6 | 'username': 'gunce',
7 | 'expired': 'true'
8 | }, {
9 | '_id': 'NnNQmTdR7LbQrCePr',
10 | 'text': 'new task',
11 | 'createdAt': new Date(),
12 | 'owner': 'jtX6xqGj29tq5Nhdh',
13 | 'username': 'gunce'
14 | }, {
15 | '_id': 'oYtokZEpZu4SRgQcF',
16 | 'text': 'completed task',
17 | 'createdAt': new Date(),
18 | 'owner': 'jtX6xqGj29tq5Nhdh',
19 | 'username': 'gunce',
20 | 'checked': true
21 | }, {
22 | '_id': 'pPRcej6wE3uGYWHJq',
23 | 'text': 'private task',
24 | 'createdAt': new Date(),
25 | 'owner': 'jtX6xqGj29tq5Nhdh',
26 | 'username': 'gunce',
27 | 'private': true
28 | }];
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/dummies/fixtures/dummyUsers.js:
--------------------------------------------------------------------------------
1 | export const DUMMY_USERS = [{
2 | '_id': 'jtX6xqGj29tq5Nhdh',
3 | 'services': {
4 | 'password': {
5 | 'bcrypt': '$2b$10$tzdAErrtFnBVIe/xyazlZe.q5DUUOVBx8iZXftOXwiudsJRtPaiye'
6 | }
7 | },
8 | 'username': 'gunce'
9 | }];
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/dummies/readme.md:
--------------------------------------------------------------------------------
1 | # Dummy data
2 | This module helps us to insert and clear dummy data from database in development.
3 |
4 | This module has no use in production.
5 |
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/dummies/server/dummies.methods.js:
--------------------------------------------------------------------------------
1 | import {dummiesService} from '../dummiesService.js';
2 |
3 | /**
4 | * These methods and dummiesService are not working
5 | * in production server
6 | * @development
7 | * @locus server
8 | */
9 | Meteor.methods({
10 | /**
11 | * Clears database of the applications to run before tests
12 | * Some collections such as roles or migrations are scoped out
13 | * @development
14 | * @locus server
15 | */
16 | 'clear.database'()
17 | {
18 | dummiesService.clearDatabase();
19 | },
20 | /**
21 | * Inserts dummy data to mimic real world examples before tests
22 | * @development
23 | * @locus server
24 | */
25 | 'insert.dummy.data'()
26 | {
27 | dummiesService.insertDummyData();
28 | }
29 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/dummies/server/index.js:
--------------------------------------------------------------------------------
1 | import './dummies.methods.js';
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/jobs/server/index.js:
--------------------------------------------------------------------------------
1 | import './tasks.expire.js';
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/jobs/server/tasks.expire.js:
--------------------------------------------------------------------------------
1 | import {Jobs} from 'meteor/msavin:sjobs';
2 | import {DateUtility} from '../../../../imports/shared/utilities/dateUtility.js';
3 | import {eventEmitter} from '../../../../imports/modules/eventEmitter/eventEmitterService.js';
4 | import {EVENT} from '../../../../imports/shared/enums/events.js';
5 |
6 | Jobs.register({
7 | 'tasks.expire': function()
8 | {
9 | let date = DateUtility.beforeDays(1);
10 |
11 | eventEmitter.emit(EVENT.TASKS.EXPIRE, {maxDate: date});
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/migrations/database/migrations.js:
--------------------------------------------------------------------------------
1 | import SimpleSchema from 'simpl-schema';
2 |
3 | const Migrations = new Mongo.Collection('_migrations');
4 |
5 | Migrations.attachSchema(
6 | new SimpleSchema({
7 | version: {
8 | type: String,
9 | defaultValue: 0
10 | }
11 | })
12 | );
13 |
14 | export {Migrations};
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/migrations/migrationRepository.js:
--------------------------------------------------------------------------------
1 | import {BaseRepository} from '../../../imports/shared/repository/baseRepository.js';
2 | import {Migrations} from './database/migrations.js';
3 |
4 | /**
5 | * @locus server
6 | */
7 | class MigrationRepository extends BaseRepository
8 | {
9 | /**
10 | * @constructor
11 | * @locus server
12 | */
13 | constructor()
14 | {
15 | super(Migrations);
16 | }
17 | }
18 |
19 | export const migrationRepository = new MigrationRepository();
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/migrations/readme.md:
--------------------------------------------------------------------------------
1 | # Migration Files
2 | - This folder includes migration files.
3 | - All files have a version number
4 | - The version of the files are not same with the project version
5 | - Current migration version is located in the database
6 | - Current migration version will be increased after each successful migration
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/migrations/server/1.0.1.js:
--------------------------------------------------------------------------------
1 | import {migrationService} from '../migrationService.js';
2 | import {log} from '../../../../imports/shared/logger/logger.js';
3 |
4 | const version = '1.0.1';
5 | const migrationName = 'A log for migration';
6 |
7 | migrationService.addMigration(version, () =>
8 | {
9 | log.info(version, migrationName);
10 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/migrations/server/index.js:
--------------------------------------------------------------------------------
1 | import './migrations.guards.js';
2 |
3 | import './1.0.1.js';
--------------------------------------------------------------------------------
/complex-todos-svelte/server/modules/migrations/server/migrations.guards.js:
--------------------------------------------------------------------------------
1 | import {Migrations} from '../database/migrations.js';
2 |
3 | // This collection is defined on server side only but
4 | // We may want to use a server side database in the shared space
5 | // Thus, defining guards is always a good practice
6 | Migrations.allow({
7 | /**
8 | * @locus server
9 | * @returns {boolean}
10 | */
11 | insert()
12 | {
13 | return false;
14 | },
15 | /**
16 | * @locus server
17 | * @returns {boolean}
18 | */
19 | update()
20 | {
21 | return false;
22 | },
23 | /**
24 | * @locus server
25 | * @returns {boolean}
26 | */
27 | remove()
28 | {
29 | return false;
30 | }
31 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/server/shared/enums/job.js:
--------------------------------------------------------------------------------
1 | export const JOB = {
2 | TASKS: {
3 | EXPIRE: 'tasks.expire'
4 | }
5 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": {
3 | "log": [
4 | "ERROR",
5 | "FATAL",
6 | "WARN",
7 | "INFO",
8 | "TRACE",
9 | "DEBUG"
10 | ]
11 | }
12 | }
--------------------------------------------------------------------------------
/complex-todos-svelte/tests/enums/users.js:
--------------------------------------------------------------------------------
1 | export const UNIT_TEST = {
2 | USER_ID: 'ecFkNaLpNATJ8avNr',
3 | USERNAME: 'Unit test user'
4 | };
--------------------------------------------------------------------------------
/complex-todos-svelte/tests/main.js:
--------------------------------------------------------------------------------
1 | import assert from 'assert';
2 | import './package.json.test.js';
3 | import '../imports/modules/tasks/tasks.methods.test.js';
4 |
5 | describe('Meteor tests', function()
6 | {
7 | if(Meteor.isClient)
8 | {
9 | it('client is not server', function()
10 | {
11 | assert.strictEqual(Meteor.isServer, false);
12 | });
13 | }
14 |
15 | if(Meteor.isServer)
16 | {
17 | it('server is not client', function()
18 | {
19 | assert.strictEqual(Meteor.isClient, false);
20 | });
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/complex-todos-svelte/tests/package.json.test.js:
--------------------------------------------------------------------------------
1 | import assert from 'assert';
2 |
3 | describe('complex-todos-svelte', function()
4 | {
5 | it('package.json has correct name', async function()
6 | {
7 | const {name} = await import('../package.json');
8 | assert.strictEqual(name, 'complex-todos-svelte');
9 | });
10 | });
--------------------------------------------------------------------------------
/complex-todos-svelte/tests/readme.md:
--------------------------------------------------------------------------------
1 | # Unit Tests
2 |
3 | This folder contains unit tests
4 |
5 | ### Test Strategy
6 |
7 | Some test may require dummy data, the responsibility of dummy data should not be on test. The test data is different
8 | from dummy data. Test data will be stored and modified by tests.
9 |
10 | ### Test Plan
11 |
12 | 1. Application
13 | - [x] package.json has correct name
14 |
15 | 1. Meteor test
16 | - [x] client is not server
17 | - [x] server is not client
18 |
19 | 1. Task methods
20 | - [x] tasksInsert
21 | - [x] tasksRemove
22 | - [x] tasksUpdateAsChecked
23 | - [ ] tasksUpdateAsPrivate
24 |
25 | ### How to start tests
26 |
27 | Type ```npm test``` into terminal
28 |
29 | ### Location of tests
30 | The ```/test/main.js``` is the entry point of tests, and it
31 | includes tests that are related with application level
32 | Other test are located in their own module folder and
33 | imported into the ```main.js```
--------------------------------------------------------------------------------
/cordova/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
3 |
--------------------------------------------------------------------------------
/cordova/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/cordova/.meteor/cordova-plugins:
--------------------------------------------------------------------------------
1 | cordova-plugin-appsettings@1.0.2
2 | cordova-plugin-statusbar@2.4.3
3 | fairmanager-cordova-plugin-universal-links@https://github.com/pathable/plugin-universal-links.git#e0177fa5f7084a679c061aa25bc2949ea6d5f95a
4 | onesignal-cordova-plugin@2.8.0
5 |
--------------------------------------------------------------------------------
/cordova/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.5.1 # Packages every Meteor app needs to have
8 | mobile-experience@1.1.0 # Packages for a great mobile UX
9 | mongo@1.13.0 # The database Meteor supports right now
10 | reactive-var@1.0.11 # Reactive variable for tracker
11 |
12 | standard-minifier-css@1.7.4 # CSS minifier run for production mode
13 | standard-minifier-js@2.7.2 # JS minifier run for production mode
14 | es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers
15 | ecmascript@0.16.0 # Enable ECMAScript2015+ syntax in app code
16 | typescript@4.4.0 # Enable TypeScript syntax in .ts and .tsx modules
17 | shell-server@0.5.0 # Server-side component of the `meteor shell` command
18 |
19 | autopublish@1.0.7 # Publish all data to the clients (for prototyping)
20 | insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
21 | static-html@1.3.2 # Define static page content in .html files
22 | server-render@0.4.0 # Inject tags into the initial HTML
23 | accounts-base@2.2.0
24 | accounts-password@2.2.0
25 | react-meteor-data
26 |
--------------------------------------------------------------------------------
/cordova/.meteor/platforms:
--------------------------------------------------------------------------------
1 | android
2 | browser
3 | ios
4 | server
5 |
--------------------------------------------------------------------------------
/cordova/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@2.5.1
2 |
--------------------------------------------------------------------------------
/cordova/.meteor/versions:
--------------------------------------------------------------------------------
1 | accounts-base@2.2.0
2 | accounts-password@2.2.0
3 | allow-deny@1.1.0
4 | autopublish@1.0.7
5 | autoupdate@1.8.0
6 | babel-compiler@7.7.0
7 | babel-runtime@1.5.0
8 | base64@1.0.12
9 | binary-heap@1.0.11
10 | blaze-tools@1.1.2
11 | boilerplate-generator@1.7.1
12 | caching-compiler@1.2.2
13 | caching-html-compiler@1.2.1
14 | callback-hook@1.4.0
15 | check@1.3.1
16 | ddp@1.4.0
17 | ddp-client@2.5.0
18 | ddp-common@1.4.0
19 | ddp-rate-limiter@1.1.0
20 | ddp-server@2.5.0
21 | diff-sequence@1.1.1
22 | dynamic-import@0.7.2
23 | ecmascript@0.16.0
24 | ecmascript-runtime@0.8.0
25 | ecmascript-runtime-client@0.12.1
26 | ecmascript-runtime-server@0.11.0
27 | ejson@1.1.1
28 | email@2.2.0
29 | es5-shim@4.8.0
30 | fetch@0.1.1
31 | geojson-utils@1.0.10
32 | hot-code-push@1.0.4
33 | html-tools@1.1.2
34 | htmljs@1.1.0
35 | id-map@1.1.1
36 | insecure@1.0.7
37 | inter-process-messaging@0.1.1
38 | launch-screen@1.3.0
39 | localstorage@1.2.0
40 | logging@1.3.1
41 | meteor@1.10.0
42 | meteor-base@1.5.1
43 | minifier-css@1.6.0
44 | minifier-js@2.7.2
45 | minimongo@1.7.0
46 | mobile-experience@1.1.0
47 | mobile-status-bar@1.1.0
48 | modern-browsers@0.1.7
49 | modules@0.17.0
50 | modules-runtime@0.12.0
51 | mongo@1.13.0
52 | mongo-decimal@0.1.2
53 | mongo-dev-server@1.1.0
54 | mongo-id@1.0.8
55 | npm-mongo@3.9.1
56 | ordered-dict@1.1.0
57 | promise@0.12.0
58 | random@1.2.0
59 | rate-limit@1.0.9
60 | react-fast-refresh@0.2.1
61 | react-meteor-data@2.4.0
62 | reactive-var@1.0.11
63 | reload@1.3.1
64 | retry@1.1.0
65 | routepolicy@1.1.1
66 | server-render@0.4.0
67 | service-configuration@1.3.0
68 | sha@1.0.9
69 | shell-server@0.5.0
70 | socket-stream-client@0.4.0
71 | spacebars-compiler@1.3.0
72 | standard-minifier-css@1.7.4
73 | standard-minifier-js@2.7.2
74 | static-html@1.3.2
75 | templating-tools@1.2.1
76 | tracker@1.2.0
77 | typescript@4.4.0
78 | underscore@1.0.10
79 | url@1.3.2
80 | webapp@1.13.0
81 | webapp-hashing@1.1.0
82 |
--------------------------------------------------------------------------------
/cordova/client/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 10px;
3 | font-family: sans-serif;
4 | }
5 |
--------------------------------------------------------------------------------
/cordova/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | MeteorApp
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/cordova/client/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meteor } from 'meteor/meteor';
3 | import { render } from 'react-dom';
4 |
5 | import '../imports/infra/serviceWorkerInit';
6 | import '../imports/infra/one-signal';
7 |
8 | import { App } from '/imports/ui/App';
9 |
10 | Meteor.startup(() => {
11 | render( , document.getElementById('react-target'));
12 | });
13 |
--------------------------------------------------------------------------------
/cordova/imports/collections/links.js:
--------------------------------------------------------------------------------
1 | import { Mongo } from 'meteor/mongo';
2 |
3 | export const LinksCollection = new Mongo.Collection('links');
4 |
--------------------------------------------------------------------------------
/cordova/imports/infra/addPlayerId.js:
--------------------------------------------------------------------------------
1 | import {Meteor} from 'meteor/meteor';
2 |
3 | Meteor.methods({
4 | addPlayerId({playerId}) {
5 | this.unblock();
6 | if (Meteor.isClient || !this.userId || !playerId) return null;
7 |
8 | Meteor.users.update(this.userId, {$addToSet: {playersIds: playerId}});
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/cordova/imports/infra/apple-app-site-association.js:
--------------------------------------------------------------------------------
1 | import { getNativeStoresInfo } from './native';
2 |
3 | export const appleAppSiteAssociation = (req, res) => {
4 | // if you have multiple apps using the same backend you can customize here
5 | // the color, name, description, etc using the req.headers
6 | const nativeStoresInfo = getNativeStoresInfo();
7 |
8 | if (!nativeStoresInfo.nativeAppEnabled) {
9 | res.setHeader('Content-Type', 'text/html');
10 | res.writeHead(405);
11 | res.end(`Native App not enabled `);
12 | return;
13 | }
14 | if (!nativeStoresInfo.appleTeamId || !nativeStoresInfo.appleItunesAppId) {
15 | res.setHeader('Content-Type', 'text/html');
16 | res.writeHead(405);
17 | res.end(
18 | `Apple iTunes App ID and Apple Prefix are not configured `
19 | );
20 | return;
21 | }
22 |
23 | const appSiteAssociation = {
24 | applinks: {
25 | apps: [],
26 | details: [
27 | {
28 | appID: `${nativeStoresInfo.appleTeamId}.${nativeStoresInfo.appleBundleId}`,
29 | paths: ['*'],
30 | },
31 | ],
32 | },
33 | };
34 |
35 | res.setHeader('Content-Type', 'application/json');
36 | res.writeHead(200);
37 | res.end(JSON.stringify(appSiteAssociation));
38 | };
39 |
--------------------------------------------------------------------------------
/cordova/imports/infra/constants.js:
--------------------------------------------------------------------------------
1 | // replace cordova-example constants below
2 | export const Colors = {BACKGROUND: 'white', PRIMARY: '#e45735'};
3 | export const LANGUAGE = 'en-US';
4 | export const NAME = 'Cordova';
5 | export const SHORT_NAME = NAME;
6 | export const DESCRIPTION = '';
7 | export const KEYWORDS = ['', ''];
8 | export const LOGO_URL_WITHOUT_EXT =
9 | 'https://com-meteor-public-assets.s3.amazonaws.com/logo-black';
10 |
--------------------------------------------------------------------------------
/cordova/imports/infra/database-seed.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 | import { LinksCollection } from '/imports/collections/links';
3 |
4 | function insertLink({ title, url }) {
5 | LinksCollection.insert({title, url, createdAt: new Date()});
6 | }
7 |
8 | Meteor.startup(() => {
9 | // If the Links collection is empty, add some data.
10 | if (LinksCollection.find().count() === 0) {
11 | insertLink({
12 | title: 'Do the Tutorial',
13 | url: 'https://www.meteor.com/tutorials/react/creating-an-app'
14 | });
15 |
16 | insertLink({
17 | title: 'Follow the Guide',
18 | url: 'http://guide.meteor.com'
19 | });
20 |
21 | insertLink({
22 | title: 'Read the Docs',
23 | url: 'https://docs.meteor.com'
24 | });
25 |
26 | insertLink({
27 | title: 'Discussions',
28 | url: 'https://forums.meteor.com'
29 | });
30 | }
31 | });
32 |
--------------------------------------------------------------------------------
/cordova/imports/infra/google-analytics.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 | import { useEffect, useRef } from 'react';
3 |
4 | const DEFAULT_ANALYTICS_TRACKER_ID =
5 | Meteor.settings.public.googleAnalyticsTrackingId;
6 |
7 | const getTrackingsIds = ({ gaWebPropertyId } = {}) =>
8 | [DEFAULT_ANALYTICS_TRACKER_ID, gaWebPropertyId].filter(Boolean);
9 |
10 | const ga = (...rest) => {
11 | const googleAnalytics = window.gtag;
12 | if (!googleAnalytics || typeof googleAnalytics !== 'function') {
13 | console.warn('googleAnalytics is not available', googleAnalytics);
14 | return;
15 | }
16 | googleAnalytics(...rest);
17 | };
18 |
19 | export const sendConfigToAnalytics = ({ store } = {}, data, options) => {
20 | getTrackingsIds(store).forEach(trackingId => {
21 | ga('config', trackingId, data, options);
22 | });
23 | };
24 |
25 | const addAnalyticsTag = (sink, trackingId) => {
26 | sink.appendToHead(`
27 |
28 |
29 |
35 | `);
36 | };
37 |
38 | export const addGoogleAnalyticsScript = sink => {
39 | addAnalyticsTag(sink, DEFAULT_ANALYTICS_TRACKER_ID);
40 | };
41 |
42 | /**
43 | * inspired by https://github.com/mib200/vue-gtm/
44 | */
45 | const hasScript = () =>
46 | Array.from(document.getElementsByName('script')).some(script =>
47 | script.src.includes('googletagmanager')
48 | );
49 |
50 | // TODO mobile do we need this?
51 | export const loadGoogleAnalytics = (store = {}) => {
52 | if (!Meteor.isClient || hasScript()) {
53 | return false;
54 | }
55 | const { gaPrimaryDomain } = store;
56 |
57 | const script = document.createElement('script');
58 | script.async = true;
59 | script.src = `https://www.googletagmanager.com/gtag/js?id=${DEFAULT_ANALYTICS_TRACKER_ID}`;
60 | document.head.appendChild(script);
61 | const scriptContent = document.createElement('script');
62 | const domain = gaPrimaryDomain
63 | ? `gtag('set', 'linker', { 'domains': '${gaPrimaryDomain}' });`
64 | : '';
65 | scriptContent.innerHTML = `
66 | window.dataLayer = window.dataLayer || [];
67 | function gtag(){dataLayer.push(arguments);}
68 | gtag('js', new Date());
69 | gtag('config', '${DEFAULT_ANALYTICS_TRACKER_ID}', { 'transport_type': 'beacon' });
70 | ${domain}
71 | `;
72 | document.head.appendChild(scriptContent);
73 | return true;
74 | };
75 |
76 | export const initializeGoogleAnalytics = () => {
77 | loadGoogleAnalytics();
78 | };
79 |
80 | export const useGoogleAnalyticsPageView = ({ title, store }) => {
81 | const pageLocationPath = window.location.pathname;
82 |
83 | const lastPageLocationPathRef = useRef(null);
84 |
85 | useEffect(() => {
86 | if (
87 | !lastPageLocationPathRef.current ||
88 | lastPageLocationPathRef.current !== pageLocationPath
89 | ) {
90 | sendConfigToAnalytics(
91 | { store },
92 | {
93 | page_title: title,
94 | page_location: window.location.href,
95 | page_path: pageLocationPath,
96 | }
97 | );
98 | }
99 | lastPageLocationPathRef.current = pageLocationPath;
100 | }, [pageLocationPath, title]);
101 | };
102 |
--------------------------------------------------------------------------------
/cordova/imports/infra/methodCall.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 |
3 | export const methodCall = (methodName, ...args) =>
4 | new Promise((resolve, reject) => {
5 | Meteor.call(methodName, ...args, (error, result) => {
6 | if (error) reject(error);
7 | else resolve(result);
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/cordova/imports/infra/native.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from "meteor/meteor";
2 |
3 | // TODO mobile replace values in settings.
4 | // replace cordova-example native details in the settings
5 | export const APPLE_ITUNES_APP_ID =
6 | Meteor.settings.public.native.appleItunesAppId;
7 | const APPLE_TEAM_ID = Meteor.settings.public.native.appleTeamId;
8 | const APPLE_BUNDLE_ID =
9 | Meteor.settings.public.native.appleBundleId;
10 | const GOOGLE_PLAY_APP_ID =
11 | Meteor.settings.public.native.googlePlayAppId;
12 | const ONE_SIGNAL_GCM_SENDER_ID = Meteor.settings.public.oneSignalGcmSenderId;
13 | export const ONE_SIGNAL_REST_API_KEY =
14 | Meteor.settings.public.native.oneSignalRestApiKey;
15 | export const ONE_SIGNAL_APP_ID =
16 | Meteor.settings.public.native.oneSignalAppId;
17 |
18 | export const getGoolePlayAppUrl = ({googlePlayAppId}) => {
19 | if (!googlePlayAppId) {
20 | return null;
21 | }
22 | return `https://play.google.com/store/apps/details?id=${googlePlayAppId}`;
23 | };
24 |
25 | export const getAppleItunesAppUrl = ({appleItunesAppId}) => {
26 | if (!appleItunesAppId) {
27 | return null;
28 | }
29 | return `https://itunes.apple.com/app/id${appleItunesAppId}`;
30 | };
31 |
32 | export const getNativeStoresInfo = () => ({
33 | appleItunesAppId: APPLE_ITUNES_APP_ID,
34 | googlePlayAppId: GOOGLE_PLAY_APP_ID,
35 | appleTeamId: APPLE_TEAM_ID,
36 | appleBundleId: APPLE_BUNDLE_ID,
37 | oneSignalGcmSenderId: ONE_SIGNAL_GCM_SENDER_ID,
38 | // change to true to disable native stuff
39 | nativeAppEnabled: true,
40 | });
41 |
--------------------------------------------------------------------------------
/cordova/imports/infra/one-signal.js:
--------------------------------------------------------------------------------
1 | import {Meteor} from 'meteor/meteor';
2 | // TODO mobile add accounts
3 | import {Accounts} from 'meteor/accounts-base';
4 |
5 | import {methodCall} from './methodCall';
6 |
7 | let currentPlayerId = null;
8 |
9 | export const addPlayerId = playerId => {
10 | methodCall('addPlayerId', {
11 | playerId,
12 | })
13 | .catch(e => {
14 | console.error(`Error adding player id ${playerId}`, e);
15 | });
16 | };
17 |
18 | const goTo = route => {
19 | const navigateTo = `${!route.startsWith('/') ? '/' : ''}${route}`;
20 | console.debug(`navigateTo ${navigateTo}`);
21 | history.push(navigateTo);
22 | };
23 |
24 | Meteor.startup(() => {
25 | Accounts.onLogin(data => {
26 | console.log('onLogin', Meteor.userId(), data);
27 | addPlayerId(currentPlayerId);
28 | });
29 |
30 | if (!Meteor.isCordova) {
31 | return;
32 | }
33 |
34 | let appId = null;
35 | // eslint-disable-next-line no-undef
36 | window.plugins.AppSettings.get(
37 | ['onesignalappid', 'universallink'],
38 | configs => {
39 | const universalLink = configs.universallink;
40 | // cordova from fairmanager-cordova-plugin-universal-links
41 | window.cordova.plugins.UniversalLinks.subscribe(null, eventData => {
42 | console.debug(`cordovaRedirect ${universalLink} ${eventData.url}`);
43 |
44 | if (!eventData.url.includes(universalLink)) return;
45 |
46 | const redirectUrl = eventData.url.replace(universalLink, '');
47 | if (redirectUrl) {
48 | const navigateTo = `${
49 | !redirectUrl.startsWith('/') ? '/' : ''
50 | }${redirectUrl}`;
51 | console.debug(`navigateTo ${navigateTo}`);
52 | history.push(navigateTo);
53 | }
54 | });
55 |
56 | appId = configs.onesignalappid;
57 | if (appId) {
58 | window.plugins.OneSignal.setLogLevel({logLevel: 4, visualLevel: 1});
59 |
60 | const notificationOpenedCallback = notification => {
61 | console.debug('received notification', JSON.stringify(notification));
62 | // TODO mobile readme: explain additionalData.route
63 | const route = notification && notification.payload &&
64 | notification.payload.additionalData &&
65 | notification.payload.additionalData.route;
66 | if (route) {
67 | goTo(route);
68 | }
69 | };
70 |
71 | window.plugins.OneSignal.startInit(appId);
72 | window.plugins.OneSignal.handleNotificationOpened(
73 | notificationOpenedCallback
74 | );
75 | window.plugins.OneSignal.getIds(ids => {
76 | currentPlayerId = ids.userId;
77 | });
78 | window.plugins.OneSignal.endInit();
79 | }
80 | },
81 | error => {
82 | console.error(
83 | 'Error getting configuration from config.xml in Cordova',
84 | error
85 | );
86 | }
87 | );
88 | });
89 |
--------------------------------------------------------------------------------
/cordova/imports/infra/pwa-json.js:
--------------------------------------------------------------------------------
1 | import {
2 | getAppleItunesAppUrl,
3 | getGoolePlayAppUrl,
4 | getNativeStoresInfo,
5 | } from './native';
6 | import {
7 | Colors, DESCRIPTION,
8 | LANGUAGE,
9 | LOGO_URL_WITHOUT_EXT,
10 | NAME,
11 | SHORT_NAME
12 | } from "./constants";
13 |
14 |
15 | export const getPwaSettings = () => {
16 | const logo = LOGO_URL_WITHOUT_EXT;
17 | const nativeStoresInfo = getNativeStoresInfo();
18 | const {
19 | appleItunesAppId,
20 | googlePlayAppId,
21 | nativeAppEnabled,
22 | oneSignalGcmSenderId,
23 | } = nativeStoresInfo;
24 |
25 | return {
26 | background_color: Colors.BACKGROUND,
27 | theme_color: Colors.PRIMARY,
28 | start_url: '/',
29 | display: 'standalone',
30 | orientation: 'portrait',
31 | lang: LANGUAGE,
32 | name: NAME,
33 | short_name: SHORT_NAME,
34 | description: DESCRIPTION,
35 | icons: [
36 | {
37 | src: `${logo}_128.png`,
38 | type: 'image/png',
39 | sizes: '128x128',
40 | },
41 | {
42 | src: `${logo}_152.png`,
43 | type: 'image/png',
44 | sizes: '152x152',
45 | },
46 | {
47 | src: `${logo}_144.png`,
48 | type: 'image/png',
49 | sizes: '144x144',
50 | },
51 | {
52 | src: `${logo}_192.png`,
53 | type: 'image/png',
54 | sizes: '192x192',
55 | },
56 | {
57 | src: `${logo}_512.png`,
58 | type: 'image/png',
59 | sizes: '512x512',
60 | },
61 | ].filter(icon => !!icon.src),
62 | gcm_sender_id: oneSignalGcmSenderId,
63 | prefer_related_applications: nativeAppEnabled,
64 | related_applications: [
65 | nativeAppEnabled &&
66 | googlePlayAppId && {
67 | platform: 'play',
68 | url: getGoolePlayAppUrl(nativeStoresInfo),
69 | id: googlePlayAppId,
70 | },
71 | nativeAppEnabled &&
72 | appleItunesAppId && {
73 | platform: 'itunes',
74 | url: getAppleItunesAppUrl(nativeStoresInfo),
75 | id: appleItunesAppId,
76 | },
77 | ].filter(Boolean),
78 | };
79 | };
80 |
81 | export const pwaJson = (req, res) => {
82 | res.setHeader('Content-Type', 'javascript/json');
83 | res.writeHead(200);
84 |
85 | // if you have multiple apps using the same backend you can customize here
86 | // the color, name, description, etc using the req.headers
87 | const pwa = getPwaSettings();
88 |
89 | res.end(JSON.stringify(pwa));
90 | };
91 |
--------------------------------------------------------------------------------
/cordova/imports/infra/rest.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from "meteor/meteor";
2 | import { WebApp } from 'meteor/webapp';
3 | import express from 'express';
4 | import bodyParser from 'body-parser';
5 | import { pwaJson } from "./pwa-json";
6 | import { appleAppSiteAssociation } from "./apple-app-site-association";
7 |
8 | Meteor.startup(() => {
9 | const app = express();
10 | app.use(bodyParser.json());
11 | app.get('/pwa.json', Meteor.bindEnvironment(pwaJson));
12 | app.get(
13 | '/apple-app-site-association',
14 | Meteor.bindEnvironment(appleAppSiteAssociation)
15 | );
16 |
17 | WebApp.connectHandlers.use(app);
18 | });
19 |
--------------------------------------------------------------------------------
/cordova/imports/infra/sendPush.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 | import request from 'request';
3 |
4 | import {ONE_SIGNAL_APP_ID, ONE_SIGNAL_REST_API_KEY} from "./native";
5 |
6 | // TODO mobile send push example
7 | export const sendPush = ({ heading, content, playersIds, data = {} }) =>
8 | new Promise((resolve, reject) => {
9 | const options = {
10 | uri: 'https://onesignal.com/api/v1/notifications',
11 | headers: {
12 | 'Content-Type': 'application/json; charset=utf-8',
13 | Authorization: `Basic ${ONE_SIGNAL_REST_API_KEY}`,
14 | },
15 | body: JSON.stringify({
16 | ...(heading ? { headings: { en: heading } } : {}),
17 | contents: { en: content },
18 | include_player_ids: playersIds,
19 | app_id: ONE_SIGNAL_APP_ID,
20 | data,
21 | web_url: Meteor.absoluteUrl(data.route),
22 | }),
23 | };
24 |
25 | request.post(options, (error, response, body) => {
26 | if (error) reject(error);
27 | resolve({
28 | response: JSON.parse(body),
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/cordova/imports/infra/serviceWorkerInit.js:
--------------------------------------------------------------------------------
1 | const iOS = () => {
2 | const iDevices = [
3 | 'iPad Simulator',
4 | 'iPhone Simulator',
5 | 'iPod Simulator',
6 | 'iPad',
7 | 'iPhone',
8 | 'iPod',
9 | ];
10 |
11 | return !!navigator.platform && iDevices.indexOf(navigator.platform) !== -1;
12 | };
13 |
14 | const register = () => {
15 | if (!('serviceWorker' in navigator)) {
16 | console.log('serviceWorker is not in navigator!');
17 | return;
18 | }
19 | if (iOS()) {
20 | console.log('iOS device then not register sw (was with error)!');
21 | return;
22 | }
23 | navigator.serviceWorker
24 | .register('/sw.js')
25 |
26 | .then(() => {
27 | console.log('serviceWorker registered with success!');
28 | })
29 | .catch(error => console.error('Error registering serviceWorker!', error));
30 | };
31 |
32 | register();
33 |
--------------------------------------------------------------------------------
/cordova/imports/methods/createUser.js:
--------------------------------------------------------------------------------
1 | import {Meteor} from 'meteor/meteor';
2 |
3 | Meteor.methods({
4 | createUser({playerId}) {
5 | this.unblock();
6 | if (Meteor.isClient || !this.userId || !playerId) return null;
7 |
8 | Meteor.users.update(this.userId, {$addToSet: {playersIds: playerId}});
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/cordova/imports/ui/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Hello} from './Hello';
3 | import {Info} from './Info';
4 | import {User} from "./User";
5 |
6 | export const App = () => (
7 |
8 |
Welcome to Meteor!
9 |
10 |
11 |
12 |
13 | );
14 |
--------------------------------------------------------------------------------
/cordova/imports/ui/Hello.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 |
3 | export const Hello = () => {
4 | const [counter, setCounter] = useState(0);
5 |
6 | const increment = () => {
7 | setCounter(counter + 1);
8 | };
9 |
10 | return (
11 |
12 |
Click Me
13 |
You've pressed the button {counter} times.
14 |
15 | );
16 | };
17 |
--------------------------------------------------------------------------------
/cordova/imports/ui/Info.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useTracker } from 'meteor/react-meteor-data';
3 | import { LinksCollection } from '/imports/collections/links';
4 |
5 | export const Info = () => {
6 | const links = useTracker(() => {
7 | return LinksCollection.find().fetch();
8 | });
9 |
10 | return (
11 |
12 |
Learn Meteor!
13 |
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/cordova/imports/ui/User.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Accounts} from "meteor/accounts-base";
3 | import {Meteor} from "meteor/meteor";
4 | import {useTracker} from 'meteor/react-meteor-data';
5 |
6 | const USERNAME = 'test@mobile.meteorapp.com';
7 | const PASSWORD = '123456';
8 |
9 | export const User = () => {
10 | const user = useTracker(() => Meteor.user());
11 | const createUser = () => {
12 | Accounts.createUser(
13 | {
14 | username: USERNAME,
15 | email: USERNAME,
16 | password: PASSWORD,
17 | },
18 | error => {
19 | if (error) {
20 | console.error(`Error creating user ${USERNAME}`, error);
21 | return;
22 | }
23 |
24 | console.log(`${USERNAME} created`);
25 | }
26 | );
27 | };
28 |
29 | const loginUser = () => {
30 | Meteor.loginWithPassword(
31 | USERNAME,
32 | PASSWORD,
33 | error => {
34 | if (!error) {
35 | console.log(`User authenticated ${USERNAME}`);
36 | return;
37 | }
38 |
39 | if (error.error === 403) {
40 | console.warn(`User not found`, error);
41 | return;
42 | }
43 |
44 | console.error(`Error authenticating user ${USERNAME}`, error);
45 | }
46 | );
47 | };
48 |
49 | const logoutUser = () => {
50 | Meteor.logout(() => console.log(`User logged out ${USERNAME}`));
51 | };
52 |
53 | return (
54 |
55 | {!user && <>
56 | Create user
57 | Login user
58 | >}
59 | {user && <>
60 | Logout {user.username}
61 | >}
62 |
63 | );
64 | };
65 |
--------------------------------------------------------------------------------
/cordova/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cordova",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run --settings private/env/dev/settings.json",
6 | "start-production": "meteor run --settings private/env/production/settings.json",
7 | "visualize": "meteor --production --extra-packages bundle-visualizer"
8 | },
9 | "dependencies": {
10 | "@babel/runtime": "^7.8.4",
11 | "bcrypt": "^4.0.1",
12 | "body-parser": "^1.19.0",
13 | "express": "^4.17.1",
14 | "meteor-node-stubs": "^1.0.0",
15 | "react": "^16.13.1",
16 | "react-dom": "^16.13.1",
17 | "request": "^2.88.2"
18 | },
19 | "meteor": {
20 | "mainModule": {
21 | "client": "client/main",
22 | "server": "server/main.js"
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cordova/private/env/production/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": {
3 | "native": {
4 | "appleItunesAppId": "2441947344",
5 | "appleTeamId": "XR7QCJTCL9",
6 | "appleBundleId": "com.meteorapp.mobile",
7 | "googlePlayAppId": "com.meteorapp.mobile",
8 | "oneSignalAppId": "a4a5axxx-59f2-493f-abdb-efce7b0c8ef6",
9 | "oneSignalRestApiKey": "XXXwMDI5MWEtNzE3MC00ZGEzLWIyNzAtNzgzYzg5NmU5ZWVj"
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/cordova/private/jenkins.groovy:
--------------------------------------------------------------------------------
1 | // Use this file as a template for a Job definition using Job DSL Jenkins Plugin https://plugins.jenkins.io/job-dsl/
2 | def generatedBy = "Generated by jenkins.groovy at ${new Date()}"
3 | def organization = "yourorg"
4 | def project = "yourapp"
5 |
6 | // You need to have a MacOS machine configured in your Nodes in Jenkins with this label
7 | def machineLabel = "macosx"
8 |
9 | def yourKeychainPassword = "yourpass"
10 |
11 | def gitProjectUrl = "git@github.com:${organization}/${project}.git"
12 | def branchName = "main"
13 |
14 | def channel = "#${project}-alerts"
15 |
16 | job("build-native") {
17 | label(machineLabel)
18 | description generatedBy
19 | scm {
20 | git(gitProjectUrl, branchName)
21 | }
22 | triggers {
23 | scm(trigger)
24 | }
25 | steps {
26 | shell("""
27 | ${installYarn}
28 | cd private/native-app/${environment}
29 | APP_ID=com.meteorapp.mobile ./build.sh
30 | APP_ID=com.meteorapp.mobile ./publish-android.sh
31 | FL_UNLOCK_KEYCHAIN_PASSWORD=${yourKeychainPassword} ./publish-ios.sh
32 | """)
33 | }
34 | configure {
35 | it / 'publishers' / 'jenkins.plugins.slack.SlackNotifier'(plugin: "slack@2.3") {
36 | room(channel)
37 | notifySuccess(true)
38 | notifyFailure(true)
39 | notifyBackToNormal(true)
40 | notifyRepeatedFailure(true)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/cordova/private/native-app/production/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # fill the data here
4 | env=production
5 | appName=Mobile
6 | buildFolder=meteor-mobile-build-production
7 | host=https://mobile.meteorapp.com
8 | pathToAndroidKeyStore=/Users/filipe/Documents/meteor/ws/mobile/keystore
9 | androidPassword=asdWEQdsaD
10 | keystoreAlias=$APP_ID
11 |
12 | # build
13 | cd ../../../
14 | rm -rf .meteor/local/cordova-build
15 | rm -rf ../../$buildFolder
16 | echo building app pointing to $host
17 | METEOR_DISABLE_OPTIMISTIC_CACHING=1 LANG=en_US.UTF-8 MOBILE_APP_ID=$APP_ID meteor build ../../$buildFolder --server=$host --mobile-settings private/env/$env/settings.json
18 |
19 | cd ../../$buildFolder
20 |
21 | # open xcode
22 | open ios/project/$appName.xcworkspace
23 |
24 | # sign android
25 | cd android/project/app/build/outputs/bundle/release
26 | rm -rf ~/app-release.aab
27 | echo 'Executing: jarsigner'
28 | jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 -keystore $pathToAndroidKeyStore --storepass $androidPassword app-release.aab $keystoreAlias
29 | cp app-release.aab ~/app-release.aab
30 |
--------------------------------------------------------------------------------
/cordova/private/native-app/production/publish-android.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | authFileAndroid=~/android_auth.json
4 |
5 | fastlane supply --aab ~/app-release.aab --json_key $authFileAndroid --package_name $APP_ID
6 |
--------------------------------------------------------------------------------
/cordova/private/native-app/production/publish-ios.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # fill the data here
4 | fastlaneApplePassword=yourpass
5 | appleUsername=yourusername
6 | applePassword=yourpassword
7 |
8 | # testflight:true
9 | FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD=$fastlaneApplePassword FL_UNLOCK_KEYCHAIN_SET_DEFAULT=true bundle exec fastlane --verbose ios appstore username:$appleUsername password:$applePassword
10 |
--------------------------------------------------------------------------------
/cordova/public/sw.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | const HTMLToCache = '/';
3 | const version = 'MSW V0.3';
4 |
5 | self.addEventListener('install', event => {
6 | event.waitUntil(
7 | caches.open(version).then(cache => {
8 | cache.add(HTMLToCache).then(self.skipWaiting());
9 | })
10 | );
11 | });
12 |
13 | self.addEventListener('activate', event => {
14 | event.waitUntil(
15 | caches
16 | .keys()
17 | .then(cacheNames =>
18 | Promise.all(
19 | cacheNames.map(cacheName => {
20 | if (version !== cacheName) return caches.delete(cacheName);
21 | })
22 | )
23 | )
24 | .then(self.clients.claim())
25 | );
26 | });
27 |
28 | self.addEventListener('fetch', event => {
29 | const requestToFetch = event.request.clone();
30 | event.respondWith(
31 | caches.match(event.request.clone()).then(cached => {
32 | // We don't return cached HTML (except if fetch failed)
33 | if (cached) {
34 | const resourceType = cached.headers.get('content-type');
35 | // We only return non css/js/html cached response e.g images
36 | if (!hasHash(event.request.url) && !/text\/html/.test(resourceType)) {
37 | return cached;
38 | }
39 |
40 | // If the CSS/JS didn't change since it's been cached, return the cached version
41 | if (
42 | hasHash(event.request.url) &&
43 | hasSameHash(event.request.url, cached.url)
44 | ) {
45 | return cached;
46 | }
47 | }
48 | return fetch(requestToFetch)
49 | .then(response => {
50 | const clonedResponse = response.clone();
51 | const contentType = clonedResponse.headers.get('content-type');
52 |
53 | if (
54 | !clonedResponse ||
55 | clonedResponse.status !== 200 ||
56 | clonedResponse.type !== 'basic' ||
57 | /\/sockjs\//.test(event.request.url)
58 | ) {
59 | return response;
60 | }
61 |
62 | if (/html/.test(contentType)) {
63 | caches
64 | .open(version)
65 | .then(cache => cache.put(HTMLToCache, clonedResponse));
66 | } else {
67 | // Delete old version of a file
68 | if (hasHash(event.request.url)) {
69 | caches.open(version).then(cache =>
70 | cache.keys().then(keys =>
71 | keys.forEach(asset => {
72 | if (
73 | new RegExp(removeHash(event.request.url)).test(
74 | removeHash(asset.url)
75 | )
76 | ) {
77 | cache.delete(asset);
78 | }
79 | })
80 | )
81 | );
82 | }
83 |
84 | caches
85 | .open(version)
86 | .then(cache => cache.put(event.request, clonedResponse));
87 | }
88 | return response;
89 | })
90 | .catch(() => {
91 | if (hasHash(event.request.url))
92 | return caches.match(event.request.url);
93 | else if (!/\/sockjs\//.test(event.request.url))
94 | // If the request URL hasn't been served from cache and isn't sockjs we suppose it's HTML
95 | return caches.match(HTMLToCache);
96 | // Only for sockjs
97 | return new Response('No connection to the server', {
98 | status: 503,
99 | statusText: 'No connection to the server',
100 | headers: new Headers({ 'Content-Type': 'text/plain' }),
101 | });
102 | });
103 | })
104 | );
105 | });
106 |
107 | function removeHash(element) {
108 | if (typeof element === 'string') return element.split('?hash=')[0];
109 | }
110 |
111 | function hasHash(element) {
112 | if (typeof element === 'string') return /\?hash=.*/.test(element);
113 | }
114 |
115 | function hasSameHash(firstUrl, secondUrl) {
116 | if (typeof firstUrl === 'string' && typeof secondUrl === 'string') {
117 | return /\?hash=(.*)/.exec(firstUrl)[1] === /\?hash=(.*)/.exec(secondUrl)[1];
118 | }
119 | }
120 |
121 | // Service worker created by Ilan Schemoul alias NitroBAY as a specific Service Worker for Meteor
122 | // Please see https://github.com/NitroBAY/meteor-service-worker for the official project source
123 |
--------------------------------------------------------------------------------
/cordova/server/main.js:
--------------------------------------------------------------------------------
1 | import '../imports/infra/meta-tags';
2 | import '../imports/infra/rest';
3 | import '../imports/infra/addPlayerId';
4 | import '../imports/infra/database-seed';
--------------------------------------------------------------------------------
/nft-marketplace/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
3 | node_modules
4 | .env
5 | coverage
6 | coverage.json
7 | typechain
8 |
9 | #Hardhat files
10 | cache
11 | artifacts
12 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 | 1.7-split-underscore-from-meteor-base
19 | 1.8.3-split-jquery-from-blaze
20 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | xv5ft06lky7c.xir3icty4q9c
8 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.5.1 # Packages every Meteor app needs to have
8 | mobile-experience@1.1.0 # Packages for a great mobile UX
9 | mongo@1.15.0 # The database Meteor supports right now
10 | reactive-var@1.0.11 # Reactive variable for tracker
11 |
12 | standard-minifier-css@1.8.1 # CSS minifier run for production mode
13 | standard-minifier-js@2.8.0 # JS minifier run for production mode
14 | es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers
15 | ecmascript@0.16.2 # Enable ECMAScript2015+ syntax in app code
16 | typescript@4.5.4 # Enable TypeScript syntax in .ts and .tsx modules
17 | shell-server@0.5.0 # Server-side component of the `meteor shell` command
18 | hot-module-replacement@0.5.1 # Update client in development without reloading the page
19 |
20 | static-html@1.3.2 # Define static page content in .html files
21 | react-meteor-data # React higher-order component for reactively tracking Meteor data
22 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@2.7.2
2 |
--------------------------------------------------------------------------------
/nft-marketplace/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@1.1.1
2 | autoupdate@1.8.0
3 | babel-compiler@7.9.0
4 | babel-runtime@1.5.0
5 | base64@1.0.12
6 | binary-heap@1.0.11
7 | blaze-tools@1.1.3
8 | boilerplate-generator@1.7.1
9 | caching-compiler@1.2.2
10 | caching-html-compiler@1.2.1
11 | callback-hook@1.4.0
12 | check@1.3.1
13 | ddp@1.4.0
14 | ddp-client@2.5.0
15 | ddp-common@1.4.0
16 | ddp-server@2.5.0
17 | diff-sequence@1.1.1
18 | dynamic-import@0.7.2
19 | ecmascript@0.16.2
20 | ecmascript-runtime@0.8.0
21 | ecmascript-runtime-client@0.12.1
22 | ecmascript-runtime-server@0.11.0
23 | ejson@1.1.2
24 | es5-shim@4.8.0
25 | fetch@0.1.1
26 | geojson-utils@1.0.10
27 | hot-code-push@1.0.4
28 | hot-module-replacement@0.5.1
29 | html-tools@1.1.3
30 | htmljs@1.1.1
31 | id-map@1.1.1
32 | inter-process-messaging@0.1.1
33 | launch-screen@1.3.0
34 | logging@1.3.1
35 | meteor@1.10.0
36 | meteor-base@1.5.1
37 | minifier-css@1.6.0
38 | minifier-js@2.7.4
39 | minimongo@1.8.0
40 | mobile-experience@1.1.0
41 | mobile-status-bar@1.1.0
42 | modern-browsers@0.1.8
43 | modules@0.18.0
44 | modules-runtime@0.13.0
45 | modules-runtime-hot@0.14.0
46 | mongo@1.15.0
47 | mongo-decimal@0.1.3
48 | mongo-dev-server@1.1.0
49 | mongo-id@1.0.8
50 | npm-mongo@4.3.1
51 | ordered-dict@1.1.0
52 | promise@0.12.0
53 | random@1.2.0
54 | react-fast-refresh@0.2.3
55 | react-meteor-data@2.4.0
56 | reactive-var@1.0.11
57 | reload@1.3.1
58 | retry@1.1.0
59 | routepolicy@1.1.1
60 | shell-server@0.5.0
61 | socket-stream-client@0.5.0
62 | spacebars-compiler@1.3.1
63 | standard-minifier-css@1.8.1
64 | standard-minifier-js@2.8.0
65 | static-html@1.3.2
66 | templating-tools@1.2.2
67 | tracker@1.2.0
68 | typescript@4.5.4
69 | underscore@1.0.10
70 | webapp@1.13.1
71 | webapp-hashing@1.1.0
72 |
--------------------------------------------------------------------------------
/nft-marketplace/README.md:
--------------------------------------------------------------------------------
1 | # NFT Marketplace
2 |
3 | This is from Nader's tutorial, but with Meteor. You can check the original tutorial here: https://dev.to/edge-and-node/building-scalable-full-stack-apps-on-ethereum-with-polygon-2cfb
4 |
5 | To run it locally, you will need to open two terminals.
6 |
7 | But first, you need to clone the project and run a `meteor npm install` to install all the dependencies.
8 |
9 | In terminal #1, you will run the following command:
10 |
11 | `npx hardhat node`
12 |
13 | The command above will give you 20 accounts with 10000 ETH each, that you can add to your Metamask and test the application locally.
14 |
15 | In terminal #2, you will then run the following commands:
16 |
17 | ```
18 | npx hardhat run scripts/deploy.js --network localhost
19 | meteor
20 | ```
21 |
22 | The command above will deploy the contract and run the Meteor application.
23 |
24 | ## Adding a wallet to MetaMask
25 |
26 | The `npx hardhat node` command will give you 20 accounts for you to test locally. To add one of these accounts to your Metamask, you will need to copy one of the private keys hardhat gave you.
27 |
28 | Then you will make sure you are in the localhost network, like in the screenshot below:
29 |
30 | 
31 |
32 | After that, you will click in the top right icon to open a menu, where you will click on Import Account, like in the image below:
33 |
34 | 
35 |
36 | Then you will paste your private key and click Import.
37 |
38 | ## Possible issues when testing locally
39 |
40 | If you're getting errors like "Nonce too high" when trying to add an NFT or doing any kind of transaction in the app, you can do the following steps:
41 |
42 | 1. Access the top right menu like you did in the last section
43 | 2. Go to Settings and then Advanced
44 | 3. Click on Reset Accounts
45 |
46 | ## How to test our deployed version
47 |
48 | You can check our deployed version using this link: https://meteor-nft-marketplace.meteorapp.com
49 |
50 | To use this version you will need to add the Mumbai Testnet to your Metamask. You can do it by following the screenshots from Nader's tutorial. You will go to Metamask settings:
51 |
52 | 
53 |
54 | Then Networks and then Add Network.
55 |
56 | 
57 |
58 | After that, you will add the following info from Polygon [docs](https://docs.polygon.technology/docs/develop/network-details/network/):
59 |
60 | Network Name: Mumbai TestNet
61 |
62 | New RPC URL: https://rpc-mumbai.maticvigil.com
63 |
64 | Chain ID: 80001
65 |
66 | Currency Symbol: Matic
67 |
68 | Click save and then you should be able to switch to this new network and use it. You will need some testnet Matic tokens, but you can get them [here](https://faucet.matic.network/)
69 |
70 | ## Screenshots of the application
71 |
72 | 
73 |
74 | 
75 |
76 | 
77 |
78 | 
79 |
80 | 
81 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState} from 'react';
2 | import { Outlet } from 'react-router-dom';
3 | import { NavBar } from "./common/NavBar";
4 | import { CheckAccount } from "./common/CheckAccount";
5 | import { Footer } from "./common/Footer";
6 |
7 | export const App = () => {
8 | const [connection, setConnection] = useState(false);
9 |
10 | if (window.ethereum !== undefined) {
11 | useEffect(() => {
12 | window.ethereum.on("accountsChanged", accounts => {
13 | if (accounts.length > 0) setConnection(true);
14 | else setConnection(false);
15 | });
16 |
17 | CheckAccount().then((accounts) => {
18 | if (accounts.length > 0) setConnection(true);
19 | else setConnection(false);
20 | })
21 | }, []);
22 |
23 | return (
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | );
32 | } else {
33 | return (
34 |
35 |
You need Metamask installed to use this store.
36 |
37 |
38 | );
39 | }
40 | };
41 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/ConnectPage.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Button } from "./components/Button";
3 | import { ConnectAccount } from "./common/ConnectAccount";
4 | import { useNavigate, useOutletContext } from "react-router-dom";
5 | import { RoutePaths } from "./common/RoutePaths";
6 |
7 | export default function ConnectPage() {
8 | const navigate = useNavigate();
9 | const [connection, setConnection] = useOutletContext();
10 |
11 | return (
12 |
13 |
Connect with your MetaMask wallet
14 |
You need an Ethereum wallet to use this store.
15 |
16 |
{
21 | ConnectAccount().then((conn) => {
22 | setConnection(true);
23 | navigate(`${RoutePaths.ACCOUNT}/${conn.selectedAddress}`);
24 | }, () => {
25 | setConnection(false)
26 | });
27 | }} />
28 |
29 | )
30 | }
31 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/CategoryOptions.jsx:
--------------------------------------------------------------------------------
1 | export const CategoryOptions = [
2 | { label: "All", value: "all" },
3 | { label: "Owned", value: "owned" },
4 | { label: "For Sale", value: "for-sale" },
5 | ];
6 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/CheckAccount.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { ethers } from "ethers";
3 |
4 | export const CheckAccount = () => {
5 | const provider = new ethers.providers.Web3Provider(
6 | window.ethereum
7 | );
8 |
9 | return provider.listAccounts();
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/ConnectAccount.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Web3Modal from "web3modal";
3 |
4 | export const ConnectAccount = async () => {
5 | const web3Modal = new Web3Modal({
6 | network: "mainnet",
7 | cacheProvider: true,
8 | });
9 |
10 | return await web3Modal.connect();
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/CurrentAccount.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { ethers } from "ethers";
3 |
4 | export const CurrentAccount = () => {
5 | const provider = new ethers.providers.Web3Provider(window.ethereum);
6 |
7 | return provider.provider.selectedAddress;
8 | }
9 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const Footer = () => {
4 | const currentYear = new Date().getFullYear();
5 |
6 | return (
7 |
8 |
9 |
{`© 2018 - ${currentYear} Ozone Networks, Inc`}
10 |
11 |
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/NavBar.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from "react-router-dom";
3 | import { RoutePaths } from "./RoutePaths";
4 | import { Disclosure } from '@headlessui/react';
5 | import { MenuIcon, XIcon } from '@heroicons/react/outline';
6 | import { CurrentAccount } from './CurrentAccount';
7 |
8 | const navigation = [
9 | { name: 'Explore', href: RoutePaths.ROOT },
10 | { name: 'Create', href: RoutePaths.SELL_NFT },
11 | ];
12 |
13 | export const NavBar = ({ connection }) => {
14 | const currentAccount = CurrentAccount();
15 |
16 | return (
17 |
18 | {({ open }) => (
19 | <>
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | {navigation.map((item) => (
29 |
30 | {item.name}
31 |
32 | ))}
33 |
34 |
35 |
36 | {connection ? (
37 |
38 |
39 | Account
40 |
41 | ) : (
42 |
43 | Connect
44 |
45 | )}
46 |
47 |
48 |
49 |
50 |
51 | {/* Mobile menu button */}
52 |
53 | Open main menu
54 | {open ? (
55 |
56 | ) : (
57 |
58 | )}
59 |
60 |
61 |
62 |
63 |
64 | {/* Mobile menu items */}
65 |
66 |
67 | {navigation.map((item) => (
68 |
74 | {item.name}
75 |
76 | ))}
77 |
78 | {connection ? (
79 |
84 |
85 | Account
86 |
87 | ) : (
88 |
93 | Connect
94 |
95 | )}
96 |
97 |
98 | >
99 | )}
100 |
101 | )
102 | }
103 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/RoutePaths.jsx:
--------------------------------------------------------------------------------
1 | export const RoutePaths = {
2 | ROOT: '/',
3 | SELL_NFT: '/sell-nft',
4 | CONNECT: '/connect',
5 | DETAILS: '/details',
6 | ACCOUNT: '/account',
7 | };
8 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/Routes.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter, Routes as ReactRoutes, Route } from 'react-router-dom';
3 | import { RoutePaths } from './RoutePaths';
4 | import { App } from "../App";
5 |
6 | const HomePage = React.lazy(() => import('../HomePage'));
7 | const SellNftPage = React.lazy(() => import('../SellNftPage'));
8 | const ConnectPage = React.lazy(() => import('../ConnectPage'));
9 | const DetailsPage = React.lazy(() => import('../DetailsPage'));
10 | const AccountPage = React.lazy(() => import('../AccountPage'));
11 |
12 | export const Routes = () => (
13 |
14 |
15 | }>
16 | } />
17 | } />
18 | } />
19 | } />
20 | } />
21 |
22 |
23 |
24 | );
25 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/common/SortOptions.jsx:
--------------------------------------------------------------------------------
1 | export const SortOptions = [
2 | { label: "Oldest Added", value: "oldest" },
3 | { label: "Newest Added", value: "newest" },
4 | { label: "Price: Low to High", value: "price-low" },
5 | { label: "Price: High to Low", value: "price-high" },
6 | ];
7 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/components/Button.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const Button = ({
4 | children,
5 | className = '',
6 | text = null,
7 | type = 'primary',
8 | onClick = () => ({}),
9 | startIcon = null,
10 | endIcon = null,
11 | disabled = false,
12 | }) => {
13 | const btnTypes = {
14 | primary: 'py-3.5 px-4 bg-dodger text-white border-none', // Full background
15 | secondary: `py-3.5 px-4 bg-transparent text-dodger border-2 border-dodger ${
16 | !disabled
17 | ? 'hover:bg-dodger hover:text-white hover:border-transparent'
18 | : ''
19 | }`, // Outline
20 | tertiary: 'py-3.5 px-4 bg-transparent text-dodger border-none', // Transparent
21 | danger: `py-3.5 px-4 bg-transparent text-vermilion border-2 border-vermilion ${
22 | !disabled
23 | ? 'hover:bg-vermilion hover:text-white hover:border-transparent'
24 | : ''
25 | }`, // Red outline
26 | };
27 |
28 | return (
29 |
36 | {startIcon && {startIcon} }
37 | {text || children}
38 | {endIcon && {endIcon} }
39 |
40 | );
41 | };
42 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/components/Card.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useNavigate } from "react-router-dom";
3 | import { RoutePaths } from "../common/RoutePaths";
4 |
5 | export const Card = ({
6 | children,
7 | className = '',
8 | itemImg = null,
9 | itemName = null,
10 | itemPrice = null,
11 | itemId = null,
12 | badge = '',
13 | }) => {
14 | const navigate = useNavigate();
15 | const badgeBackgroundColor = (badge === "owned") ? "bg-burst" : "bg-dodger";
16 |
17 | return (
18 | navigate(`${RoutePaths.DETAILS}/${itemId}`)}>
19 |
20 | {badge && (
21 |
{badge}
22 | )}
23 |
24 |
25 |
26 |
27 |
{itemName}
28 |
{itemPrice} ETH
29 |
30 |
#{itemId}
31 |
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/components/Fields/InputField.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useField } from './useField';
3 |
4 | export const InputField = ({
5 | classNameContainer,
6 | textArea,
7 | inputClasses,
8 | label,
9 | disabled,
10 | name = '',
11 | placeholder = '',
12 | onChange,
13 | value,
14 | ...props
15 | }) => {
16 | const { handleChange, active } = useField({
17 | onChange,
18 | value,
19 | label,
20 | });
21 | return (
22 |
23 |
24 | {textArea ? (
25 |
35 | ) : (
36 |
46 | )}
47 |
48 | {label && (
49 |
58 | {label}
59 |
60 | )}
61 |
62 |
63 | );
64 | };
65 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/components/Fields/Select.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const Select = ({
4 | children,
5 | className = '',
6 | onChange = () => ({}),
7 | }) => {
8 | return (
9 |
13 | {children}
14 |
15 | );
16 | };
17 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/components/Fields/useField.jsx:
--------------------------------------------------------------------------------
1 | import { useLayoutEffect, useRef, useState } from 'react';
2 |
3 | export const useField = ({ onChange, value, label }) => {
4 | const firstUpdate = useRef(0);
5 | const [active, setActive] = useState(false);
6 |
7 | useLayoutEffect(() => {
8 | if (firstUpdate.current <= 1 && label) {
9 | firstUpdate.current += 1;
10 | setActive(!!value);
11 | }
12 | if (!value && label && firstUpdate.current > 1) {
13 | setActive(!!value);
14 | }
15 | }, [value]);
16 |
17 | const handleChange = e => {
18 | if (label) {
19 | setActive(!!e.target.value);
20 | }
21 | if (onChange) {
22 | onChange(e);
23 | }
24 | };
25 |
26 | return { handleChange, active };
27 | };
28 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/util/formatPrice.js:
--------------------------------------------------------------------------------
1 | export const formatPrice = (price) => {
2 | return +(price).toFixed(15)
3 | }
4 |
--------------------------------------------------------------------------------
/nft-marketplace/app/ui/util/usePriceConverter.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 |
3 | export const usePriceConverter = () => {
4 | const [data, setData] = useState({});
5 | const URL = 'https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd';
6 | const request = async () => {
7 | try {
8 | const response = await fetch(URL);
9 | const parsed = await response.json();
10 | setData(parsed);
11 | } catch (error) {
12 | console.error(error);
13 | }
14 | };
15 |
16 | useEffect(() => {
17 | request();
18 | }, []);
19 |
20 | return {
21 | converterData: data,
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/nft-marketplace/client/main.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | body {
7 | @apply bg-whisper;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/nft-marketplace/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | Meteor NFT
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/nft-marketplace/client/main.jsx:
--------------------------------------------------------------------------------
1 | import React, { Suspense } from 'react';
2 | import { Meteor } from 'meteor/meteor';
3 | import { render } from 'react-dom';
4 | import { Routes } from "../app/ui/common/Routes";
5 |
6 | Meteor.startup(() => {
7 | render(
8 | Loading... }>
9 |
10 | ,
11 | document.getElementById('react-target')
12 | );
13 | });
14 |
--------------------------------------------------------------------------------
/nft-marketplace/config.js:
--------------------------------------------------------------------------------
1 |
2 | export const marketplaceAddress = "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
3 |
--------------------------------------------------------------------------------
/nft-marketplace/hardhat.config.js:
--------------------------------------------------------------------------------
1 | require("@nomiclabs/hardhat-waffle")
2 |
3 | module.exports = {
4 | defaultNetwork: "hardhat",
5 | networks: {
6 | hardhat: {
7 | chainId: 1337
8 | },
9 | // mumbai: {
10 | // url: "https://rpc-mumbai.maticvigil.com",
11 | // accounts: [process.env.privateKey]
12 | // }
13 | },
14 | solidity: {
15 | version: "0.8.4",
16 | settings: {
17 | optimizer: {
18 | enabled: true,
19 | runs: 200
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/nft-marketplace/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nft-marketplace",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run",
6 | "test": "meteor test --once --driver-package meteortesting:mocha",
7 | "test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha",
8 | "visualize": "meteor --production --extra-packages bundle-visualizer"
9 | },
10 | "dependencies": {
11 | "@babel/runtime": "^7.15.4",
12 | "@headlessui/react": "^1.6.1",
13 | "@heroicons/react": "^1.0.6",
14 | "@nomiclabs/hardhat-ethers": "^2.0.5",
15 | "@nomiclabs/hardhat-waffle": "^2.0.3",
16 | "@openzeppelin/contracts": "^4.6.0",
17 | "autoprefixer": "^10.4.7",
18 | "axios": "^0.27.2",
19 | "chai": "^4.3.6",
20 | "electron": "^18.2.0",
21 | "ethereum-waffle": "^3.4.4",
22 | "ethers": "^5.6.5",
23 | "hardhat": "^2.9.3",
24 | "ipfs-http-client": "^56.0.3",
25 | "meteor-node-stubs": "^1.2.1",
26 | "pluralize": "^8.0.0",
27 | "postcss": "^8.4.13",
28 | "postcss-load-config": "^3.1.4",
29 | "react": "^17.0.2",
30 | "react-dom": "^17.0.2",
31 | "react-router-dom": "^6.3.0",
32 | "tailwindcss": "^3.0.24",
33 | "truncate-eth-address": "^1.0.2",
34 | "web3modal": "^1.9.7"
35 | },
36 | "meteor": {
37 | "mainModule": {
38 | "client": "client/main.jsx",
39 | "server": "server/main.js"
40 | },
41 | "testModule": "tests/main.js"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/nft-marketplace/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/nft-marketplace/public/images/bg-stars.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/nft-marketplace/public/images/default-profile-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/nft-marketplace/public/images/default-profile-avatar.png
--------------------------------------------------------------------------------
/nft-marketplace/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/nft-marketplace/public/images/logo.png
--------------------------------------------------------------------------------
/nft-marketplace/public/images/metamask-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/nft-marketplace/public/images/metamask-logo.png
--------------------------------------------------------------------------------
/nft-marketplace/scripts/deploy.js:
--------------------------------------------------------------------------------
1 | const hre = require("hardhat");
2 | const fs = require('fs');
3 |
4 | async function main() {
5 | const NFTMarketplace = await hre.ethers.getContractFactory("NFTMarketplace");
6 | const nftMarketplace = await NFTMarketplace.deploy();
7 | await nftMarketplace.deployed();
8 | console.log("nftMarketplace deployed to:", nftMarketplace.address);
9 |
10 | fs.writeFileSync('./config.js', `
11 | export const marketplaceAddress = "${nftMarketplace.address}"
12 | `)
13 | }
14 |
15 | main()
16 | .then(() => process.exit(0))
17 | .catch((error) => {
18 | console.error(error);
19 | process.exit(1);
20 | });
21 |
--------------------------------------------------------------------------------
/nft-marketplace/server/main.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 |
3 | Meteor.startup(() => {
4 | });
5 |
--------------------------------------------------------------------------------
/nft-marketplace/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: ["./app/ui/**/*.{js,jsx}"],
3 | theme: {
4 | colors: {
5 | // Primary
6 | dodger: '#595DFF',
7 | burst: '#1B2448',
8 | orange: '#FF6A3E',
9 | white: '#FFFFFF',
10 |
11 | // Secondary
12 | manatee: '#8D91A3',
13 | rhino: '#292B5E',
14 | martinique: '#302C4D',
15 | violet: '#4746B9',
16 | lilac: '#EFF0F9',
17 | whisper: '#F9F9FD',
18 | porcelain: '#F3F4F5',
19 | vermilion: '#FF460F',
20 | green: '#2AAF62',
21 | paypal: '#FFBC32',
22 | black: '#000000',
23 | lightOrange: '#FFF3F0',
24 |
25 | // Etc
26 | transparent: 'transparent',
27 | },
28 |
29 | fontSize: {
30 | h1: ['36px', '1.2'],
31 | h2: ['28px', '1.2'],
32 | h3: ['24px', '1.2'],
33 | h4: ['20px', '1.2'],
34 | h5: ['16px', '1.2'],
35 | subtitle: ['20px', '1.4'],
36 | overline: ['12px', '1'],
37 | body: ['16px', '1'],
38 | p: ['16px', '1.5'],
39 | 'p-big': ['18px', '1.5'],
40 | small: ['14px', '1.4'],
41 | caption: ['12px', '1.5'],
42 | button: ['14px', '1.5'],
43 | big: ['40px', '1.2'],
44 | huge: ['56px', '1.2'],
45 | },
46 |
47 | fontFamily: {
48 | display: ['Pulp Display', 'Arial', 'sans-serif'],
49 | body: ['Pulp Display', 'Arial', 'sans-serif'],
50 | },
51 |
52 | extend: {
53 | backgroundImage: {
54 | 'bg-stars': "url('/images/bg-stars.svg')",
55 | },
56 | },
57 | },
58 | plugins: [],
59 | }
60 |
--------------------------------------------------------------------------------
/nft-marketplace/tests/hardhat.js:
--------------------------------------------------------------------------------
1 | describe("NFTMarket", function() {
2 | it("Should create and execute market sales", async function() {
3 | /* deploy the marketplace */
4 | const NFTMarketplace = await ethers.getContractFactory("NFTMarketplace")
5 | const nftMarketplace = await NFTMarketplace.deploy()
6 | await nftMarketplace.deployed()
7 |
8 | let listingPrice = await nftMarketplace.getListingPrice()
9 | listingPrice = listingPrice.toString()
10 |
11 | const auctionPrice = ethers.utils.parseUnits('1', 'ether')
12 |
13 | /* create two tokens */
14 | await nftMarketplace.createToken("https://www.mytokenlocation.com", auctionPrice, { value: listingPrice })
15 | await nftMarketplace.createToken("https://www.mytokenlocation2.com", auctionPrice, { value: listingPrice })
16 |
17 | const [_, buyerAddress] = await ethers.getSigners()
18 |
19 | /* execute sale of token to another user */
20 | await nftMarketplace.connect(buyerAddress).createMarketSale(1, { value: auctionPrice })
21 |
22 | /* resell a token */
23 | await nftMarketplace.connect(buyerAddress).resellToken(1, auctionPrice, { value: listingPrice })
24 |
25 | /* query for and return the unsold items */
26 | items = await nftMarketplace.fetchMarketItems()
27 | items = await Promise.all(items.map(async i => {
28 | const tokenUri = await nftMarketplace.tokenURI(i.tokenId)
29 | let item = {
30 | price: i.price.toString(),
31 | tokenId: i.tokenId.toString(),
32 | seller: i.seller,
33 | owner: i.owner,
34 | tokenUri
35 | }
36 | return item
37 | }))
38 | console.log('items: ', items)
39 | })
40 | })
41 |
--------------------------------------------------------------------------------
/nft-marketplace/tests/main.js:
--------------------------------------------------------------------------------
1 | import assert from "assert";
2 |
3 | describe("nft-marketplace", function () {
4 | it("package.json has correct name", async function () {
5 | const { name } = await import("../package.json");
6 | assert.strictEqual(name, "nft-marketplace");
7 | });
8 |
9 | if (Meteor.isClient) {
10 | it("client is not server", function () {
11 | assert.strictEqual(Meteor.isServer, false);
12 | });
13 | }
14 |
15 | if (Meteor.isServer) {
16 | it("server is not client", function () {
17 | assert.strictEqual(Meteor.isClient, false);
18 | });
19 | }
20 | });
21 |
--------------------------------------------------------------------------------
/parties/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/parties/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 | 1.7-split-underscore-from-meteor-base
19 | 1.8.3-split-jquery-from-blaze
20 |
--------------------------------------------------------------------------------
/parties/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/parties/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | bjmvobfa3oxf.js3k197m568
8 |
--------------------------------------------------------------------------------
/parties/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.5.1 # Packages every Meteor app needs to have
8 | mobile-experience@1.1.0 # Packages for a great mobile UX
9 | mongo@1.12.0 # The database Meteor supports right now
10 | blaze-html-templates # Compile .html files into Meteor Blaze views
11 | jquery # Wrapper package for npm-installed jquery
12 | reactive-var@1.0.11 # Reactive variable for tracker
13 | tracker@1.2.0 # Meteor's client-side reactive programming library
14 |
15 | standard-minifier-css@1.7.3 # CSS minifier run for production mode
16 | standard-minifier-js@2.6.1 # JS minifier run for production mode
17 | es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers
18 | ecmascript@0.15.3 # Enable ECMAScript2015+ syntax in app code
19 | typescript@4.3.5 # Enable TypeScript syntax in .ts and .tsx modules
20 | shell-server@0.5.0 # Server-side component of the `meteor shell` command
21 | session@1.2.0
22 | check@1.3.1
23 | audit-argument-checks@1.0.7
24 | email@2.1.1
25 | accounts-facebook@1.3.3
26 | accounts-twitter@1.5.0
27 | d3
28 | accounts-password@2.0.0
29 | accounts-ui@1.4.0
30 |
--------------------------------------------------------------------------------
/parties/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/parties/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@2.3.5
2 |
--------------------------------------------------------------------------------
/parties/.meteor/versions:
--------------------------------------------------------------------------------
1 | accounts-base@2.0.1
2 | accounts-facebook@1.3.3
3 | accounts-oauth@1.3.0
4 | accounts-password@2.0.0
5 | accounts-twitter@1.5.0
6 | accounts-ui@1.4.0
7 | accounts-ui-unstyled@1.5.0
8 | allow-deny@1.1.0
9 | audit-argument-checks@1.0.7
10 | autoupdate@1.7.0
11 | babel-compiler@7.7.0
12 | babel-runtime@1.5.0
13 | base64@1.0.12
14 | binary-heap@1.0.11
15 | blaze@2.5.0
16 | blaze-html-templates@1.2.1
17 | blaze-tools@1.1.2
18 | boilerplate-generator@1.7.1
19 | caching-compiler@1.2.2
20 | caching-html-compiler@1.2.0
21 | callback-hook@1.3.1
22 | check@1.3.1
23 | d3@1.0.0
24 | ddp@1.4.0
25 | ddp-client@2.5.0
26 | ddp-common@1.4.0
27 | ddp-rate-limiter@1.1.0
28 | ddp-server@2.4.1
29 | diff-sequence@1.1.1
30 | dynamic-import@0.7.1
31 | ecmascript@0.15.3
32 | ecmascript-runtime@0.7.0
33 | ecmascript-runtime-client@0.11.1
34 | ecmascript-runtime-server@0.10.1
35 | ejson@1.1.1
36 | email@2.1.1
37 | es5-shim@4.8.0
38 | facebook-oauth@1.9.1
39 | fetch@0.1.1
40 | geojson-utils@1.0.10
41 | hot-code-push@1.0.4
42 | html-tools@1.1.2
43 | htmljs@1.1.1
44 | http@2.0.0
45 | id-map@1.1.1
46 | inter-process-messaging@0.1.1
47 | jquery@3.0.0
48 | launch-screen@1.3.0
49 | less@3.0.2
50 | localstorage@1.2.0
51 | logging@1.2.0
52 | meteor@1.9.3
53 | meteor-base@1.5.1
54 | minifier-css@1.5.4
55 | minifier-js@2.6.1
56 | minimongo@1.7.0
57 | mobile-experience@1.1.0
58 | mobile-status-bar@1.1.0
59 | modern-browsers@0.1.5
60 | modules@0.16.0
61 | modules-runtime@0.12.0
62 | mongo@1.12.0
63 | mongo-decimal@0.1.2
64 | mongo-dev-server@1.1.0
65 | mongo-id@1.0.8
66 | npm-mongo@3.9.1
67 | oauth@2.0.0
68 | oauth1@1.4.1
69 | oauth2@1.3.1
70 | observe-sequence@1.0.19
71 | ordered-dict@1.1.0
72 | promise@0.12.0
73 | random@1.2.0
74 | rate-limit@1.0.9
75 | react-fast-refresh@0.1.1
76 | reactive-dict@1.3.0
77 | reactive-var@1.0.11
78 | reload@1.3.1
79 | retry@1.1.0
80 | routepolicy@1.1.1
81 | service-configuration@1.1.0
82 | session@1.2.0
83 | sha@1.0.9
84 | shell-server@0.5.0
85 | socket-stream-client@0.4.0
86 | spacebars@1.2.0
87 | spacebars-compiler@1.2.1
88 | standard-minifier-css@1.7.3
89 | standard-minifier-js@2.6.1
90 | templating@1.4.1
91 | templating-compiler@1.4.1
92 | templating-runtime@1.5.0
93 | templating-tools@1.2.0
94 | tracker@1.2.0
95 | twitter-oauth@1.3.0
96 | typescript@4.3.5
97 | ui@1.0.13
98 | underscore@1.0.10
99 | url@1.3.2
100 | webapp@1.11.1
101 | webapp-hashing@1.1.0
102 |
--------------------------------------------------------------------------------
/parties/client/main.css:
--------------------------------------------------------------------------------
1 | .header {
2 | padding: 20px 0;
3 | }
4 |
5 | .details {
6 | margin-top: -18px;
7 | }
8 |
9 | .mask {
10 | position: absolute;
11 | width: 100%;
12 | height: 100%;
13 | top: 0px;
14 | left: 0px;
15 | background-color: #000000;
16 | opacity: .4;
17 | z-index: 1;
18 | }
19 |
20 | .invite-row .invite {
21 | margin: 10px 10px 10px 0;
22 | }
23 |
24 | .rsvp-buttons {
25 | text-align: center;
26 | margin: 40px 0 40px 0;
27 | }
28 |
29 | .attendance .who {
30 | margin-bottom: 5px;
31 | }
32 |
33 | .attendance .invite {
34 | text-align: center;
35 | }
36 |
37 | input.chosen {
38 | font-weight: bold;
39 | }
40 |
41 | .map {
42 | position: relative;
43 | background-image: url('/soma.png');
44 | background-position: -20px -20px;
45 | width: 500px;
46 | height: 500px;
47 | }
48 |
49 | .map circle.public {
50 | fill: #49AFCD;
51 | }
52 |
53 | .map circle.private {
54 | fill: #DA4F49;
55 | }
56 |
57 | .map text {
58 | text-anchor: middle;
59 | fill: white;
60 | font-weight: bold;
61 | }
62 |
63 | .map circle.callout {
64 | stroke-width: 5px;
65 | stroke-dasharray: 9, 5;
66 | stroke-opacity: .8;
67 | fill: none;
68 | stroke: red;
69 | }
70 |
71 | .attribution {
72 | position: absolute;
73 | bottom: 0;
74 | background-color: white;
75 | padding: 3px;
76 | padding-bottom: 0;
77 | }
78 |
79 | .modal {
80 | display: block !important;
81 | overflow-x: hidden !important;
82 | overflow-y: auto !important;
83 | }
--------------------------------------------------------------------------------
/parties/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parties",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run --exclude-archs web.browser.legacy",
6 | "test": "meteor test --once --driver-package meteortesting:mocha",
7 | "test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha",
8 | "visualize": "meteor --production --extra-packages bundle-visualizer"
9 | },
10 | "dependencies": {
11 | "@babel/runtime": "^7.15.3",
12 | "bcrypt": "^5.0.1",
13 | "bootstrap": "^3.4.1",
14 | "jquery": "^3.6.0",
15 | "lodash": "^4.17.21",
16 | "meteor-node-stubs": "^1.1.0"
17 | },
18 | "meteor": {
19 | "mainModule": {
20 | "client": "client/main.js",
21 | "server": "server/main.js"
22 | },
23 | "testModule": "tests/main.js"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/parties/public/soma.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/parties/public/soma.png
--------------------------------------------------------------------------------
/parties/server/main.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 | import { Parties } from '../imports/model';
3 |
4 | Meteor.publish("directory", () => {
5 | return Meteor.users.find({}, {fields: {emails: 1, profile: 1}});
6 | });
7 |
8 | Meteor.publish("parties", () => {
9 | return Parties.find(
10 | {$or: [{"public": true}, {invited: this.userId}, {owner: this.userId}]});
11 | });
12 |
13 | Meteor.startup(() => {
14 | // code to run on server at startup
15 | });
16 |
--------------------------------------------------------------------------------
/parties/tests/main.js:
--------------------------------------------------------------------------------
1 | import assert from "assert";
2 |
3 | describe("parties", function () {
4 | it("package.json has correct name", async function () {
5 | const { name } = await import("../package.json");
6 | assert.strictEqual(name, "parties");
7 | });
8 |
9 | if (Meteor.isClient) {
10 | it("client is not server", function () {
11 | assert.strictEqual(Meteor.isServer, false);
12 | });
13 | }
14 |
15 | if (Meteor.isServer) {
16 | it("server is not client", function () {
17 | assert.strictEqual(Meteor.isClient, false);
18 | });
19 | }
20 | });
21 |
--------------------------------------------------------------------------------
/tailwindcss/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | yarn.lock
61 |
62 | # next.js build output
63 | .next
64 |
65 | # webstorm
66 | **/.idea/*
67 | !.idea/runConfigurations
68 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 | 1.7-split-underscore-from-meteor-base
19 | 1.8.3-split-jquery-from-blaze
20 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | eayxv1ctyi5j.dpq413mdo90p
8 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/packages:
--------------------------------------------------------------------------------
1 | meteor-base@1.5.1
2 | mobile-experience@1.1.0
3 | mongo@1.16.0
4 | reactive-var@1.0.11
5 |
6 | standard-minifier-js@2.8.1
7 | es5-shim@4.8.0
8 | ecmascript@0.16.2
9 | shell-server@0.5.0
10 |
11 | static-html@1.3.2
12 | hot-module-replacement@0.5.1
13 | dev-error-overlay@0.1.1
14 |
15 | juliancwirko:postcss
16 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@2.8.0
2 |
--------------------------------------------------------------------------------
/tailwindcss/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@1.1.1
2 | autoupdate@1.8.0
3 | babel-compiler@7.9.2
4 | babel-runtime@1.5.1
5 | base64@1.0.12
6 | binary-heap@1.0.11
7 | blaze-tools@1.1.3
8 | boilerplate-generator@1.7.1
9 | caching-compiler@1.2.2
10 | caching-html-compiler@1.2.1
11 | callback-hook@1.4.0
12 | check@1.3.1
13 | ddp@1.4.0
14 | ddp-client@2.6.0
15 | ddp-common@1.4.0
16 | ddp-server@2.6.0
17 | dev-error-overlay@0.1.1
18 | diff-sequence@1.1.1
19 | dynamic-import@0.7.2
20 | ecmascript@0.16.2
21 | ecmascript-runtime@0.8.0
22 | ecmascript-runtime-client@0.12.1
23 | ecmascript-runtime-server@0.11.0
24 | ejson@1.1.2
25 | es5-shim@4.8.0
26 | fetch@0.1.1
27 | geojson-utils@1.0.10
28 | hot-code-push@1.0.4
29 | hot-module-replacement@0.5.1
30 | html-tools@1.1.3
31 | htmljs@1.1.1
32 | id-map@1.1.1
33 | inter-process-messaging@0.1.1
34 | juliancwirko:postcss@2.1.0
35 | launch-screen@1.3.0
36 | logging@1.3.1
37 | meteor@1.10.1
38 | meteor-base@1.5.1
39 | minifier-css@1.6.1
40 | minifier-js@2.7.5
41 | minimongo@1.9.0
42 | mobile-experience@1.1.0
43 | mobile-status-bar@1.1.0
44 | modern-browsers@0.1.8
45 | modules@0.19.0
46 | modules-runtime@0.13.0
47 | modules-runtime-hot@0.14.0
48 | mongo@1.16.0
49 | mongo-decimal@0.1.3
50 | mongo-dev-server@1.1.0
51 | mongo-id@1.0.8
52 | npm-mongo@4.9.0
53 | ordered-dict@1.1.0
54 | promise@0.12.0
55 | random@1.2.0
56 | react-fast-refresh@0.2.3
57 | reactive-var@1.0.11
58 | reload@1.3.1
59 | retry@1.1.0
60 | routepolicy@1.1.1
61 | shell-server@0.5.0
62 | socket-stream-client@0.5.0
63 | spacebars-compiler@1.3.1
64 | standard-minifier-js@2.8.1
65 | static-html@1.3.2
66 | templating-tools@1.2.2
67 | tmeasday:check-npm-versions@1.0.2
68 | tracker@1.2.0
69 | typescript@4.5.4
70 | underscore@1.0.10
71 | webapp@1.13.1
72 | webapp-hashing@1.1.0
73 |
--------------------------------------------------------------------------------
/tailwindcss/.postcssrc.js:
--------------------------------------------------------------------------------
1 | module.exports = ctx => {
2 | // This flag is set when loading configuration by this package.
3 | if (ctx.meteor) {
4 | const config = {
5 | plugins: {
6 | tailwindcss: {},
7 | autoprefixer: {},
8 | },
9 | };
10 |
11 | if (ctx.env === 'production') {
12 | // "autoprefixer" is reported to be slow,
13 | // so we use it only in production.
14 | config.plugins.autoprefixer = {
15 | overrideBrowserslist: ['defaults'],
16 | };
17 | }
18 |
19 | return config;
20 | } else {
21 | return {};
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/tailwindcss/README.md:
--------------------------------------------------------------------------------
1 | # tailwind Meteor example
2 |
3 | ## Tailwind setup
4 |
5 | The setup is already done in this project, but if you want to do it in another project you can follow the steps below.
6 |
7 | They are very similar to the recommendation in the [installation page](https://tailwindcss.com/docs/installation) of Tailwind.
8 |
9 | ### 1 - Install npm dependencies
10 | ```bash
11 | meteor npm install tailwindcss@latest postcss@latest postcss-load-config@latest autoprefixer@latest
12 | ```
13 | See [package.json](package.json) as example.
14 |
15 | ### 2 - Install Meteor package for postcss
16 |
17 | And remove the standard minifier.
18 |
19 | ```bash
20 | meteor remove standard-minifier-css
21 | meteor add juliancwirko:postcss
22 | ```
23 |
24 | See [packages](.meteor/packages) as example.
25 |
26 | ### 3 - Configure postcss
27 |
28 | See [.postcssrc.js](.postcssrc.js) as example.
29 |
30 | ### 4 - Include Tailwind in your CSS
31 |
32 | ```css
33 | @tailwind base;
34 | @tailwind components;
35 | @tailwind utilities;
36 | ```
37 | See [main.css](client/main.css) as example.
38 |
39 | ### 5 - Configure Tailwind
40 |
41 | See [tailwind.config.js](tailwind.config.js) as example.
42 |
43 | ## Running the example
44 |
45 | ### Install dependencies
46 |
47 | ```bash
48 | meteor npm install
49 | ```
50 |
51 | ### Running
52 |
53 | ```bash
54 | meteor
55 | ```
56 |
--------------------------------------------------------------------------------
/tailwindcss/client/main.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/tailwindcss/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | tailwindcss example
3 |
4 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tailwindcss/client/main.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meteor } from 'meteor/meteor';
3 | import { render } from 'react-dom';
4 | import { App } from '../imports/ui/App';
5 |
6 | Meteor.startup(() => {
7 | render( , document.getElementById('app'));
8 | });
9 |
--------------------------------------------------------------------------------
/tailwindcss/imports/ui/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Dashboard} from './Dashboard';
3 | import {List} from './List';
4 |
5 | const Title = () => (
6 |
7 |
Meteor tailwindcss Example
8 |
9 |
10 | );
11 |
12 | export const App = () => {
13 | return (
14 |
15 |
16 |
17 |
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/tailwindcss/imports/ui/Dashboard.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | /**
4 | * https://tailwindcomponents.com/component/dashboard-metrics-default
5 | */
6 | export const Dashboard = () => {
7 | return (
8 |
9 |
10 |
11 |
12 |
Total Sales
13 |
14 |
$9850.90
15 |
17 |
23 |
30 |
31 | 1.8%
32 |
33 |
34 |
35 |
36 |
Net Revenue
37 |
38 |
$7520.50
39 |
41 |
47 |
54 |
55 | 2.5%
56 |
57 |
58 |
59 |
60 |
Customers
61 |
62 |
1375
63 |
65 |
71 |
78 |
79 | 5.2%
80 |
81 |
82 |
83 |
84 |
MRR
85 |
86 |
$250.00
87 |
89 |
95 |
102 |
103 | 2.2%
104 |
105 |
106 |
107 |
108 |
109 |
110 | );
111 | };
112 |
--------------------------------------------------------------------------------
/tailwindcss/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind-meteor-example",
3 | "scripts": {
4 | "start": "yarn && meteor run"
5 | },
6 | "dependencies": {
7 | "@babel/runtime": "^7.13.9",
8 | "autoprefixer": "^10.2.5",
9 | "meteor-node-stubs": "^1.0.1",
10 | "postcss": "^8.4.18",
11 | "postcss-load-config": "^3.0.1",
12 | "react": "^17.0.1",
13 | "react-dom": "^17.0.1",
14 | "tailwindcss": "^2.0.3"
15 | },
16 | "meteor": {
17 | "mainModule": {
18 | "client": "client/main.js",
19 | "server": "server/main.js"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tailwindcss/public/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
16 |
17 |
--------------------------------------------------------------------------------
/tailwindcss/server/main.js:
--------------------------------------------------------------------------------
1 | Meteor.startup(() => {
2 | console.info('server ready');
3 | });
4 |
--------------------------------------------------------------------------------
/tailwindcss/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const colors = require('tailwindcss/colors');
2 |
3 | module.exports = {
4 | purge: ['./imports/ui/**/*.{js,jsx,ts,tsx}', './public/*.html'],
5 | darkMode: false, // or 'media' or 'class'
6 | theme: {
7 | fontFamily: {
8 | display: ['Martel Sans', 'sans-serif'],
9 | body: ['Martel Sans', 'sans-serif'],
10 | },
11 | extend: {
12 | spacing: {
13 | '128': '32rem',
14 | '112': '28rem',
15 | '96': '24rem',
16 | '80': '20rem',
17 | '7': '1.875rem',
18 | },
19 | fontSize: {
20 | '4xs': '0.625rem',
21 | '3xs': '0.6875rem',
22 | '2xs': '0.75rem',
23 | xs: '0.8125rem',
24 | },
25 | colors: {
26 | fuchsia: colors.amber,
27 | },
28 | },
29 | },
30 | variants: {
31 | extend: {},
32 | },
33 | plugins: [],
34 | };
35 |
--------------------------------------------------------------------------------
/tic-tac-toe/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .idea/
3 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 | 1.4.3-split-account-service-packages
17 | 1.5-add-dynamic-import-package
18 | 1.7-split-underscore-from-meteor-base
19 | 1.8.3-split-jquery-from-blaze
20 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | e5k7zke3l6m3.wwqnjor0gk7
8 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.5.2-beta300.6 # Packages every Meteor app needs to have
8 | mobile-experience@1.1.1-beta300.6 # Packages for a great mobile UX
9 | mongo@2.0.0-beta300.6 # The database Meteor supports right now
10 | reactive-var@1.0.13-beta300.6 # Reactive variable for tracker
11 |
12 | standard-minifier-css@1.9.3-beta300.6 # CSS minifier run for production mode
13 | standard-minifier-js@3.0.0-beta300.6 # JS minifier run for production mode
14 | es5-shim@4.8.1-beta300.6 # ECMAScript 5 compatibility for older browsers
15 | ecmascript@0.16.8-beta300.6 # Enable ECMAScript2015+ syntax in app code
16 | typescript@5.3.3-beta300.6 # Enable TypeScript syntax in .ts and .tsx modules
17 | shell-server@0.6.0-beta300.6 # Server-side component of the `meteor shell` command
18 | hot-module-replacement@0.5.4-beta300.6 # Update client in development without reloading the page
19 |
20 | insecure@1.0.8-beta300.6 # Allow all DB writes from clients (for prototyping)
21 | static-html@1.3.3-beta300.6 # Define static page content in .html files
22 | react-meteor-data@3.0.0-beta300.1
23 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@3.0-beta.6
2 |
--------------------------------------------------------------------------------
/tic-tac-toe/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@2.0.0-beta300.6
2 | autoupdate@2.0.0-beta300.6
3 | babel-compiler@7.11.0-beta300.6
4 | babel-runtime@1.5.2-beta300.6
5 | base64@1.0.13-beta300.6
6 | binary-heap@1.0.12-beta300.6
7 | blaze-tools@2.0.0-alpha300.17
8 | boilerplate-generator@2.0.0-beta300.6
9 | caching-compiler@2.0.0-beta300.6
10 | caching-html-compiler@2.0.0-alpha300.17
11 | callback-hook@1.6.0-beta300.6
12 | check@1.3.3-beta300.6
13 | core-runtime@1.0.0-beta300.6
14 | ddp@1.4.2-beta300.6
15 | ddp-client@3.0.0-beta300.6
16 | ddp-common@1.4.1-beta300.6
17 | ddp-server@3.0.0-beta300.6
18 | diff-sequence@1.1.3-beta300.6
19 | dynamic-import@0.7.4-beta300.6
20 | ecmascript@0.16.8-beta300.6
21 | ecmascript-runtime@0.8.2-beta300.6
22 | ecmascript-runtime-client@0.12.2-beta300.6
23 | ecmascript-runtime-server@0.11.1-beta300.6
24 | ejson@1.1.4-beta300.6
25 | es5-shim@4.8.1-beta300.6
26 | facts-base@1.0.2-beta300.6
27 | fetch@0.1.4-beta300.6
28 | geojson-utils@1.0.12-beta300.6
29 | hot-code-push@1.0.5-beta300.6
30 | hot-module-replacement@0.5.4-beta300.6
31 | html-tools@2.0.0-alpha300.17
32 | htmljs@2.0.0-alpha300.17
33 | id-map@1.2.0-beta300.6
34 | insecure@1.0.8-beta300.6
35 | inter-process-messaging@0.1.2-beta300.6
36 | launch-screen@1.3.1-beta300.6
37 | logging@1.3.3-beta300.6
38 | meteor@2.0.0-beta300.6
39 | meteor-base@1.5.2-beta300.6
40 | minifier-css@2.0.0-beta300.6
41 | minifier-js@3.0.0-beta300.6
42 | minimongo@2.0.0-beta300.6
43 | mobile-experience@1.1.1-beta300.6
44 | mobile-status-bar@1.1.1-beta300.6
45 | modern-browsers@0.1.10-beta300.6
46 | modules@0.19.1-beta300.6
47 | modules-runtime@0.13.2-beta300.6
48 | modules-runtime-hot@0.14.3-beta300.6
49 | mongo@2.0.0-beta300.6
50 | mongo-decimal@0.1.4-beta300.6
51 | mongo-dev-server@1.1.1-beta300.6
52 | mongo-id@1.0.9-beta300.6
53 | npm-mongo@4.16.1-beta300.6
54 | ordered-dict@1.2.0-beta300.6
55 | promise@1.0.0-beta300.6
56 | random@1.2.2-beta300.6
57 | react-fast-refresh@0.2.8-beta300.6
58 | react-meteor-data@3.0.0-beta300.1
59 | reactive-var@1.0.13-beta300.6
60 | reload@1.3.2-beta300.6
61 | retry@1.1.1-beta300.6
62 | routepolicy@1.1.2-beta300.6
63 | shell-server@0.6.0-beta300.6
64 | socket-stream-client@0.5.2-beta300.6
65 | spacebars-compiler@2.0.0-alpha300.17
66 | standard-minifier-css@1.9.3-beta300.6
67 | standard-minifier-js@3.0.0-beta300.6
68 | static-html@1.3.3-beta300.6
69 | templating-tools@2.0.0-alpha300.17
70 | tracker@1.3.3-beta300.6
71 | typescript@5.3.3-beta300.6
72 | underscore@1.0.14-beta300.6
73 | webapp@2.0.0-beta300.6
74 | webapp-hashing@1.1.2-beta300.6
75 |
--------------------------------------------------------------------------------
/tic-tac-toe/README.md:
--------------------------------------------------------------------------------
1 | #Tic tac toe
2 | Simple multiplayer game with multi-room support.
3 |
4 |
5 | ## Running the example
6 |
7 | ### Install dependencies
8 |
9 | ```bash
10 | meteor npm install
11 | ```
12 |
13 | ### Running
14 |
15 | ```bash
16 | meteor
17 | ```
18 |
19 | ## How to play it
20 |
21 | https://www.loom.com/share/6631f5dc1f8848e399616e75bf156b6c
22 |
--------------------------------------------------------------------------------
/tic-tac-toe/client/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 10px;
3 | font-family: sans-serif;
4 | }
5 |
--------------------------------------------------------------------------------
/tic-tac-toe/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | tic-tac-toe
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tic-tac-toe/client/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Meteor } from 'meteor/meteor';
3 | import { App } from '/imports/ui/App';
4 | import { render } from 'react-dom'
5 |
6 | Meteor.startup(() => {
7 | const root = document.getElementById('react-target')
8 | render( , root)
9 | });
10 |
--------------------------------------------------------------------------------
/tic-tac-toe/imports/api/rooms.js:
--------------------------------------------------------------------------------
1 | import { Mongo } from "meteor/mongo";
2 | import { Meteor } from "meteor/meteor";
3 |
4 | export const RoomCollection = new Mongo.Collection("rooms");
5 |
6 | function checkEndGame(gameState) {
7 | const sameColor = (x, y, z) =>
8 | new Set([gameState[x - 1], gameState[y - 1], gameState[z - 1]]).size ===
9 | 1 &&
10 | gameState[x - 1] !== "empty" &&
11 | gameState[x - 1];
12 | return (
13 | sameColor(1, 2, 3) ||
14 | sameColor(4, 5, 6) ||
15 | sameColor(7, 8, 9) ||
16 | sameColor(1, 4, 7) ||
17 | sameColor(2, 5, 8) ||
18 | sameColor(3, 6, 9) ||
19 | sameColor(1, 5, 9) ||
20 | sameColor(3, 5, 7)
21 | );
22 | }
23 |
24 | Meteor.methods({
25 | async createRoom() {
26 | const roomId = await RoomCollection.insertAsync({
27 | createdAt: new Date(),
28 | capacity: 2,
29 | gameState: new Array(9).fill("empty"),
30 | colorTurn: "cross",
31 | winner: null,
32 | });
33 | return RoomCollection.findOneAsync(roomId);
34 | },
35 | async joinRoom({ roomId }) {
36 | await RoomCollection.updateAsync(
37 | { _id: roomId, capacity: { $gte: 1 } },
38 | { $inc: { capacity: -1 } }
39 | );
40 | const room = await RoomCollection.findOneAsync(roomId);
41 | if (!room) {
42 | throw new Meteor.Error("Room not found, or full!");
43 | }
44 | return {
45 | room,
46 | color: room.capacity === 1 ? "cross" : "circle",
47 | };
48 | },
49 | async makePlay({ roomId, playState: { color, play } }) {
50 | const otherColor = color === "cross" ? "circle" : "cross";
51 | const query = {
52 | _id: roomId,
53 | colorTurn: color,
54 | winner: null,
55 | [`gameState.${play}`]: "empty",
56 | };
57 | await RoomCollection.updateAsync(query, {
58 | $set: { colorTurn: otherColor, [`gameState.${play}`]: color },
59 | });
60 | const room = await RoomCollection.findOneAsync(roomId);
61 |
62 | if (!room) {
63 | throw new Meteor.Error("invalid-play");
64 | }
65 | const winner = checkEndGame(room.gameState);
66 | if (winner && winner !== "empty") {
67 | await RoomCollection.updateAsync(roomId, { $set: { winner } });
68 | return await RoomCollection.findOneAsync(roomId);
69 | }
70 |
71 | return room;
72 | },
73 | });
74 |
--------------------------------------------------------------------------------
/tic-tac-toe/imports/ui/App.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
4 | import { GameScreen } from "/imports/ui/GameScreen";
5 | import { RoomList } from "/imports/ui/RoomList";
6 |
7 | export const App = () => (
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 |
--------------------------------------------------------------------------------
/tic-tac-toe/imports/ui/GameScreen.jsx:
--------------------------------------------------------------------------------
1 | import "./game.css";
2 | import React, { useEffect } from "react";
3 | import { useHistory, useLocation, useParams } from "react-router";
4 | import { useTracker, useFind } from "meteor/react-meteor-data";
5 | import { RoomCollection } from "../api/rooms";
6 |
7 | const Slot = ({ id, room: { gameState, _id } }) => {
8 | const location = useLocation();
9 | const { color } = location.state;
10 | return (
11 | {
14 | try {
15 | await Meteor.callAsync("makePlay", {
16 | roomId: _id,
17 | playState: { play: id - 1, color },
18 | });
19 | } catch (e) {
20 | if (e.error === "invalid-play") {
21 | alert(
22 | "This move is invalid. You might need to wait for your turn!"
23 | );
24 | } else {
25 | alert(e.message);
26 | }
27 | }
28 | }}
29 | >
30 | {gameState[id - 1] === "cross" ?
: ""}
31 | {gameState[id - 1] === "circle" ?
: ""}
32 |
33 | );
34 | };
35 |
36 | export const GameScreen = () => {
37 | const { id } = useParams();
38 | const location = useLocation();
39 | const history = useHistory();
40 | const { color } = location.state;
41 | const roomLoading = useTracker(() => {
42 | // Note that this subscription will get cleaned up
43 | // when your component is unmounted or deps change.
44 | const handle = Meteor.subscribe("room", { _id: id });
45 | return !handle.ready();
46 | }, [id]);
47 | const [room] = useFind(() => RoomCollection.find({ _id: id }), [id]);
48 |
49 | useEffect(() => {
50 | if (room && room.winner) {
51 | alert(room.winner === color ? "You Won!" : "You Lost!!");
52 | history.push("/");
53 | }
54 | }, [room]);
55 |
56 | if (roomLoading) return "Loading...";
57 |
58 | return (
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | );
77 | };
78 |
--------------------------------------------------------------------------------
/tic-tac-toe/imports/ui/RoomList.jsx:
--------------------------------------------------------------------------------
1 | import { useSubscribe, useFind } from "meteor/react-meteor-data";
2 | import React from "react";
3 | import { RoomCollection } from "../api/rooms";
4 | import { useHistory } from "react-router";
5 |
6 | export const RoomList = () => {
7 | const history = useHistory();
8 | const listLoading = useSubscribe("rooms");
9 | const rooms = useFind(() => RoomCollection.find({}), []);
10 |
11 | if (listLoading()) return "Loading...";
12 | return (
13 |
14 |
{
16 | await Meteor.callAsync("createRoom");
17 | }}
18 | >
19 | {" "}
20 | Create Room{" "}
21 |
22 |
23 | {rooms.map(({ _id, capacity, winner }) => (
24 |
25 | Room {_id}
26 | {winner ? `Winner:${winner}` : ""}
27 |
28 | {
31 | Meteor.callAsync("joinRoom", { roomId: _id }).then(
32 | ({ room, color }) => {
33 | history.push(`/game/${room._id}`, { color });
34 | }
35 | );
36 | }}
37 | >
38 | {" "}
39 | Join Room{" "}
40 |
41 |
42 | ))}
43 |
44 |
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/tic-tac-toe/imports/ui/game.css:
--------------------------------------------------------------------------------
1 | .game {
2 | display: flex;
3 | flex-direction: column;
4 | width: calc(100vw - 3px);
5 | height: calc(100vh - 6px);
6 | }
7 | .line {
8 | display: flex;
9 | flex-direction: row;
10 | width: 100%;
11 | height: calc(100% / 3);
12 | }
13 | .slot {
14 | border: solid black 3px;
15 | flex-basis: calc(100% / 3);
16 | height: 100%;
17 | }
18 | html,
19 | body,
20 | body div,
21 | span,
22 | object,
23 | iframe,
24 | h1,
25 | h2,
26 | h3,
27 | h4,
28 | h5,
29 | h6,
30 | p,
31 | blockquote,
32 | pre,
33 | abbr,
34 | address,
35 | cite,
36 | code,
37 | del,
38 | dfn,
39 | em,
40 | img,
41 | ins,
42 | kbd,
43 | q,
44 | samp,
45 | small,
46 | strong,
47 | sub,
48 | sup,
49 | var,
50 | b,
51 | i,
52 | dl,
53 | dt,
54 | dd,
55 | ol,
56 | ul,
57 | li,
58 | fieldset,
59 | form,
60 | label,
61 | legend,
62 | table,
63 | caption,
64 | tbody,
65 | tfoot,
66 | thead,
67 | tr,
68 | th,
69 | td,
70 | article,
71 | aside,
72 | figure,
73 | footer,
74 | header,
75 | hgroup,
76 | menu,
77 | nav,
78 | section,
79 | time,
80 | mark,
81 | audio,
82 | video {
83 | margin: 0;
84 | padding: 0;
85 | border: 0;
86 | outline: 0;
87 | font-size: 100%;
88 | vertical-align: baseline;
89 | background: transparent;
90 | }
91 |
--------------------------------------------------------------------------------
/tic-tac-toe/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tic-tac-toe",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run",
6 | "test": "meteor test --once --driver-package meteortesting:mocha",
7 | "test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha",
8 | "visualize": "meteor --production --extra-packages bundle-visualizer"
9 | },
10 | "dependencies": {
11 | "@babel/runtime": "^7.19.0",
12 | "meteor-node-stubs": "^1.2.5",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "react-router": "^5.3.3",
16 | "react-router-dom": "^5.3.3"
17 | },
18 | "meteor": {
19 | "mainModule": {
20 | "client": "client/main.jsx",
21 | "server": "server/main.js"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/tic-tac-toe/public/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/tic-tac-toe/public/circle.png
--------------------------------------------------------------------------------
/tic-tac-toe/public/cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/meteor/examples/c44bd2426dac0d3b6edf2535e82a7c39236f6e6e/tic-tac-toe/public/cross.png
--------------------------------------------------------------------------------
/tic-tac-toe/server/main.js:
--------------------------------------------------------------------------------
1 | import "/imports/api/rooms";
2 | import { RoomCollection } from "../imports/api/rooms";
3 |
4 | Meteor.publish("rooms", function() {
5 | return RoomCollection.find({});
6 | });
7 | Meteor.publish("room", function({ _id }) {
8 | return RoomCollection.find({ _id });
9 | });
10 |
--------------------------------------------------------------------------------