nitro-web 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/app.tsx +1 -1
- package/client/index.ts +0 -4
- package/client/store.ts +1 -1
- package/components/auth/reset.tsx +1 -1
- package/components/auth/signin.tsx +1 -1
- package/components/auth/signup.tsx +1 -1
- package/components/partials/element/avatar.tsx +1 -1
- package/components/partials/element/message.tsx +1 -1
- package/components/partials/element/sidebar.tsx +13 -14
- package/components/partials/form/drop.tsx +1 -1
- package/components/partials/form/input.tsx +1 -1
- package/components/partials/form/select.tsx +1 -1
- package/components/partials/styleguide.tsx +1 -1
- package/components/settings/settings-team--member.tsx +1 -1
- package/package.json +23 -53
- package/semver-updater.cjs +7 -6
- package/tsconfig.json +1 -1
- package/tsconfig.types.json +15 -0
- package/types.ts +3 -1
- package/.github/workflows/deploy.yml +0 -36
- package/_example/.env +0 -16
- package/_example/client/config.ts +0 -2
- package/_example/client/css/index.css +0 -35
- package/_example/client/fonts/inter-v13-latin-300.woff2 +0 -0
- package/_example/client/fonts/inter-v13-latin-500.woff2 +0 -0
- package/_example/client/fonts/inter-v13-latin-600.woff2 +0 -0
- package/_example/client/fonts/inter-v13-latin-700.woff2 +0 -0
- package/_example/client/fonts/inter-v13-latin-800.woff2 +0 -0
- package/_example/client/fonts/inter-v13-latin-900.woff2 +0 -0
- package/_example/client/fonts/inter-v13-latin-regular.woff2 +0 -0
- package/_example/client/imgs/android-chrome-512x512.png +0 -0
- package/_example/client/imgs/favicon.png +0 -0
- package/_example/client/imgs/logo/logo-white.svg +0 -13
- package/_example/client/imgs/logo/logo.svg +0 -13
- package/_example/client/index.html +0 -12
- package/_example/client/index.ts +0 -9
- package/_example/components/auth.api.js +0 -1
- package/_example/components/index.tsx +0 -230
- package/_example/components/partials/layouts.tsx +0 -10
- package/_example/components/settings.api.js +0 -1
- package/_example/package.json +0 -112
- package/_example/server/config.js +0 -130
- package/_example/server/email/welcome.html +0 -27
- package/_example/server/index.js +0 -33
- package/_example/tailwind.config.js +0 -75
- package/_example/tsconfig.json +0 -35
- package/_example/types.ts +0 -1
- package/_example/webpack.config.js +0 -3
- package/components/partials/layout/layout1.tsx +0 -29
- package/components/partials/layout/layout2.tsx +0 -48
- package/readme.md +0 -74
- package/webpack.config.js +0 -356
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Any component with a .route property is called a page component. Any page component found under /components
|
|
3
|
-
* will be automatically imported and setup by the client router, we're just listing them all here for the sake of example.
|
|
4
|
-
*/
|
|
5
|
-
import { css, theme } from 'twin.macro'
|
|
6
|
-
import config from '../client/config'
|
|
7
|
-
import { isDemo } from 'nitro-web'
|
|
8
|
-
import {
|
|
9
|
-
Signin,
|
|
10
|
-
Signup,
|
|
11
|
-
ResetInstructions,
|
|
12
|
-
ResetPassword,
|
|
13
|
-
Dashboard,
|
|
14
|
-
Styleguide,
|
|
15
|
-
NotFound,
|
|
16
|
-
// SettingsAccount,
|
|
17
|
-
// SettingsBusiness,
|
|
18
|
-
// SettingsTeam,
|
|
19
|
-
} from 'nitro-web'
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// Signin page (can be saved onto a seperate .jsx/.tsx file under the components folder)
|
|
23
|
-
export const SigninPage = () => <Signin config={config} />
|
|
24
|
-
SigninPage.route = {
|
|
25
|
-
'/signin': true,
|
|
26
|
-
'/signout': true,
|
|
27
|
-
'meta': { 'title': 'Sign In', layout: 2 },
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Signup page
|
|
31
|
-
export const SignupPage = () => <Signup config={config} />
|
|
32
|
-
SignupPage.route = {
|
|
33
|
-
'/signup': true,
|
|
34
|
-
'meta': { 'title': 'Sign Up', layout: 2 },
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Reset instructions page
|
|
38
|
-
export const ResetInstructionsPage = () => <ResetInstructions />
|
|
39
|
-
ResetInstructionsPage.route = {
|
|
40
|
-
'/reset': true,
|
|
41
|
-
'meta': { 'title': 'Reset password', layout: 2 },
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Reset password page
|
|
45
|
-
export const ResetPasswordPage = () => <ResetPassword />
|
|
46
|
-
ResetPasswordPage.route = {
|
|
47
|
-
'/reset/:token': true,
|
|
48
|
-
'meta': { 'title': 'Reset password', layout: 2 },
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// // Settings Account page
|
|
52
|
-
// export const SettingsAccountPage = () => <SettingsAccount />
|
|
53
|
-
// SettingsAccountPage.route = {
|
|
54
|
-
// '/settings/account': ['isUser'],
|
|
55
|
-
// 'meta': { 'title': 'Account Settings', layout: 1 },
|
|
56
|
-
// }
|
|
57
|
-
|
|
58
|
-
// // Settings Business page
|
|
59
|
-
// export const SettingsBusinessPage = () => <SettingsBusiness config={config} />
|
|
60
|
-
// SettingsBusinessPage.route = {
|
|
61
|
-
// '/settings/business': ['isUser'],
|
|
62
|
-
// 'meta': { 'title': 'Business Settings', layout: 1 },
|
|
63
|
-
// }
|
|
64
|
-
|
|
65
|
-
// // Settings Team page
|
|
66
|
-
// export const SettingsTeamPage = () => <SettingsTeam config={config} />
|
|
67
|
-
// SettingsTeamPage.route = {
|
|
68
|
-
// '/settings/team': ['isUser'],
|
|
69
|
-
// 'meta': { 'title': 'Team Settings', layout: 1 },
|
|
70
|
-
// }
|
|
71
|
-
|
|
72
|
-
// Dashboard page
|
|
73
|
-
export const DashboardPage = () => <Dashboard config={config} />
|
|
74
|
-
DashboardPage.route = {
|
|
75
|
-
'/': true,
|
|
76
|
-
'meta': { 'title': 'Dashboard', layout: 1 },
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Styleguide page
|
|
80
|
-
export const StyleguidePage = () => <Styleguide config={config} />
|
|
81
|
-
StyleguidePage.route = {
|
|
82
|
-
'/styleguide': true,
|
|
83
|
-
'meta': { title: `${isDemo ? 'Design System' : 'Style Guide'}`, layout: 1 },
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Not found page
|
|
87
|
-
export const NotFoundPage = () => <NotFound />
|
|
88
|
-
NotFoundPage.route = {
|
|
89
|
-
'*': true,
|
|
90
|
-
'meta': { 'title': 'Nothing found', layout: 1 },
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Custom Tailwind UI page example
|
|
94
|
-
export function PricingPage() {
|
|
95
|
-
const tiers = [
|
|
96
|
-
{
|
|
97
|
-
name: 'Hobby',
|
|
98
|
-
id: 'tier-hobby',
|
|
99
|
-
href: '#',
|
|
100
|
-
priceMonthly: '$29',
|
|
101
|
-
description: 'The perfect plan if you\'re just getting started with our product.',
|
|
102
|
-
features: ['25 products', 'Up to 10,000 subscribers', 'Advanced analytics', '24-hour support response time'],
|
|
103
|
-
featured: false,
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
name: 'Enterprise',
|
|
107
|
-
id: 'tier-enterprise',
|
|
108
|
-
href: '#',
|
|
109
|
-
priceMonthly: '$99',
|
|
110
|
-
description: 'Dedicated support and infrastructure for your company.',
|
|
111
|
-
features: [
|
|
112
|
-
'Unlimited products',
|
|
113
|
-
'Unlimited subscribers',
|
|
114
|
-
'Advanced analytics',
|
|
115
|
-
'Dedicated support representative',
|
|
116
|
-
'Marketing automations',
|
|
117
|
-
'Custom integrations',
|
|
118
|
-
],
|
|
119
|
-
featured: true,
|
|
120
|
-
},
|
|
121
|
-
]
|
|
122
|
-
function classNames(...classes: string[]) {
|
|
123
|
-
return classes.filter(Boolean).join(' ')
|
|
124
|
-
}
|
|
125
|
-
return (
|
|
126
|
-
<div className="relative isolate bg-white py-12 md:py-16 px-6" css={style}>
|
|
127
|
-
<div aria-hidden="true" className="absolute inset-x-0 -top-3 -z-10 transform-gpu overflow-hidden px-36 blur-3xl">
|
|
128
|
-
<div
|
|
129
|
-
style={{
|
|
130
|
-
clipPath:
|
|
131
|
-
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%,'
|
|
132
|
-
+' 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
|
|
133
|
-
}}
|
|
134
|
-
className="mx-auto aspect-[1155/678] w-[72.1875rem] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30"
|
|
135
|
-
/>
|
|
136
|
-
</div>
|
|
137
|
-
<div className="mx-auto max-w-4xl text-center">
|
|
138
|
-
<h2 className="text-base/7 font-semibold text-indigo-600">Pricing</h2>
|
|
139
|
-
<p className="mt-2 text-balance text-5xl font-semibold tracking-tight text-gray-900 sm:text-5xl">
|
|
140
|
-
Choose the right plan for you
|
|
141
|
-
</p>
|
|
142
|
-
</div>
|
|
143
|
-
<p className="mx-auto mt-6 max-w-3xl text-pretty text-center text-lg font-medium text-gray-600 sm:text-xl/8">
|
|
144
|
-
This is a
|
|
145
|
-
<a class="underline" href="https://tailwindui.com/components/marketing/sections/pricing" target="_blank" rel="noreferrer">
|
|
146
|
-
pricing page
|
|
147
|
-
</a> example using one of the
|
|
148
|
-
<a class="underline" href="https://tailwindui.com/components" target="_blank" rel="noreferrer">
|
|
149
|
-
Tailwind UI
|
|
150
|
-
</a> components. With minor composition changes, it's almost copy/paste.
|
|
151
|
-
</p>
|
|
152
|
-
<div className="mx-auto mt-16 grid max-w-lg grid-cols-1 items-center gap-y-6 sm:mt-20 sm:gap-y-0 lg:max-w-4xl lg:grid-cols-2">
|
|
153
|
-
{tiers.map((tier, tierIdx) => (
|
|
154
|
-
<div
|
|
155
|
-
key={tier.id}
|
|
156
|
-
className={classNames(
|
|
157
|
-
tier.featured ? 'relative bg-gray-900 shadow-2xl' : 'bg-white/60 sm:mx-8 lg:mx-0',
|
|
158
|
-
tier.featured
|
|
159
|
-
? ''
|
|
160
|
-
: tierIdx === 0
|
|
161
|
-
? 'rounded-t-3xl sm:rounded-b-none lg:rounded-bl-3xl lg:rounded-tr-none'
|
|
162
|
-
: 'sm:rounded-t-none lg:rounded-bl-none lg:rounded-tr-3xl',
|
|
163
|
-
'rounded-3xl p-8 ring-1 ring-gray-900/10 sm:p-10'
|
|
164
|
-
)}
|
|
165
|
-
>
|
|
166
|
-
<h3
|
|
167
|
-
id={tier.id}
|
|
168
|
-
className={classNames(tier.featured ? 'text-indigo-400' : 'text-indigo-600', 'text-base/7 font-semibold')}
|
|
169
|
-
>
|
|
170
|
-
{tier.name}
|
|
171
|
-
</h3>
|
|
172
|
-
<p className="mt-4 flex items-baseline gap-x-2">
|
|
173
|
-
<span
|
|
174
|
-
className={classNames(
|
|
175
|
-
tier.featured ? 'text-white' : 'text-gray-900',
|
|
176
|
-
'text-5xl font-semibold tracking-tight'
|
|
177
|
-
)}
|
|
178
|
-
>
|
|
179
|
-
{tier.priceMonthly}
|
|
180
|
-
</span>
|
|
181
|
-
<span className={classNames(tier.featured ? 'text-gray-400' : 'text-gray-500', 'text-base')}>/month</span>
|
|
182
|
-
</p>
|
|
183
|
-
<p className={classNames(tier.featured ? 'text-gray-300' : 'text-gray-600', 'mt-6 text-base/7')}>
|
|
184
|
-
{tier.description}
|
|
185
|
-
</p>
|
|
186
|
-
<ul
|
|
187
|
-
role="list"
|
|
188
|
-
className={classNames(
|
|
189
|
-
tier.featured ? 'text-gray-300' : 'text-gray-600',
|
|
190
|
-
'mt-8 space-y-3 text-sm/6 sm:mt-10'
|
|
191
|
-
)}
|
|
192
|
-
>
|
|
193
|
-
{tier.features.map((feature) => (
|
|
194
|
-
<li key={feature} className="flex gap-x-3">
|
|
195
|
-
{/* <CheckIcon
|
|
196
|
-
aria-hidden="true"
|
|
197
|
-
className={classNames(tier.featured ? 'text-indigo-400' : 'text-indigo-600', 'h-6 w-5 flex-none')}
|
|
198
|
-
/> */}
|
|
199
|
-
{feature}
|
|
200
|
-
</li>
|
|
201
|
-
))}
|
|
202
|
-
</ul>
|
|
203
|
-
<a
|
|
204
|
-
href={tier.href}
|
|
205
|
-
aria-describedby={tier.id}
|
|
206
|
-
className={classNames(
|
|
207
|
-
tier.featured
|
|
208
|
-
? 'bg-indigo-500 text-white shadow-sm hover:bg-indigo-400 focus-visible:outline-indigo-500'
|
|
209
|
-
: 'text-indigo-600 ring-1 ring-inset ring-indigo-200 hover:ring-indigo-300 focus-visible:outline-indigo-600',
|
|
210
|
-
'mt-8 block rounded-md px-3.5 py-2.5 text-center text-sm font-semibold focus-visible:outline '
|
|
211
|
-
+ 'focus-visible:outline-2 focus-visible:outline-offset-2 sm:mt-10'
|
|
212
|
-
)}
|
|
213
|
-
>
|
|
214
|
-
Get started today
|
|
215
|
-
</a>
|
|
216
|
-
</div>
|
|
217
|
-
))}
|
|
218
|
-
</div>
|
|
219
|
-
</div>
|
|
220
|
-
)
|
|
221
|
-
}
|
|
222
|
-
const style = css`
|
|
223
|
-
.example-usage-of-tailwind-variable {
|
|
224
|
-
color: ${theme('colors.dark')};
|
|
225
|
-
}
|
|
226
|
-
`
|
|
227
|
-
PricingPage.route = {
|
|
228
|
-
'/pricing': true,
|
|
229
|
-
'meta': { 'title': 'Pricing', layout: 1 },
|
|
230
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Layout1 as L1, Layout2 as L2 } from 'nitro-web'
|
|
2
|
-
import Logo from '../../client/imgs/logo/logo.svg'
|
|
3
|
-
import { Config } from 'types'
|
|
4
|
-
|
|
5
|
-
const links = [
|
|
6
|
-
{ name: 'Nitro on Github', to: 'https://github.com/boycce/nitro-web', initial: 'G' },
|
|
7
|
-
]
|
|
8
|
-
|
|
9
|
-
export const Layout1 = ({ config }: { config: Config }) => { return <L1 Logo={Logo} links={links} config={config} /> }
|
|
10
|
-
export const Layout2 = ({ config }: { config: Config }) => { return <L2 Logo={Logo} config={config} /> }
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { settings as default } from 'nitro-web/server'
|
package/_example/package.json
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "example",
|
|
3
|
-
"private": true,
|
|
4
|
-
"version": "0.0.1",
|
|
5
|
-
"main": "webpack.config.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"homepage": "https://boycce.github.io/nitro-web/",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "NODE_ENV=production webpack --target=web",
|
|
10
|
-
"dev": "clear && npm run dev:lint --silent & npm run dev:server --silent & npm run dev:client --silent",
|
|
11
|
-
"dev:client": "webpack serve --progress --config ./webpack.config.js",
|
|
12
|
-
"dev:client-only": "isStatic=true npm run dev:client",
|
|
13
|
-
"dev:server": "nodemon ./server -q -w ./server/ -w ./components/ -e js",
|
|
14
|
-
"dev:lint": "eslint ./components ./server/",
|
|
15
|
-
"minor": "standard-version --release-as minor && git push staging",
|
|
16
|
-
"patch": "standard-version --release-as patch && git push staging",
|
|
17
|
-
"start": "node ./server",
|
|
18
|
-
"stripe": "stripe listen --forward-to localhost:3001/api/stripe/webhook"
|
|
19
|
-
},
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@headlessui/react": "^2.2.0",
|
|
22
|
-
"@heroicons/react": "^2.2.0",
|
|
23
|
-
"@hokify/axios": "^0.19.1",
|
|
24
|
-
"@stripe/stripe-js": "^1.34.0",
|
|
25
|
-
"axios-retry": "^3.3.1",
|
|
26
|
-
"monastery": "~3.5.2",
|
|
27
|
-
"nitro-web": "file:..",
|
|
28
|
-
"react": "^18.3.1",
|
|
29
|
-
"react-dom": "^18.3.1",
|
|
30
|
-
"stripe": "^9.16.0",
|
|
31
|
-
"tailwindcss": "^3.4.17",
|
|
32
|
-
"twin.macro": "^3.4.1"
|
|
33
|
-
},
|
|
34
|
-
"devDependencies": {
|
|
35
|
-
"@babel/core": "^7.8.0",
|
|
36
|
-
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
37
|
-
"@babel/plugin-transform-runtime": "^7.17.0",
|
|
38
|
-
"@babel/preset-env": "^7.8.0",
|
|
39
|
-
"@babel/preset-react": "^7.9.4",
|
|
40
|
-
"@babel/preset-typescript": "^7.24.7",
|
|
41
|
-
"@emotion/babel-plugin": "^11.11.0",
|
|
42
|
-
"@emotion/eslint-plugin": "^11.11.0",
|
|
43
|
-
"@emotion/react": "^11.11.4",
|
|
44
|
-
"@emotion/styled": "^11.11.4",
|
|
45
|
-
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
|
46
|
-
"@svgr/webpack": "^8.1.0",
|
|
47
|
-
"@types/react": "^19.0.2",
|
|
48
|
-
"@types/react-dom": "^19.0.2",
|
|
49
|
-
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
|
50
|
-
"@typescript-eslint/parser": "^8.18.1",
|
|
51
|
-
"autoprefixer": "^9.8.8",
|
|
52
|
-
"babel-loader": "^8.0.6",
|
|
53
|
-
"babel-plugin-macros": "^3.1.0",
|
|
54
|
-
"babel-plugin-react-html-attrs": "^2.1.0",
|
|
55
|
-
"clean-terminal-webpack-plugin": "https://github.com/boycce/clean-terminal-webpack-plugin.git",
|
|
56
|
-
"clean-webpack-plugin": "^4.0.0",
|
|
57
|
-
"color": "^4.2.3",
|
|
58
|
-
"copy-webpack-plugin": "^12.0.2",
|
|
59
|
-
"core-js": "^3.12.1",
|
|
60
|
-
"css-loader": "^3.6.0",
|
|
61
|
-
"csv-loader": "^3.0.5",
|
|
62
|
-
"eslint": "^8.57.1",
|
|
63
|
-
"eslint-plugin-import": "^2.26.0",
|
|
64
|
-
"eslint-plugin-react": "^7.19.0",
|
|
65
|
-
"eslint-plugin-react-hooks": "^4.0.0",
|
|
66
|
-
"eslint-webpack-plugin": "^2.7.0",
|
|
67
|
-
"html-loader": "^1.3.2",
|
|
68
|
-
"html-webpack-plugin": "^5.6.0",
|
|
69
|
-
"mini-css-extract-plugin": "^2.9.0",
|
|
70
|
-
"nodemon": "^2.0.1",
|
|
71
|
-
"postcss": "^8.4.49",
|
|
72
|
-
"postcss-for": "^2.1.1",
|
|
73
|
-
"postcss-import": "^16.1.0",
|
|
74
|
-
"postcss-loader": "^8.1.1",
|
|
75
|
-
"postcss-nested": "^7.0.2",
|
|
76
|
-
"react-refresh": "^0.14.2",
|
|
77
|
-
"standard-version": "^9.3.2",
|
|
78
|
-
"string-replace-loader": "^3.1.0",
|
|
79
|
-
"tailwind-merge": "^2.6.0",
|
|
80
|
-
"typescript": "^5.5.2",
|
|
81
|
-
"webpack": "^5.92.1",
|
|
82
|
-
"webpack-cli": "^5.1.4",
|
|
83
|
-
"webpack-dev-server": "^4.6.0",
|
|
84
|
-
"webpack-node-externals": "^1.7.2"
|
|
85
|
-
},
|
|
86
|
-
"eslintConfig": {
|
|
87
|
-
"extends": "../.eslintrc.json"
|
|
88
|
-
},
|
|
89
|
-
"engines": {
|
|
90
|
-
"node": ">=18"
|
|
91
|
-
},
|
|
92
|
-
"browserslist": [
|
|
93
|
-
"> 1%",
|
|
94
|
-
"last 2 versions",
|
|
95
|
-
"not ie <= 10"
|
|
96
|
-
],
|
|
97
|
-
"nodemonConfig": {
|
|
98
|
-
"events": {
|
|
99
|
-
"restart": "echo \"\\033[0;35mExpress restarting..\\033[0m\""
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
"standard-version": {
|
|
103
|
-
"releaseCommitMessageFormat": "{{currentTag}}",
|
|
104
|
-
"sign": true,
|
|
105
|
-
"skip": {
|
|
106
|
-
"changelog": true,
|
|
107
|
-
"tag": true
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
"author": "",
|
|
111
|
-
"license": "ISC"
|
|
112
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config'
|
|
2
|
-
import { createRequire } from 'module'
|
|
3
|
-
const _require = createRequire(import.meta.url)
|
|
4
|
-
const env = process.env.env || (process.env.NODE_ENV !== 'production' ? 'development' : process.env.NODE_ENV)
|
|
5
|
-
const pwd = process.env.PWD + '/'
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
inject:
|
|
9
|
-
'awsUrl clientUrl currencies countries env googleMapsApiKey isStatic name placeholderEmail ' +
|
|
10
|
-
'stripePublishableKey titleSeparator version',
|
|
11
|
-
|
|
12
|
-
clientUrl: process.env.originUrl || 'http://localhost:3000',
|
|
13
|
-
emailFrom: process.env.emailFrom,
|
|
14
|
-
emailReplyTo: process.env.emailReplyTo,
|
|
15
|
-
emailTestMode: process.env.emailTestMode,
|
|
16
|
-
env: env,
|
|
17
|
-
homepage: _require(pwd + 'package.json').homepage,
|
|
18
|
-
isStatic: process.env.isStatic,
|
|
19
|
-
masterPassword: process.env.masterPassword,
|
|
20
|
-
mongoUrl: process.env.mongoUrl,
|
|
21
|
-
name: 'Nitro',
|
|
22
|
-
placeholderEmail: process.env.placeholderEmail,
|
|
23
|
-
publicPath: process.env.publicPath,
|
|
24
|
-
pwd: pwd, // change to rootDir
|
|
25
|
-
version: _require(pwd + 'package.json').version,
|
|
26
|
-
|
|
27
|
-
awsUrl: process.env.awsUrl,
|
|
28
|
-
googleMapsApiKey: process.env.googleMapsApiKey,
|
|
29
|
-
mailgunDomain: process.env.mailgunDomain,
|
|
30
|
-
mailgunKey: process.env.mailgunKey,
|
|
31
|
-
stripePublishableKey: process.env.stripePublishableKey,
|
|
32
|
-
stripeSecretKey: process.env.stripeSecretKey,
|
|
33
|
-
stripeWebhookSecret: process.env.stripeWebhookSecret,
|
|
34
|
-
|
|
35
|
-
monasteryOptions: {
|
|
36
|
-
noDefaults: true,
|
|
37
|
-
nullObjects: true,
|
|
38
|
-
useMilliseconds: true,
|
|
39
|
-
imagePlugin: process.env.awsSecretAccessKey
|
|
40
|
-
? {
|
|
41
|
-
awsBucket: process.env.awsBucket,
|
|
42
|
-
awsRegion: process.env.awsRegion,
|
|
43
|
-
awsAccessKeyId: process.env.awsAccessKeyId,
|
|
44
|
-
awsSecretAccessKey: process.env.awsSecretAccessKey,
|
|
45
|
-
formats: ['png', 'jpg', 'jpeg', 'bmp', 'tiff', 'gif', 'webp'],
|
|
46
|
-
}
|
|
47
|
-
: undefined,
|
|
48
|
-
// show mongod selection error faster in development
|
|
49
|
-
serverSelectionTimeoutMS: env == 'development' ? 3000 : undefined,
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
countries: {
|
|
53
|
-
nz: {
|
|
54
|
-
currency: 'nzd',
|
|
55
|
-
name: 'New Zealand',
|
|
56
|
-
numberFormats: {
|
|
57
|
-
currency: '¤#,##0.00',
|
|
58
|
-
percentage: '¤#,##0.00%',
|
|
59
|
-
},
|
|
60
|
-
dateFormats: {
|
|
61
|
-
full: 'dddd, D MMMM YYYY',
|
|
62
|
-
long: 'D MMMM YYYY',
|
|
63
|
-
medium: 'D/MM/YYYY',
|
|
64
|
-
short: 'D/MM/YY',
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
au: {
|
|
68
|
-
currency: 'aud',
|
|
69
|
-
name: 'Australia',
|
|
70
|
-
numberFormats: {
|
|
71
|
-
currency: '¤#,##0.00',
|
|
72
|
-
percentage: '¤#,##0.00%',
|
|
73
|
-
},
|
|
74
|
-
dateFormats: {
|
|
75
|
-
full: 'dddd, D MMMM YYYY',
|
|
76
|
-
long: 'D MMMM YYYY',
|
|
77
|
-
medium: 'D/MM/YYYY',
|
|
78
|
-
short: 'D/MM/YY',
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
currencies: {
|
|
84
|
-
nzd: {
|
|
85
|
-
name: 'New Zealand Dollar',
|
|
86
|
-
symbol: '$',
|
|
87
|
-
},
|
|
88
|
-
aud: {
|
|
89
|
-
name: 'Australian Dollar',
|
|
90
|
-
symbol: '$',
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
middleware: {
|
|
95
|
-
isAdmin: (req, res, next) => {
|
|
96
|
-
// Still need to remove cookie matching in favour of uid..
|
|
97
|
-
// E.g. Cookie matching handy for rare issues, e.g. signout > signin (to a different user on another tab)
|
|
98
|
-
let cookieMatch = req.user && (!req.headers.userid || req.user._id.toString() == req.headers.userid)
|
|
99
|
-
if (cookieMatch && req.user.type.match(/admin/)) next()
|
|
100
|
-
else if (req.user && req.user.type.match(/admin/)) res.unauthorized('Invalid cookie, please refresh your browser')
|
|
101
|
-
else if (req.user) res.unauthorized('You are not authorised to make this request.')
|
|
102
|
-
else res.unauthorized('Please sign in first.')
|
|
103
|
-
},
|
|
104
|
-
isCompanyOwner: (req, res, next) => {
|
|
105
|
-
let user = req.user || { companies: [] }
|
|
106
|
-
let cid = req.params.cid
|
|
107
|
-
let company = user.companies.find((o) => o._id.toString() == cid)
|
|
108
|
-
let companyUser = company?.users?.find((o) => o._id.toString() == user._id.toString())
|
|
109
|
-
if (!user._id) return res.unauthorized('Please sign in first.')
|
|
110
|
-
else if (!company || !companyUser) res.unauthorized('You are not authorised to make this request.')
|
|
111
|
-
else if (companyUser.type != 'owner') res.unauthorized('Only owners can make this request.')
|
|
112
|
-
else next()
|
|
113
|
-
},
|
|
114
|
-
isCompanyUser: (req, res, next) => {
|
|
115
|
-
let user = req.user || { companies: [] }
|
|
116
|
-
let cid = req.params.cid
|
|
117
|
-
let company = user.companies.find((o) => o._id.toString() == cid)
|
|
118
|
-
if (!user._id) return res.unauthorized('Please sign in first.')
|
|
119
|
-
else if (!company) res.unauthorized('You are not authorised to make this request.')
|
|
120
|
-
else next()
|
|
121
|
-
},
|
|
122
|
-
isUser: (req, res, next) => {
|
|
123
|
-
// todo: need to double check that uid is always defined
|
|
124
|
-
let uid = req.params.uid
|
|
125
|
-
if (req.user && (typeof uid == 'undefined' || req.user._id.toString() == uid)) next()
|
|
126
|
-
else if (req.user) res.unauthorized('You are not authorised to make this request.')
|
|
127
|
-
else res.unauthorized('Please sign in first.')
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<!-- You can view templates at http://localhost:3001/email/welcome -->
|
|
2
|
-
<!-- To modify the css, add your own /server/email/partials/email.css file -->
|
|
3
|
-
|
|
4
|
-
<!-- extends references the default nitro layout file -->
|
|
5
|
-
{% extends "partials/layout1.swig" %}
|
|
6
|
-
|
|
7
|
-
<!-- block content is the content of the email -->
|
|
8
|
-
{% block content %}
|
|
9
|
-
|
|
10
|
-
[[ subject = Welcome to Nitro ]]
|
|
11
|
-
<b>%recipient.greet%</b>,<br/>
|
|
12
|
-
<br/>
|
|
13
|
-
Thanks for trying out Nitro (the example)! <br/>
|
|
14
|
-
<br/>
|
|
15
|
-
If you have any feature requests, feedback or questions, please don't hesitate to reach out to us at <a href="mailto:%recipient.replyToEmail%">%recipient.replyToEmail%</a>.<br/>
|
|
16
|
-
<br/>
|
|
17
|
-
<br/>
|
|
18
|
-
<span mc:edit="button">
|
|
19
|
-
<a class="button" href="%recipient.domain%/signin?email=%recipient.email%" target="_blank">
|
|
20
|
-
Account Sign In
|
|
21
|
-
</a>
|
|
22
|
-
</span><br/>
|
|
23
|
-
<br/>
|
|
24
|
-
Thanks,<br/>
|
|
25
|
-
<b>The Nitro Team</b>
|
|
26
|
-
|
|
27
|
-
{% endblock %}
|
package/_example/server/index.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config'
|
|
2
|
-
import db from 'monastery'
|
|
3
|
-
import config from './config.js'
|
|
4
|
-
import { setupRouter, setupDefaultModels } from 'nitro-web/server'
|
|
5
|
-
|
|
6
|
-
// Setup monastery models
|
|
7
|
-
db.manager(config.mongoUrl, config.monasteryOptions)
|
|
8
|
-
await db.models(config.pwd + 'server/models')
|
|
9
|
-
await setupDefaultModels(db)
|
|
10
|
-
|
|
11
|
-
// Catch mongod not running
|
|
12
|
-
if (config.env === 'development') {
|
|
13
|
-
db.onError((err) => console.log(err))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Setup router
|
|
17
|
-
const server = await setupRouter(config)
|
|
18
|
-
|
|
19
|
-
// Start express
|
|
20
|
-
server.listen(process.env.PORT || 3001, '0.0.0.0', async () => {
|
|
21
|
-
// ...success
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
// You can send transactional Mailgun emails like so:
|
|
25
|
-
// import { sendEmail } from '#nitro-web/server.js'
|
|
26
|
-
// const html = await sendEmail({
|
|
27
|
-
// config: config,
|
|
28
|
-
// data: { name: 'Test' },
|
|
29
|
-
// template: 'welcome',
|
|
30
|
-
// test: true,
|
|
31
|
-
// to: 'test@test.com',
|
|
32
|
-
// })
|
|
33
|
-
// console.log(html)
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import defaultTheme from 'tailwindcss/defaultTheme'
|
|
2
|
-
import colors from 'tailwindcss/colors'
|
|
3
|
-
import path from 'path'
|
|
4
|
-
import Color from 'color'
|
|
5
|
-
|
|
6
|
-
const lighten = (clr, val) => Color(clr).lighten(val).rgb().string()
|
|
7
|
-
const darken = (clr, val) => Color(clr).darken(val).rgb().string()
|
|
8
|
-
const nitroDir = path.dirname(require.resolve('nitro-web'))
|
|
9
|
-
|
|
10
|
-
export default {
|
|
11
|
-
content: {
|
|
12
|
-
relative: true,
|
|
13
|
-
files: [
|
|
14
|
-
'./components/**/*.{ts,tsx}',
|
|
15
|
-
path.join(nitroDir, '../components/**/*.{ts,tsx}'),
|
|
16
|
-
],
|
|
17
|
-
},
|
|
18
|
-
experimental: {
|
|
19
|
-
optimizeUniversalDefaults: true, // remove undesired variables from universal selectors
|
|
20
|
-
},
|
|
21
|
-
theme: {
|
|
22
|
-
// Full list: https://github.com/tailwindlabs/tailwindcss/blob/main/stubs/config.full.js#L889
|
|
23
|
-
extend: {
|
|
24
|
-
boxShadow: {
|
|
25
|
-
'dropdown-ul': '0 2px 8px 0 rgba(0, 0, 0, 0.05)',
|
|
26
|
-
},
|
|
27
|
-
colors: {
|
|
28
|
-
// Main colors
|
|
29
|
-
'primary': '#4c50f9',
|
|
30
|
-
'primary-dark': darken('#4c50f9', 0.05),
|
|
31
|
-
'primary-hover': lighten('#4c50f9', 0.05),
|
|
32
|
-
'secondary': colors.green[500],
|
|
33
|
-
'secondary-dark': colors.green[600],
|
|
34
|
-
'secondary-hover': lighten(colors.green[500], 0.05),
|
|
35
|
-
'label': colors.gray[900],
|
|
36
|
-
'link': colors.black,
|
|
37
|
-
'link-hover': colors.blue[200],
|
|
38
|
-
'link-focus': colors.blue[200],
|
|
39
|
-
'light': colors.gray[100],
|
|
40
|
-
'dark': colors.gray[900],
|
|
41
|
-
// Alert colors
|
|
42
|
-
'critical': '#ff0000',
|
|
43
|
-
'danger': '#ff0000',
|
|
44
|
-
'danger-dark': colors.red[800],
|
|
45
|
-
'info': colors.blue[500],
|
|
46
|
-
'success': colors.green[500],
|
|
47
|
-
// Element colors
|
|
48
|
-
'input': colors.gray[900],
|
|
49
|
-
'input-placeholder': colors.gray[400],
|
|
50
|
-
'input-border': colors.gray[300],
|
|
51
|
-
'dropdown-ul-border': colors.gray[200],
|
|
52
|
-
},
|
|
53
|
-
fontFamily: {
|
|
54
|
-
sans: ['Inter', ...defaultTheme.fontFamily.sans],
|
|
55
|
-
},
|
|
56
|
-
fontSize: {
|
|
57
|
-
'2xs': ['12px', { lineHeight: '1.5' }],
|
|
58
|
-
'xs': ['13px', { lineHeight: '1.5' }],
|
|
59
|
-
'sm': ['13.5px', { lineHeight: '1.5' }],
|
|
60
|
-
'md': ['14px', { lineHeight: '1.5' }],
|
|
61
|
-
'base': ['15.5px', { lineHeight: '1.5' }],
|
|
62
|
-
'lg': ['18px', { lineHeight: '1.75' }],
|
|
63
|
-
'xl': ['20px', { lineHeight: '1.75' }],
|
|
64
|
-
'2xl': ['22.5px', { lineHeight: '1.75' }],
|
|
65
|
-
'3xl': ['30px', { lineHeight: '1.75' }],
|
|
66
|
-
},
|
|
67
|
-
spacing: {
|
|
68
|
-
'input-before': '0.625rem',
|
|
69
|
-
'input-after': '1.5rem',
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
plugins: [],
|
|
74
|
-
}
|
|
75
|
-
|
package/_example/tsconfig.json
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowJs": true,
|
|
4
|
-
"allowSyntheticDefaultImports": true,
|
|
5
|
-
"downlevelIteration": true,
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"forceConsistentCasingInFileNames": true,
|
|
8
|
-
"isolatedModules": true,
|
|
9
|
-
"jsx": "react-jsx",
|
|
10
|
-
"lib": ["es6", "dom", "dom.iterable", "esnext"],
|
|
11
|
-
"module": "esnext",
|
|
12
|
-
"moduleResolution": "node",
|
|
13
|
-
"noEmit": false,
|
|
14
|
-
"noFallthroughCasesInSwitch": true,
|
|
15
|
-
"noImplicitAny": true,
|
|
16
|
-
"noImplicitReturns": false,
|
|
17
|
-
"noImplicitThis": true,
|
|
18
|
-
"noStrictGenericChecks": false,
|
|
19
|
-
"outDir": "./dist",
|
|
20
|
-
"paths": {
|
|
21
|
-
"types": ["./types.ts"]
|
|
22
|
-
},
|
|
23
|
-
"resolveJsonModule": true,
|
|
24
|
-
"skipLibCheck": true,
|
|
25
|
-
"sourceMap": true,
|
|
26
|
-
"strict": true,
|
|
27
|
-
"target": "es6"
|
|
28
|
-
},
|
|
29
|
-
"include": [
|
|
30
|
-
"client",
|
|
31
|
-
"components/**/*.tsx",
|
|
32
|
-
"components/**/*.ts",
|
|
33
|
-
"types"
|
|
34
|
-
]
|
|
35
|
-
}
|
package/_example/types.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type { Config, Errors, User } from 'nitro-web/types'
|