@tamagui/cli 1.52.3 → 1.52.5

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.
Files changed (59) hide show
  1. package/dist/dev/clientInjectPlugin.js +104 -0
  2. package/dist/dev/clientInjectPlugin.js.map +6 -0
  3. package/dist/dev/createDevServer.js +59 -39
  4. package/dist/dev/createDevServer.js.map +2 -2
  5. package/dist/dev/types.js +17 -0
  6. package/dist/dev/types.js.map +6 -0
  7. package/dist/dev.js +144 -87
  8. package/dist/dev.js.map +2 -2
  9. package/dist/vendor/repack/dev-server/src/createServer.js +15 -2
  10. package/dist/vendor/repack/dev-server/src/createServer.js.map +2 -2
  11. package/dist/vendor/repack/dev-server/src/plugins/wss/WebSocketRouter.js +0 -3
  12. package/dist/vendor/repack/dev-server/src/plugins/wss/WebSocketRouter.js.map +1 -1
  13. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/HermesInspectorProxy.js +1 -1
  14. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/HermesInspectorProxy.js.map +1 -1
  15. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketApiServer.js +4 -1
  16. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketApiServer.js.map +1 -1
  17. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketEventsServer.js +1 -0
  18. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketEventsServer.js.map +1 -1
  19. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketHMRServer.js +2 -2
  20. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketHMRServer.js.map +1 -1
  21. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketMessageServer.js +1 -0
  22. package/dist/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketMessageServer.js.map +1 -1
  23. package/dist/vendor/repack/dev-server/src/plugins/wss/wssPlugin.js +4 -1
  24. package/dist/vendor/repack/dev-server/src/plugins/wss/wssPlugin.js.map +1 -1
  25. package/dist/vendor/repack/dev-server/src/types.js.map +1 -1
  26. package/package.json +11 -7
  27. package/src/dev/clientInjectPlugin.ts +112 -0
  28. package/src/dev/createDevServer.ts +59 -47
  29. package/src/dev/types.ts +1 -0
  30. package/src/dev.ts +197 -95
  31. package/src/vendor/repack/dev-server/src/createServer.ts +17 -7
  32. package/src/vendor/repack/dev-server/src/plugins/wss/WebSocketRouter.ts +1 -5
  33. package/src/vendor/repack/dev-server/src/plugins/wss/servers/HermesInspectorProxy.ts +1 -1
  34. package/src/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketApiServer.ts +4 -1
  35. package/src/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketEventsServer.ts +3 -0
  36. package/src/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketHMRServer.ts +2 -2
  37. package/src/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketMessageServer.ts +3 -0
  38. package/src/vendor/repack/dev-server/src/plugins/wss/wssPlugin.ts +5 -5
  39. package/src/vendor/repack/dev-server/src/types.ts +4 -0
  40. package/types/dev/WebpackHMRClient.d.ts +1 -0
  41. package/types/dev/clientInjectPlugin.d.ts +7 -0
  42. package/types/dev/clientInjectPlugin.d.ts.map +1 -0
  43. package/types/dev/createDevServer.d.ts +4 -1
  44. package/types/dev/createDevServer.d.ts.map +1 -1
  45. package/types/dev/types.d.ts +5 -0
  46. package/types/dev/types.d.ts.map +1 -0
  47. package/types/dev.d.ts.map +1 -1
  48. package/types/vendor/repack/dev-server/src/createServer.d.ts.map +1 -1
  49. package/types/vendor/repack/dev-server/src/plugins/wss/WebSocketRouter.d.ts.map +1 -1
  50. package/types/vendor/repack/dev-server/src/plugins/wss/servers/HermesInspectorProxy.d.ts.map +1 -1
  51. package/types/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketApiServer.d.ts.map +1 -1
  52. package/types/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketEventsServer.d.ts.map +1 -1
  53. package/types/vendor/repack/dev-server/src/plugins/wss/servers/WebSocketMessageServer.d.ts.map +1 -1
  54. package/types/vendor/repack/dev-server/src/plugins/wss/wssPlugin.d.ts +2 -0
  55. package/types/vendor/repack/dev-server/src/plugins/wss/wssPlugin.d.ts.map +1 -1
  56. package/types/vendor/repack/dev-server/src/types.d.ts +3 -0
  57. package/types/vendor/repack/dev-server/src/types.d.ts.map +1 -1
  58. package/src/vendor/repack/dev-server/vendor/metro-inspector-proxy/src/Device.cjs +0 -1
  59. package/src/vendor/repack/dev-server/vendor/metro-inspector-proxy/src/Device.js +0 -1
