-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add @remix-run/azure-functions
package
#2521
Closed
Closed
Changes from 67 commits
Commits
Show all changes
68 commits
Select commit
Hold shift + click to select a range
bf83669
test(express): add basic test for createRemixRequest
mcansh 010d5c4
test(architect): add tests for headers
mcansh f1f10ba
test(vercel): extract headers conversion function, start adding tests…
mcansh 5e64fd3
test(vercel): shutdown server after running test
mcansh 70bc39f
chore: remove `Object.fromEntries(responseHeaders)` spreading
mcansh 6f8d02b
test(vercel): add more tests
mcansh 10f1b11
test(vercel): add test for createRequestHandler
mcansh e19177b
test(vercel): use supertest for better header testing
mcansh 5c94bd3
fix(express): read port from request app settings
mcansh cabc7ac
fix(express): req.get("host") returns the port
mcansh df40493
test(express): update request mocking
mcansh b36f60d
feat: initial azure adapter
mcansh b7c613d
test(azure): add test for createRemixRequest
mcansh 22e2292
test(azure): add initial test for createRequestHandler
mcansh b40a51f
chore: update remix-node version
mcansh 389719c
chore: update notes
mcansh 7e50834
chore(azure): use return instead of `context.res = {}`
mcansh 9206f3d
chore: input headers are just a string
mcansh 4983217
feat: add initial azure template
mcansh d7406f2
chore(azure): update template readme, add tweaked github action that …
mcansh 265521d
chore(azure): use generic secret name in github action
mcansh 6835d4c
chore(azure): remove erroneous 'a'
mcansh d6d4ba4
Add space after comma
mjackson a39c439
feat(getDocumentHeaders): re-add support for multiple set-cookie headers
mcansh 6b3f71b
chore(azure): update adapter to use update request/response/headers
mcansh 505647b
chore: rename azure action
mcansh b18919c
chore(init/azure): update handler
mcansh f82b0e7
chore(init/azure): add rewrites and required index.html file
mcansh fca6d0a
feat(azure): add support for dev
mcansh fc6bcdb
Revert "feat(azure): add support for dev"
mcansh 36070e9
chore(CLA)
aaronpowell 0bdbe0c
chore: fix up from linting problems
aaronpowell 369ee57
fix: better package name and sample app
aaronpowell e37e686
renamed the template
aaronpowell 32bb27f
tweaking the deps and adding ts
aaronpowell 19a1f6d
fix: forgot typescript dep
aaronpowell 27df6b1
fix: adding function tools as a dependency
aaronpowell 7f152ff
fix: forgot to set worker/language on init to avoid prompting
aaronpowell 49e463c
fix: bad merge on styling doc
aaronpowell bc19122
Apply suggestions from code review
aaronpowell 0bac793
fix: missing .eslintrc and wrong favicon
aaronpowell 74d77b6
fix: linting mistakes
aaronpowell c9a21ed
fix: using @remix-run/node not server directly
aaronpowell 4c150dd
chore: reverting whitespace from merge
aaronpowell cc6a1b8
Update packages/remix-azure-functions/package.json
aaronpowell 97766bd
Update templates/azure-functions/.eslintrc
aaronpowell b5204bb
fix: using the correct packages
aaronpowell 292e671
fix: azure template works
aaronpowell a81bcb1
chore: linting fixes
aaronpowell bf336fa
feat: Adding Azure to the list of templates
aaronpowell 6e43ff1
Apply suggestions from code review
aaronpowell 49f4245
chore: removing mock that's no longer needed
aaronpowell bbfc8f8
chore: should be a devDep
aaronpowell 3e6103b
fix: azure-functions extension tests weren't included
aaronpowell 4fa2072
test: fixing the azure functions tests
aaronpowell ee10de7
test: adding missing tests
aaronpowell adb6781
Apply suggestions from code review
aaronpowell 266d4b2
chore: tidying up docs for azure functions
aaronpowell 8373aab
chore: alphabetising the order
aaronpowell 86edd6b
fix: missing jest setup
aaronpowell 408cdea
chore: update `yarn.lock`
MichaelDeBoey cb539af
Apply suggestions from code review
aaronpowell 58be825
chore(remix-azure-functions): run `sort-package-json`
MichaelDeBoey 63783db
chore(remix-azure-functions): update dependencies
MichaelDeBoey a2ffdf0
chore(remix-azure-functions): add `engines` field to `package.json`
MichaelDeBoey 8e94a44
Apply suggestions from code review
aaronpowell ecaaeef
Update templates/azure-functions/app/entry.client.tsx
aaronpowell f9b65ff
Apply suggestions from code review
aaronpowell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
- aaronpowell | ||
- aaronpowell96 | ||
- aaronshaf | ||
- abereghici | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Welcome to Remix! | ||
|
||
[Remix](https://remix.run) is a web framework that helps you build better websites with React. | ||
|
||
To get started, open a new shell and run: | ||
|
||
```sh | ||
npx create-remix@latest | ||
``` | ||
|
||
Then follow the prompts you see in your terminal. | ||
|
||
For more information about Remix, [visit remix.run](https://remix.run)! | ||
|
||
## About | ||
|
||
This package can be used to host Remix within an [Azure Function](https://docs.microsoft.com/azure/azure-functions/) or in [Azure Static Web Apps](https://docs.microsoft.com/azure/static-web-apps) (using the built-in Azure Functions support). |
269 changes: 269 additions & 0 deletions
269
packages/remix-azure-functions/__tests__/server-test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,269 @@ | ||
import type { Context, HttpRequest } from "@azure/functions"; | ||
import { | ||
createRequestHandler as createRemixRequestHandler, | ||
} from "@remix-run/node"; | ||
|
||
import { | ||
createRemixHeaders, | ||
createRemixRequest, | ||
createRequestHandler, | ||
} from "../server"; | ||
|
||
// We don't want to test that the remix server works here (that's what the | ||
// puppetteer tests do), we just want to test the express adapter | ||
jest.mock("@remix-run/node", () => { | ||
let original = jest.requireActual("@remix-run/node"); | ||
return { | ||
...original, | ||
createRequestHandler: jest.fn(), | ||
}; | ||
}); | ||
|
||
let mockedCreateRequestHandler = | ||
createRemixRequestHandler as jest.MockedFunction< | ||
typeof createRemixRequestHandler | ||
>; | ||
|
||
describe("azure createRequestHandler", () => { | ||
let context: Context; | ||
|
||
beforeEach(() => { | ||
context = { log: jest.fn() } as unknown as Context; | ||
}); | ||
|
||
describe("basic requests", () => { | ||
afterEach(() => { | ||
mockedCreateRequestHandler.mockReset(); | ||
}); | ||
|
||
afterAll(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
|
||
it("handles requests", async () => { | ||
mockedCreateRequestHandler.mockImplementation(() => async (req) => { | ||
return new Response(`URL: ${new URL(req.url).pathname}`); | ||
}); | ||
|
||
let mockedRequest: HttpRequest = { | ||
method: "GET", | ||
url: "/foo/bar", | ||
rawBody: "", | ||
headers: { | ||
"x-ms-original-url": "http://localhost:3000/foo/bar", | ||
}, | ||
params: {}, | ||
query: {}, | ||
body: "", | ||
}; | ||
|
||
let res = await createRequestHandler({ build: undefined })( | ||
context, | ||
mockedRequest | ||
); | ||
|
||
expect(res.status).toBe(200); | ||
expect(res.body).toBe("URL: /foo/bar"); | ||
}); | ||
|
||
it("handles status codes", async () => { | ||
mockedCreateRequestHandler.mockImplementation(() => async () => { | ||
return new Response (null, { status: 204 }); | ||
}); | ||
|
||
let mockedRequest: HttpRequest = { | ||
method: "GET", | ||
url: "/foo/bar", | ||
rawBody: "", | ||
headers: { | ||
"x-ms-original-url": "http://localhost:3000/foo/bar", | ||
}, | ||
params: {}, | ||
query: {}, | ||
body: "", | ||
}; | ||
|
||
let res = await createRequestHandler({ build: undefined })( | ||
context, | ||
mockedRequest | ||
); | ||
|
||
expect(res.status).toBe(204); | ||
}); | ||
|
||
it("sets headers", async () => { | ||
mockedCreateRequestHandler.mockImplementation(() => async (req) => { | ||
let headers = new Headers({ "X-Time-Of-Year": "most wonderful" }); | ||
headers.append( | ||
"Set-Cookie", | ||
"first=one; Expires=0; Path=/; HttpOnly; Secure; SameSite=Lax" | ||
); | ||
headers.append( | ||
"Set-Cookie", | ||
"second=two; MaxAge=1209600; Path=/; HttpOnly; Secure; SameSite=Lax" | ||
); | ||
headers.append( | ||
"Set-Cookie", | ||
"third=three; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Path=/; HttpOnly; Secure; SameSite=Lax" | ||
); | ||
for(let [key, value] of req.headers.entries()) { | ||
headers.set(key, value); | ||
} | ||
return new Response (null, { headers }); | ||
}); | ||
|
||
let mockedRequest: HttpRequest = { | ||
method: "GET", | ||
url: "/foo/bar", | ||
rawBody: "", | ||
headers: { | ||
"x-ms-original-url": "http://localhost:3000/foo/bar", | ||
}, | ||
params: {}, | ||
query: {}, | ||
body: "", | ||
}; | ||
|
||
let res = await createRequestHandler({ build: undefined })( | ||
context, | ||
mockedRequest | ||
); | ||
|
||
expect(res.headers["x-ms-original-url"]).toEqual(["http://localhost:3000/foo/bar"]); | ||
expect(res.headers["X-Time-Of-Year"]).toEqual(["most wonderful"]); | ||
expect(res.headers["Set-Cookie"]).toEqual([ | ||
"first=one; Expires=0; Path=/; HttpOnly; Secure; SameSite=Lax", | ||
"second=two; MaxAge=1209600; Path=/; HttpOnly; Secure; SameSite=Lax", | ||
"third=three; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Path=/; HttpOnly; Secure; SameSite=Lax", | ||
]); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("azure createRemixHeaders", () => { | ||
describe("creates fetch headers from azure headers", () => { | ||
it("handles empty headers", () => { | ||
expect(createRemixHeaders({})).toMatchInlineSnapshot(` | ||
Headers { | ||
Symbol(map): Object {}, | ||
} | ||
`); | ||
}); | ||
|
||
it("handles simple headers", () => { | ||
expect(createRemixHeaders({ "x-foo": "bar" })).toMatchInlineSnapshot(` | ||
Headers { | ||
Symbol(map): Object { | ||
"x-foo": Array [ | ||
"bar", | ||
], | ||
}, | ||
} | ||
`); | ||
}); | ||
|
||
it("handles multiple headers", () => { | ||
expect(createRemixHeaders({ "x-foo": "bar", "x-bar": "baz" })) | ||
.toMatchInlineSnapshot(` | ||
Headers { | ||
Symbol(map): Object { | ||
"x-bar": Array [ | ||
"baz", | ||
], | ||
"x-foo": Array [ | ||
"bar", | ||
], | ||
}, | ||
} | ||
`); | ||
}); | ||
|
||
it("handles headers with multiple values", () => { | ||
expect(createRemixHeaders({ "x-foo": "bar, baz" })) | ||
.toMatchInlineSnapshot(` | ||
Headers { | ||
Symbol(map): Object { | ||
"x-foo": Array [ | ||
"bar, baz", | ||
], | ||
}, | ||
} | ||
`); | ||
}); | ||
|
||
it("handles headers with multiple values and multiple headers", () => { | ||
expect(createRemixHeaders({ "x-foo": "bar, baz", "x-bar": "baz" })) | ||
.toMatchInlineSnapshot(` | ||
Headers { | ||
Symbol(map): Object { | ||
"x-bar": Array [ | ||
"baz", | ||
], | ||
"x-foo": Array [ | ||
"bar, baz", | ||
], | ||
}, | ||
} | ||
`); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("azure createRemixRequest", () => { | ||
it("creates a request with the correct headers", async () => { | ||
let request: HttpRequest = { | ||
method: "GET", | ||
url: "/foo/bar", | ||
rawBody: "", | ||
headers: { | ||
"x-ms-original-url": "http://localhost:3000/foo/bar", | ||
}, | ||
params: {}, | ||
query: {}, | ||
body: "", | ||
}; | ||
|
||
expect(createRemixRequest(request)).toMatchInlineSnapshot(` | ||
NodeRequest { | ||
"abortController": undefined, | ||
"agent": undefined, | ||
"compress": true, | ||
"counter": 0, | ||
"follow": 20, | ||
"size": 0, | ||
"timeout": 0, | ||
Symbol(Body internals): Object { | ||
"body": null, | ||
"disturbed": false, | ||
"error": null, | ||
}, | ||
Symbol(Request internals): Object { | ||
"headers": Headers { | ||
Symbol(map): Object { | ||
"x-ms-original-url": Array [ | ||
"http://localhost:3000/foo/bar", | ||
], | ||
}, | ||
}, | ||
"method": "GET", | ||
"parsedURL": Url { | ||
"auth": null, | ||
"hash": null, | ||
"host": "localhost:3000", | ||
"hostname": "localhost", | ||
"href": "http://localhost:3000/foo/bar", | ||
"path": "/foo/bar", | ||
"pathname": "/foo/bar", | ||
"port": "3000", | ||
"protocol": "http:", | ||
"query": null, | ||
"search": null, | ||
"slashes": true, | ||
}, | ||
"redirect": "follow", | ||
"signal": null, | ||
}, | ||
} | ||
`); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import { installGlobals } from "@remix-run/node"; | ||
installGlobals(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import { installGlobals } from "@remix-run/node"; | ||
installGlobals(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import "./globals"; | ||
|
||
export type { GetLoadContextFunction, RequestHandler } from "./server"; | ||
export { createRequestHandler } from "./server"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/** @type {import('@jest/types').Config.InitialOptions} */ | ||
module.exports = { | ||
...require("../../jest/jest.config.shared"), | ||
displayName: "azure-functions", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
|
||
// Re-export everything from this package that is available in `remix`. | ||
aaronpowell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export { | ||
RequestHandler, | ||
createRequestHandler, | ||
GetLoadContextFunction, | ||
} from "@remix-run/azure-functions"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "@remix-run/azure-functions", | ||
"version": "1.6.8", | ||
aaronpowell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"description": "Azure Functions server request handler for Remix", | ||
"bugs": { | ||
"url": "https://github.com/remix-run/remix/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/remix-run/remix", | ||
"directory": "packages/remix-azure-functions" | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"@remix-run/node": "1.6.8" | ||
aaronpowell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
"devDependencies": { | ||
"@azure/functions": "^3.2.0", | ||
"@types/supertest": "^2.0.12", | ||
"node-mocks-http": "^1.11.0", | ||
"supertest": "^6.2.4" | ||
}, | ||
"peerDependencies": { | ||
"@azure/functions": "^3.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=14" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
const { getAdapterConfig } = require("../../rollup.utils"); | ||
|
||
/** @returns {import("rollup").RollupOptions[]} */ | ||
module.exports = function rollup() { | ||
return [getAdapterConfig("azure-functions")]; | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now have a new way of handling
magicExports
.Please add the magic exports in
getMagicExports
function of the root'srollup.utils.js