Skip to content

Commit 2d47030

Browse files
committed
Allow web deploy and proxy of domain.
Update docs.
1 parent 55f814c commit 2d47030

File tree

3 files changed

+144
-11
lines changed

3 files changed

+144
-11
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ package = "netlify-plugin-nimbella"
7575

7676
[plugins.inputs]
7777
path = "/api" # The prefix path to access your deployed packages.
78+
web = false # Deploy frontend and proxy domain to Nimbella (allowed values are true or false).
7879
env = [] # Environment variables to export to serverless APIs.
7980
```
8081

@@ -105,6 +106,15 @@ site
105106

106107
The APIs are `auth/login`, `auth/logout`, `todos/create`, and so on. An API may be a single file, or built from a set of files within an enclosing directory. You may mix languages, and deploy functions as source, without even building languages that require compilation. To API end point for any of the actions is constructed in the same way. For example the serverless API implemented by `auth/login/index.js` is invoked with the REST end point `https://your-site.com/api/auth/login`.
107108

109+
Your Nimbella project may also include a `web` folder which can be deployed to the Nimbella cloud as well. The web folder represents the frontend assets for your projects (e.g., HTML, CSS, JavaScript). In a typical deployment of a Nimbella project using Netlify, you will use the Netlify CDN to serve your web assets. There are however some use-cases where you want to deploy the entire project to Nimbella, and proxy to your Nimbella domain from your Netlify site. To do this, you need to enable the deployment of the web portion of your project by setting an option `web = true` in the `plugins.inputs` section of your `netlify.toml` file.
110+
111+
```toml
112+
[plugins.inputs]
113+
# Deploy the web folder and proxy your site entirely to your Nimbella deployment.
114+
web = true
115+
```
116+
117+
108118
## Exporting Environment Variables to Serverless APIs
109119

110120
If your serverless APIs require environment variables, you have to export the variables explicitly in the `plugins.input` section of the `netlify.toml` file. This is to avoid exporting the entire environment to your APIs, and instead selecting exporting only the variables the actions need access to.

src/index.js

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const {homedir} = require('os')
55

66
const nimConfig = join(homedir(), '.nimbella')
77
let isProject = false
8+
let deployWeb = false
89

