@wervt/nuxt 0.3.3 → 0.3.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.
- package/dist/dev.d.ts +1 -3
- package/dist/dev.js +33 -11
- package/dist/env-types.js +1 -2
- package/dist/icons.js +1 -2
- package/dist/loading.js +30 -0
- package/dist/module.d.ts +0 -2
- package/dist/module.js +3 -2
- package/dist/node_modules/.pnpm/nitro@3.0.260903-beta/node_modules/nitro/dist/runtime/internal/task.js +1 -2
- package/dist/og-image.js +1 -2
- package/dist/preview.d.ts +1 -3
- package/dist/preview.js +1 -2
- package/dist/provision.d.ts +12 -2
- package/dist/provision.js +35 -21
- package/dist/route-tools.js +1 -2
- package/dist/runtime/app/plugins/analytics.client.d.ts +0 -2
- package/dist/runtime/app/plugins/analytics.client.js +1 -2
- package/dist/runtime/app/plugins/feedback.client.d.ts +0 -2
- package/dist/runtime/app/plugins/feedback.client.js +1 -2
- package/dist/runtime/app/plugins/update.client.d.ts +0 -2
- package/dist/runtime/app/plugins/update.client.js +1 -2
- package/dist/runtime/app/plugins/user.client.d.ts +0 -2
- package/dist/runtime/app/plugins/user.client.js +1 -2
- package/dist/runtime/app/plugins/webmcp.client.d.ts +0 -2
- package/dist/runtime/app/plugins/webmcp.client.js +1 -2
- package/dist/runtime/app/preview-error.d.ts +26 -0
- package/dist/runtime/app/preview-error.js +69 -0
- package/dist/runtime/app/snapshot.d.ts +1 -3
- package/dist/runtime/app/snapshot.js +1 -2
- package/dist/runtime/app/useShape.d.ts +1 -3
- package/dist/runtime/app/useShape.js +3 -4
- package/dist/runtime/app/useWervtFeedback.d.ts +0 -2
- package/dist/runtime/app/useWervtFeedback.js +1 -2
- package/dist/runtime/app/useWervtTrack.d.ts +1 -3
- package/dist/runtime/app/useWervtTrack.js +1 -2
- package/dist/runtime/app/useWervtUpdate.d.ts +1 -3
- package/dist/runtime/app/useWervtUpdate.js +2 -3
- package/dist/runtime/app/useWervtUser.d.ts +1 -3
- package/dist/runtime/app/useWervtUser.js +1 -2
- package/dist/runtime/email/components.d.ts +1 -3
- package/dist/runtime/email/components.js +1 -2
- package/dist/runtime/email/invite.d.ts +1 -3
- package/dist/runtime/email/invite.js +1 -2
- package/dist/runtime/email/render.d.ts +1 -3
- package/dist/runtime/email/render.js +1 -2
- package/dist/runtime/server/access.d.ts +1 -3
- package/dist/runtime/server/access.js +1 -2
- package/dist/runtime/server/agent-token-plugin.d.ts +0 -2
- package/dist/runtime/server/agent-token-plugin.js +1 -2
- package/dist/runtime/server/anthropic.d.ts +1 -3
- package/dist/runtime/server/anthropic.js +1 -2
- package/dist/runtime/server/boot.d.ts +0 -2
- package/dist/runtime/server/boot.js +1 -2
- package/dist/runtime/server/db.d.ts +1 -3
- package/dist/runtime/server/db.js +1 -2
- package/dist/runtime/server/dev-auth.d.ts +0 -2
- package/dist/runtime/server/dev-auth.js +1 -2
- package/dist/runtime/server/email-preview.d.ts +0 -2
- package/dist/runtime/server/email-preview.js +1 -2
- package/dist/runtime/server/identity.d.ts +1 -3
- package/dist/runtime/server/identity.js +1 -2
- package/dist/runtime/server/logger.d.ts +0 -2
- package/dist/runtime/server/logger.js +1 -2
- package/dist/runtime/server/mail.d.ts +1 -3
- package/dist/runtime/server/mail.js +1 -2
- package/dist/runtime/server/mcp-auth-server.d.ts +0 -2
- package/dist/runtime/server/mcp-auth-server.js +1 -2
- package/dist/runtime/server/mcp-auth.d.ts +1 -3
- package/dist/runtime/server/mcp-auth.js +1 -2
- package/dist/runtime/server/mcp-claims.d.ts +1 -3
- package/dist/runtime/server/mcp-claims.js +1 -2
- package/dist/runtime/server/mcp-metadata.d.ts +0 -2
- package/dist/runtime/server/mcp-metadata.js +1 -2
- package/dist/runtime/server/mcp.d.ts +0 -2
- package/dist/runtime/server/mcp.js +1 -2
- package/dist/runtime/server/preview-errors-plugin.d.ts +13 -0
- package/dist/runtime/server/preview-errors-plugin.js +19 -0
- package/dist/runtime/server/seed.d.ts +1 -3
- package/dist/runtime/server/seed.js +1 -2
- package/dist/runtime/server/shape.d.ts +1 -3
- package/dist/runtime/server/shape.js +1 -2
- package/dist/runtime/server/storage-plugin.d.ts +1 -3
- package/dist/runtime/server/storage-plugin.js +1 -2
- package/dist/runtime/server/task-handlers.d.ts +1 -3
- package/dist/runtime/server/task-handlers.js +1 -2
- package/dist/runtime/server/task-list-nitro2.d.ts +0 -2
- package/dist/runtime/server/task-list-nitro2.js +1 -2
- package/dist/runtime/server/task-list-nitro3.d.ts +0 -2
- package/dist/runtime/server/task-list-nitro3.js +1 -2
- package/dist/runtime/server/task-run-nitro2.d.ts +0 -2
- package/dist/runtime/server/task-run-nitro2.js +1 -2
- package/dist/runtime/server/task-run-nitro3.d.ts +0 -2
- package/dist/runtime/server/task-run-nitro3.js +1 -2
- package/dist/runtime/server/tasks.d.ts +1 -3
- package/dist/runtime/server/tasks.js +1 -2
- package/dist/runtime/server/tool-handlers.d.ts +1 -3
- package/dist/runtime/server/tool-handlers.js +1 -2
- package/dist/runtime/server/tool-list.js +1 -2
- package/dist/runtime/server/tool-run.js +1 -2
- package/dist/runtime/server/tools.d.ts +0 -2
- package/dist/runtime/server/tools.js +1 -2
- package/dist/runtime/server/user-route.d.ts +0 -2
- package/dist/runtime/server/user-route.js +1 -2
- package/dist/runtime/server/user.d.ts +0 -2
- package/dist/runtime/server/user.js +1 -2
- package/dist/runtime/server/validate.d.ts +0 -2
- package/dist/runtime/server/validate.js +1 -2
- package/dist/runtime/shared/agent-token.d.ts +1 -3
- package/dist/runtime/shared/agent-token.js +1 -2
- package/dist/runtime/shared/mark.d.ts +1 -0
- package/dist/runtime/shared/mark.js +3 -0
- package/dist/runtime/shared/preview-errors.d.ts +10 -0
- package/dist/runtime/shared/preview-errors.js +14 -0
- package/dist/runtime/shared/shape.d.ts +0 -2
- package/dist/runtime/shared/shape.js +1 -2
- package/dist/runtime/shared/user.d.ts +1 -3
- package/dist/runtime/shared/user.js +1 -2
- package/dist/seed.js +1 -2
- package/dist/shapes.js +1 -2
- package/dist/storage.d.ts +2 -3
- package/dist/storage.js +7 -2
- package/dist/studio-preview.js +38 -0
- package/package.json +6 -6
package/dist/dev.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { WervtRole } from "./runtime/shared/user.js";
|
|
2
2
|
import "nuxt/schema";
|
|
3
|
-
//#region src/dev.d.ts
|
|
4
3
|
export interface DevOptions {
|
|
5
4
|
/** Superuser URL of the local wervt Postgres. */
|
|
6
5
|
adminUrl?: string;
|
|
@@ -29,5 +28,4 @@ export interface DevOptions {
|
|
|
29
28
|
accounts?: Record<string, string>;
|
|
30
29
|
role?: WervtRole;
|
|
31
30
|
};
|
|
32
|
-
}
|
|
33
|
-
//#endregion
|
|
31
|
+
}
|
package/dist/dev.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createStorage } from "./storage.js";
|
|
2
|
-
import { appDatabaseUrl, dbRole, provisionDatabase, storageCredentials } from "./provision.js";
|
|
2
|
+
import { appDatabaseUrl, dbRole, migrateAs, provisionDatabase, storageCredentials } from "./provision.js";
|
|
3
3
|
import { SEED_TASK, runDevSeed } from "./seed.js";
|
|
4
4
|
import { useLogger } from "nuxt/kit";
|
|
5
5
|
import { existsSync, watch } from "node:fs";
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
-
|
|
8
|
+
// src/dev.ts
|
|
9
9
|
const DEFAULTS = {
|
|
10
10
|
adminUrl: "postgres://postgres:postgres@localhost:5432/wervt",
|
|
11
11
|
dbSecret: "dev-secret",
|
|
@@ -22,6 +22,7 @@ const logger = useLogger("wervt");
|
|
|
22
22
|
* points the dev server at the app's database and Electric.
|
|
23
23
|
*/
|
|
24
24
|
async function setupDev(nuxt, app, options, features = {}) {
|
|
25
|
+
forgetOwnEnv(nuxt.options.rootDir);
|
|
25
26
|
const config = {
|
|
26
27
|
adminUrl: process.env.WERVT_PG_ADMIN_URL ?? options.adminUrl ?? DEFAULTS.adminUrl,
|
|
27
28
|
dbSecret: process.env.WERVT_DB_SECRET ?? options.dbSecret ?? DEFAULTS.dbSecret,
|
|
@@ -43,13 +44,18 @@ async function setupDev(nuxt, app, options, features = {}) {
|
|
|
43
44
|
secret: config.dbSecret,
|
|
44
45
|
migrationsFolder
|
|
45
46
|
};
|
|
47
|
+
const given = process.env.DATABASE_URL && process.env.WERVT_DB_SCHEMA ? {
|
|
48
|
+
url: process.env.DATABASE_URL,
|
|
49
|
+
schema: process.env.WERVT_DB_SCHEMA
|
|
50
|
+
} : void 0;
|
|
51
|
+
const database = given?.schema ?? dbRole(app);
|
|
46
52
|
let serverUrl;
|
|
47
53
|
let seedPending = false;
|
|
48
54
|
const seed = async () => {
|
|
49
55
|
if (!seedPending || !serverUrl) return;
|
|
50
56
|
seedPending = false;
|
|
51
57
|
try {
|
|
52
|
-
if ((await runDevSeed(serverUrl)).status === "seeded") logger.success(`Seeded \`${
|
|
58
|
+
if ((await runDevSeed(serverUrl)).status === "seeded") logger.success(`Seeded \`${database}\` (${SEED_TASK})`);
|
|
53
59
|
} catch (e) {
|
|
54
60
|
logger.warn(`\`${SEED_TASK}\` failed:`, e instanceof Error ? e.message : e);
|
|
55
61
|
}
|
|
@@ -60,21 +66,29 @@ async function setupDev(nuxt, app, options, features = {}) {
|
|
|
60
66
|
});
|
|
61
67
|
const migrate = async () => {
|
|
62
68
|
try {
|
|
63
|
-
const { fresh } = await
|
|
64
|
-
|
|
69
|
+
const { fresh } = given ? await migrateAs({
|
|
70
|
+
...given,
|
|
71
|
+
migrationsFolder
|
|
72
|
+
}) : await provisionDatabase(provision);
|
|
73
|
+
logger.success(`Database \`${database}\` is up to date`);
|
|
65
74
|
if (fresh && options.seed !== false) {
|
|
66
75
|
seedPending = true;
|
|
67
76
|
seed();
|
|
68
77
|
}
|
|
69
78
|
} catch (e) {
|
|
70
|
-
logger.warn(`Could not migrate \`${
|
|
79
|
+
logger.warn(given ? `Could not migrate \`${database}\`.` : `Could not migrate \`${database}\`. Is the wervt stack running (docker compose up -d)?`, e instanceof Error ? e.message : e);
|
|
71
80
|
}
|
|
72
81
|
};
|
|
73
82
|
await migrate();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
const own = {
|
|
84
|
+
DATABASE_URL: await appDatabaseUrl(provision),
|
|
85
|
+
WERVT_DB_SCHEMA: dbRole(app),
|
|
86
|
+
ELECTRIC_URL: config.electricUrl,
|
|
87
|
+
ELECTRIC_SECRET: config.electricSecret
|
|
88
|
+
};
|
|
89
|
+
const set = Object.fromEntries(Object.entries(own).filter(([key]) => process.env[key] === void 0));
|
|
90
|
+
Object.assign(process.env, set);
|
|
91
|
+
process.env[OWN_ENV] = JSON.stringify(set);
|
|
78
92
|
let timer;
|
|
79
93
|
const watcher = watch(migrationsFolder, { recursive: true }, (_event, file) => {
|
|
80
94
|
if (!file?.endsWith(".sql")) return;
|
|
@@ -86,6 +100,15 @@ async function setupDev(nuxt, app, options, features = {}) {
|
|
|
86
100
|
});
|
|
87
101
|
nuxt.hook("close", () => watcher.close());
|
|
88
102
|
}
|
|
103
|
+
const OWN_ENV = "WERVT_DEV_OWN_ENV";
|
|
104
|
+
function forgetOwnEnv(rootDir) {
|
|
105
|
+
const own = process.env[OWN_ENV];
|
|
106
|
+
if (!own) return;
|
|
107
|
+
for (const [key, value] of Object.entries(JSON.parse(own))) if (process.env[key] === value) delete process.env[key];
|
|
108
|
+
delete process.env[OWN_ENV];
|
|
109
|
+
const file = join(rootDir, ".env");
|
|
110
|
+
if (existsSync(file)) process.loadEnvFile(file);
|
|
111
|
+
}
|
|
89
112
|
/** The app's bucket in the local Garage, and WERVT_S3_* for ablage, like in production. */
|
|
90
113
|
async function setupStorage(app, secret, options) {
|
|
91
114
|
const s3Url = process.env.WERVT_S3_URL ?? options.s3Url ?? DEFAULTS.s3Url;
|
|
@@ -118,5 +141,4 @@ async function resolveAppName(rootDir, name) {
|
|
|
118
141
|
}
|
|
119
142
|
return name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
120
143
|
}
|
|
121
|
-
//#endregion
|
|
122
144
|
export { resolveAppName, setupDev };
|
package/dist/env-types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/env-types.ts
|
|
2
2
|
/** `.nuxt/types/wervt-env.d.ts`: types for the `process.env` the isolate provides. */
|
|
3
3
|
const PROCESS_ENV_TYPES = `declare namespace NodeJS {
|
|
4
4
|
interface ProcessEnv {
|
|
@@ -10,5 +10,4 @@ const PROCESS_ENV_TYPES = `declare namespace NodeJS {
|
|
|
10
10
|
}
|
|
11
11
|
declare var process: NodeJS.Process
|
|
12
12
|
`;
|
|
13
|
-
//#endregion
|
|
14
13
|
export { PROCESS_ENV_TYPES };
|
package/dist/icons.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dependencyNames } from "./og-image.js";
|
|
2
|
-
|
|
2
|
+
// src/icons.ts
|
|
3
3
|
const ICONIFY_JSON = "@iconify-json/";
|
|
4
4
|
/** The whole Iconify set in one package; @nuxt/icon finds every collection in it. */
|
|
5
5
|
const ICONIFY_ALL = "@iconify/json";
|
|
@@ -27,5 +27,4 @@ function iconWarning(sources, nuxtUi) {
|
|
|
27
27
|
if (nuxtUi && !sources.collections.includes("lucide")) return "Nuxt UI uses Lucide icons, but `@iconify-json/lucide` is not installed, so they won't render on wervt (the isolate can't reach the Iconify API). Run `pnpm add -D @iconify-json/lucide`, plus `@iconify-json/<name>` for every other icon collection the app uses.";
|
|
28
28
|
if (sources.collections.length === 0) return "No icon collection is installed, so icons won't render on wervt (the isolate can't reach the Iconify API). Install the collections the app uses, e.g. `pnpm add -D @iconify-json/lucide`.";
|
|
29
29
|
}
|
|
30
|
-
//#endregion
|
|
31
30
|
export { iconDefaults, iconSources, iconWarning };
|
package/dist/loading.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { WERVT_MARK } from "./runtime/shared/mark.js";
|
|
2
|
+
// src/loading.ts
|
|
3
|
+
const previewLoadingTemplate = () => `<!doctype html>
|
|
4
|
+
<html lang="de">
|
|
5
|
+
<head>
|
|
6
|
+
<meta charset="utf-8">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
8
|
+
<title>Einen Moment …</title>
|
|
9
|
+
<style>
|
|
10
|
+
:root { color-scheme: light dark; --fg: #0a0a0b; --muted: #6b6b70; --bg: #fafaf9; --a: #2f5bff; }
|
|
11
|
+
@media (prefers-color-scheme: dark) { :root { --fg: #fafaf9; --muted: #a1a1a6; --bg: #0a0a0b; --a: #5885ff; } }
|
|
12
|
+
html, body { height: 100%; margin: 0; }
|
|
13
|
+
body { display: grid; place-content: center; justify-items: center; gap: 1rem; background: var(--bg);
|
|
14
|
+
color: var(--fg); font: 500 1rem/1.4 system-ui, -apple-system, sans-serif; text-align: center; }
|
|
15
|
+
svg { width: 3rem; height: 3rem; color: var(--fg); animation: pulse 1.6s ease-in-out infinite; }
|
|
16
|
+
p { margin: 0; color: var(--muted); }
|
|
17
|
+
@keyframes pulse { 50% { opacity: .45; transform: scale(.94); } }
|
|
18
|
+
@media (prefers-reduced-motion: reduce) { svg { animation: none; } }
|
|
19
|
+
</style>
|
|
20
|
+
</head>
|
|
21
|
+
<body>
|
|
22
|
+
${WERVT_MARK}
|
|
23
|
+
<p id="m">Einen Moment, die App wird gerade aktualisiert …</p>
|
|
24
|
+
<script>
|
|
25
|
+
if (!navigator.language.toLowerCase().startsWith('de'))
|
|
26
|
+
document.getElementById('m').textContent = 'One moment, the app is being updated …'
|
|
27
|
+
<\/script>
|
|
28
|
+
</body>
|
|
29
|
+
</html>`;
|
|
30
|
+
export { previewLoadingTemplate };
|
package/dist/module.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DevOptions } from "./dev.js";
|
|
2
2
|
import { PreviewOptions } from "./preview.js";
|
|
3
|
-
//#region src/module.d.ts
|
|
4
3
|
export interface ModuleOptions {
|
|
5
4
|
/** App name on wervt. Defaults to the package.json name. */
|
|
6
5
|
app?: string;
|
|
@@ -82,5 +81,4 @@ export interface TasksManifest {
|
|
|
82
81
|
timezone?: string;
|
|
83
82
|
}
|
|
84
83
|
declare const _default: import("nuxt/schema").NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
85
|
-
//#endregion
|
|
86
84
|
export { _default as default };
|
package/dist/module.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SEED_TASK, unscheduleSeed } from "./seed.js";
|
|
2
2
|
import { resolveAppName, setupDev } from "./dev.js";
|
|
3
|
+
import { setupStudioPreview } from "./studio-preview.js";
|
|
3
4
|
import { PROCESS_ENV_TYPES } from "./env-types.js";
|
|
4
5
|
import { dependencyNames, ogImageDefaults, ogImageWarning } from "./og-image.js";
|
|
5
6
|
import { iconDefaults, iconSources, iconWarning } from "./icons.js";
|
|
@@ -12,7 +13,7 @@ import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
|
12
13
|
import { builtinModules, createRequire } from "node:module";
|
|
13
14
|
import { dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
14
15
|
import evlog from "evlog/nuxt";
|
|
15
|
-
|
|
16
|
+
// src/module.ts
|
|
16
17
|
const CONTENT_DATABASE = {
|
|
17
18
|
type: "postgres",
|
|
18
19
|
url: "{{DATABASE_URL}}"
|
|
@@ -275,6 +276,7 @@ var module_default = defineNuxtModule({
|
|
|
275
276
|
if (nuxt.options.dev && nitroMajor >= 3) {
|
|
276
277
|
if (!hasPackage(nuxt.options.rootDir, "vue")) logger.warn("`vue` is not a dependency of this app, so `nuxt dev` fails with \"module is not defined\". Run `pnpm add vue`.");
|
|
277
278
|
}
|
|
279
|
+
if (nuxt.options.dev && process.env.WERVT_PREVIEW) setupStudioPreview(nuxt);
|
|
278
280
|
if (nuxt.options.dev && !nuxt.options._prepare) {
|
|
279
281
|
const app = await resolveAppName(nuxt.options.rootDir, options.app);
|
|
280
282
|
await setupDev(nuxt, app, options.dev ?? {}, { storage: useAblage });
|
|
@@ -535,5 +537,4 @@ function exceptRuntime(pattern) {
|
|
|
535
537
|
if (pattern.source.startsWith("^")) return pattern;
|
|
536
538
|
return new RegExp(`^(?![\\s\\S]*[\\\\/]@wervt[\\\\/]nuxt[\\\\/]src[\\\\/]runtime[\\\\/])[\\s\\S]*?(?:${pattern.source})`, pattern.flags);
|
|
537
539
|
}
|
|
538
|
-
//#endregion
|
|
539
540
|
export { module_default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tasks } from "#nitro/virtual/tasks";
|
|
2
2
|
import { HTTPError } from "h3";
|
|
3
|
-
|
|
3
|
+
// ../../node_modules/.pnpm/nitro@3.0.260903-beta/node_modules/nitro/dist/runtime/internal/task.mjs
|
|
4
4
|
const __runningTasks__ = {};
|
|
5
5
|
async function runTask(name, { payload = {}, context = {} } = {}) {
|
|
6
6
|
if (__runningTasks__[name]) return __runningTasks__[name];
|
|
@@ -25,5 +25,4 @@ async function runTask(name, { payload = {}, context = {} } = {}) {
|
|
|
25
25
|
delete __runningTasks__[name];
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
//#endregion
|
|
29
28
|
export { runTask };
|
package/dist/og-image.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
|
|
3
|
+
// src/og-image.ts
|
|
4
4
|
/** The app's dependencies and devDependencies, by name. */
|
|
5
5
|
async function dependencyNames(rootDir) {
|
|
6
6
|
const pkg = JSON.parse(await readFile(join(rootDir, "package.json"), "utf8").catch(() => "{}"));
|
|
@@ -35,5 +35,4 @@ function ogImageWarning(dependencies) {
|
|
|
35
35
|
if (missing.length === 0) return void 0;
|
|
36
36
|
return `OG images render with WebAssembly on wervt (an isolate can't load native renderers), and nuxt-og-image's build also wants the native package, but ${missing.map((name) => `\`${name}\``).join(", ")} ${missing.length > 1 ? "are" : "is"} not installed. Run \`pnpm add ${missing.join(" ")}\`.`;
|
|
37
37
|
}
|
|
38
|
-
//#endregion
|
|
39
38
|
export { dependencyNames, ogImageDefaults, ogImageWarning };
|
package/dist/preview.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
//#region src/preview.d.ts
|
|
2
1
|
export interface PreviewOptions {
|
|
3
2
|
/** Defaults to the app's `app.head.title`. */
|
|
4
3
|
title?: string;
|
|
@@ -10,5 +9,4 @@ export interface PreviewOptions {
|
|
|
10
9
|
icon?: string;
|
|
11
10
|
/** Defaults to the app's `theme-color` meta tag. */
|
|
12
11
|
themeColor?: string;
|
|
13
|
-
}
|
|
14
|
-
//#endregion
|
|
12
|
+
}
|
package/dist/preview.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/preview.ts
|
|
2
2
|
/**
|
|
3
3
|
* What the runtime shows. Without `preview`, only the app's name and icon: for some private apps
|
|
4
4
|
* the title alone says too much, so the rest of the head is only used once the app opts in.
|
|
@@ -35,5 +35,4 @@ function localFiles(manifest) {
|
|
|
35
35
|
if (!manifest) return [];
|
|
36
36
|
return [manifest.image, manifest.icon].filter((path) => !!path && path.startsWith("/") && !path.startsWith("//"));
|
|
37
37
|
}
|
|
38
|
-
//#endregion
|
|
39
38
|
export { localFiles, previewManifest };
|
package/dist/provision.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { MAX_KEY_BYTES, ObjectDetails, ObjectListing, StorageError, StorageOptions, StorageQuota, StorageUsage, StoredObject, createStorage } from "./storage.js";
|
|
2
|
-
//#region src/provision.d.ts
|
|
3
2
|
export interface ProvisionOptions {
|
|
4
3
|
/** App name, `[a-z0-9-]+`. */
|
|
5
4
|
app: string;
|
|
@@ -49,6 +48,18 @@ export declare function appDatabaseUrl({ app, adminUrl, secret }: ProvisionOptio
|
|
|
49
48
|
export declare function provisionDatabase(options: ProvisionOptions): Promise<{
|
|
50
49
|
fresh: boolean;
|
|
51
50
|
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Runs the Drizzle migrations as the app's own role, into its schema. The role needs CREATE on
|
|
53
|
+
* the database while this runs (see `provisionDatabase`). `fresh` is true when no migration had
|
|
54
|
+
* been applied before.
|
|
55
|
+
*/
|
|
56
|
+
export declare function migrateAs({ url, schema, migrationsFolder }: {
|
|
57
|
+
url: string;
|
|
58
|
+
schema: string;
|
|
59
|
+
migrationsFolder: string;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
fresh: boolean;
|
|
62
|
+
}>;
|
|
52
63
|
/** The role PgBouncer signs in with to look up app roles' password hashes (`auth_query`). */
|
|
53
64
|
export declare const POOLER_ROLE = "pgbouncer";
|
|
54
65
|
/**
|
|
@@ -63,5 +74,4 @@ export declare function setupPooler({ adminUrl, password }: {
|
|
|
63
74
|
}): Promise<void>;
|
|
64
75
|
/** Drops the app's schema (all its data) and role. */
|
|
65
76
|
export declare function dropDatabase({ app, adminUrl }: Pick<ProvisionOptions, 'app' | 'adminUrl'>): Promise<void>;
|
|
66
|
-
//#endregion
|
|
67
77
|
export { MAX_KEY_BYTES, type ObjectDetails, type ObjectListing, StorageError, type StorageOptions, type StorageQuota, type StorageUsage, type StoredObject, createStorage };
|
package/dist/provision.js
CHANGED
|
@@ -2,7 +2,7 @@ import { MAX_KEY_BYTES, StorageError, createStorage } from "./storage.js";
|
|
|
2
2
|
import { drizzle } from "drizzle-orm/postgres-js";
|
|
3
3
|
import { migrate } from "drizzle-orm/postgres-js/migrator";
|
|
4
4
|
import postgres from "postgres";
|
|
5
|
-
|
|
5
|
+
// src/provision.ts
|
|
6
6
|
const DEFAULT_ROLE_TIMEOUTS = {
|
|
7
7
|
statement: "30s",
|
|
8
8
|
idleInTransaction: "60s"
|
|
@@ -110,35 +110,50 @@ async function provisionDatabase(options) {
|
|
|
110
110
|
await admin.unsafe(`grant connect on database "${database}" to "${role}"`);
|
|
111
111
|
await admin.unsafe(`revoke all on schema public from public`);
|
|
112
112
|
if (!migrationsFolder) return { fresh: false };
|
|
113
|
-
const table = `"${role}"."__drizzle_migrations"`;
|
|
114
|
-
const [state] = await admin`
|
|
115
|
-
select to_regclass(${table}) is not null as exists`;
|
|
116
|
-
let fresh = !state?.exists;
|
|
117
|
-
if (!fresh) {
|
|
118
|
-
const [row] = await admin.unsafe(`select exists(select 1 from ${table}) as applied`);
|
|
119
|
-
fresh = !row?.applied;
|
|
120
|
-
}
|
|
121
113
|
await admin.unsafe(`grant create on database "${database}" to "${role}"`);
|
|
122
|
-
const client = postgres(await appDatabaseUrl(options), {
|
|
123
|
-
max: 1,
|
|
124
|
-
onnotice: () => {}
|
|
125
|
-
});
|
|
126
114
|
try {
|
|
127
|
-
await
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
115
|
+
return await migrateAs({
|
|
116
|
+
url: await appDatabaseUrl(options),
|
|
117
|
+
schema: role,
|
|
118
|
+
migrationsFolder
|
|
131
119
|
});
|
|
132
120
|
} finally {
|
|
133
|
-
await client.end();
|
|
134
121
|
await admin.unsafe(`revoke create on database "${database}" from "${role}"`);
|
|
135
122
|
}
|
|
136
|
-
return { fresh };
|
|
137
123
|
} finally {
|
|
138
124
|
await admin.end();
|
|
139
125
|
}
|
|
140
126
|
}
|
|
141
127
|
/**
|
|
128
|
+
* Runs the Drizzle migrations as the app's own role, into its schema. The role needs CREATE on
|
|
129
|
+
* the database while this runs (see `provisionDatabase`). `fresh` is true when no migration had
|
|
130
|
+
* been applied before.
|
|
131
|
+
*/
|
|
132
|
+
async function migrateAs({ url, schema, migrationsFolder }) {
|
|
133
|
+
const client = postgres(url, {
|
|
134
|
+
max: 1,
|
|
135
|
+
onnotice: () => {}
|
|
136
|
+
});
|
|
137
|
+
try {
|
|
138
|
+
const table = `"${schema}"."__drizzle_migrations"`;
|
|
139
|
+
const [state] = await client`
|
|
140
|
+
select to_regclass(${table}) is not null as exists`;
|
|
141
|
+
let fresh = !state?.exists;
|
|
142
|
+
if (!fresh) {
|
|
143
|
+
const [row] = await client.unsafe(`select exists(select 1 from ${table}) as applied`);
|
|
144
|
+
fresh = !row?.applied;
|
|
145
|
+
}
|
|
146
|
+
await client.unsafe("set statement_timeout = 0; set idle_in_transaction_session_timeout = 0");
|
|
147
|
+
await migrate(drizzle({ client }), {
|
|
148
|
+
migrationsFolder,
|
|
149
|
+
migrationsSchema: schema
|
|
150
|
+
});
|
|
151
|
+
return { fresh };
|
|
152
|
+
} finally {
|
|
153
|
+
await client.end();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
142
157
|
* Gives the role its schema and everything in it back. A dump restored with `--no-owner`
|
|
143
158
|
* (Coolify's backups) leaves all of it owned by the restoring superuser.
|
|
144
159
|
*/
|
|
@@ -220,5 +235,4 @@ async function dropDatabase({ app, adminUrl }) {
|
|
|
220
235
|
await admin.end();
|
|
221
236
|
}
|
|
222
237
|
}
|
|
223
|
-
|
|
224
|
-
export { DEFAULT_ROLE_TIMEOUTS, MAX_KEY_BYTES, POOLER_ROLE, StorageError, appDatabaseUrl, createStorage, dbPassword, dbRole, dropDatabase, hmac, parseDuration, provisionDatabase, setRoleTimeouts, setupPooler, storageCredentials };
|
|
238
|
+
export { DEFAULT_ROLE_TIMEOUTS, MAX_KEY_BYTES, POOLER_ROLE, StorageError, appDatabaseUrl, createStorage, dbPassword, dbRole, dropDatabase, hmac, migrateAs, parseDuration, provisionDatabase, setRoleTimeouts, setupPooler, storageCredentials };
|
package/dist/route-tools.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile, readdir } from "node:fs/promises";
|
|
2
2
|
import { extname, join, sep } from "node:path";
|
|
3
|
-
|
|
3
|
+
// src/route-tools.ts
|
|
4
4
|
const EXTENSIONS = /* @__PURE__ */ new Set([
|
|
5
5
|
".ts",
|
|
6
6
|
".js",
|
|
@@ -40,5 +40,4 @@ async function findRouteTools(dir, prefix = []) {
|
|
|
40
40
|
}
|
|
41
41
|
return found;
|
|
42
42
|
}
|
|
43
|
-
//#endregion
|
|
44
43
|
export { findRouteTools, routeToolName };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineNuxtPlugin, useRouter, useRuntimeConfig } from "#app";
|
|
2
|
-
|
|
2
|
+
// src/runtime/app/plugins/analytics.client.ts
|
|
3
3
|
var analytics_client_default = defineNuxtPlugin({
|
|
4
4
|
name: "wervt:analytics",
|
|
5
5
|
setup() {
|
|
@@ -12,5 +12,4 @@ var analytics_client_default = defineNuxtPlugin({
|
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
//#endregion
|
|
16
15
|
export { analytics_client_default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { pendingFeedbackContext } from "../useWervtFeedback.js";
|
|
2
2
|
import { defineNuxtPlugin, onNuxtReady, useRuntimeConfig } from "#app";
|
|
3
|
-
|
|
3
|
+
// src/runtime/app/plugins/feedback.client.ts
|
|
4
4
|
var feedback_client_default = defineNuxtPlugin({
|
|
5
5
|
name: "wervt:feedback",
|
|
6
6
|
setup() {
|
|
@@ -28,5 +28,4 @@ var feedback_client_default = defineNuxtPlugin({
|
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
|
-
//#endregion
|
|
32
31
|
export { feedback_client_default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useUpdateAvailable, useWervtUpdate } from "../useWervtUpdate.js";
|
|
2
2
|
import { defineNuxtPlugin, onNuxtReady, useRuntimeConfig } from "#app";
|
|
3
|
-
|
|
3
|
+
// src/runtime/app/plugins/update.client.ts
|
|
4
4
|
const INTERVAL_MS = 6e4;
|
|
5
5
|
/** Focus and visibility changes come in bursts; one check covers them. */
|
|
6
6
|
const MIN_GAP_MS = 1e4;
|
|
@@ -73,5 +73,4 @@ function showBanner(reload) {
|
|
|
73
73
|
bar.append(text, button("Reload", "background:#fafafa;color:#18181b", reload), close);
|
|
74
74
|
document.body.append(bar);
|
|
75
75
|
}
|
|
76
|
-
//#endregion
|
|
77
76
|
export { update_client_default as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useWervtUser } from "../useWervtUser.js";
|
|
2
2
|
import { defineNuxtPlugin } from "#app";
|
|
3
|
-
|
|
3
|
+
// src/runtime/app/plugins/user.client.ts
|
|
4
4
|
var user_client_default = defineNuxtPlugin({
|
|
5
5
|
name: "wervt:user",
|
|
6
6
|
async setup(nuxtApp) {
|
|
@@ -14,5 +14,4 @@ var user_client_default = defineNuxtPlugin({
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
|
-
//#endregion
|
|
18
17
|
export { user_client_default as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineNuxtPlugin, onNuxtReady, useRuntimeConfig } from "#app";
|
|
2
|
-
|
|
2
|
+
// src/runtime/app/plugins/webmcp.client.ts
|
|
3
3
|
function pageModelContext() {
|
|
4
4
|
const context = document.modelContext ?? navigator.modelContext;
|
|
5
5
|
return typeof context?.registerTool === "function" ? context : void 0;
|
|
@@ -46,5 +46,4 @@ var webmcp_client_default = defineNuxtPlugin({
|
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
|
-
//#endregion
|
|
50
49
|
export { webmcp_client_default as default };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { PropType } from "vue";
|
|
2
|
+
declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
3
|
+
error: {
|
|
4
|
+
type: PropType<{
|
|
5
|
+
status?: number;
|
|
6
|
+
statusCode?: number;
|
|
7
|
+
}>;
|
|
8
|
+
default: () => {};
|
|
9
|
+
};
|
|
10
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
11
|
+
[key: string]: any;
|
|
12
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
13
|
+
error: {
|
|
14
|
+
type: PropType<{
|
|
15
|
+
status?: number;
|
|
16
|
+
statusCode?: number;
|
|
17
|
+
}>;
|
|
18
|
+
default: () => {};
|
|
19
|
+
};
|
|
20
|
+
}>> & Readonly<{}>, {
|
|
21
|
+
error: {
|
|
22
|
+
status?: number;
|
|
23
|
+
statusCode?: number;
|
|
24
|
+
};
|
|
25
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
26
|
+
export { _default as default };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { WERVT_MARK } from "../shared/mark.js";
|
|
2
|
+
import { clearError, useRequestHeaders, useRequestURL, useState } from "#app";
|
|
3
|
+
import { defineComponent, h } from "vue";
|
|
4
|
+
// src/runtime/app/preview-error.ts
|
|
5
|
+
const TEXT = {
|
|
6
|
+
de: {
|
|
7
|
+
missing: "Diese Seite gibt es noch nicht",
|
|
8
|
+
building: "Die Startseite entsteht gerade",
|
|
9
|
+
broken: "Hier hakt gerade etwas",
|
|
10
|
+
hint: "Studio sieht den Fehler und kann ihn beheben.",
|
|
11
|
+
home: "Zur Startseite",
|
|
12
|
+
reload: "Neu laden"
|
|
13
|
+
},
|
|
14
|
+
en: {
|
|
15
|
+
missing: "This page doesn’t exist yet",
|
|
16
|
+
building: "The start page is being built",
|
|
17
|
+
broken: "Something isn’t working here",
|
|
18
|
+
hint: "Studio sees the error and can fix it.",
|
|
19
|
+
home: "Go to start",
|
|
20
|
+
reload: "Reload"
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const STYLE = `
|
|
24
|
+
.wervt-preview-error { min-height: 100dvh; display: grid; place-content: center; justify-items: center;
|
|
25
|
+
gap: .75rem; padding: 2rem; text-align: center; font: 500 1rem/1.4 system-ui, -apple-system, sans-serif;
|
|
26
|
+
color: #0a0a0b; background: #fafaf9; --a: #2f5bff; }
|
|
27
|
+
.wervt-preview-error svg { width: 2.5rem; height: 2.5rem; margin-bottom: .5rem; }
|
|
28
|
+
.wervt-preview-error h1 { margin: 0; font-size: 1.25rem; font-weight: 600; }
|
|
29
|
+
.wervt-preview-error p { margin: 0; color: #6b6b70; }
|
|
30
|
+
.wervt-preview-error button { margin-top: .75rem; padding: .7rem 1.4rem; border: 0; border-radius: 999px;
|
|
31
|
+
background: #0a0a0b; color: #fafaf9; font: inherit; cursor: pointer; }
|
|
32
|
+
@media (prefers-color-scheme: dark) {
|
|
33
|
+
.wervt-preview-error { color: #fafaf9; background: #0a0a0b; --a: #5885ff; }
|
|
34
|
+
.wervt-preview-error p { color: #a1a1a6; }
|
|
35
|
+
.wervt-preview-error button { background: #fafaf9; color: #0a0a0b; }
|
|
36
|
+
}`;
|
|
37
|
+
var preview_error_default = defineComponent({
|
|
38
|
+
name: "WervtPreviewError",
|
|
39
|
+
props: { error: {
|
|
40
|
+
type: Object,
|
|
41
|
+
default: () => ({})
|
|
42
|
+
} },
|
|
43
|
+
setup(props) {
|
|
44
|
+
const lang = useState("wervt-preview-lang", () => {
|
|
45
|
+
return (import.meta.server ? useRequestHeaders(["accept-language"])["accept-language"] ?? "" : navigator.language).toLowerCase().startsWith("en") ? "en" : "de";
|
|
46
|
+
});
|
|
47
|
+
const path = useRequestURL().pathname;
|
|
48
|
+
return () => {
|
|
49
|
+
const text = TEXT[lang.value];
|
|
50
|
+
const notFound = (props.error.status ?? props.error.statusCode) === 404;
|
|
51
|
+
const building = notFound && path === "/";
|
|
52
|
+
const missing = notFound && !building;
|
|
53
|
+
return h("main", { class: "wervt-preview-error" }, [
|
|
54
|
+
h("style", STYLE),
|
|
55
|
+
h("span", {
|
|
56
|
+
innerHTML: WERVT_MARK,
|
|
57
|
+
"aria-hidden": "true"
|
|
58
|
+
}),
|
|
59
|
+
h("h1", building ? text.building : missing ? text.missing : text.broken),
|
|
60
|
+
notFound ? null : h("p", text.hint),
|
|
61
|
+
h("button", {
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: () => missing ? clearError({ redirect: "/" }) : window.location.reload()
|
|
64
|
+
}, missing ? text.home : text.reload)
|
|
65
|
+
]);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
export { preview_error_default as default };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Message, Offset, Row } from "@electric-sql/client";
|
|
2
|
-
//#region src/runtime/app/snapshot.d.ts
|
|
3
2
|
export interface ShapeSnapshot<T> {
|
|
4
3
|
rows: [string, T][];
|
|
5
4
|
offset: Offset;
|
|
@@ -13,5 +12,4 @@ export interface ShapeSnapshot<T> {
|
|
|
13
12
|
/** The rows of the shape at `url` (absolute) as of now, without subscribing. */
|
|
14
13
|
export declare function loadSnapshot<T extends Row<unknown>>(url: string, fetchClient?: typeof fetch): Promise<ShapeSnapshot<T>>;
|
|
15
14
|
/** Applies Electric change messages to `rows`. Returns whether anything changed. */
|
|
16
|
-
export declare function applyMessages<T extends Row<unknown>>(rows: Map<string, T>, messages: Message<T>[]): boolean;
|
|
17
|
-
//#endregion
|
|
15
|
+
export declare function applyMessages<T extends Row<unknown>>(rows: Map<string, T>, messages: Message<T>[]): boolean;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { shapeParser } from "../shared/shape.js";
|
|
2
2
|
import { ShapeStream, isChangeMessage, isControlMessage } from "@electric-sql/client";
|
|
3
|
-
|
|
3
|
+
// src/runtime/app/snapshot.ts
|
|
4
4
|
/** The rows of the shape at `url` (absolute) as of now, without subscribing. */
|
|
5
5
|
async function loadSnapshot(url, fetchClient) {
|
|
6
6
|
const rows = /* @__PURE__ */ new Map();
|
|
@@ -60,5 +60,4 @@ function applyMessages(rows, messages) {
|
|
|
60
60
|
}
|
|
61
61
|
return changed;
|
|
62
62
|
}
|
|
63
|
-
//#endregion
|
|
64
63
|
export { applyMessages, loadSnapshot };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Row } from "@electric-sql/client";
|
|
2
1
|
import { Ref, ShallowRef } from "vue";
|
|
3
|
-
|
|
2
|
+
import { Row } from "@electric-sql/client";
|
|
4
3
|
declare global {
|
|
5
4
|
/**
|
|
6
5
|
* Shape routes and their rows, generated from `server/api/shapes/` (`.nuxt/types/wervt-shapes.d.ts`).
|
|
@@ -50,5 +49,4 @@ export declare function preloadShape<P extends keyof WervtShapeRoutes>(path: P,
|
|
|
50
49
|
export declare function preloadShape(path: string, options?: {
|
|
51
50
|
key?: string;
|
|
52
51
|
}): Promise<void>;
|
|
53
|
-
//#endregion
|
|
54
52
|
export {};
|