Enable routing to env variable
This commit is contained in:
parent
8acfa11bf1
commit
79205efae3
@ -3,10 +3,10 @@ import useWebSocket from 'react-use-websocket'
|
|||||||
|
|
||||||
import assertNever from '~/common/assertNever.ts'
|
import assertNever from '~/common/assertNever.ts'
|
||||||
|
|
||||||
import { useUser } from '../user.tsx'
|
|
||||||
|
|
||||||
import { AsyncHandle, GameCommand, GameAction } from './types.ts'
|
import { AsyncHandle, GameCommand, GameAction } from './types.ts'
|
||||||
|
|
||||||
|
const WS_URL = Deno.env.get("WS_URL")
|
||||||
|
|
||||||
const MY_ID = (function(){
|
const MY_ID = (function(){
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||||
@ -81,10 +81,9 @@ interface SocketHandle {
|
|||||||
export default function useServerSocket(
|
export default function useServerSocket(
|
||||||
onUpdate: (action: GameAction) => void
|
onUpdate: (action: GameAction) => void
|
||||||
): AsyncHandle<SocketHandle> {
|
): AsyncHandle<SocketHandle> {
|
||||||
const profile = useUser()
|
|
||||||
const [state, dispatch] = React.useReducer(reducer, initialState)
|
const [state, dispatch] = React.useReducer(reducer, initialState)
|
||||||
|
|
||||||
// prep socket
|
/* prep socket */
|
||||||
|
|
||||||
const onMessage = React.useCallback((message: WebSocketEventMap['message']) => {
|
const onMessage = React.useCallback((message: WebSocketEventMap['message']) => {
|
||||||
const data = JSON.parse(message.data)
|
const data = JSON.parse(message.data)
|
||||||
@ -157,13 +156,8 @@ export default function useServerSocket(
|
|||||||
dispatch({type: 'close'})
|
dispatch({type: 'close'})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const url = React.useMemo(
|
|
||||||
() => `ws://localhost:7636/ws`,
|
|
||||||
[profile],
|
|
||||||
)
|
|
||||||
|
|
||||||
const {sendJsonMessage} = useWebSocket(
|
const {sendJsonMessage} = useWebSocket(
|
||||||
url,
|
WS_URL,
|
||||||
{onMessage, onOpen, onError, onClose, shouldReconnect},
|
{onMessage, onOpen, onError, onClose, shouldReconnect},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -182,7 +176,7 @@ export default function useServerSocket(
|
|||||||
})
|
})
|
||||||
}, [state, sendJson])
|
}, [state, sendJson])
|
||||||
|
|
||||||
// effects to push the coordinator along
|
/* effects to push the coordinator along */
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (state.status !== 'finding-game') return
|
if (state.status !== 'finding-game') return
|
||||||
@ -194,7 +188,7 @@ export default function useServerSocket(
|
|||||||
sendJson({command: 'join', player_id: state.playerId, match_id: state.matchId})
|
sendJson({command: 'join', player_id: state.playerId, match_id: state.matchId})
|
||||||
}, [sendJson, state])
|
}, [sendJson, state])
|
||||||
|
|
||||||
// return game command handler in wrapper
|
/* return game command handler in wrapper */
|
||||||
|
|
||||||
const handle = React.useMemo<AsyncHandle<SocketHandle>>(() => {
|
const handle = React.useMemo<AsyncHandle<SocketHandle>>(() => {
|
||||||
switch (state.status) {
|
switch (state.status) {
|
||||||
|
1
run-local.sh
Executable file
1
run-local.sh
Executable file
@ -0,0 +1 @@
|
|||||||
|
WS_URL=ws://localhost:7636 deno run --allow-read --allow-write --unstable --allow-env --allow-net --import-map import_map.json ./server/server.ts
|
@ -5,6 +5,66 @@ import { Router } from 'oak'
|
|||||||
|
|
||||||
// import App from '~/client/App.tsx'
|
// import App from '~/client/App.tsx'
|
||||||
|
|
||||||
|
function indexOfAll(source: string, query: string): number[] {
|
||||||
|
let currentPosition = 0
|
||||||
|
const buffer: number[] = []
|
||||||
|
while (currentPosition !== -1) {
|
||||||
|
const lastPosition = currentPosition
|
||||||
|
currentPosition = source.indexOf(query, lastPosition + 1)
|
||||||
|
if (currentPosition !== -1) buffer.push(currentPosition)
|
||||||
|
}
|
||||||
|
// ensure it's sorted in case while loop betrays us
|
||||||
|
return buffer.sort()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ResolvedEnvVar {
|
||||||
|
callsiteBounds: [number, number]
|
||||||
|
varname: string
|
||||||
|
value?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ENV_SEARCH_STRING = "Deno.env.get(\""
|
||||||
|
const ENV_SEARCH_END_STRING = "\")"
|
||||||
|
|
||||||
|
function resolveClientDenoEnvVars(source: string): string {
|
||||||
|
const startIndices = indexOfAll(source, ENV_SEARCH_STRING)
|
||||||
|
const resolved = startIndices.map((startIndex) => {
|
||||||
|
const endIndex = source.indexOf(ENV_SEARCH_END_STRING, startIndex)
|
||||||
|
const varname = source.slice(startIndex + ENV_SEARCH_STRING.length, endIndex)
|
||||||
|
const bounds = [startIndex, endIndex + ENV_SEARCH_END_STRING.length]
|
||||||
|
const value = Deno.env.get(varname)
|
||||||
|
return {
|
||||||
|
callsiteBounds: bounds,
|
||||||
|
varname,
|
||||||
|
value: `"${value}"`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function replaceBounds(input: string, newText: string | undefined, start: number, end: number) {
|
||||||
|
return `${input.slice(0, start)}${newText}${input.slice(end)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// reassemble source code by reversing the order and replacing strings
|
||||||
|
const reassembledSource = resolved.reverse().reduce(
|
||||||
|
(currentSource, {callsiteBounds, value, varname}) => {
|
||||||
|
if (value === undefined)
|
||||||
|
throw new Error(`Deno env variable ${varname} found in client code but not provided to server.`)
|
||||||
|
return replaceBounds(currentSource, value, callsiteBounds[0], callsiteBounds[1])
|
||||||
|
},
|
||||||
|
source,
|
||||||
|
)
|
||||||
|
return reassembledSource
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDict<T, U>(
|
||||||
|
dict: Record<string, T>,
|
||||||
|
fn: (entry: [string, T], index: number) => [string, U],
|
||||||
|
): Record<string, U> {
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(dict).map(fn)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async function createClientBundle() {
|
async function createClientBundle() {
|
||||||
const {files} = await Deno.emit('server/client.tsx', {
|
const {files} = await Deno.emit('server/client.tsx', {
|
||||||
bundle: 'module',
|
bundle: 'module',
|
||||||
@ -16,7 +76,15 @@ async function createClientBundle() {
|
|||||||
strictPropertyInitialization: false,
|
strictPropertyInitialization: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return files
|
const bundle = mapDict(files, ([path, source], i) => {
|
||||||
|
const resolved = resolveClientDenoEnvVars(source)
|
||||||
|
if (Deno.env.get("DEBUG")) {
|
||||||
|
Deno.writeTextFileSync(`debug/output${i}.js`, source)
|
||||||
|
Deno.writeTextFileSync(`debug/resolved${i}.js`, resolved)
|
||||||
|
}
|
||||||
|
return [path, resolved]
|
||||||
|
})
|
||||||
|
return bundle
|
||||||
}
|
}
|
||||||
|
|
||||||
const bundle = await createClientBundle()
|
const bundle = await createClientBundle()
|
||||||
|
Loading…
Reference in New Issue
Block a user