@antelopejs/dms-frontend 0.1.9 → 0.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/README.md +10 -8
- package/dist/commands/build.js +2 -0
- package/dist/commands/dev.js +2 -0
- package/dist/commands/start.js +2 -0
- package/dist/config.js +13 -0
- package/dist/index.js +3 -0
- package/dist/materialize.js +1 -1
- package/dist/verify-source-runner.js +1 -1
- package/package.json +1 -1
- package/templates/vue/vite.config.ts +1 -1
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ making the template root (`src/materialize.ts`) and the manifest query
|
|
|
44
44
|
`--renderer` flag and no renderer registry; the single-renderer assumption is
|
|
45
45
|
deliberate until a second renderer exists. Whatever a renderer names its module
|
|
46
46
|
entry is its own convention: `dms.frontend.ts` and the
|
|
47
|
-
`#dms
|
|
47
|
+
`#dms/frontend-module` alias belong to the Vue renderer, not to the
|
|
48
48
|
loader.
|
|
49
49
|
|
|
50
50
|
## Application ownership
|
|
@@ -104,7 +104,7 @@ Manifest negotiation and module materialization are the renderer contract descri
|
|
|
104
104
|
|
|
105
105
|
The generated Vue application uses `@inertiajs/vue3`, `@nuxt/ui/vite` with `{ router: "inertia" }`, and `@nuxt/ui/vue-plugin`. The Node server resolves each Inertia visit through `/dms/page?path=…`, including fresh shared data so account, tenant, and permission changes update navigation state. It proxies backend routes and manages authentication through server-side sessions. `DMS_BOOTSTRAP_SECRET` is used only by the CLI's server-to-server frontend manifest and module archive requests and is never sent by, or exposed to, browser traffic.
|
|
106
106
|
|
|
107
|
-
Vue modules
|
|
107
|
+
Vue modules register through `dms.frontend.ts` and import the SDK from the `#dms/frontend-module` alias, which the loader resolves to the generated `frontend-module.ts`: `defineDmsPlugin`, `useDmsRouter`, the page and session types, and everything else a module needs from the host. Email templates register separately through `dms.email.ts`.
|
|
108
108
|
|
|
109
109
|
An email entry exports `serverEmailTemplates` and may export a plain `appConfig` object, such as shared branding defaults. Email rendering merges these configurations in manifest-priority order and provides them to `useDmsAppConfig` per render. Public runtime options come from the module manifest; `DMS_CLIENT_BASE_URL` overrides `public.dms.clientBaseUrl`. Email entries must not import the browser frontend module.
|
|
110
110
|
|
|
@@ -117,7 +117,7 @@ A materialized module opts into the Vue adapter with a root `dms.frontend.ts`:
|
|
|
117
117
|
```ts
|
|
118
118
|
import MyBlock from "./components/MyBlock.vue";
|
|
119
119
|
import MyPage from "./pages/MyPage.vue";
|
|
120
|
-
import type { DmsFrontendModule } from "
|
|
120
|
+
import type { DmsFrontendModule } from "#dms/frontend-module";
|
|
121
121
|
|
|
122
122
|
const frontendModule: DmsFrontendModule = {
|
|
123
123
|
setup(sdk) {
|
|
@@ -163,11 +163,13 @@ started by `dev`, and the production server started by `start`, because those
|
|
|
163
163
|
child processes inherit the environment. A missing file is not an error; an
|
|
164
164
|
unreadable one is reported and skipped.
|
|
165
165
|
|
|
166
|
-
`
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
166
|
+
`ajs dms dev` generates a fresh ephemeral 32-byte secret when
|
|
167
|
+
`DMS_SESSION_SECRET` is absent; all sessions are invalidated when that dev
|
|
168
|
+
server restarts. An explicit value is preserved, but empty or shorter than 32
|
|
169
|
+
characters is rejected. `build` and `start` require a configured secret and
|
|
170
|
+
never generate one, which is required for production so sessions survive
|
|
171
|
+
restarts. The generated server also validates the value as a safety net.
|
|
172
|
+
Generate one with `openssl rand -hex 32`.
|
|
171
173
|
|
|
172
174
|
### Opening a session from a module flow
|
|
173
175
|
|
package/dist/commands/build.js
CHANGED
|
@@ -21,6 +21,7 @@ function cmdBuild() {
|
|
|
21
21
|
(0, cli_ui_1.error)("Backend URL is required. Use -b <url> or set DMS_API_BASE_URL.");
|
|
22
22
|
process.exit(1);
|
|
23
23
|
}
|
|
24
|
+
const sessionSecret = (0, common_1.resolveSessionSecret)("build");
|
|
24
25
|
const spinner = new cli_ui_1.Spinner("Setting up workspace...");
|
|
25
26
|
await spinner.start();
|
|
26
27
|
try {
|
|
@@ -44,6 +45,7 @@ function cmdBuild() {
|
|
|
44
45
|
cwd: workspaceDir,
|
|
45
46
|
env: {
|
|
46
47
|
...process.env,
|
|
48
|
+
DMS_SESSION_SECRET: sessionSecret,
|
|
47
49
|
NODE_OPTIONS: "--max-old-space-size=4096",
|
|
48
50
|
NODE_PATH: nodeModulesDir,
|
|
49
51
|
},
|
package/dist/commands/dev.js
CHANGED
|
@@ -44,6 +44,7 @@ function cmdDev() {
|
|
|
44
44
|
.action(async (options) => {
|
|
45
45
|
const { backendUrl, workspaceKey } = resolveBackend(options);
|
|
46
46
|
const bootstrapSecret = (0, common_1.resolveBootstrapSecret)(options.bootstrapSecret, backendUrl);
|
|
47
|
+
const sessionSecret = (0, common_1.resolveSessionSecret)("dev");
|
|
47
48
|
const requestedPort = Number.parseInt(options.port, 10);
|
|
48
49
|
if (Number.isNaN(requestedPort)) {
|
|
49
50
|
(0, cli_ui_1.error)(`Invalid port: ${options.port}`);
|
|
@@ -101,6 +102,7 @@ function cmdDev() {
|
|
|
101
102
|
DMS_COOKIE_SECURE: process.env.DMS_COOKIE_SECURE ?? "false",
|
|
102
103
|
DMS_API_BASE_URL: backendUrl,
|
|
103
104
|
DMS_BOOTSTRAP_SECRET: bootstrapSecret,
|
|
105
|
+
DMS_SESSION_SECRET: sessionSecret,
|
|
104
106
|
NODE_OPTIONS: "--max-old-space-size=4096",
|
|
105
107
|
NODE_PATH: nodeModulesDir,
|
|
106
108
|
},
|
package/dist/commands/start.js
CHANGED
|
@@ -20,6 +20,7 @@ function cmdStart() {
|
|
|
20
20
|
(0, cli_ui_1.error)("Backend URL is required. Use -b <url> or set DMS_API_BASE_URL.");
|
|
21
21
|
process.exit(1);
|
|
22
22
|
}
|
|
23
|
+
const sessionSecret = (0, common_1.resolveSessionSecret)("start");
|
|
23
24
|
const workspaceDir = (0, common_1.getWorkspaceDir)(options.backendUrl);
|
|
24
25
|
const serverPath = (0, node_path_1.join)(workspaceDir, "server.mjs");
|
|
25
26
|
const clientPath = (0, node_path_1.join)(workspaceDir, "dist", "client", "index.html");
|
|
@@ -41,6 +42,7 @@ function cmdStart() {
|
|
|
41
42
|
...process.env,
|
|
42
43
|
PORT: options.port,
|
|
43
44
|
DMS_API_BASE_URL: options.backendUrl,
|
|
45
|
+
DMS_SESSION_SECRET: sessionSecret,
|
|
44
46
|
DMS_COOKIE_SECURE: process.env.DMS_COOKIE_SECURE ?? "true",
|
|
45
47
|
},
|
|
46
48
|
});
|
package/dist/config.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.Options = exports.TAILWIND_SOURCE_GLOB = exports.PNPM_LIFECYCLE_SCRIPTS = exports.layerCopyIgnore = exports.LAYER_COPY_BLOCKLIST = exports.AUTH_ESTABLISH_FILE = exports.FRONTEND_MODULE_ENTRY = exports.LAYERS_SUBDIR = exports.TEMPLATE_FILES = exports.WORKSPACE_DIR_MODE = exports.DEPS_HASH_FILE = exports.DMS_FRONTEND_HOME = void 0;
|
|
7
7
|
exports.writeSecretBearingFile = writeSecretBearingFile;
|
|
8
8
|
exports.normalizeBootstrapSecret = normalizeBootstrapSecret;
|
|
9
|
+
exports.resolveSessionSecret = resolveSessionSecret;
|
|
9
10
|
exports.resolveBootstrapSecret = resolveBootstrapSecret;
|
|
10
11
|
exports.sha256Hex = sha256Hex;
|
|
11
12
|
exports.canonicalizeBackendUrl = canonicalizeBackendUrl;
|
|
@@ -109,6 +110,18 @@ function normalizeBootstrapSecret(value, source = DEFAULT_CREDENTIAL_SOURCE) {
|
|
|
109
110
|
}
|
|
110
111
|
return trimmed;
|
|
111
112
|
}
|
|
113
|
+
function resolveSessionSecret(mode, value = process.env.DMS_SESSION_SECRET) {
|
|
114
|
+
if (value === undefined && mode === "dev") {
|
|
115
|
+
return (0, node_crypto_1.randomBytes)(32).toString("hex");
|
|
116
|
+
}
|
|
117
|
+
if (value === undefined || value.length < 32) {
|
|
118
|
+
throw new Error("DMS_SESSION_SECRET must contain at least 32 characters; " +
|
|
119
|
+
(mode === "dev"
|
|
120
|
+
? "set it explicitly or omit it to generate an ephemeral dev secret"
|
|
121
|
+
: "set it explicitly for build and start"));
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
112
125
|
function resolveBootstrapSecret(explicit, backendUrl, options = {}) {
|
|
113
126
|
const normalized = normalizeBootstrapSecret(explicit);
|
|
114
127
|
if (normalized)
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,9 @@ Environment:
|
|
|
38
38
|
the other variables below can live in the project's .env. A variable already
|
|
39
39
|
set in the environment always wins over a file, and .env.local wins over .env.
|
|
40
40
|
The generated workspace never loads a .env of its own.
|
|
41
|
+
'dev' generates an ephemeral 32-byte DMS_SESSION_SECRET when it is absent;
|
|
42
|
+
restarting dev invalidates its sessions. 'build' and 'start' require a
|
|
43
|
+
configured secret of at least 32 characters.
|
|
41
44
|
|
|
42
45
|
Workspaces:
|
|
43
46
|
Each canonical backend URL gets its own workspace under
|
package/dist/materialize.js
CHANGED
|
@@ -140,7 +140,7 @@ function writeFrontendModuleRegistry(workspaceDir, layers) {
|
|
|
140
140
|
}
|
|
141
141
|
function writeFrontendTypePaths(workspaceDir, registry) {
|
|
142
142
|
const paths = {
|
|
143
|
-
"#dms
|
|
143
|
+
"#dms/frontend-module": ["./frontend-module.ts"],
|
|
144
144
|
"@frontend/*": ["./frontend-modules/*"],
|
|
145
145
|
};
|
|
146
146
|
[...registry.modules].reverse().forEach((module) => {
|
|
@@ -53,7 +53,7 @@ function removeDevelopmentDependencies(root) {
|
|
|
53
53
|
if (!process.env.DMS_LAYER_SOURCE)
|
|
54
54
|
throw new Error("DMS_LAYER_SOURCE must identify a frontend package");
|
|
55
55
|
const sourceRoot = (0, node_path_1.resolve)(process.env.DMS_LAYER_SOURCE);
|
|
56
|
-
const workspace = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "dms-
|
|
56
|
+
const workspace = (0, node_fs_1.mkdtempSync)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "dms-frontend-real-source-"));
|
|
57
57
|
const templateRoot = (0, node_path_1.join)((0, common_1.getPackageRoot)(), "templates", "vue");
|
|
58
58
|
const commandEnvironment = { ...process.env };
|
|
59
59
|
const EMAIL_BUILD_SIZE_CEILING_BYTES = 256 * 1024;
|
package/package.json
CHANGED
|
@@ -135,7 +135,7 @@ export default defineConfig({
|
|
|
135
135
|
resolve: {
|
|
136
136
|
dedupe: ["vue", "reka-ui", "@nuxt/ui"],
|
|
137
137
|
alias: {
|
|
138
|
-
"#dms
|
|
138
|
+
"#dms/frontend-module": resolve(__dirname, "frontend-module.ts"),
|
|
139
139
|
"#build/nuxt-icon-client-bundle": "virtual:nuxt-ui-icons",
|
|
140
140
|
"#shortcuts-aggregated": resolve(
|
|
141
141
|
__dirname,
|