Skip to content

Commit 4778668

Browse files
author
Ryan Clements
authored
Merge pull request #54 from mantis-apps/deployability
feat: allow deployment on netlify
2 parents 6df5f00 + 1fea301 commit 4778668

12 files changed

Lines changed: 119 additions & 76 deletions

File tree

src/commands/init.command.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,17 @@ export default new Command('init')
2525
});
2626
const workspacePath = path.join(process.cwd(), workspaceName);
2727

28-
const dbUrl = await promptForDbUrl();
28+
const { isLocal, dbUrl } = await promptForDbUrl();
2929

3030
await copyTemplate({
3131
template: { name: templateName, path: templatePath },
3232
workspace: { name: workspaceName, path: workspacePath },
3333
secrets: { dbUrl },
3434
});
3535
await installDependenciesWithMessage(workspacePath);
36-
await startApplications(workspacePath);
36+
await startApplications(workspacePath, {
37+
startLocalDb: isLocal,
38+
});
3739
});
3840

3941
const promptForWorkspaceName = async ({
@@ -63,7 +65,10 @@ const promptForWorkspaceName = async ({
6365
return workspaceName;
6466
};
6567

66-
const promptForDbUrl = async () => {
68+
const promptForDbUrl = async (): Promise<{
69+
dbUrl: string;
70+
isLocal: boolean;
71+
}> => {
6772
interface DbTypePromptResult {
6873
dbType: string;
6974
}
@@ -88,7 +93,7 @@ const promptForDbUrl = async () => {
8893
},
8994
});
9095
if (dbType === 'local') {
91-
return 'local';
96+
return { isLocal: true, dbUrl: 'mongodb://127.0.0.1:27017' };
9297
}
9398
interface DbUrlPromptResult {
9499
dbUrl: string;
@@ -109,7 +114,7 @@ const promptForDbUrl = async () => {
109114
},
110115
},
111116
]);
112-
return dbUrl;
117+
return { isLocal: false, dbUrl };
113118
};
114119