@@ -1,14 +1,23 @@
1
1
  import { CLIResolvedOptions } from '@tamagui/types'
2
+ import mime from 'mime/lite'
2
3
 
3
4
  import { DEFAULT_PORT } from '../utils/constants'
4
5
  import { Server, createServer } from '../vendor/repack/dev-server/src'
6
+ import { HMRListener } from './types'
5
7
 
6
8
  export async function createDevServer(
7
9
  options: CLIResolvedOptions,
8
10
  {
9
11
  indexJson,
12
+ listenForHMR,
10
13
  getIndexBundle,
11
- }: { indexJson: Object; getIndexBundle: () => Promise<string> }
14
+ hotUpdatedCJSFiles,
15
+ }: {
16
+ indexJson: Object
17
+ getIndexBundle: () => Promise<string>
18
+ listenForHMR: (cb: HMRListener) => void
19
+ hotUpdatedCJSFiles: Map<string, string>
20
+ }
12
21
  ) {
13
22
  const { start, stop } = await createServer({
14
23
  options: {
@@ -46,19 +55,34 @@ export async function createDevServer(
46
55
  // ctx.broadcastToHmrClients({ action: 'building' }, platform)
47
56
  // })
48
57
 
49
- // compiler.on(
50
- // 'done',
51
- // ({ platform, stats }: { platform: string; stats: webpack.StatsCompilation }) => {
52
- // ctx.notifyBuildEnd(platform)
53
- // lastStats = stats
54
- // ctx.broadcastToHmrClients(
55
- // { action: 'built', body: createHmrBody(stats) },
56
- // platform
57
- // )
58
- // }
59
- // )
58
+ const platform = 'ios'
59
+ listenForHMR((update) => {
60
+ ctx.notifyBuildEnd(platform)
61
+ ctx.broadcastToHmrClients(
62
+ {
63
+ action: 'built',
64
+ body: createHmrBody({
65
+ errors: [],
66
+ warnings: [],
67
+ hash: `${Math.random()}`,
68
+ modules: {},
69
+ name: '',
70
+ time: 0,
71
+ }),
72
+ },
73
+ platform
74
+ )
75
+ })
60
76
 
61
77
  return {
78
+ hotFiles: {
79
+ getSource: (path) => {
80
+ const next = hotUpdatedCJSFiles.get(path)
81
+ hotUpdatedCJSFiles.delete(path) // memory leak prevent
82
+ return next || ''
83
+ },
84
+ },
85
+
62
86
  compiler: {
63
87
  getAsset: async (filename, platform, sendProgress) => {
64
88
  console.log('[GET] - ', filename)
@@ -70,9 +94,7 @@ export async function createDevServer(
70
94
  },
71
95
 
72
96
  getMimeType: (filename) => {
73
- console.log('getMimeType', filename)
74
- return 'application/javascript'
75
- // return compiler.getMimeType(filename)
97
+ return mime.getType(filename) || 'application/javascript'
76
98
  },
77
99
 
78
100
  inferPlatform: (uri) => {
@@ -96,7 +118,6 @@ export async function createDevServer(
96
118
  return ''
97
119
  },
98
120
  getSourceMap: async (fileUrl) => {
99
- console.log('get source map', fileUrl)
100
121
  // const { filename, platform } = parseFileUrl(fileUrl)
101
122
  // if (!platform) {
102
123
  // throw new Error('Cannot infer platform for file URL')
@@ -112,18 +133,16 @@ export async function createDevServer(
112
133
  },
113
134
 
114
135
  hmr: {
115
- getUriPath: () => '/hot',
136
+ getUriPath: () => '/__hmr',
116
137
  onClientConnected: (platform, clientId) => {
117
138
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
118
- console.log('client connected to hot')
119
139
  // todo
120
- const lastStats = {}
121
-
122
- ctx.broadcastToHmrClients(
123
- { action: 'sync', body: createHmrBody(lastStats) },
124
- platform,
125
- [clientId]
126
- )
140
+ // const lastStats = {}
141
+ // ctx.broadcastToHmrClients(
142
+ // { action: 'sync', body: createHmrBody(lastStats) },
143
+ // platform,
144
+ // [clientId]
145
+ // )
127
146
  },
128
147
  },
129
148
 
@@ -136,9 +155,21 @@ export async function createDevServer(
136
155
  onMessage: (log) => {
137
156
  const logEntry = makeLogEntryFromFastifyLog(log)
138
157
  logEntry.issuer = 'DevServer'
158
+
159
+ // ignore for now
160
+ if (logEntry.type === 'debug') return
161
+
139
162
  // error DevServer, warn DevServer
140
163
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
141
- console.log('[logger]', logEntry.type, logEntry.issuer, logEntry.message)
164
+ console.log(
165
+ '[logger]',
166
+ logEntry.type === 'info' ? '' : logEntry.type,
167
+ logEntry.message
168
+ .map((m) => {
169
+ return `${m.msg}`
170
+ })
171
+ .join(', ')
172
+ )
142
173
  // reporter.process(logEntry)
143
174
  },
144
175
  },
@@ -170,27 +201,8 @@ export async function createDevServer(
170
201
  }
171
202
  }
172
203
 
173
- function createHmrBody(stats?: any): HMRMessageBody | null {
174
- if (!stats) {
175
- return null
176
- }
177
-
178
- const modules: Record<string, string> = {}
179
- for (const module of stats.modules ?? []) {
180
- const { identifier, name } = module
181
- if (identifier !== undefined && name) {
182
- modules[identifier] = name
183
- }
184
- }
185
-
186
- return {
187
- name: stats.name ?? '',
188
- time: stats.time ?? 0,
189
- hash: stats.hash ?? '',
190
- warnings: stats.warnings || [],
191
- errors: stats.errors || [],
192
- modules,
193
- }
204
+ function createHmrBody(body: HMRMessageBody): HMRMessageBody | null {
205
+ return body
194
206
  }
195
207
 
196
208
  /**
@@ -0,0 +1 @@
1
+ export type HMRListener = (update: { file: string; contents: string }) => void
package/src/dev.ts CHANGED
@@ -1,122 +1,164 @@
1
1
  import { readFile } from 'fs/promises'
2
- import { AddressInfo } from 'net'
3
2
  import { join } from 'path'
4
3
 
5
4
  import { CLIResolvedOptions } from '@tamagui/types'
6
- import { nativePlugin, nativePrebuild, tamaguiPlugin } from '@tamagui/vite-plugin'
5
+ import viteReactPlugin, { swcTransform } from '@tamagui/vite-native-swc'
6
+ import { nativeBabelTransform, nativePlugin, nativePrebuild } from '@tamagui/vite-plugin'
7
7
  import chalk from 'chalk'
8
- import fs, { ensureDir, pathExists } from 'fs-extra'
9
- import { build, createServer } from 'vite'
8
+ import fs, { pathExists } from 'fs-extra'
9
+ import { InlineConfig, build, createServer, resolveConfig } from 'vite'
10
10
 
11
+ import { clientInjectionsPlugin } from './dev/clientInjectPlugin'
11
12
  import { createDevServer } from './dev/createDevServer'
13
+ import { HMRListener } from './dev/types'
12
14
  import { registerDispose } from './utils'
13
15
 
14
16
  export const dev = async (options: CLIResolvedOptions) => {
15
17
  const { root, mode, paths } = options
16
-
17
- process.chdir(process.cwd())
18
+ const projectRoot = root
18
19
 
19
20
  const packageRootDir = join(__dirname, '..')
20
21
 
21
22
  // build react-native
22
23
  await nativePrebuild()
23
24
 
25
+ // react native port (it scans 19000 +5)
26
+ const port = options.port || 8081
27
+
24
28
  const plugins = [
25
29
  // tamaguiPlugin({
26
30
  // components: ['tamagui'],
27
31
  // target: 'native',
28
32
  // }),
29
- nativePlugin(),
33
+ viteReactPlugin({
34
+ tsDecorators: true,
35
+ }),
36
+ nativePlugin({
37
+ port,
38
+ }),
30
39
  ]
31
40
 
32
- const rootFile = join(root, 'src/test-tamagui-stack.tsx')
33
-
34
- console.log('root', root, rootFile)
41
+ const hmrListeners: HMRListener[] = []
42
+ const hotUpdatedCJSFiles = new Map<string, string>()
35
43
 
36
- const server = await createServer({
37
- root: rootFile,
44
+ let serverConfig = {
45
+ root,
38
46
  mode: 'development',
39
- plugins,
47
+ clearScreen: false,
48
+ plugins: [
49
+ ...plugins,
50
+
51
+ {
52
+ name: `tamagui-hot-update`,
53
+ async handleHotUpdate({ file, read, modules }) {
54
+ // idk why but its giving me dist asset stuff
55
+ if (!file.includes('/src/')) {
56
+ return
57
+ }
58
+
59
+ const id = modules[0]?.url || file.replace(root, '')
60
+
61
+ if (!id) {
62
+ console.log('⚠️ no modules?', file)
63
+ return
64
+ }
65
+
66
+ try {
67
+ const raw = await read()
68
+
69
+ // swc isnt applied here weird
70
+ const swcout = await swcTransform(
71
+ file,
72
+ raw,
73
+ {
74
+ tsDecorators: true,
75
+ },
76
+ true
77
+ )
78
+
79
+ if (!swcout) {
80
+ throw 'sadsad'
81
+ }
82
+
83
+ let contents = await nativeBabelTransform(swcout.code)
84
+
85
+ contents = `exports = ((exports) => { ${contents}; return exports })({})`
86
+
87
+ // set here to be fetched next
88
+ // i'd have just sent it in the websocket but maybe theres some size limits
89
+ hotUpdatedCJSFiles.set(id, contents)
90
+
91
+ // for (const listener of hmrListeners) {
92
+ // listener({
93
+ // file,
94
+ // contents,
95
+ // })
96
+ // }
97
+ } catch (err) {
98
+ console.log('error hmring', err)
99
+ }
100
+ },
101
+ },
102
+ ],
40
103
  server: {
104
+ cors: true,
41
105
  port: options.port,
42
- host: options.host || 'localhost',
106
+ host: options.host || '127.0.0.1',
43
107
  },
44
- })
108
+ } satisfies InlineConfig
45
109
 
46
- await server.listen()
110
+ // first resolve config so we can pass into client plugin, then add client plugin:
111
+ const resolvedConfig = await resolveConfig(serverConfig, 'serve')
112
+ const viteRNClient = clientInjectionsPlugin(resolvedConfig)
47
113
 
48
- await ensureDir(options.paths.dotDir)
49
- // const res = await watchTamaguiConfig(options.tamaguiOptions)
114
+ plugins.push(viteRNClient)
50
115
 
51
- const info = server.httpServer?.address() as AddressInfo
116
+ serverConfig = {
117
+ ...serverConfig,
118
+ plugins: [...serverConfig.plugins],
119
+ }
52
120
 
53
- // react native port (it scans 19000 +5)
54
- const port = 8081
121
+ const server = await createServer(serverConfig)
55
122
 
56
- const defaultResponse = {
57
- name: 'myapp',
58
- slug: 'myapp',
59
- scheme: 'myapp',
60
- version: '1.0.0',
61
- jsEngine: 'jsc',
62
- orientation: 'portrait',
63
- icon: './assets/icon.png',
64
- userInterfaceStyle: 'light',
65
- splash: {
66
- image: './assets/splash.png',
67
- resizeMode: 'contain',
68
- backgroundColor: '#ffffff',
69
- imageUrl: 'http://127.0.0.1:8081/assets/./assets/splash.png',
70
- },
71
- updates: { fallbackToCacheTimeout: 0 },
72
- assetBundlePatterns: ['**/*'],
73
- ios: { supportsTablet: true, bundleIdentifier: 'com.natew.myapp' },
74
- android: {
75
- package: 'com.tamagui.myapp',
76
- adaptiveIcon: {
77
- foregroundImage: './assets/adaptive-icon.png',
78
- backgroundColor: '#FFFFFF',
79
- foregroundImageUrl: 'http://127.0.0.1:8081/assets/./assets/adaptive-icon.png',
80
- },
81
- },
82
- web: { favicon: './assets/favicon.png' },
83
- extra: { eas: { projectId: '061b4470-78c7-4d6a-b850-8167fb0a3434' } },
84
- _internal: {
85
- isDebug: false,
86
- projectRoot: '/Users/n8/tamagui/apps/kitchen-sink',
87
- dynamicConfigPath: null,
88
- staticConfigPath: '/Users/n8/tamagui/apps/kitchen-sink/app.json',
89
- packageJsonPath: '/Users/n8/tamagui/apps/kitchen-sink/package.json',
90
- },
91
- sdkVersion: '47.0.0',
92
- platforms: ['ios', 'android', 'web'],
93
- iconUrl: `http://127.0.0.1:${port}/assets/./assets/icon.png`,
94
- debuggerHost: `127.0.0.1:${port}`,
95
- logUrl: `http://127.0.0.1:${port}/logs`,
96
- developer: { tool: 'expo-cli', projectRoot: '/Users/n8/tamagui/apps/kitchen-sink' },
97
- packagerOpts: { dev: true },
98
- mainModuleName: 'index',
99
- __flipperHack: 'React Native packager is running',
100
- hostUri: `127.0.0.1:${port}`,
101
- bundleUrl: `http://127.0.0.1:${port}/index.bundle?platform=ios&dev=true&hot=false&lazy=true`,
102
- id: '@anonymous/myapp-473c4543-3c36-4786-9db1-c66a62ac9b78',
103
- }
123
+ await server.listen()
104
124
 
105
- // new server
106
- const outputJsPath = join(process.cwd(), '.tamagui', 'bundle.js')
125
+ // need to simulate browser fetching a file so vite loads module into module graph and hmr works
126
+ // no luck yet:
127
+
128
+ // trying to see whats going on with this:
129
+ // server.moduleGraph = new Proxy(server.moduleGraph, {
130
+ // get(t, p) {
131
+ // console.log('get', p)
132
+ // const out = Reflect.get(t, p)
133
+ // if (typeof out === 'function') {
134
+ // return new Proxy(out, {
135
+ // apply(a, b, c) {
136
+ // console.log('apply', p, c)
137
+ // return Reflect.apply(a as any, b, c)
138
+ // },
139
+ // })
140
+ // }
141
+ // return out
142
+ // },
143
+ // })
144
+
145
+ // server.moduleGraph.resolveUrl('/src/App.tsx')
146
+ // server.moduleGraph.getModuleByUrl('/src/App.tsx')
147
+ // server.moduleGraph.ensureEntryFromUrl('/src/App.tsx', false)
148
+ // await ensureDir(options.paths.dotDir)
149
+ // const res = await watchTamaguiConfig(options.tamaguiOptions)
107
150
 
108
151
  const dispose = await createDevServer(options, {
152
+ hotUpdatedCJSFiles,
153
+ listenForHMR(cb) {
154
+ hmrListeners.push(cb)
155
+ },
109
156
  getIndexBundle: async function getBundle() {
110
157
  const outputCode = await getBundleCode()
111
158
 
112
- // so you can debug output easier
113
- setTimeout(() => {
114
- fs.writeFile(outputJsPath, outputCode)
115
- })
116
-
117
159
  return outputCode
118
160
  },
119
- indexJson: defaultResponse,
161
+ indexJson: getIndexJsonReponse({ port, root }),
120
162
  })
121
163
 
122
164
  // rome-ignore lint/nursery/noConsoleLog: ok
@@ -132,10 +174,13 @@ export const dev = async (options: CLIResolvedOptions) => {
132
174
 
133
175
  async function getBundleCode() {
134
176
  // for easier quick testing things:
135
- const tmpBundle = join(packageRootDir, 'bundle.tmp.js')
177
+ const tmpBundle = join(process.cwd(), 'bundle.tmp.js')
136
178
  if (await pathExists(tmpBundle)) {
137
179
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
138
- console.log('returning temp bundle', tmpBundle)
180
+ console.log(
181
+ '⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ returning temp bundle ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️',
182
+ tmpBundle
183
+ )
139
184
  return await readFile(tmpBundle, 'utf-8')
140
185
  }
141
186
 
@@ -145,12 +190,9 @@ export const dev = async (options: CLIResolvedOptions) => {
145
190
  plugins,
146
191
  appType: 'custom',
147
192
  root,
193
+ clearScreen: false,
148
194
  build: {
149
- ssr: true,
150
- },
151
- ssr: {
152
- format: 'cjs',
153
- target: 'node',
195
+ ssr: false,
154
196
  },
155
197
  mode: 'development',
156
198
  define: {
@@ -159,17 +201,23 @@ export const dev = async (options: CLIResolvedOptions) => {
159
201
  },
160
202
  })
161
203
 
162
- const appCode = 'output' in buildOutput ? buildOutput.output[0].code : null
204
+ const appCodeIn = 'output' in buildOutput ? buildOutput.output[0].code : null
163
205
 
164
- if (!appCode) {
206
+ if (!appCodeIn) {
165
207
  throw `❌`
166
208
  }
167
209
 
168
- const [react, reactJsxRuntime, reactNative] = await Promise.all([
169
- readFile(join(process.cwd(), 'testing-area', 'react.js'), 'utf-8'),
170
- readFile(join(process.cwd(), 'testing-area', 'react-jsx-runtime.js'), 'utf-8'),
171
- readFile(join(process.cwd(), 'testing-area', 'react-native.js'), 'utf-8'),
172
- ])
210
+ const appCode = await nativeBabelTransform(appCodeIn)
211
+
212
+ const paths = [
213
+ join(process.cwd(), 'testing-area', 'react.js'),
214
+ join(process.cwd(), 'testing-area', 'react-jsx-runtime.js'),
215
+ join(process.cwd(), 'testing-area', 'react-native.js'),
216
+ ]
217
+
218
+ const [react, reactJsxRuntime, reactNative] = await Promise.all(
219
+ paths.map((p) => readFile(p, 'utf-8'))
220
+ )
173
221
 
174
222
  const reactCode = react.replace(
175
223
  `module.exports = require_react_development();`,
@@ -179,16 +227,19 @@ export const dev = async (options: CLIResolvedOptions) => {
179
227
  const reactJSXRuntimeCode = reactJsxRuntime.replace(
180
228
  `module.exports = require_react_jsx_runtime_production_min();`,
181
229
  `return require_react_jsx_runtime_production_min()`
230
+ // `module.exports = require_react_jsx_dev_runtime_development();`,
231
+ // `return require_react_jsx_dev_runtime_development();`
182
232
  )
183
233
 
184
234
  const reactNativeCode = reactNative
185
235
  .replace(
186
236
  `module.exports = require_react_native();`,
187
- `return require_react_native()`
237
+ `require_ReactNative(); return require_react_native()`
188
238
  )
239
+ // forcing onto global so i can re-thread it into require
189
240
  .replace(
190
- `renderable = /* @__PURE__ */ react(RootComponentWithMeaningfulName, null, renderable);`,
191
- ``
241
+ `ReactRefreshRuntime.injectIntoGlobalHook(global);`,
242
+ `globalThis['_ReactRefreshRuntime'] = ReactRefreshRuntime; ReactRefreshRuntime.injectIntoGlobalHook(global);`
192
243
  )
193
244
 
194
245
  const templateFile = join(packageRootDir, 'react-native-template.js')
@@ -197,6 +248,57 @@ export const dev = async (options: CLIResolvedOptions) => {
197
248
  .replace(`// -- react --`, reactCode)
198
249
  .replace(`// -- react-native --`, reactNativeCode)
199
250
  .replace(`// -- react/jsx-runtime --`, reactJSXRuntimeCode)
200
- .replace(`// -- app --`, appCode)
251
+ .replace(`// -- app --`, appCode.replace('"use strict";', ''))
252
+ }
253
+ }
254
+
255
+ function getIndexJsonReponse({ port, root }: { port: number | string; root }) {
256
+ return {
257
+ name: 'myapp',
258
+ slug: 'myapp',
259
+ scheme: 'myapp',
260
+ version: '1.0.0',
261
+ jsEngine: 'jsc',
262
+ orientation: 'portrait',
263
+ icon: './assets/icon.png',
264
+ userInterfaceStyle: 'light',
265
+ splash: {
266
+ image: './assets/splash.png',
267
+ resizeMode: 'contain',
268
+ backgroundColor: '#ffffff',
269
+ imageUrl: 'http://127.0.0.1:8081/assets/./assets/splash.png',
270
+ },
271
+ updates: { fallbackToCacheTimeout: 0 },
272
+ assetBundlePatterns: ['**/*'],
273
+ ios: { supportsTablet: true, bundleIdentifier: 'com.natew.myapp' },
274
+ android: {
275
+ package: 'com.tamagui.myapp',
276
+ adaptiveIcon: {
277
+ foregroundImage: './assets/adaptive-icon.png',
278
+ backgroundColor: '#FFFFFF',
279
+ foregroundImageUrl: 'http://127.0.0.1:8081/assets/./assets/adaptive-icon.png',
280
+ },
281
+ },
282
+ web: { favicon: './assets/favicon.png' },
283
+ extra: { eas: { projectId: '061b4470-78c7-4d6a-b850-8167fb0a3434' } },
284
+ _internal: {
285
+ isDebug: false,
286
+ projectRoot: root,
287
+ dynamicConfigPath: null,
288
+ staticConfigPath: join(root, 'app.json'),
289
+ packageJsonPath: join(root, 'package.json'),
290
+ },
291
+ sdkVersion: '47.0.0',
292
+ platforms: ['ios', 'android', 'web'],
293
+ iconUrl: `http://127.0.0.1:${port}/assets/./assets/icon.png`,
294
+ debuggerHost: `127.0.0.1:${port}`,
295
+ logUrl: `http://127.0.0.1:${port}/logs`,
296
+ developer: { tool: 'expo-cli', projectRoot: root },
297
+ packagerOpts: { dev: true },
298
+ mainModuleName: 'index',
299
+ __flipperHack: 'React Native packager is running',
300
+ hostUri: `127.0.0.1:${port}`,
301
+ bundleUrl: `http://127.0.0.1:${port}/index.bundle?platform=ios&dev=true&hot=false&lazy=true`,
302
+ id: '@anonymous/myapp-473c4543-3c36-4786-9db1-c66a62ac9b78',
201
303
  }
202
304
  }
@@ -61,6 +61,16 @@ export async function createServer(config: Server.Config) {
61
61
  },
62
62
  })
63
63
 
64
+ // fuck delegates
65
+ instance.register(async (inst) => {
66
+ inst.get('/file', async (req, reply) => {
67
+ const query = req.query as Record<string, string>
68
+ console.log('getting', query.file)
69
+ const source = delegate.hotFiles.getSource(query.file)
70
+ reply.send(source)
71
+ })
72
+ })
73
+
64
74
  // Register plugins
65
75
  await instance.register(fastifySensible)
66
76
  await instance.register(wssPlugin, {
@@ -82,12 +92,13 @@ export async function createServer(config: Server.Config) {
82
92
  options: config.options,
83
93
  })
84
94
 
85
- console.warn('disable debugger-ui + favicon for now')
86
- // await instance.register(fastifyStatic, {
87
- // root: debuggerAppPath,
88
- // prefix: '/debugger-ui',
89
- // prefixAvoidTrailingSlash: true,
90
- // })
95
+ const debuggerAppPath = (await import('@callstack/repack-debugger-app')).default
96
+
97
+ await instance.register(fastifyStatic, {
98
+ root: debuggerAppPath,
99
+ prefix: '/debugger-ui',
100
+ prefixAvoidTrailingSlash: true,
101
+ })
91
102
 
92
103
  // below is to prevent showing `GET 400 /favicon.ico`
93
104
  // errors in console when requesting the bundle via browser
@@ -105,7 +116,6 @@ export async function createServer(config: Server.Config) {
105
116
  })
106
117
 
107
118
  // Register routes
108
- instance.head('/', async () => '')
109
119
  instance.get('/', async () => delegate.messages.getHello())
110
120
  instance.get('/status', async () => delegate.messages.getStatus())
111
121
 
@@ -33,20 +33,16 @@ export class WebSocketRouter {
33
33
  let matched = false
34
34
 
35
35
  if (pathname === '/inspector/device') {
36
+ // ignore
36
37
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
37
- console.log('ignoring', pathname)
38
38
  // socket.destroy()
39
39
  return
40
40
  }
41
41
 
42
- // rome-ignore lint/nursery/noConsoleLog: <explanation>
43
- console.log('check for upgrade', pathname)
44
-
45
42
  for (const server of this.servers) {
46
43
  if (server.shouldUpgrade(pathname)) {
47
44
  matched = true
48
45
  // rome-ignore lint/nursery/noConsoleLog: <explanation>
49
- console.log('matched', pathname)
50
46
  server.upgrade(request, socket, head)
51
47
  break
52
48
  }
@@ -2,9 +2,9 @@ import type { IncomingMessage } from 'http'
2
2
  import { URL } from 'url'
3
3
 
4
4
  import type { FastifyInstance, FastifyReply, FastifyRequest, LogLevel } from 'fastify'
5
+ import Device from 'metro-inspector-proxy/src/Device'
5
6
  import WebSocket from 'ws'
6
7
 
7
- import Device from '../../../../vendor/metro-inspector-proxy/src/Device'
8
8
  import { Server } from '../../../types'
9
9
  import { WebSocketServer } from '../WebSocketServer'
10
10
 
@@ -60,7 +60,10 @@ export class WebSocketApiServer extends WebSocketServer {
60
60
  this.clients.delete(clientId)
61
61
  }
62
62
 
63
- socket.addEventListener('error', onClose)
63
+ socket.addEventListener('error', () => {
64
+ console.log('error1')
65
+ onClose()
66
+ })
64
67
  socket.addEventListener('close', onClose)
65
68
  }
66
69
  }
@@ -69,6 +69,9 @@ export class WebSocketEventsServer extends WebSocketServer {
69
69
  parseMessage(data: string): Command | undefined {
70
70
  try {
71
71
  const message = JSON.parse(data)
72
+
73
+ console.log('event message', message)
74
+
72
75
  if (message.version === WebSocketEventsServer.PROTOCOL_VERSION) {
73
76
  return message
74
77
  }
@@ -42,7 +42,7 @@ export class WebSocketHMRServer extends WebSocketServer {
42
42
  key.platform !== platform ||
43
43
  !(clientIds ?? [key.clientId]).includes(key.clientId)
44
44
  ) {
45
- return
45
+ continue
46
46
  }
47
47
 
48
48
  try {
@@ -65,7 +65,7 @@ export class WebSocketHMRServer extends WebSocketServer {
65
65
  */
66
66
  onConnection(socket: WebSocket, request: IncomingMessage) {
67
67
  const { searchParams } = new URL(request.url || '', 'http://localhost')
68
- const platform = searchParams.get('platform')
68
+ const platform = searchParams.get('platform') || 'ios'
69
69
 
70
70
  if (!platform) {
71
71
  this.fastify.log.info({