@ternkit/tern 1.1.0 → 1.2.1
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/dist/goscript/index.svelte.d.ts +44 -0
- package/dist/goscript/index.svelte.js +204 -0
- package/dist/image/Image.svelte +32 -9
- package/dist/image/Image.svelte.d.ts +10 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/dist/runtime/api.d.ts +18 -0
- package/dist/runtime/api.js +55 -0
- package/dist/runtime/base.d.ts +2 -0
- package/dist/runtime/base.js +10 -0
- package/dist/runtime/realtime.svelte.d.ts +78 -0
- package/dist/runtime/realtime.svelte.js +163 -0
- package/dist/runtime/router.svelte.js +2 -0
- package/dist/server/email.d.ts +18 -0
- package/dist/server/email.js +34 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +3 -0
- package/dist/server/intl.js +1 -1
- package/dist/server/polyfills.d.ts +1 -2
- package/dist/server/polyfills.js +29 -2
- package/dist/server/url.d.ts +56 -0
- package/dist/server/url.js +594 -0
- package/dist/server/web.d.ts +74 -0
- package/dist/server/web.js +395 -0
- package/dist/vite/goscript.d.ts +12 -0
- package/dist/vite/goscript.js +226 -0
- package/dist/vite/index.d.ts +6 -0
- package/dist/vite/index.js +83 -4
- package/package.json +9 -5
package/dist/vite/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
3
4
|
import path from 'node:path';
|
|
5
|
+
import { goScriptPlugin, goScriptPreprocessor } from './goscript.js';
|
|
4
6
|
import { imagePlugin } from './image.js';
|
|
7
|
+
/** Packages whose browser build works in the server renderer and whose default build needs Node. */
|
|
8
|
+
const BROWSER_BUILDS = ['nanoid'];
|
|
5
9
|
/** Paths shared with the Go code generator; keep in sync with internal/codegen. */
|
|
6
10
|
const CLIENT_ENTRY = '.tern/generated/client.js';
|
|
7
11
|
const SERVER_ENTRY = '.tern/generated/server.js';
|
|
@@ -10,6 +14,8 @@ const SW_MODULE = '$service-worker';
|
|
|
10
14
|
const SERVER_OUT = '.tern/output/server';
|
|
11
15
|
/** The dev endpoint the Go app calls to server-render a page. */
|
|
12
16
|
const RENDER_PATH = '/__tern/render';
|
|
17
|
+
/** The dev endpoint the Go app calls to render an email. */
|
|
18
|
+
const EMAIL_PATH = '/__tern/email';
|
|
13
19
|
/**
|
|
14
20
|
* The Vite plugin for Tern apps. It includes the Svelte plugin, so it is
|
|
15
21
|
* the only plugin a Tern app needs:
|
|
@@ -27,6 +33,8 @@ const RENDER_PATH = '/__tern/render';
|
|
|
27
33
|
*/
|
|
28
34
|
export function tern(options = {}) {
|
|
29
35
|
let root = process.cwd();
|
|
36
|
+
let ssrBuild = false;
|
|
37
|
+
const browserBuilds = new Set([...BROWSER_BUILDS, ...(options.ssrBrowserBuilds ?? [])]);
|
|
30
38
|
const plugin = {
|
|
31
39
|
name: 'tern',
|
|
32
40
|
config(config, env) {
|
|
@@ -38,7 +46,8 @@ export function tern(options = {}) {
|
|
|
38
46
|
resolve: {
|
|
39
47
|
alias: {
|
|
40
48
|
$lib: path.join(root, 'src/lib'),
|
|
41
|
-
$routes: path.join(root, '.tern/generated/routes.js')
|
|
49
|
+
$routes: path.join(root, '.tern/generated/routes.js'),
|
|
50
|
+
$api: path.join(root, '.tern/generated/api.js')
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
};
|
|
@@ -63,6 +72,7 @@ export function tern(options = {}) {
|
|
|
63
72
|
};
|
|
64
73
|
}
|
|
65
74
|
if (env.isSsrBuild) {
|
|
75
|
+
ssrBuild = true;
|
|
66
76
|
return {
|
|
67
77
|
...shared,
|
|
68
78
|
publicDir: false,
|
|
@@ -78,8 +88,10 @@ export function tern(options = {}) {
|
|
|
78
88
|
}
|
|
79
89
|
},
|
|
80
90
|
// One self-contained file: the renderer runs in an embedded engine
|
|
81
|
-
// without a module loader or Node built-ins.
|
|
82
|
-
|
|
91
|
+
// without a module loader or Node built-ins. Without the "node"
|
|
92
|
+
// condition, libraries resolve to their portable builds instead of
|
|
93
|
+
// ones that use Buffer or node:crypto.
|
|
94
|
+
ssr: { noExternal: true, resolve: { conditions: ['module', 'development|production'] } },
|
|
83
95
|
// Libraries often read process.env.NODE_ENV; the engine has no
|
|
84
96
|
// process object, so replace it at build time.
|
|
85
97
|
define: { 'process.env.NODE_ENV': JSON.stringify('production') }
|
|
@@ -122,6 +134,17 @@ export function tern(options = {}) {
|
|
|
122
134
|
return serviceWorkerModule(root, readBasePath(root));
|
|
123
135
|
},
|
|
124
136
|
configureServer(server) {
|
|
137
|
+
server.middlewares.use(EMAIL_PATH, (req, res) => {
|
|
138
|
+
void emailInDev(server, req).then((body) => {
|
|
139
|
+
res.setHeader('Content-Type', 'application/json');
|
|
140
|
+
res.end(body);
|
|
141
|
+
}, (err) => {
|
|
142
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
143
|
+
server.ssrFixStacktrace(e);
|
|
144
|
+
res.statusCode = 500;
|
|
145
|
+
res.end(e.stack ?? e.message);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
125
148
|
server.middlewares.use(RENDER_PATH, (req, res) => {
|
|
126
149
|
void renderInDev(server, req).then((body) => {
|
|
127
150
|
res.setHeader('Content-Type', 'application/json');
|
|
@@ -146,7 +169,45 @@ export function tern(options = {}) {
|
|
|
146
169
|
const mod = (await server.ssrLoadModule(path.join(root, SERVER_ENTRY)));
|
|
147
170
|
return mod.render(payload, href);
|
|
148
171
|
}
|
|
149
|
-
|
|
172
|
+
async function emailInDev(server, req) {
|
|
173
|
+
if (req.method !== 'POST')
|
|
174
|
+
throw new Error('POST required');
|
|
175
|
+
const chunks = [];
|
|
176
|
+
for await (const chunk of req)
|
|
177
|
+
chunks.push(chunk);
|
|
178
|
+
const { name, props } = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
179
|
+
const mod = (await server.ssrLoadModule(path.join(root, SERVER_ENTRY)));
|
|
180
|
+
if (!mod.renderEmail)
|
|
181
|
+
return JSON.stringify(name === '' ? {} : { subject: '', html: '', error: 'the app has no src/emails' });
|
|
182
|
+
return mod.renderEmail(name, props);
|
|
183
|
+
}
|
|
184
|
+
// Runs before Vite's own resolver, which would pick the default build.
|
|
185
|
+
const browserBuildsPlugin = {
|
|
186
|
+
name: 'tern:ssr-browser-builds',
|
|
187
|
+
enforce: 'pre',
|
|
188
|
+
resolveId(id, importer) {
|
|
189
|
+
if (!ssrBuild || !browserBuilds.has(id))
|
|
190
|
+
return undefined;
|
|
191
|
+
return browserBuild(id, importer ?? path.join(root, 'package.json'));
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
// Email templates carry their styles in the HTML, since mail clients
|
|
195
|
+
// can't load the app's stylesheets.
|
|
196
|
+
const userDynamic = options.svelte?.dynamicCompileOptions;
|
|
197
|
+
const userPreprocess = options.svelte?.preprocess;
|
|
198
|
+
const svelteOptions = {
|
|
199
|
+
...options.svelte,
|
|
200
|
+
// <script lang="go"> runs before the user's preprocessors.
|
|
201
|
+
preprocess: [goScriptPreprocessor(() => root), ...(Array.isArray(userPreprocess) ? userPreprocess : userPreprocess ? [userPreprocess] : [])],
|
|
202
|
+
dynamicCompileOptions: async (args) => {
|
|
203
|
+
const user = (await userDynamic?.(args)) ?? undefined;
|
|
204
|
+
if (args.filename.includes(`${path.sep}src${path.sep}emails${path.sep}`) || args.filename.includes('/src/emails/')) {
|
|
205
|
+
return { ...user, css: 'injected' };
|
|
206
|
+
}
|
|
207
|
+
return user;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
return [browserBuildsPlugin, imagePlugin(), goScriptPlugin(() => root), ...svelte(svelteOptions), plugin];
|
|
150
211
|
}
|
|
151
212
|
/** The $service-worker module: what this build produced, for caching. */
|
|
152
213
|
function serviceWorkerModule(root, base) {
|
|
@@ -180,6 +241,24 @@ function serviceWorkerModule(root, base) {
|
|
|
180
241
|
`export const version = ${JSON.stringify(version)};`
|
|
181
242
|
].join('\n');
|
|
182
243
|
}
|
|
244
|
+
/** The file a package's "browser" export points to, or undefined to resolve normally. */
|
|
245
|
+
function browserBuild(pkg, importer) {
|
|
246
|
+
try {
|
|
247
|
+
const require = createRequire(importer);
|
|
248
|
+
const manifestPath = require.resolve(`${pkg}/package.json`);
|
|
249
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
250
|
+
const dot = manifest.exports?.['.'];
|
|
251
|
+
let target = typeof dot === 'object' && dot !== null ? dot.browser : undefined;
|
|
252
|
+
if (typeof target === 'object' && target !== null)
|
|
253
|
+
target = target.default ?? target.import;
|
|
254
|
+
if (typeof target !== 'string' && typeof manifest.browser === 'string')
|
|
255
|
+
target = manifest.browser;
|
|
256
|
+
return typeof target === 'string' ? path.join(path.dirname(manifestPath), target) : undefined;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
183
262
|
/** Lists files below dir, relative to it, with forward slashes. */
|
|
184
263
|
function walk(dir, prefix = '') {
|
|
185
264
|
let entries;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ternkit/tern",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Client runtime and Vite plugin for Tern: Svelte on the client, Go on the server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"svelte": "./dist/runtime/client.js",
|
|
30
30
|
"default": "./dist/runtime/client.js"
|
|
31
31
|
},
|
|
32
|
+
"./goscript": {
|
|
33
|
+
"types": "./dist/goscript/index.svelte.d.ts",
|
|
34
|
+
"svelte": "./dist/goscript/index.svelte.js",
|
|
35
|
+
"default": "./dist/goscript/index.svelte.js"
|
|
36
|
+
},
|
|
32
37
|
"./server": {
|
|
33
38
|
"types": "./dist/server/index.d.ts",
|
|
34
39
|
"svelte": "./dist/server/index.js",
|
|
@@ -55,13 +60,12 @@
|
|
|
55
60
|
"test": "vitest run"
|
|
56
61
|
},
|
|
57
62
|
"peerDependencies": {
|
|
63
|
+
"sharp": ">=0.33.0",
|
|
58
64
|
"svelte": "^5.46.4",
|
|
59
|
-
"vite": "^8.0.0"
|
|
60
|
-
"sharp": ">=0.33.0"
|
|
65
|
+
"vite": "^8.0.0"
|
|
61
66
|
},
|
|
62
67
|
"dependencies": {
|
|
63
|
-
"@sveltejs/vite-plugin-svelte": "^7.3.1"
|
|
64
|
-
"core-js": "^3.51.0"
|
|
68
|
+
"@sveltejs/vite-plugin-svelte": "^7.3.1"
|
|
65
69
|
},
|
|
66
70
|
"devDependencies": {
|
|
67
71
|
"@sveltejs/package": "^3.0.2",
|