ajo-kit 0.1.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/LICENSE +15 -0
- package/README.md +468 -0
- package/dist/bin/kit.js +109 -0
- package/dist/chunks/constants-5Eu0naK3.js +168 -0
- package/dist/chunks/discover-D-b8Pqm8.js +34 -0
- package/dist/chunks/headers-BDszzwLw.js +23 -0
- package/dist/chunks/migrate-C9Iytqx4.js +89 -0
- package/dist/chunks/ssr-CCxCGcm6.js +421 -0
- package/dist/client.js +134 -0
- package/dist/database.js +38 -0
- package/dist/index.js +2 -0
- package/dist/mail.js +15 -0
- package/dist/node.js +104 -0
- package/dist/server.js +502 -0
- package/dist/validate.js +15 -0
- package/dist/vite.js +110 -0
- package/package.json +106 -0
- package/src/app.tsx +484 -0
- package/src/cache.ts +85 -0
- package/src/client.tsx +167 -0
- package/src/constants.ts +339 -0
- package/src/database.ts +55 -0
- package/src/discover.ts +42 -0
- package/src/form.ts +39 -0
- package/src/freshness.ts +63 -0
- package/src/head.tsx +125 -0
- package/src/headers.ts +32 -0
- package/src/index.ts +31 -0
- package/src/mail/index.ts +25 -0
- package/src/migrate.ts +132 -0
- package/src/node.ts +134 -0
- package/src/server.tsx +584 -0
- package/src/ssr.ts +8 -0
- package/src/timing.ts +60 -0
- package/src/validate.ts +33 -0
- package/src/virtual.d.ts +10 -0
- package/src/vite.ts +166 -0
package/src/vite.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import type { Plugin } from 'vite'
|
|
2
|
+
import { discover } from './discover'
|
|
3
|
+
|
|
4
|
+
type Pattern = RegExp | string | ((id: string) => boolean)
|
|
5
|
+
|
|
6
|
+
const match = (id: string, pattern: Pattern) =>
|
|
7
|
+
typeof pattern === 'function' ? pattern(id) :
|
|
8
|
+
typeof pattern === 'string' ? id.includes(pattern) :
|
|
9
|
+
pattern.test(id)
|
|
10
|
+
|
|
11
|
+
const any = (id: string, patterns: Pattern[]) =>
|
|
12
|
+
patterns.some(p => match(id, p))
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Prevents server-only modules from being imported into client code.
|
|
16
|
+
* Tracks the import chain to catch transitive imports through barrel files.
|
|
17
|
+
*/
|
|
18
|
+
const guard = (patterns: Pattern[]): Plugin => {
|
|
19
|
+
|
|
20
|
+
const chain = new Map<string, string>()
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
name: 'ajo-server-only',
|
|
24
|
+
enforce: 'pre',
|
|
25
|
+
resolveId: {
|
|
26
|
+
order: 'pre',
|
|
27
|
+
async handler(source, importer) {
|
|
28
|
+
|
|
29
|
+
if (this.environment.name !== 'client') return
|
|
30
|
+
|
|
31
|
+
if (!importer) return
|
|
32
|
+
|
|
33
|
+
const resolved = await this.resolve(source, importer, { skipSelf: true })
|
|
34
|
+
|
|
35
|
+
if (!resolved) return
|
|
36
|
+
|
|
37
|
+
const id = resolved.id
|
|
38
|
+
|
|
39
|
+
// Track who imported this module
|
|
40
|
+
chain.set(id, importer)
|
|
41
|
+
|
|
42
|
+
// *.client.* modules are explicitly client-safe; their own imports are still checked
|
|
43
|
+
if (/\.client\.[jt]sx?$/.test(id)) return
|
|
44
|
+
|
|
45
|
+
// Check if this module is server-only
|
|
46
|
+
if (any(id, patterns)) {
|
|
47
|
+
|
|
48
|
+
// Build the import chain for error message
|
|
49
|
+
const trace = [id]
|
|
50
|
+
let current = importer
|
|
51
|
+
|
|
52
|
+
while (current && trace.length < 10) {
|
|
53
|
+
trace.unshift(current)
|
|
54
|
+
current = chain.get(current)!
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const path = trace.map(p => p.replace(/^.*\/src\//, 'src/')).join('\n → ')
|
|
58
|
+
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Server-only module imported into client code:\n\n ${path}\n\n` +
|
|
61
|
+
`Module "${id.replace(/^.*\/src\//, 'src/')}" cannot be imported by client code.`
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const hmr = (pattern: RegExp): Plugin => ({
|
|
70
|
+
name: 'ajo-hmr',
|
|
71
|
+
apply: 'serve',
|
|
72
|
+
transform(code, id) {
|
|
73
|
+
|
|
74
|
+
if (!pattern.test(id)) return null
|
|
75
|
+
|
|
76
|
+
const HMR = `Symbol.for('ajo.hmr')`
|
|
77
|
+
const path = '/' + id.replace(/^.*?(src\/)/, '$1')
|
|
78
|
+
|
|
79
|
+
const tagged = code.match(/export\s+default\s+(\w+)\s*[\n;]/)
|
|
80
|
+
? code.replace(/export\s+default\s+(\w+)/, `export default $1;$1[${HMR}]=${JSON.stringify(path)}`)
|
|
81
|
+
: code
|
|
82
|
+
|
|
83
|
+
const accept = `
|
|
84
|
+
if(import.meta.hot)import.meta.hot.accept(m=>{
|
|
85
|
+
if(m?.default)m.default[${HMR}]=${JSON.stringify(path)};
|
|
86
|
+
if(m)(globalThis.__MODULES__??=new Map).set(${JSON.stringify(path)},m),globalThis.__HMR__?.(${JSON.stringify(path)});
|
|
87
|
+
})`
|
|
88
|
+
|
|
89
|
+
return { code: tagged + accept, map: null }
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
/** Options for the ajo-kit Vite plugin. */
|
|
94
|
+
export interface Options {
|
|
95
|
+
guard?: Pattern[]
|
|
96
|
+
css?: string[]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Default file locations used by the kit CLI. */
|
|
100
|
+
export const defaults = {
|
|
101
|
+
database: './database.sqlite',
|
|
102
|
+
migrations: 'db/migrations',
|
|
103
|
+
seeds: 'db/seeds',
|
|
104
|
+
} as const
|
|
105
|
+
|
|
106
|
+
const guards = (found: ReturnType<typeof discover>): Pattern[] => [
|
|
107
|
+
/(handler|wares)\.[jt]sx?$/,
|
|
108
|
+
...found.filter(p => p.serverOnly).map(p => new RegExp(`${p.name}/`)),
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
/** Returns the Vite plugins required by an ajo-kit app. */
|
|
112
|
+
export function kit(options?: Options): Plugin[] {
|
|
113
|
+
|
|
114
|
+
const css = options?.css ?? []
|
|
115
|
+
const found = discover()
|
|
116
|
+
|
|
117
|
+
return [
|
|
118
|
+
{
|
|
119
|
+
name: 'ajo-kit',
|
|
120
|
+
resolveId(id) {
|
|
121
|
+
if (id === 'virtual:ajo/routes') return '\0virtual:ajo/routes'
|
|
122
|
+
if (id === 'virtual:ajo/handlers') return '\0virtual:ajo/handlers'
|
|
123
|
+
},
|
|
124
|
+
load(id) {
|
|
125
|
+
if (id === '\0virtual:ajo/routes') {
|
|
126
|
+
return "export const routes = import.meta.glob('/src/**/{layout,page}.{j,t}s{,x}')"
|
|
127
|
+
}
|
|
128
|
+
if (id === '\0virtual:ajo/handlers') {
|
|
129
|
+
return [
|
|
130
|
+
"export const handlers = import.meta.glob('/src/**/handler.{j,t}s{,x}')",
|
|
131
|
+
"export const wares = import.meta.glob('/src/**/wares.{j,t}s{,x}')",
|
|
132
|
+
].join('\n')
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
transform(code, id) {
|
|
136
|
+
if (css.length && id.includes('ajo-kit') && id.endsWith('client.tsx')) {
|
|
137
|
+
return css.map(c => `import '${c}'`).join('\n') + '\n' + code
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
config() {
|
|
141
|
+
const aliases = found
|
|
142
|
+
.filter(p => p.alias)
|
|
143
|
+
.map(p => ({ find: new RegExp(`^@kit/${p.alias}(/|$)`), replacement: `${p.name}$1` }))
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
ssr: { noExternal: [/^ajo-/] },
|
|
147
|
+
resolve: {
|
|
148
|
+
alias: [
|
|
149
|
+
...aliases,
|
|
150
|
+
{ find: /^@kit(\/|$)/, replacement: 'ajo-kit$1' },
|
|
151
|
+
{ find: '/src/client', replacement: 'ajo-kit/client' },
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
guard([...guards(found), ...(options?.guard ?? [])]),
|
|
158
|
+
hmr(/(page|layout)\.[jt]sx?$/),
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Vite esbuild JSX settings for Ajo components. */
|
|
163
|
+
export const jsx = {
|
|
164
|
+
jsx: 'automatic',
|
|
165
|
+
jsxImportSource: 'ajo',
|
|
166
|
+
} as const
|