@octane-xplat/workshop 0.15.0 → 0.16.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/build/discover.js +404 -0
- package/dist/build/macos-node.js +77 -0
- package/dist/build/mobile-node.js +96 -0
- package/dist/build/mobile-regex.js +40 -0
- package/dist/build/node.js +426 -0
- package/dist/build/vite-mobile.js +75 -0
- package/dist/build/vite.js +230 -0
- package/dist/build/windows/preflight.js +83 -0
- package/dist/index.js +2 -0
- package/package.json +15 -15
- package/src/{discover.mjs → build/discover.ts} +1 -0
- package/src/{macos/shell.macos.mjs → build/macos/shell.macos.ts} +4 -3
- package/src/{macos-node.mjs → build/macos-node.ts} +14 -11
- package/src/{macos-vite.mjs → build/macos-vite.ts} +2 -1
- package/src/{mobile-node.mjs → build/mobile-node.ts} +2 -1
- package/src/{mobile-regex.mjs → build/mobile-regex.ts} +1 -1
- package/src/{node.mjs → build/node.ts} +7 -6
- package/src/{vite-mobile.d.ts → build/vite-mobile.d.ts} +1 -1
- package/src/{vite-mobile.mjs → build/vite-mobile.ts} +3 -2
- package/src/{vite.d.ts → build/vite.d.ts} +1 -1
- package/src/{vite.mjs → build/vite.ts} +4 -3
- /package/dist/{node/index.js → contract.js} +0 -0
- /package/src/{node.d.ts → build/node.d.ts} +0 -0
- /package/src/{windows/preflight.mjs → build/windows/preflight.ts} +0 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { discoverStories, normalizeInclude } from "./discover.js";
|
|
2
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
//#region src/build/vite.ts
|
|
6
|
+
/**
|
|
7
|
+
* xplatWorkshop — the workshop dev-server plugin.
|
|
8
|
+
*
|
|
9
|
+
* Emits a virtual catalog module whose metadata comes from static discovery
|
|
10
|
+
* (never module evaluation), a virtual entry that boots the adaptive shell,
|
|
11
|
+
* and a virtual index.html. Story modules stay lazily imported per selection;
|
|
12
|
+
* loaders exist only for stories applicable to the build target, so a
|
|
13
|
+
* platform-specific leaf is never imported into an incompatible bundle.
|
|
14
|
+
*/
|
|
15
|
+
var CATALOG_ID = "\0xplat-workshop-catalog";
|
|
16
|
+
var ENTRY_ID = "\0xplat-workshop-entry";
|
|
17
|
+
var STORY_FILE_RE = /\.stories(?:\.(?:web|mobile|ios|android|macos|windows|linux))?\.(?:[cm]?[jt]s|[jt]sx|[jt]srx)$/;
|
|
18
|
+
var TARGET_RESOLUTION = {
|
|
19
|
+
web: {
|
|
20
|
+
conditions: ["web"],
|
|
21
|
+
extensions: [
|
|
22
|
+
".web.tsrx",
|
|
23
|
+
".tsrx",
|
|
24
|
+
".web.tsx",
|
|
25
|
+
".tsx",
|
|
26
|
+
".web.ts",
|
|
27
|
+
".ts",
|
|
28
|
+
".mts",
|
|
29
|
+
".ts",
|
|
30
|
+
".jsx",
|
|
31
|
+
".js",
|
|
32
|
+
".json"
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
linux: {
|
|
36
|
+
conditions: ["linux", "web"],
|
|
37
|
+
extensions: [
|
|
38
|
+
".linux.tsrx",
|
|
39
|
+
".web.tsrx",
|
|
40
|
+
".tsrx",
|
|
41
|
+
".linux.tsx",
|
|
42
|
+
".web.tsx",
|
|
43
|
+
".tsx",
|
|
44
|
+
".linux.ts",
|
|
45
|
+
".web.ts",
|
|
46
|
+
".ts",
|
|
47
|
+
".mts",
|
|
48
|
+
".ts",
|
|
49
|
+
".jsx",
|
|
50
|
+
".js",
|
|
51
|
+
".json"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var fsUrl = (file) => `/@fs/${file.split(sep).join("/")}`;
|
|
56
|
+
function catalogCode(root, config, target) {
|
|
57
|
+
const storiesConfig = config?.stories ?? {};
|
|
58
|
+
const { entries, diagnostics } = discoverStories(root, {
|
|
59
|
+
include: storiesConfig.include,
|
|
60
|
+
exclude: storiesConfig.exclude,
|
|
61
|
+
target
|
|
62
|
+
});
|
|
63
|
+
const include = JSON.stringify(normalizeInclude(storiesConfig.include));
|
|
64
|
+
const loaders = entries.filter((entry) => entry.applicable && diagnostics.length === 0).map((entry) => `\t${JSON.stringify(entry.id)}: (stamp) => stamp === undefined
|
|
65
|
+
\t\t? import(${JSON.stringify(fsUrl(entry.file))})
|
|
66
|
+
\t\t: import(/* @vite-ignore */ ${JSON.stringify(fsUrl(entry.file))} + '?t=' + encodeURIComponent(String(stamp))),`).join("\n");
|
|
67
|
+
return `import { catalogDidUpdate } from '@octane-xplat/workshop/web'
|
|
68
|
+
|
|
69
|
+
export const catalogMeta = ${JSON.stringify(entries)}
|
|
70
|
+
export const diagnostics = ${JSON.stringify(diagnostics)}
|
|
71
|
+
export const includePatterns = ${include}
|
|
72
|
+
|
|
73
|
+
const loaders = {
|
|
74
|
+
${loaders}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const catalog = catalogMeta.map((entry) =>
|
|
78
|
+
loaders[entry.id] ? { ...entry, load: loaders[entry.id] } : entry,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
export function loadStory(id, stamp) {
|
|
82
|
+
const entry = catalog.find((item) => item.id === id)
|
|
83
|
+
if (!entry?.load) {
|
|
84
|
+
return Promise.reject(
|
|
85
|
+
new Error(
|
|
86
|
+
entry
|
|
87
|
+
? 'story "' + id + '" is not supported on this target'
|
|
88
|
+
: 'story "' + id + '" is not in the catalog',
|
|
89
|
+
),
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
return entry.load(stamp)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
catalogDidUpdate(catalog, diagnostics)
|
|
96
|
+
if (import.meta.hot) {
|
|
97
|
+
import.meta.hot.accept((next) => catalogDidUpdate(next?.catalog ?? catalog, next?.diagnostics ?? diagnostics))
|
|
98
|
+
}
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
function entryCode(config, target, story, packageDir, root) {
|
|
102
|
+
const providerModules = config?.providerModules ?? [];
|
|
103
|
+
const imports = providerModules.map((specifier, index) => {
|
|
104
|
+
const abs = resolve(root, specifier);
|
|
105
|
+
return `import * as __workshopPreset${index} from ${JSON.stringify(fsUrl(abs))}`;
|
|
106
|
+
}).join("\n");
|
|
107
|
+
const providers = providerModules.map((_, index) => `...(__workshopPreset${index}.providers ?? __workshopPreset${index}.default ?? [])`).join(", ");
|
|
108
|
+
const shellCss = fsUrl(join(packageDir, "web", "shell.css"));
|
|
109
|
+
return `import { catalog, loadStory, diagnostics } from ${JSON.stringify(CATALOG_ID)}
|
|
110
|
+
import { startWorkshop } from '@octane-xplat/workshop/web'
|
|
111
|
+
import '@octane-xplat/ui/theme/tokens.css'
|
|
112
|
+
import ${JSON.stringify(shellCss)}
|
|
113
|
+
${imports}
|
|
114
|
+
|
|
115
|
+
startWorkshop({
|
|
116
|
+
catalog,
|
|
117
|
+
diagnostics,
|
|
118
|
+
loadStory,
|
|
119
|
+
target: ${JSON.stringify(target)},
|
|
120
|
+
initialStoryId: ${JSON.stringify(story ?? null)},
|
|
121
|
+
globalProviders: [${providers}],
|
|
122
|
+
hot: import.meta.hot,
|
|
123
|
+
})
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
var WORKSHOP_HTML = `<!doctype html>
|
|
127
|
+
<html lang="en">
|
|
128
|
+
<head>
|
|
129
|
+
<meta charset="utf-8" />
|
|
130
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
131
|
+
<title>octane-xplat workshop</title>
|
|
132
|
+
<style>html,body{margin:0;height:100%}#workshop-root{height:100%}</style>
|
|
133
|
+
</head>
|
|
134
|
+
<body>
|
|
135
|
+
<div id="workshop-root"></div>
|
|
136
|
+
<script type="module" src="/@id/__x00__xplat-workshop-entry"><\/script>
|
|
137
|
+
</body>
|
|
138
|
+
</html>
|
|
139
|
+
`;
|
|
140
|
+
/**
|
|
141
|
+
* @param {object} [options]
|
|
142
|
+
* @param {string} options.cwd - consumer project root
|
|
143
|
+
* @param {object} [options.config] - resolved workshop.config.* contents
|
|
144
|
+
* @param {string} [options.target] - launch target (DOM hosts: 'web' | 'linux')
|
|
145
|
+
* @param {string} [options.story] - initial stable story id
|
|
146
|
+
*/
|
|
147
|
+
function xplatWorkshop(options = {}) {
|
|
148
|
+
const target = options.target ?? "web";
|
|
149
|
+
const story = options.story ?? null;
|
|
150
|
+
const resolution = TARGET_RESOLUTION[target] ?? TARGET_RESOLUTION.web;
|
|
151
|
+
let root = options.cwd ?? process.cwd();
|
|
152
|
+
let config = options.config ?? {};
|
|
153
|
+
return [{
|
|
154
|
+
name: "xplat-workshop-virtual",
|
|
155
|
+
configResolved(resolved) {
|
|
156
|
+
root = options.cwd ?? resolved.root;
|
|
157
|
+
},
|
|
158
|
+
resolveId(id) {
|
|
159
|
+
if (id === CATALOG_ID || id === ENTRY_ID) return id;
|
|
160
|
+
return null;
|
|
161
|
+
},
|
|
162
|
+
load(id) {
|
|
163
|
+
if (id === CATALOG_ID) return catalogCode(root, config, target);
|
|
164
|
+
if (id === ENTRY_ID) return entryCode(config, target, story, dirname(fileURLToPath(import.meta.url)), root);
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
}, {
|
|
168
|
+
name: "xplat-workshop-shell",
|
|
169
|
+
config() {
|
|
170
|
+
return {
|
|
171
|
+
optimizeDeps: {
|
|
172
|
+
exclude: ["@octane-xplat/workshop"],
|
|
173
|
+
include: ["@octane-xplat/workshop > storybook/preview-api"]
|
|
174
|
+
},
|
|
175
|
+
resolve: { conditions: [...resolution.conditions] }
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
configResolved(resolved) {
|
|
179
|
+
const apply = (scope) => {
|
|
180
|
+
scope.resolve.extensions = [...resolution.extensions, ...scope.resolve.extensions.filter((ext) => !resolution.extensions.includes(ext))];
|
|
181
|
+
scope.resolve.conditions = [...resolution.conditions, ...scope.resolve.conditions.filter((cond) => !resolution.conditions.includes(cond))];
|
|
182
|
+
};
|
|
183
|
+
apply(resolved);
|
|
184
|
+
for (const env of Object.values(resolved.environments ?? {})) apply(env);
|
|
185
|
+
},
|
|
186
|
+
hotUpdate: {
|
|
187
|
+
order: "pre",
|
|
188
|
+
handler(ctx) {
|
|
189
|
+
if (this.environment.name !== "client" || !STORY_FILE_RE.test(ctx.file)) return;
|
|
190
|
+
const catalog = this.environment.moduleGraph.getModuleById(CATALOG_ID);
|
|
191
|
+
if (!catalog) return;
|
|
192
|
+
this.environment.moduleGraph.invalidateModule(catalog);
|
|
193
|
+
return [catalog];
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
configureServer(s) {
|
|
197
|
+
s.middlewares.use((req, res, next) => {
|
|
198
|
+
const url = (req.url ?? "").split("?")[0];
|
|
199
|
+
if (url === "/" || url === "/index.html") {
|
|
200
|
+
res.statusCode = 200;
|
|
201
|
+
res.setHeader("content-type", "text/html; charset=utf-8");
|
|
202
|
+
res.end(WORKSHOP_HTML);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (url.startsWith("/@workshop-assets/")) return serveAsset(config, root, url, res, next);
|
|
206
|
+
next();
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}];
|
|
210
|
+
}
|
|
211
|
+
function serveAsset(config, root, url, res, next) {
|
|
212
|
+
const assets = config?.assets ?? {};
|
|
213
|
+
const rest = url.slice(18);
|
|
214
|
+
const name = rest.split("/")[0];
|
|
215
|
+
const dir = assets[name] ? resolve(root, assets[name]) : null;
|
|
216
|
+
if (!dir) {
|
|
217
|
+
next();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const file = resolve(dir, rest.slice(name.length + 1));
|
|
221
|
+
if (!(file === dir || file.startsWith(dir + sep)) || !existsSync(file) || !statSync(file).isFile()) {
|
|
222
|
+
res.statusCode = 404;
|
|
223
|
+
res.end("not found");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
res.statusCode = 200;
|
|
227
|
+
res.end(readFileSync(file));
|
|
228
|
+
}
|
|
229
|
+
//#endregion
|
|
230
|
+
export { xplatWorkshop };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
//#region src/build/windows/preflight.ts
|
|
6
|
+
/** Read-only Windows setup evidence. Prerequisites never qualify a host. */
|
|
7
|
+
function commandOutput(command, args) {
|
|
8
|
+
try {
|
|
9
|
+
return execFileSync(command, args, {
|
|
10
|
+
encoding: "utf8",
|
|
11
|
+
timeout: 5e3,
|
|
12
|
+
maxBuffer: 65536,
|
|
13
|
+
stdio: [
|
|
14
|
+
"ignore",
|
|
15
|
+
"pipe",
|
|
16
|
+
"pipe"
|
|
17
|
+
],
|
|
18
|
+
windowsHide: true
|
|
19
|
+
}).trim();
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function windowsPreflight(root, { platform = process.platform, run = commandOutput } = {}) {
|
|
25
|
+
const manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
26
|
+
const require = createRequire(join(root, "package.json"));
|
|
27
|
+
const installed = (name) => {
|
|
28
|
+
for (const specifier of [`${name}/package.json`, name]) try {
|
|
29
|
+
require.resolve(specifier);
|
|
30
|
+
return true;
|
|
31
|
+
} catch {}
|
|
32
|
+
return false;
|
|
33
|
+
};
|
|
34
|
+
const runtime = manifest.devDependencies?.["@nativescript/windows"] ?? manifest.dependencies?.["@nativescript/windows"];
|
|
35
|
+
const requirements = {
|
|
36
|
+
"Windows host": platform === "win32",
|
|
37
|
+
"nativescript.config": [
|
|
38
|
+
"ts",
|
|
39
|
+
"mts",
|
|
40
|
+
"js",
|
|
41
|
+
"mjs"
|
|
42
|
+
].some((ext) => existsSync(join(root, `nativescript.config.${ext}`))),
|
|
43
|
+
"App_Resources/Windows/Package.appxmanifest": existsSync(join(root, "App_Resources/Windows/Package.appxmanifest")),
|
|
44
|
+
"@nativescript/windows exact version": typeof runtime === "string" && /^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(runtime)
|
|
45
|
+
};
|
|
46
|
+
for (const name of [
|
|
47
|
+
"@nativescript/windows",
|
|
48
|
+
"@nativescript/core",
|
|
49
|
+
"@nativescript-community/octane",
|
|
50
|
+
"@nativescript/vite",
|
|
51
|
+
"nativescript",
|
|
52
|
+
"vite"
|
|
53
|
+
]) requirements[name] = installed(name);
|
|
54
|
+
if (platform === "win32") {
|
|
55
|
+
const sdk = run("dotnet", ["--version"]);
|
|
56
|
+
requirements[".NET SDK >= 10"] = typeof sdk === "string" && /^\d+\.\d+\.\d+/.test(sdk) && Number(sdk.split(".")[0]) >= 10;
|
|
57
|
+
requirements["Developer Mode (development launch)"] = run("powershell", [
|
|
58
|
+
"-NoProfile",
|
|
59
|
+
"-NonInteractive",
|
|
60
|
+
"-Command",
|
|
61
|
+
"(Get-ItemProperty \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock\" -Name AllowDevelopmentWithoutDevLicense -ErrorAction SilentlyContinue).AllowDevelopmentWithoutDevLicense"
|
|
62
|
+
])?.trim() === "1";
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
backend: "experimental nativescript/winui",
|
|
66
|
+
executionHost: {
|
|
67
|
+
required: "win32",
|
|
68
|
+
current: platform,
|
|
69
|
+
reachable: platform === "win32"
|
|
70
|
+
},
|
|
71
|
+
qualification: "unverified",
|
|
72
|
+
requirements,
|
|
73
|
+
status: platform !== "win32" ? "remote-host-required" : Object.values(requirements).every(Boolean) ? "unqualified-backend" : "missing-prerequisites",
|
|
74
|
+
note: "Windows workshop mounting, shell and reload are not implemented or host-qualified. " + (platform !== "win32" ? "Run these commands in a Windows checkout; SDK and Developer Mode checks were not run. " : "") + "Prerequisites do not prove renderer compatibility, input, accessibility or lifecycle support. No web fallback is used."
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function windowsLaunchBlocker(report) {
|
|
78
|
+
if (report.status === "remote-host-required") return "Windows workshop requires a real Windows host. Run `xplat workshop doctor` in that host’s checkout. No web fallback is used.";
|
|
79
|
+
const missing = Object.entries(report.requirements).filter(([, ok]) => !ok).map(([name]) => name);
|
|
80
|
+
return (missing.length ? `Windows prerequisites missing: ${missing.join(", ")}. ` : "") + "Windows workshop mounting, shell and reload remain unimplemented and unqualified; launch is blocked. Run `xplat workshop doctor` for setup evidence.";
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { windowsLaunchBlocker, windowsPreflight };
|
package/dist/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octane-xplat/workshop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Development-only component workshop for Octane Xplat — typed stories, metadata discovery, adaptive shell, lifecycle and warm reload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"components",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"types",
|
|
24
|
-
"dist
|
|
24
|
+
"dist",
|
|
25
25
|
"src",
|
|
26
26
|
"MOBILE.md",
|
|
27
27
|
"!src/**/*.test.*",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"exports": {
|
|
32
32
|
".": {
|
|
33
33
|
"types": "./types/generated/index.d.ts",
|
|
34
|
-
"node": "./dist/
|
|
34
|
+
"node": "./dist/index.js",
|
|
35
35
|
"default": "./src/index.ts"
|
|
36
36
|
},
|
|
37
37
|
"./web": {
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"default": "./src/web/index.web.ts"
|
|
40
40
|
},
|
|
41
41
|
"./vite": {
|
|
42
|
-
"types": "./src/vite.d.ts",
|
|
43
|
-
"default": "./
|
|
42
|
+
"types": "./src/build/vite.d.ts",
|
|
43
|
+
"default": "./dist/build/vite.js"
|
|
44
44
|
},
|
|
45
45
|
"./node": {
|
|
46
|
-
"types": "./src/node.d.ts",
|
|
47
|
-
"default": "./
|
|
46
|
+
"types": "./src/build/node.d.ts",
|
|
47
|
+
"default": "./dist/build/node.js"
|
|
48
48
|
},
|
|
49
49
|
"./package.json": "./package.json",
|
|
50
50
|
"./mobile": {
|
|
@@ -52,8 +52,8 @@
|
|
|
52
52
|
"default": "./src/mobile/index.mobile.ts"
|
|
53
53
|
},
|
|
54
54
|
"./vite-mobile": {
|
|
55
|
-
"types": "./src/vite-mobile.d.ts",
|
|
56
|
-
"default": "./
|
|
55
|
+
"types": "./src/build/vite-mobile.d.ts",
|
|
56
|
+
"default": "./dist/build/vite-mobile.js"
|
|
57
57
|
},
|
|
58
58
|
"./macos": {
|
|
59
59
|
"types": "./types/generated/macos/index.macos.d.ts",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@babel/core": "7.29.7",
|
|
68
68
|
"@babel/plugin-transform-unicode-property-regex": "7.29.7",
|
|
69
|
-
"@octane-xplat/cli": "0.
|
|
70
|
-
"@octane-xplat/platform": "0.
|
|
71
|
-
"@octane-xplat/ui": "0.
|
|
69
|
+
"@octane-xplat/cli": "0.16.1",
|
|
70
|
+
"@octane-xplat/platform": "0.16.1",
|
|
71
|
+
"@octane-xplat/ui": "0.16.1",
|
|
72
72
|
"storybook": "10.6.1",
|
|
73
73
|
"tinyglobby": "0.2.17"
|
|
74
74
|
},
|
|
@@ -77,10 +77,10 @@
|
|
|
77
77
|
"@nativescript/core": "9.1.3",
|
|
78
78
|
"@nativescript/macos-node-api": "0.4.4-next.2026-08-09-31292056208",
|
|
79
79
|
"@nativescript/types": "9.1.4",
|
|
80
|
-
"@octane-xplat/macos-renderer": "0.
|
|
80
|
+
"@octane-xplat/macos-renderer": "0.16.1",
|
|
81
81
|
"@octanejs/vite-plugin": "0.1.61",
|
|
82
82
|
"octane": "0.11.0",
|
|
83
|
-
"tsrx-typegen": "0.3.
|
|
83
|
+
"tsrx-typegen": "0.3.1",
|
|
84
84
|
"typescript": "5.9.3",
|
|
85
85
|
"vite": "8.3.0"
|
|
86
86
|
},
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
},
|
|
113
113
|
"scripts": {
|
|
114
114
|
"typegen": "tsrx-typegen --target workshop",
|
|
115
|
-
"typecheck": "node ../../scripts/typecheck.
|
|
115
|
+
"typecheck": "node ../../scripts/typecheck.ts",
|
|
116
116
|
"test": "vitest run && tsrx-tsc --noEmit -p tsconfig.test.json",
|
|
117
117
|
"test:e2e": "pnpm --filter @xplat/workshop-demo test:e2e",
|
|
118
118
|
"test:packed": "pnpm build && node tests/packed-consumer.web.mjs",
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
// @ts-nocheck — .mjs→.ts port: annotations pending (transitional)
|
|
1
2
|
import '@nativescript/macos-node-api'
|
|
2
3
|
import * as native from 'octane/universal/native'
|
|
3
4
|
import * as signals from 'octane/signals'
|
|
4
5
|
import * as signalsClient from 'octane/signals/client'
|
|
5
6
|
import * as internal from 'octane/internal/client'
|
|
6
7
|
import * as renderer from '@octane-xplat/macos-renderer'
|
|
7
|
-
import { createMacOSStageHost } from '
|
|
8
|
-
import { MacOSWorkshopController } from '
|
|
9
|
-
import { UNSET, isUnsettable } from '
|
|
8
|
+
import { createMacOSStageHost } from '../../macos/stage.macos.ts'
|
|
9
|
+
import { MacOSWorkshopController } from '../../macos/controller.ts'
|
|
10
|
+
import { UNSET, isUnsettable } from '../../controls.ts'
|
|
10
11
|
|
|
11
12
|
// The compiled story bundle requires these exact instances after each edit.
|
|
12
13
|
// Never bundle a second renderer/core runtime into the story revision.
|
|
@@ -29,19 +29,22 @@ export async function workshopMacOSDev({ root, config, story }) {
|
|
|
29
29
|
const cache = join(root, 'node_modules/.cache/xplat/workshop-macos')
|
|
30
30
|
await mkdir(cache, { recursive: true })
|
|
31
31
|
const directory = await mkdtemp(join(cache, 'session-'))
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
// Payload sources (fed to the consumer's vite as file paths) ship under
|
|
33
|
+
// src/ only — resolve through src/ whether this module runs from src/ or
|
|
34
|
+
// dist/build/.
|
|
35
|
+
const source = dirname(fileURLToPath(import.meta.url)).replace('/dist/', '/src/')
|
|
36
|
+
const catalogPlugin = join(source, 'macos-vite.ts')
|
|
37
|
+
const shell = join(source, 'macos/shell.macos.ts')
|
|
35
38
|
const bundle = join(directory, 'stories.cjs')
|
|
36
39
|
const shellBundle = join(directory, 'shell.cjs')
|
|
37
|
-
const catalogFile = join(directory, 'catalog.gen.
|
|
40
|
+
const catalogFile = join(directory, 'catalog.gen.ts')
|
|
38
41
|
const common = `import { xplatMacOS } from '@octane-xplat/cli/macos/vite'
|
|
39
42
|
import { macOSCatalogPlugin } from ${JSON.stringify(catalogPlugin)}
|
|
40
43
|
const root = ${JSON.stringify(root)}
|
|
41
44
|
`
|
|
42
45
|
|
|
43
46
|
await writeFile(
|
|
44
|
-
join(directory, 'stories.config.
|
|
47
|
+
join(directory, 'stories.config.ts'),
|
|
45
48
|
common +
|
|
46
49
|
`
|
|
47
50
|
export default async ({ mode }) => {
|
|
@@ -54,7 +57,7 @@ export default async ({ mode }) => {
|
|
|
54
57
|
)
|
|
55
58
|
|
|
56
59
|
await writeFile(
|
|
57
|
-
join(directory, 'entry.
|
|
60
|
+
join(directory, 'entry.ts'),
|
|
58
61
|
`import { startMacOSWorkshop } from ${JSON.stringify(shell)}
|
|
59
62
|
startMacOSWorkshop({ bundleFile: ${JSON.stringify(bundle)}, initialStoryId: ${JSON.stringify(story ?? null)},
|
|
60
63
|
offscreen: process.env.OCTANE_WORKSHOP_OFFSCREEN === '1' })
|
|
@@ -62,13 +65,13 @@ startMacOSWorkshop({ bundleFile: ${JSON.stringify(bundle)}, initialStoryId: ${JS
|
|
|
62
65
|
)
|
|
63
66
|
|
|
64
67
|
await writeFile(
|
|
65
|
-
join(directory, 'shell.config.
|
|
68
|
+
join(directory, 'shell.config.ts'),
|
|
66
69
|
common +
|
|
67
70
|
`
|
|
68
71
|
export default async ({ mode }) => {
|
|
69
|
-
const settings = await xplatMacOS(mode, { root, packaged: true, entry: ${JSON.stringify(join(directory, 'entry.
|
|
72
|
+
const settings = await xplatMacOS(mode, { root, packaged: true, entry: ${JSON.stringify(join(directory, 'entry.ts'))} })
|
|
70
73
|
return { ...settings, build: { ...settings.build, outDir: ${JSON.stringify(directory)}, emptyOutDir: false,
|
|
71
|
-
lib: { entry: ${JSON.stringify(join(directory, 'entry.
|
|
74
|
+
lib: { entry: ${JSON.stringify(join(directory, 'entry.ts'))}, formats: ['cjs'], fileName: () => 'shell.cjs' } } }
|
|
72
75
|
}
|
|
73
76
|
`,
|
|
74
77
|
)
|
|
@@ -82,9 +85,9 @@ export default async ({ mode }) => {
|
|
|
82
85
|
renderer: 'appkit',
|
|
83
86
|
dev: {
|
|
84
87
|
productName: 'Octane component workshop',
|
|
85
|
-
viteConfig: relative(root, join(directory, 'stories.config.
|
|
88
|
+
viteConfig: relative(root, join(directory, 'stories.config.ts')),
|
|
86
89
|
bundleFile: relative(root, bundle),
|
|
87
|
-
shellViteConfig: relative(root, join(directory, 'shell.config.
|
|
90
|
+
shellViteConfig: relative(root, join(directory, 'shell.config.ts')),
|
|
88
91
|
shellBundleFile: relative(root, shellBundle),
|
|
89
92
|
},
|
|
90
93
|
},
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
// @ts-nocheck — .mjs→.ts port: annotations pending (transitional)
|
|
1
2
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
3
|
import { resolve } from 'node:path'
|
|
3
|
-
import { discoverStories } from './discover.
|
|
4
|
+
import { discoverStories } from './discover.ts'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Regenerates the real catalog module on every (re)build. Static applicability
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — .mjs→.ts port: annotations pending (transitional)
|
|
1
2
|
import { createRequire } from 'node:module'
|
|
2
3
|
import { existsSync, readFileSync } from 'node:fs'
|
|
3
4
|
import { dirname, join, resolve } from 'node:path'
|
|
@@ -8,7 +9,7 @@ const CONFIGS = [
|
|
|
8
9
|
'vite.config.native.ts',
|
|
9
10
|
'vite.config.mts',
|
|
10
11
|
'vite.config.ts',
|
|
11
|
-
'vite.config.
|
|
12
|
+
'vite.config.ts',
|
|
12
13
|
]
|
|
13
14
|
|
|
14
15
|
export function mobilePrerequisites(root, target, host = process.platform, env = process.env) {
|
|
@@ -3,7 +3,7 @@ import unicodeProperties from '@babel/plugin-transform-unicode-property-regex'
|
|
|
3
3
|
|
|
4
4
|
// Compatibility approach shared with apps/mobile/visual-regex.mjs; no testing-host dependency.
|
|
5
5
|
/** Compile Unicode properties for the pinned iOS runtime without changing globals. */
|
|
6
|
-
export function transformMobileRegex(code, filename = 'workshop-host.
|
|
6
|
+
export function transformMobileRegex(code, filename = 'workshop-host.ts') {
|
|
7
7
|
return transformAsync(code, {
|
|
8
8
|
filename,
|
|
9
9
|
configFile: false,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — .mjs→.ts port: annotations pending (transitional)
|
|
1
2
|
/**
|
|
2
3
|
* Node backend for `xplat workshop …` — the CLI resolves this module from
|
|
3
4
|
* the consumer's installed @octane-xplat/workshop and delegates.
|
|
@@ -9,16 +10,16 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
|
9
10
|
import { dirname, join, relative, resolve } from 'node:path'
|
|
10
11
|
import { pathToFileURL } from 'node:url'
|
|
11
12
|
import { realpathSync } from 'node:fs'
|
|
12
|
-
import { discoverStories } from './discover.
|
|
13
|
-
import { windowsPreflight, windowsLaunchBlocker } from './windows/preflight.
|
|
14
|
-
import { xplatWorkshop } from './vite.
|
|
15
|
-
import { launchMobile, mobilePrerequisites } from './mobile-node.
|
|
13
|
+
import { discoverStories } from './discover.ts'
|
|
14
|
+
import { windowsPreflight, windowsLaunchBlocker } from './windows/preflight.ts'
|
|
15
|
+
import { xplatWorkshop } from './vite.ts'
|
|
16
|
+
import { launchMobile, mobilePrerequisites } from './mobile-node.ts'
|
|
16
17
|
import { xplatBoundary, xplatDevBridge, xplatNodeEnvDefine } from '@octane-xplat/cli/vite'
|
|
17
18
|
|
|
18
19
|
const CONFIG_NAMES = [
|
|
19
20
|
'workshop.config.ts',
|
|
20
21
|
'workshop.config.mts',
|
|
21
|
-
'workshop.config.
|
|
22
|
+
'workshop.config.ts',
|
|
22
23
|
'workshop.config.js',
|
|
23
24
|
]
|
|
24
25
|
|
|
@@ -409,7 +410,7 @@ export async function workshopDev({ cwd, target = 'web', story, port, device } =
|
|
|
409
410
|
const root = consumerRoot(cwd)
|
|
410
411
|
if (target === 'macos') {
|
|
411
412
|
const { config } = await loadWorkshopConfig(root)
|
|
412
|
-
const { workshopMacOSDev } = await import('./macos-node.
|
|
413
|
+
const { workshopMacOSDev } = await import('./macos-node.ts')
|
|
413
414
|
return workshopMacOSDev({ root, config, story })
|
|
414
415
|
}
|
|
415
416
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { UserConfig } from 'vite'
|
|
2
|
-
import type { WorkshopConfig } from '
|
|
2
|
+
import type { WorkshopConfig } from '../../types/generated/contract.js'
|
|
3
3
|
/** Preserves the consumer config and prepends the native workshop's pre HMR hook. */
|
|
4
4
|
export declare function withWorkshopMobile(
|
|
5
5
|
config: UserConfig,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// @ts-nocheck — .mjs→.ts port: annotations pending (transitional)
|
|
1
2
|
import { readFileSync } from 'node:fs'
|
|
2
3
|
import { resolve } from 'node:path'
|
|
3
|
-
import { mobileRegexPlugin } from './mobile-regex.
|
|
4
|
-
import { discoverStories } from './discover.
|
|
4
|
+
import { mobileRegexPlugin } from './mobile-regex.ts'
|
|
5
|
+
import { discoverStories } from './discover.ts'
|
|
5
6
|
|
|
6
7
|
export const MOBILE_CATALOG_ID = '\0xplat-workshop-mobile-catalog'
|
|
7
8
|
const fsUrl = (file) => `/@fs/${file.replaceAll('\\', '/')}`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — .mjs→.ts port: annotations pending (transitional)
|
|
1
2
|
/**
|
|
2
3
|
* xplatWorkshop — the workshop dev-server plugin.
|
|
3
4
|
*
|
|
@@ -10,7 +11,7 @@
|
|
|
10
11
|
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
11
12
|
import { dirname, join, resolve, sep } from 'node:path'
|
|
12
13
|
import { fileURLToPath } from 'node:url'
|
|
13
|
-
import { discoverStories, normalizeInclude } from './discover.
|
|
14
|
+
import { discoverStories, normalizeInclude } from './discover.ts'
|
|
14
15
|
|
|
15
16
|
const CATALOG_ID = '\0xplat-workshop-catalog'
|
|
16
17
|
const ENTRY_ID = '\0xplat-workshop-entry'
|
|
@@ -23,7 +24,7 @@ const WEB_EXTENSIONS = [
|
|
|
23
24
|
'.web.tsx',
|
|
24
25
|
'.tsx',
|
|
25
26
|
'.web.ts',
|
|
26
|
-
'.
|
|
27
|
+
'.ts',
|
|
27
28
|
'.mts',
|
|
28
29
|
'.ts',
|
|
29
30
|
'.jsx',
|
|
@@ -48,7 +49,7 @@ const TARGET_RESOLUTION = {
|
|
|
48
49
|
'.tsx',
|
|
49
50
|
'.linux.ts',
|
|
50
51
|
'.web.ts',
|
|
51
|
-
'.
|
|
52
|
+
'.ts',
|
|
52
53
|
'.mts',
|
|
53
54
|
'.ts',
|
|
54
55
|
'.jsx',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|