910
// Disable auto updates of nim.
1011
process.env.NIM_DISABLE_AUTOUPDATE = '1'
@@ -21,35 +22,48 @@ async function getApiHost(run) {
2122
/**
2223
* Deploy a Nimbella Project.
2324
* @param {*} run - function provided under utils by Netlify to build event functions.
25+
* @param {bool} includeWeb - flag to include/exclude web assets from project deploy
2426
*/
25-
async function deployProject(run) {
26-
await run.command(`nim project deploy . --exclude=web`)
27+
async function deployProject(run, includeWeb) {
28+
if (includeWeb) {
29+
await run.command(`nim project deploy .`) // Do not exclude web folder
30+
} else {
31+
await run.command(`nim project deploy . --exclude=web`)
32+
}
2733
}
2834

2935
// Creates or updates the _redirects file; this file takes precedence
3036
// over other redirect declarations, and is processed from top to bottom
3137
//
3238
// If there is an API path directive input.path in the plugin settings, add a
3339
// matching rule to the _redirects file. The target is the Nimbella namespace/:splat.
40+
//
41+
// If deploying the web assets as well, then proxy the entire domain instead.
3442
async function processRedirects(run, inputs) {
3543
const redirectRules = []
3644
const {stdout: namespace} = await run.command(`nim auth current`)
3745
const apihost = await getApiHost(run)
3846

39-
let {path: redirectPath} = inputs
40-
redirectPath = redirectPath.endsWith('/') ? redirectPath : redirectPath + '/'
41-
if (redirectPath) {
42-
redirectRules.push(
43-
`${redirectPath}* https://${apihost}/api/v1/web/${namespace}/:splat 200!`
44-
)
47+
if (deployWeb) {
48+
redirectRules.push(`/* https://${namespace}-${apihost}/:splat 200!`)
49+
} else {
50+
let {path: redirectPath} = inputs
51+
redirectPath = redirectPath.endsWith('/')
52+
? redirectPath
53+
: redirectPath + '/'
54+
if (redirectPath) {
55+
redirectRules.push(
56+
`${redirectPath}* https://${apihost}/api/v1/web/${namespace}/:splat 200!`
57+
)
58+
}
4559
}
4660

4761
return redirectRules
4862
}
4963

5064
module.exports = {
5165
// Execute before build starts.
52-
onPreBuild: async ({utils}) => {
66+
onPreBuild: async ({utils, inputs}) => {
5367
if (
5468
!process.env.NIMBELLA_LOGIN_TOKEN &&
5569
!(await utils.cache.has(nimConfig))
@@ -100,7 +114,14 @@ module.exports = {
100114
}
101115
}
102116

103-
isProject = existsSync('packages')
117+
deployWeb = false
118+
if (typeof inputs.web === 'boolean') {
119+
deployWeb = inputs.web
120+
} else if (typeof inputs.web === 'string') {
121+
deployWeb = inputs.web.toLowerCase() === 'true'
122+
}
123+
124+
isProject = existsSync('packages') || (deployWeb && existsSync('web'))
104125
},
105126
// Build and deploy the Nimbella project
106127
onBuild: async ({utils, inputs}) => {
@@ -117,7 +138,7 @@ module.exports = {
117138
}
118139

119140
try {
120-
await deployProject(utils.run)
141+
await deployProject(utils.run, deployWeb)
121142
} catch (error) {
122143
utils.build.failBuild('Failed to build and deploy the project', {
123144
error

test/index.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,54 @@ describe('onBuild()', () => {
230230
`nim project deploy . --exclude=web`
231231
)
232232
})
233+
234+
test("should run nim project deploy excluding 'web' if inputs.web is not set", async () => {
235+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue'
236+
process.env.CONTEXT = 'production'
237+
238+
const pluginInputs = {
239+
utils,
240+
constants: {CONFIG_PATH: './netlify.toml', PUBLISH_DIR: ''},
241+
inputs: {
242+
path: ''
243+
}
244+
}
245+
246+
mockFs({
247+
packages: {},
248+
web: {}
249+
})
250+
await plugin.onPreBuild(pluginInputs)
251+
await plugin.onBuild(pluginInputs)
252+
mockFs.restore()
253+
254+
expect(utils.run.command.mock.calls[1][0]).toEqual(
255+
`nim project deploy . --exclude=web`
256+
)
257+
})
258+
259+
test("should run nim project deploy if 'web' directory exists and inputs.web is set", async () => {
260+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue'
261+
process.env.CONTEXT = 'production'
262+
263+
const pluginInputs = {
264+
utils,
265+
constants: {CONFIG_PATH: './netlify.toml', PUBLISH_DIR: ''},
266+
inputs: {
267+
path: '',
268+
web: 'true'
269+
}
270+
}
271+
272+
mockFs({
273+
web: {}
274+
})
275+
await plugin.onPreBuild(pluginInputs)
276+
await plugin.onBuild(pluginInputs)
277+
mockFs.restore()
278+
279+
expect(utils.run.command.mock.calls[1][0]).toEqual(`nim project deploy .`)
280+
})
233281
})
234282

235283
describe('onPostBuild()', () => {
@@ -334,4 +382,58 @@ describe('onPostBuild()', () => {
334382
expect(redirects[1]).toEqual('/mypath https://example.com') // Original rewrites come last
335383
expect(redirects[2]).toEqual('/fn2 /.netlify/functions/fn2 200') // Original rewrites come last
336384
})
385+
386+
test('should proxy entire domain if deploying web assets', async () => {
387+
process.env.NIMBELLA_LOGIN_TOKEN = 'somevalue'
388+
process.env.CONTEXT = 'production'
389+
390+
utils.run.command = jest.fn((cmd) => {
391+
if (cmd === 'nim auth current') return {stdout: 'namespace'}
392+
if (cmd === 'nim auth current --apihost') return {stdout: 'somehost'}
393+
return {stdout: '???'}
394+
})
395+
396+
const pluginInputs = {
397+
utils,
398+
constants: {CONFIG_PATH: 'netlify.toml', PUBLISH_DIR: ''},
399+
inputs: {
400+
path: '/api',
401+
web: 'true'
402+
}
403+
}
404+
405+
mockFs({
406+
packages: {},
407+
web: {},
408+
'netlify.toml': `
409+
[[redirects]]
410+
from = "/home"
411+
to = "/index.html"
412+
status = 200
413+
414+
[[redirects]]
415+
from = "/somefn"
416+
to = "/.netlify/functions/fn"
417+
status = 200
418+
`,
419+
'some-dir': {
420+
'create.js': '',
421+
'update.js': ''
422+
},
423+
_redirects: [
424+
'/mypath https://example.com',
425+
'/fn2 /.netlify/functions/fn2 200'
426+
].join('\n')
427+
})
428+
429+
await plugin.onPreBuild(pluginInputs)
430+
await plugin.onPostBuild(pluginInputs)
431+
const redirects = String(fs.readFileSync('_redirects')).trim().split('\n')
432+
mockFs.restore()
433+
434+
expect(redirects.length).toEqual(3)
435+
expect(redirects[0]).toEqual('/* https://namespace-somehost/:splat 200!') // And input directive
436+
expect(redirects[1]).toEqual('/mypath https://example.com') // Original rewrites come last
437+
expect(redirects[2]).toEqual('/fn2 /.netlify/functions/fn2 200') // Original rewrites come last
438+
})
337439
})

0 commit comments

Comments
 (0)