115120
const copyTemplate = async ({
@@ -183,15 +188,18 @@ const installDependenciesWithMessage = async (workspacePath: string) => {
183188
spinner.succeed('Installed dependencies');
184189
};
185190

186-
const startApplications = async (workspacePath: string) => {
191+
const startApplications = async (
192+
workspacePath: string,
193+
{ startLocalDb }: { startLocalDb: boolean },
194+
) => {
187195
console.log(`${logSymbols.info} Starting applications...`);
188196
try {
189197
await execa(
190198
'npx',
191199
[
192200
'nx',
193201
'run-many',
194-
'--target=serve',
202+
startLocalDb ? '--targets=serve,start-local-db' : '--target=serve',
195203
'--projects=web-client,mobile-client',
196204
],
197205
{ cwd: workspacePath, stdio: 'inherit' },

templates/mantis-todo/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,6 @@ Thumbs.db
4545
*.local
4646

4747

48-
storybook-static
48+
storybook-static
49+
50+
.netlify
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
22
"typescript.preferences.autoImportFileExcludePatterns": [
33
"@ionic/angular/common"
4-
]
4+
],
5+
"editor.defaultFormatter": "esbenp.prettier-vscode",
6+
"[javascript]": {
7+
"editor.defaultFormatter": "esbenp.prettier-vscode"
8+
}
59
}

templates/mantis-todo/README.md

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,44 @@
88

99
- Run `npm install` to install all dependencies
1010

11-
2. (Optional) Create a remote mongo instance
11+
2. Choose your mongo instance
1212

13-
- You will need a remote mongo instance set up to deploy this project, but a local instance will be created for you for development if you set `MONGODB_URI='local'` in the `.env.local` file mentioned below.
14-
- If you don't already have a Mongo db instance you can use, follow the steps to [set up an instance with MongoDB Atlas (it's free)](https://www.mongodb.com/docs/atlas/getting-started/).
13+
- Option 1: Use a local instance
1514

16-
1. Create a config file in `apps/web-client` called `.env.local` i.e. `apps/web-client/.env.local`.
17-
2. Place your mongo connection string in that file as the following environment variable
15+
- A local instance can be created for you if you run `npx nx run web-client:start-local-db` and will remain running for as long as that command hasn't exited.
16+
- To connect to it, follow these steps.
1817

19-
```shell
20-
# Example
21-
MONGODB_URI='mongodb+srv://<user>:<password>@<cluster-name>.mongodb.net/?retryWrites=true&w=majority'
22-
```
18+
1. Create a config file in `apps/web-client` called `.env.local` i.e. `apps/web-client/.env.local`.
19+
2. Place your mongo connection string in that file as the following environment variable.
20+
21+
```shell
22+
MONGODB_URI='mongodb://127.0.0.1:27017'
23+
```
24+
25+
3. Whenever you start the `web-client` ensure you run `npx nx run web-client:start-local-db` also (example in [Start the apps](#start-the-apps)).
26+
27+
- Option 2: Use a remote instance
28+
29+
- You will need a remote mongo instance set up to deploy this project so this will need to be considered regardless.
30+
- If you don't already have a Mongo db instance you can use, follow the steps to [set up an instance with MongoDB Atlas (it's free)](https://www.mongodb.com/docs/atlas/getting-started/).
31+
- Once you have a connection string, follow these steps.
32+
33+
1. Create a config file in `apps/web-client` called `.env.local` i.e. `apps/web-client/.env.local`.
34+
2. Place your mongo connection string in that file as the following environment variable.
35+
36+
```shell
37+
MONGODB_URI='<the connection string>'
38+
```
2339

2440
> To learn more about how Nx loads environment variables, see [Definte Environment Variables](https://nx.dev/recipes/tips-n-tricks/define-environment-variables#define-environment-variables)
2541

26-
## Start the web app
42+
## Start the apps
43+
44+
To start the full stack locally with a local db, run `npx nx run-many --targets=serve,start-local-db --projects=web-client,mobile-client`.
45+
46+
To start the full stack locally without a local db, run `npx nx run-many --targets=serve --projects=web-client,mobile-client`.
2747

28-
To start the development servers run `npx nx run-many --target=serve --projects=web-client,mobile-client`. Open your browser and navigate to `http://localhost:4200/` to see the web app and `http://localhost:4300/` for the mobile app. Happy coding!
48+
Open your browser and navigate to `http://localhost:4200/` to see the web app and `http://localhost:4300/` for the mobile app. Happy coding!
2949

3050
## Storybook
3151

templates/mantis-todo/_gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,6 @@ Thumbs.db
4545
*.local
4646

4747

48-
storybook-static
48+
storybook-static
49+
50+
.netlify
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FRONTEND_URLS="https://mantis-todo.netlify.app"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[build]
2+
command = "nx build web-client"
3+
publish = "dist/apps/web-client/analog/public"
4+
functions = "dist/apps/web-client/analog"

templates/mantis-todo/apps/web-client/project.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@
6464
"staticFilePath": "dist/apps/web-client/browser"
6565
}
6666
},
67+
"start-local-db": {
68+
"executor": "nx:run-commands",
69+
"options": {
70+
"command": "node {projectRoot}/scripts/startLocalDb.js"
71+
}
72+
},
6773
"storybook": {
6874
"executor": "@storybook/angular:start-storybook",
6975
"options": {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { MongoMemoryServer } from 'mongodb-memory-server';
2+
import { join } from 'node:path';
3+
import { tmpdir } from 'node:os';
4+
import { createServer } from 'node:net';
5+
import { ensureDir } from 'fs-extra';
6+
7+
const port = 27017;
8+
const uri = `mongodb://127.0.0.1:${port}`;
9+
const dbPath = join(tmpdir(), 'mantis-todo-db');
10+
if (await isPortInUse(27017)) {
11+
console.log(
12+
`Local database already running at uri: ${uri}, dbPath: ${dbPath}`,
13+
);
14+
} else {
15+
await ensureDir(dbPath);
16+
await MongoMemoryServer.create({
17+
instance: {
18+
// Without specifying a dbPath a random path will be selected
19+
dbPath,
20+
// Without specifying the port a random port will be selected
21+
port,
22+
// Persists the data to disk
23+
storageEngine: 'wiredTiger',
24+
},
25+
});
26+
console.log(`Started local database at uri: ${uri}, dbPath: ${dbPath}`);
27+
}
28+
29+
function isPortInUse(port) {
30+
return new Promise((resolve, reject) => {
31+
const server = createServer();
32+
server.once('error', (err) => {
33+
server.close();
34+
if (err.code != 'EADDRINUSE') return reject(err);
35+
resolve(true);
36+
});
37+
server.once('listening', () => {
38+
server.close();
39+
resolve(false);
40+
});
41+
server.listen(port);
42+
});
43+
}

templates/mantis-todo/apps/web-client/src/server/db/mongo.ts

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,13 @@ import mongoose, {
33
type Schema,
44
type CompileModelOptions,
55
} from 'mongoose';
6-
import { MongoMemoryServer } from 'mongodb-memory-server';
7-
import path from 'node:path';
8-
import { tmpdir } from 'node:os';
9-
import net from 'node:net';
10-
import fs from 'fs-extra';
116

127
let cachedConnection: typeof mongoose | null = null;
138
export async function getConnection(): Promise<typeof mongoose> {
149
if (cachedConnection) {
1510
return cachedConnection;
1611
}
17-
const uri = await getUri();
12+
const uri = getUri();
1813
const newConnection = await mongoose.connect(uri);
1914
cachedConnection = newConnection;
2015
return newConnection;
@@ -32,56 +27,10 @@ export const useModel = async function <TSchema extends Schema>(
3227
: conn.model(name, schema, collection, options);
3328
} as typeof model;
3429

35-
let cachedUri: string | null = null;
36-
async function getUri(): Promise<string> {
37-
if (cachedUri) {
38-
return cachedUri;
39-
}
30+
function getUri(): string {
4031
const uri = import.meta.env.MONGODB_URI;
4132
if (typeof uri !== 'string') {
4233
throw new Error('MONGODB_URI environment variable is not set');
4334
}
44-
const useLocalDb = uri === 'local';
45-
if (useLocalDb) {
46-
const port = 27017;
47-
const uri = `mongodb://127.0.0.1:${port}`;
48-
const dbPath = path.join(tmpdir(), 'mantis-todo-db');
49-
if (await isPortInUse(27017)) {
50-
console.log(`Local database found at uri: ${uri}, dbPath: ${dbPath}`);
51-
return uri;
52-
}
53-
await fs.ensureDir(dbPath);
54-
await MongoMemoryServer.create({
55-
instance: {
56-
// Without specifying a dbPath a random path will be selected
57-
dbPath,
58-
// Without specifying the port a random port will be selected
59-
port,
60-
// Persists the data to disk
61-
storageEngine: 'wiredTiger',
62-
},
63-
});
64-
console.log(`Started local database at uri: ${uri}, dbPath: ${dbPath}`);
65-
cachedUri = uri;
66-
return uri;
67-
} else {
68-
cachedUri = uri;
69-
return uri;
70-
}
71-
}
72-
73-
function isPortInUse(port: number): Promise<boolean> {
74-
return new Promise((resolve, reject) => {
75-
const server = net.createServer();
76-
server.once('error', (err: NodeJS.ErrnoException) => {
77-
server.close();
78-
if (err.code != 'EADDRINUSE') return reject(err);
79-
resolve(true);
80-
});
81-
server.once('listening', () => {
82-
server.close();
83-
resolve(false);
84-
});
85-
server.listen(port);
86-
});
35+
return uri;
8736
}

0 commit comments

Comments
 (0)