-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmodule.ts
More file actions
192 lines (179 loc) · 6.22 KB
/
module.ts
File metadata and controls
192 lines (179 loc) · 6.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import { defineNuxtModule, addPlugin, createResolver, addImportsDir, addServerHandler, addVitePlugin, addComponentsDir } from '@nuxt/kit'
import { defu } from 'defu'
import type { Tlv2RouteKey } from './runtime/route-keys'
// Config handler
export interface ModuleOptions {
// Bulma config
bulma: string
// Link sources
safelinkUtmSource?: string
// Route resolver
routes?: Partial<Record<Tlv2RouteKey, string>>
// Proxy options
useProxy: boolean
proxyBase?: string
apiBase?: string
// Login gate
loginGate?: boolean
requireLogin?: boolean
// Api keys
protomapsApikey?: string
nearmapsApikey?: string
mixpanelApikey?: string
// Auth0
auth0ClientId?: string
auth0Domain?: string
auth0Audience?: string
auth0Scope?: string
auth0RedirectUri?: string
auth0LogoutUri?: string
}
export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'tlv2-ui',
version: '0.3.0',
configKey: 'tlv2',
compatibility: {
nuxt: '^4.0.0'
}
},
moduleDependencies: {
'nuxt-csurf': {
defaults: {
addCsrfTokenToEventCtx: true
}
}
},
defaults: {
bulma: '',
useProxy: false,
loginGate: false,
requireLogin: false,
safelinkUtmSource: undefined,
proxyBase: undefined,
apiBase: undefined,
protomapsApikey: undefined,
nearmapsApikey: undefined,
auth0ClientId: undefined,
auth0Domain: undefined,
auth0Audience: undefined,
auth0Scope: undefined,
auth0RedirectUri: undefined,
auth0LogoutUri: undefined,
},
async setup (options, nuxt) {
// Create resolver to resolve relative paths
const resolver = createResolver(import.meta.url)
const resolveRuntimeModule = (path: string) => resolver.resolve('./runtime', path)
const useProxy = !!options.useProxy
// Private runtime options (server-side only)
// Nuxt 4 recommended pattern: merge at the nested key level
Object.assign(nuxt.options.runtimeConfig, defu(nuxt.options.runtimeConfig, {
tlv2: {
graphqlApikey: '',
proxyBase: {
default: options.proxyBase,
stationEditor: '',
feedManagement: ''
},
}
}))
// Public runtime options (available on both server and client)
// Nuxt 4 recommended pattern: merge at the nested key level
Object.assign(nuxt.options.runtimeConfig.public, defu(nuxt.options.runtimeConfig.public, {
tlv2: {
useProxy: useProxy,
safelinkUtmSource: options.safelinkUtmSource,
apiBase: {
default: options.apiBase,
stationEditor: '',
feedManagement: '',
},
protomapsApikey: options.protomapsApikey,
nearmapsApikey: options.nearmapsApikey,
mixpanelApikey: options.mixpanelApikey,
loginGate: options.loginGate,
requireLogin: options.requireLogin,
routes: options.routes,
auth0Domain: options.auth0Domain,
auth0ClientId: options.auth0ClientId,
auth0RedirectUri: options.auth0RedirectUri,
auth0LogoutUri: options.auth0LogoutUri,
auth0Audience: options.auth0Audience,
auth0Scope: options.auth0Scope,
}
}))
// Setup CSS
nuxt.options.css.push(resolveRuntimeModule('assets/main.css'))
nuxt.options.css.push('@mdi/font/css/materialdesignicons.css')
// Setup plugins (run in order added)
addPlugin(resolveRuntimeModule('plugins/apollo'))
addPlugin(resolveRuntimeModule('plugins/mixpanel.client'))
addPlugin(resolveRuntimeModule('plugins/auth.client'))
addImportsDir(resolveRuntimeModule('composables'))
// Proxy options
if (useProxy) {
addServerHandler({
route: '/api/v2/**',
handler: resolveRuntimeModule('plugins/proxy')
})
}
// Add assets
nuxt.hook('nitro:config', (nitroConfig) => {
nitroConfig.publicAssets ||= []
nitroConfig.publicAssets.push({
dir: resolveRuntimeModule('public'),
maxAge: 60 * 60 * 24 * 365 // 1 year
})
})
// Add components
addComponentsDir({
path: resolveRuntimeModule('components'),
pathPrefix: true,
prefix: 'tl'
})
// Add controls (t-* components)
addComponentsDir({
path: resolveRuntimeModule('controls'),
prefix: 't'
})
// Nuxt 4: Transpile packages for SSR compatibility
// These packages need transpilation because they:
// - Ship as ESM but need to work in SSR/Node context
// - Use modern JS features or TypeScript
// - Contain Vue components or framework-specific code
nuxt.options.build.transpile = nuxt.options.build.transpile || []
nuxt.options.build.transpile.push(
'@vue/apollo-composable', // Vue 3 Composition API wrapper - contains Vue reactivity code
'@apollo/client', // GraphQL client with modern JS/TS - needs transpilation for SSR
'markdown-it', // Markdown parser - ESM package used in SSR
'markdown-it-anchor', // Markdown-it plugin - must match parent's transpilation
)
// Add Vite plugin - Nuxt 4 pattern
addVitePlugin(() => ({
name: 'tlv2-ui:vite-config',
// Note: optimizeDeps.include was removed because it caused resolution errors
// under pnpm's strict node_modules layout. Vite 7 handles dependency discovery
// automatically. shamefully-hoist=true in .npmrc is needed for this repo's
// dev/playground setup only — consumers of the published module are not affected.
config (config) {
// Fix for local development with symlinks (pnpm link, --stub mode)
// https://github.com/nuxt/nuxt/issues/20001
// Without this, Vite fails to resolve module files when using symlinked dependencies
config.resolve = config.resolve || {}
config.resolve.preserveSymlinks = true
// Ensure Apollo packages resolve to a single instance in production builds.
// Without this, the Apollo plugin (from tlv2-ui) and consumer useQuery calls
// can reference different module instances, causing "client not found" errors.
config.resolve.dedupe = config.resolve.dedupe || []
if (Array.isArray(config.resolve.dedupe)) {
config.resolve.dedupe.push(
'@vue/apollo-composable',
'@apollo/client',
'graphql',
)
}
}
}))
}
})