@aistrike-dev/ui-shell-dev 1.0.3 → 1.0.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/README.md CHANGED
@@ -53,7 +53,12 @@ Read from the Vite root when present (or from the plugin's `devFile` option).
53
53
 
54
54
  `profile` defaults to `local`, `overrides` point other domains at their own dev servers (bare origins, no path; your
55
55
  own domain is overridden automatically), `idleTimeoutMs` defaults to `0` (idle timeout off), and `claims` is merged
56
- over the default dev claims. The plugin's `claims`, `ttlMs` and `noToken` options win over the file.
56
+ over the default dev claims. The plugin's `claims`, `ttlMs` and `noToken` options win over the file. `"lab": true`
57
+ shows Octopus UI's Design Lab (its live controls for the open design questions, in a Picture-in-Picture window) over
58
+ your pages, so you can judge them on your own screens. `"lab": { "designSystem": "../octopus-ui" }` also names an
59
+ Octopus checkout (relative to the Vite root): **Lock in** then writes a work-loop item into its `.backlog/`, through
60
+ Octopus's Lock-in plugin (`@aistrike-dev/ui/lab/vite`, loaded from the installed `@aistrike-dev/ui`). Without one, or
61
+ when the path is not an Octopus checkout, Lock in downloads the same item instead.
57
62
 
58
63
  ## Commands
59
64
 
package/dist/devfile.d.ts CHANGED
@@ -2,6 +2,9 @@ import type { DevConfig, DevDomain } from '@aistrike-dev/ui-shell-sdk/shell';
2
2
  import type { Session } from '@aistrike-dev/ui-shell-sdk';
3
3
  import type { DevClaimsInput } from './token.js';
4
4
  export declare const DEV_FILE = "shell.dev.json";
5
+ export interface DevLab {
6
+ designSystem?: string;
7
+ }
5
8
  export interface DevFile {
6
9
  profile?: string;
7
10
  overrides?: {
@@ -10,6 +13,11 @@ export interface DevFile {
10
13
  domains?: DevDomain[];
11
14
  idleTimeoutMs?: number;
12
15
  landing?: string;
16
+ /**
17
+ * Shows Octopus UI's Design Lab over this MFE's pages, to judge open design questions on them. As an object, it is on,
18
+ * and `designSystem` is the path (from the Vite root) of the Octopus checkout its locks are written to.
19
+ */
20
+ lab?: boolean | DevLab;
13
21
  claims?: DevClaimsInput;
14
22
  }
15
23
  /** Dev claims must be a plain object of known keys; `iss`/`exp`/`iat` and friends cannot be smuggled into the token. */
package/dist/devfile.js CHANGED
@@ -41,7 +41,7 @@ function normalizeOverrides(overrides) {
41
41
  }
42
42
  return result;
43
43
  }
44
- const FILE_KEYS = ['profile', 'overrides', 'domains', 'idleTimeoutMs', 'landing', 'claims'];
44
+ const FILE_KEYS = ['profile', 'overrides', 'domains', 'idleTimeoutMs', 'landing', 'lab', 'claims'];
45
45
  const DOMAIN_KEYS = ['id', 'route', 'nav', 'devPort'];
46
46
  const NAV_KEYS = ['label', 'icon'];
47
47
  const ROUTE = /^\/[a-z0-9-]+$/;
@@ -111,6 +111,24 @@ function validateLanding(value) {
111
111
  }
112
112
  return value;
113
113
  }
114
+ const LAB_KEYS = ['designSystem'];
115
+ function validateLab(lab) {
116
+ if (typeof lab === 'boolean') {
117
+ return lab;
118
+ }
119
+ if (!isPlainObject(lab)) {
120
+ throw new Error('lab must be true, false or an object');
121
+ }
122
+ rejectUnknownKeys(lab, LAB_KEYS, 'lab');
123
+ const { designSystem } = lab;
124
+ if (designSystem === undefined) {
125
+ return {};
126
+ }
127
+ if (typeof designSystem !== 'string' || designSystem === '') {
128
+ throw new Error('lab.designSystem must be a non-empty string');
129
+ }
130
+ return { designSystem };
131
+ }
114
132
  function readExtras(parsed, result) {
115
133
  if (parsed.idleTimeoutMs !== undefined) {
116
134
  result.idleTimeoutMs = validateIdle(parsed.idleTimeoutMs);
@@ -118,6 +136,9 @@ function readExtras(parsed, result) {
118
136
  if (parsed.landing !== undefined) {
119
137
  result.landing = validateLanding(parsed.landing);
120
138
  }
139
+ if (parsed.lab !== undefined) {
140
+ result.lab = validateLab(parsed.lab);
141
+ }
121
142
  if (parsed.claims !== undefined) {
122
143
  result.claims = assertClaimsInput(parsed.claims, 'claims');
123
144
  }
@@ -169,6 +190,10 @@ export function loadDevFile(path, cwd = process.cwd()) {
169
190
  function landingOf(file, args) {
170
191
  return args.landing ?? file?.landing;
171
192
  }
193
+ /** The lab flag, only when the file sets it: a config without one is the same config it always was. */
194
+ function labOf(file) {
195
+ return file?.lab === undefined ? {} : { lab: file.lab !== false };
196
+ }
172
197
  /** Explicit overrides win over the file; the profile defaults to `local`; the idle timeout defaults to off for local work. */
173
198
  export function buildDevConfig(file, args, session) {
174
199
  return {
@@ -177,6 +202,7 @@ export function buildDevConfig(file, args, session) {
177
202
  domains: file?.domains ?? [],
178
203
  idleTimeoutMs: file?.idleTimeoutMs ?? 0,
179
204
  landing: landingOf(file, args),
205
+ ...labOf(file),
180
206
  session,
181
207
  };
182
208
  }
@@ -31,6 +31,30 @@ const SHELL_ASSET_TAG = /<(script|link)\b([^>]*?\s(?:src|href)=["']\/assets\/)/g
31
31
  export function markShellAssets(html) {
32
32
  return html.replace(SHELL_ASSET_TAG, '<$1 vite-ignore$2');
33
33
  }
34
+ /**
35
+ * Mounts Octopus UI's Lock-in endpoint when the dev file names a design-system checkout (`lab.designSystem`), so the
36
+ * Design Lab's "Lock in" writes a work-loop item into that checkout's backlog. The plugin is Octopus's, loaded from the
37
+ * copy installed beside this package. Without a checkout, nothing is mounted and the lab downloads the lock instead.
38
+ */
39
+ async function mountLabLock(context, server, file, root) {
40
+ const lab = file?.lab;
41
+ if (typeof lab !== 'object' || lab.designSystem === undefined) {
42
+ return;
43
+ }
44
+ let plugin;
45
+ try {
46
+ const { labLockPlugin } = await import('@aistrike-dev/ui/lab/vite');
47
+ plugin = labLockPlugin({ designSystem: lab.designSystem, root });
48
+ }
49
+ catch {
50
+ console.warn('[octopus-lab] lock-in is disabled: @aistrike-dev/ui/lab/vite could not be loaded');
51
+ return;
52
+ }
53
+ const { configureServer } = plugin;
54
+ if (typeof configureServer === 'function') {
55
+ await configureServer.call(context, server);
56
+ }
57
+ }
34
58
  function sendHtml(res, html) {
35
59
  res.statusCode = 200;
36
60
  res.setHeader('Content-Type', CONTENT_TYPES['.html'] ?? 'text/html');
@@ -104,13 +128,14 @@ export function shellDevHost(options = {}) {
104
128
  config = resolved;
105
129
  id = mfeId(resolved);
106
130
  },
107
- configureServer(server) {
131
+ async configureServer(server) {
108
132
  if (!config) {
109
133
  throw new Error('aistrike:shell-dev-host: configureServer ran before configResolved');
110
134
  }
111
135
  const base = config.base;
112
136
  const scheme = server.config.server.https ? 'https' : 'http';
113
137
  const file = loadDevFile(options.devFile, config.root);
138
+ await mountLabLock(this, server, file, config.root);
114
139
  let session;
115
140
  if (options.noToken !== true) {
116
141
  const claims = { ...(file?.claims ?? {}), ...(options.claims ?? {}) };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aistrike-dev/ui-shell-dev",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A Vite plugin that serves the AiStrike UI shell from your micro front-end's dev server, plus a dev-token CLI.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {
@@ -46,14 +46,19 @@
46
46
  "e2e": "node scripts/check-pack.mjs && playwright test"
47
47
  },
48
48
  "peerDependencies": {
49
+ "@aistrike-dev/ui": ">=6.0.0-alpha.6",
49
50
  "vite": "^8.0.0"
50
51
  },
51
52
  "peerDependenciesMeta": {
53
+ "@aistrike-dev/ui": {
54
+ "optional": true
55
+ },
52
56
  "vite": {
53
57
  "optional": true
54
58
  }
55
59
  },
56
60
  "devDependencies": {
61
+ "@aistrike-dev/ui": "6.0.0-alpha.6",
57
62
  "@aistrike-dev/ui-shell-sdk": "workspace:*",
58
63
  "@playwright/test": "^1.63.0",
59
64
  "@types/node": "^24.0.0",