@hummingbirdworks/proxy 0.1.0 → 0.2.0
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/README.md +65 -9
- package/package.json +17 -1
- package/powerapp_dev_proxy.py +6 -1
- package/vite/index.d.ts +22 -0
- package/vite/index.js +49 -0
package/README.md
CHANGED
|
@@ -127,14 +127,70 @@ instructions for your OS/browser.
|
|
|
127
127
|
open DevTools → Application → Service Workers and check "Bypass for network"
|
|
128
128
|
to disable the service worker cache.
|
|
129
129
|
|
|
130
|
-
##
|
|
130
|
+
## Using with Vite (HMR)
|
|
131
|
+
|
|
132
|
+
A `devserver` rule routes a web resource's requests to a running Vite dev
|
|
133
|
+
server, giving you hot module reload on the Dynamics-hosted page.
|
|
134
|
+
|
|
135
|
+
The dev server can stay on plain HTTP — the browser only talks to the proxy, and
|
|
136
|
+
the proxy relays requests (including the HMR websocket) to `localhost`. Because
|
|
137
|
+
the Dynamics page is HTTPS, the browser would block an insecure `ws://` HMR
|
|
138
|
+
socket as mixed content, so point the HMR client at `wss` and let the proxy
|
|
139
|
+
forward it to the HTTP dev server. No dev-server cert (or `vite-plugin-mkcert`)
|
|
140
|
+
is needed.
|
|
141
|
+
|
|
142
|
+
### Vite config
|
|
143
|
+
|
|
144
|
+
The package ships a Vite plugin that helps with the configuration of web resources.
|
|
145
|
+
It sets the base path, configures settings to support HMR with the proxy, and turns
|
|
146
|
+
off cache busting since powerapps already has cache busting when you publish customizations.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import { defineConfig } from 'vite'
|
|
150
|
+
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
|
151
|
+
import { powerAppsWebResource } from '@hummingbirdworks/proxy/vite'
|
|
152
|
+
|
|
153
|
+
export default defineConfig({
|
|
154
|
+
plugins: [
|
|
155
|
+
svelte(), // or react(), vue(), etc.
|
|
156
|
+
powerAppsWebResource({ prefix: 'test_/myapp/' }),
|
|
157
|
+
],
|
|
158
|
+
server: { port: 5173 },
|
|
159
|
+
})
|
|
160
|
+
```
|
|
131
161
|
|
|
132
|
-
|
|
133
|
-
config path, defaulting to `./proxy.config.toml` in the current directory. It
|
|
134
|
-
passes the resolved absolute path to the addon via the
|
|
135
|
-
`HUMMINGBIRD_PROXY_CONFIG` environment variable.
|
|
136
|
-
- **Running the addon directly** (without the CLI) is also supported:
|
|
162
|
+
Options:
|
|
137
163
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
164
|
+
- `prefix` (required): the web resource path, e.g. `test_/myapp/`.
|
|
165
|
+
- `hmrClientPort` (default `443`): port the browser uses for the HMR socket.
|
|
166
|
+
- `stableFilenames` (default `true`): emit unhashed filenames and a single
|
|
167
|
+
stylesheet. Set `false` to keep Vite's defaults.
|
|
168
|
+
|
|
169
|
+
If your HTML entry isn't `index.html`, add it to `build.rollupOptions.input`.
|
|
170
|
+
|
|
171
|
+
### Proxy rule
|
|
172
|
+
|
|
173
|
+
Point a `devserver` rule at the dev server. The `url` scheme/port must match
|
|
174
|
+
what Vite serves (`http://localhost:5173` by default here):
|
|
175
|
+
|
|
176
|
+
```toml
|
|
177
|
+
[[rules]]
|
|
178
|
+
type = "devserver"
|
|
179
|
+
name = "test_/myapp/"
|
|
180
|
+
url = "http://localhost:5173"
|
|
181
|
+
domain = "myorg.crm.dynamics.com"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Run
|
|
185
|
+
|
|
186
|
+
Start the dev server and the proxy, then browse through the proxy:
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
npm run dev
|
|
190
|
+
npm run proxy
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Open the Dynamics page hosting the web resource. Edit → save → the page updates
|
|
194
|
+
without a manual refresh. If HMR doesn't trigger, confirm Vite's port matches
|
|
195
|
+
the rule `url`, that the HMR socket connects over `wss`, and that the service
|
|
196
|
+
worker cache is bypassed (see Notes above).
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hummingbirdworks/proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "mitmproxy-based dev proxy that redirects Dataverse / Dynamics 365 web resources and PCF control assets to local dev builds or a running dev server.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"hummingbird-proxy": "bin/hummingbird-proxy.js"
|
|
7
7
|
},
|
|
8
|
+
"exports": {
|
|
9
|
+
"./vite": {
|
|
10
|
+
"types": "./vite/index.d.ts",
|
|
11
|
+
"default": "./vite/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
8
15
|
"files": [
|
|
9
16
|
"bin/",
|
|
17
|
+
"vite/",
|
|
10
18
|
"powerapp_dev_proxy.py",
|
|
11
19
|
"proxy.config.example.toml",
|
|
12
20
|
"README.md"
|
|
@@ -14,6 +22,14 @@
|
|
|
14
22
|
"engines": {
|
|
15
23
|
"node": ">=16"
|
|
16
24
|
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"vite": ">=4"
|
|
27
|
+
},
|
|
28
|
+
"peerDependenciesMeta": {
|
|
29
|
+
"vite": {
|
|
30
|
+
"optional": true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
17
33
|
"keywords": [
|
|
18
34
|
"mitmproxy",
|
|
19
35
|
"powerapps",
|
package/powerapp_dev_proxy.py
CHANGED
|
@@ -184,7 +184,12 @@ def _web_resource_name(request: http.Request) -> str | None:
|
|
|
184
184
|
components = request.path_components
|
|
185
185
|
for i, component in enumerate(components):
|
|
186
186
|
if component.lower() == "webresources":
|
|
187
|
-
|
|
187
|
+
name = "/".join(components[i + 1:])
|
|
188
|
+
# path_components drops a trailing slash; keep it so dev-server root
|
|
189
|
+
# requests (e.g. the Vite HMR base URL) still match a rule prefix.
|
|
190
|
+
if name and request.path.split("?", 1)[0].endswith("/"):
|
|
191
|
+
name += "/"
|
|
192
|
+
return name
|
|
188
193
|
return None
|
|
189
194
|
|
|
190
195
|
|
package/vite/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
export interface WebResourceOptions {
|
|
4
|
+
/** Web resource path prefix, e.g. `test_/myapp/`. Leading/trailing slashes are optional. */
|
|
5
|
+
prefix: string;
|
|
6
|
+
/** Port the browser uses for the HMR websocket. Defaults to `443`. */
|
|
7
|
+
hmrClientPort?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Emit unhashed filenames and a single stylesheet so solution components stay
|
|
10
|
+
* stable across builds. Defaults to `true`; set `false` to keep Vite's defaults.
|
|
11
|
+
*/
|
|
12
|
+
stableFilenames?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Vite plugin that aligns the dev server and build output with a Dataverse /
|
|
17
|
+
* Dynamics 365 web resource served through `@hummingbirdworks/proxy`.
|
|
18
|
+
*
|
|
19
|
+
* Sets `base` (absolute in dev, relative in build) and a `wss` HMR socket, and
|
|
20
|
+
* optionally emits stable filenames.
|
|
21
|
+
*/
|
|
22
|
+
export function powerAppsWebResource(options: WebResourceOptions): Plugin;
|
package/vite/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Vite plugin that configures a project so its dev server and build output line
|
|
4
|
+
// up with a Dataverse / Dynamics 365 web resource served through the proxy.
|
|
5
|
+
|
|
6
|
+
function powerAppsWebResource(options) {
|
|
7
|
+
if (!options || typeof options.prefix !== "string") {
|
|
8
|
+
throw new Error(
|
|
9
|
+
"powerAppsWebResource: 'prefix' is required, e.g. 'test_/myapp/'."
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
const prefix = options.prefix.replace(/^\/+|\/+$/g, "");
|
|
13
|
+
if (!prefix) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"powerAppsWebResource: 'prefix' must not be empty, e.g. 'test_/myapp/'."
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
const clientPort = options.hmrClientPort != null ? options.hmrClientPort : 443;
|
|
19
|
+
const stableFilenames = options.stableFilenames !== false;
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
name: "@hummingbirdworks/proxy:webresource",
|
|
23
|
+
config(_config, env) {
|
|
24
|
+
const isServe = env.command === "serve";
|
|
25
|
+
// Dynamics pages are HTTPS, so the HMR socket must be wss to avoid
|
|
26
|
+
// mixed-content blocking; the proxy relays it to the HTTP dev server.
|
|
27
|
+
const config = {
|
|
28
|
+
base: isServe ? "/webresources/" + prefix + "/" : "./",
|
|
29
|
+
server: { hmr: { protocol: "wss", clientPort: clientPort } },
|
|
30
|
+
};
|
|
31
|
+
if (stableFilenames) {
|
|
32
|
+
config.build = {
|
|
33
|
+
cssCodeSplit: false,
|
|
34
|
+
rollupOptions: {
|
|
35
|
+
output: {
|
|
36
|
+
// Stable filenames — Dynamics does its own cache busting on publish.
|
|
37
|
+
entryFileNames: "[name].js",
|
|
38
|
+
chunkFileNames: "[name].js",
|
|
39
|
+
assetFileNames: "[name].[ext]",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return config;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
exports.powerAppsWebResource = powerAppsWebResource;
|