@scenar/cli 0.2.1 → 0.4.0
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/example-bundle/embed.js +1 -0
- package/example-bundle/pack-manifest.json +6 -0
- package/package.json +4 -8
- package/src/__tests__/embed-loader.test.ts +29 -0
- package/src/__tests__/embed-snippet.test.ts +48 -1
- package/src/__tests__/install-command.test.ts +97 -0
- package/src/__tests__/local-url.test.ts +17 -0
- package/src/__tests__/run-install.test.ts +222 -0
- package/src/api.d.ts +3 -1
- package/src/api.d.ts.map +1 -1
- package/src/api.js +3 -1
- package/src/api.js.map +1 -1
- package/src/api.ts +10 -1
- package/src/commands/install.d.ts +3 -0
- package/src/commands/install.d.ts.map +1 -0
- package/src/commands/install.js +67 -0
- package/src/commands/install.js.map +1 -0
- package/src/commands/install.ts +89 -0
- package/src/commands/pack.js +2 -2
- package/src/commands/pack.js.map +1 -1
- package/src/commands/pack.ts +2 -2
- package/src/commands/publish.d.ts.map +1 -1
- package/src/commands/publish.js +3 -1
- package/src/commands/publish.js.map +1 -1
- package/src/commands/publish.ts +5 -1
- package/src/commands/serve.d.ts.map +1 -1
- package/src/commands/serve.js +3 -2
- package/src/commands/serve.js.map +1 -1
- package/src/commands/serve.ts +5 -2
- package/src/commands/try.js +1 -1
- package/src/commands/try.ts +1 -1
- package/src/{deploy → embed}/embed-snippet.d.ts +16 -0
- package/src/embed/embed-snippet.d.ts.map +1 -0
- package/src/{deploy → embed}/embed-snippet.js +27 -0
- package/src/embed/embed-snippet.js.map +1 -0
- package/src/{deploy → embed}/embed-snippet.ts +28 -0
- package/src/index.d.ts.map +1 -1
- package/src/index.js +3 -5
- package/src/index.js.map +1 -1
- package/src/index.ts +3 -5
- package/src/install/run-install.d.ts +72 -0
- package/src/install/run-install.d.ts.map +1 -0
- package/src/install/run-install.js +378 -0
- package/src/install/run-install.js.map +1 -0
- package/src/install/run-install.ts +461 -0
- package/src/install/scaffold.d.ts +29 -0
- package/src/install/scaffold.d.ts.map +1 -0
- package/src/install/scaffold.js +233 -0
- package/src/install/scaffold.js.map +1 -0
- package/src/install/scaffold.ts +255 -0
- package/src/pack/embed-loader.d.ts +18 -0
- package/src/pack/embed-loader.d.ts.map +1 -0
- package/src/pack/embed-loader.js +25 -0
- package/src/pack/embed-loader.js.map +1 -0
- package/src/pack/embed-loader.ts +27 -0
- package/src/pack/pack-manifest.d.ts +1 -1
- package/src/pack/pack-manifest.d.ts.map +1 -1
- package/src/pack/pack-manifest.ts +1 -1
- package/src/pack/run-pack.d.ts.map +1 -1
- package/src/pack/run-pack.js +6 -0
- package/src/pack/run-pack.js.map +1 -1
- package/src/pack/run-pack.ts +7 -0
- package/src/publish/publish-flow.d.ts +3 -3
- package/src/publish/publish-flow.js +3 -3
- package/src/publish/publish-flow.ts +3 -3
- package/src/publish/run-publish.d.ts +2 -0
- package/src/publish/run-publish.d.ts.map +1 -1
- package/src/publish/run-publish.js +3 -2
- package/src/publish/run-publish.js.map +1 -1
- package/src/publish/run-publish.ts +5 -2
- package/src/render/detect-render-export.d.ts +2 -2
- package/src/render/detect-render-export.js +2 -2
- package/src/render/detect-render-export.ts +2 -2
- package/src/serve/local-url.d.ts +8 -0
- package/src/serve/local-url.d.ts.map +1 -0
- package/src/serve/local-url.js +21 -0
- package/src/serve/local-url.js.map +1 -0
- package/src/serve/local-url.ts +20 -0
- package/src/serve/run-serve.d.ts +2 -0
- package/src/serve/run-serve.d.ts.map +1 -1
- package/src/serve/run-serve.js +4 -3
- package/src/serve/run-serve.js.map +1 -1
- package/src/serve/run-serve.ts +6 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/src/__tests__/deploy-command.test.ts +0 -45
- package/src/__tests__/deploy-flow.test.ts +0 -125
- package/src/__tests__/deploy-upload.test.ts +0 -39
- package/src/commands/deploy.d.ts +0 -3
- package/src/commands/deploy.d.ts.map +0 -1
- package/src/commands/deploy.js +0 -150
- package/src/commands/deploy.js.map +0 -1
- package/src/commands/deploy.ts +0 -186
- package/src/commands/preview.d.ts +0 -3
- package/src/commands/preview.d.ts.map +0 -1
- package/src/commands/preview.js +0 -93
- package/src/commands/preview.js.map +0 -1
- package/src/commands/preview.ts +0 -138
- package/src/deploy/client.d.ts +0 -20
- package/src/deploy/client.d.ts.map +0 -1
- package/src/deploy/client.js +0 -22
- package/src/deploy/client.js.map +0 -1
- package/src/deploy/client.ts +0 -28
- package/src/deploy/deploy-flow.d.ts +0 -78
- package/src/deploy/deploy-flow.d.ts.map +0 -1
- package/src/deploy/deploy-flow.js +0 -53
- package/src/deploy/deploy-flow.js.map +0 -1
- package/src/deploy/deploy-flow.ts +0 -115
- package/src/deploy/embed-snippet.d.ts.map +0 -1
- package/src/deploy/embed-snippet.js.map +0 -1
- package/src/deploy/upload.d.ts +0 -10
- package/src/deploy/upload.d.ts.map +0 -1
- package/src/deploy/upload.js +0 -23
- package/src/deploy/upload.js.map +0 -1
- package/src/deploy/upload.ts +0 -29
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Base dependencies every Scenar demos project needs to author tours. The
|
|
5
|
+
* starter tour is built from `@scenar/react` shells, so `@scenar/react` is
|
|
6
|
+
* recorded as `"*"` (resolves to the latest published — pin it once you know
|
|
7
|
+
* the version you want). React is constrained to the major the `@scenar/*`
|
|
8
|
+
* packages target so the embed and the user's real components (added later)
|
|
9
|
+
* share a single React.
|
|
10
|
+
*/
|
|
11
|
+
export const BASE_DEPENDENCIES = {
|
|
12
|
+
"@scenar/react": "*",
|
|
13
|
+
react: "^19.0.0",
|
|
14
|
+
"react-dom": "^19.0.0",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Scaffold a fresh Scenar demos project in `dir`.
|
|
18
|
+
*
|
|
19
|
+
* Creates a minimal `package.json`, a `tsconfig.json` tuned for JSX, a
|
|
20
|
+
* `.gitignore` that ignores build output, and a runnable **starter tour** under
|
|
21
|
+
* `tours/example-tour/` (a `steps.ts` timeline, an `index.tsx` that exports
|
|
22
|
+
* `renderStep`, and a `.scenar/providers.tsx`). The starter is built from
|
|
23
|
+
* `@scenar/react` shells so `scenar pack` works immediately; the author then
|
|
24
|
+
* swaps in their real components and wires data in `providers.tsx`.
|
|
25
|
+
*
|
|
26
|
+
* Existing files are never overwritten — this only fills in what is missing, so
|
|
27
|
+
* it is safe to re-run.
|
|
28
|
+
*/
|
|
29
|
+
export function scaffoldProject(dir) {
|
|
30
|
+
const created = [];
|
|
31
|
+
writeIfMissing(dir, "package.json", renderPackageJson(path.basename(dir)), created);
|
|
32
|
+
writeIfMissing(dir, "tsconfig.json", TSCONFIG, created);
|
|
33
|
+
writeIfMissing(dir, ".gitignore", GITIGNORE, created);
|
|
34
|
+
writeIfMissing(dir, path.join(TOUR_DIR, "steps.ts"), TOUR_STEPS, created);
|
|
35
|
+
writeIfMissing(dir, path.join(TOUR_DIR, "index.tsx"), TOUR_INDEX, created);
|
|
36
|
+
writeIfMissing(dir, path.join(TOUR_DIR, ".scenar", "providers.tsx"), TOUR_PROVIDERS, created);
|
|
37
|
+
return { created };
|
|
38
|
+
}
|
|
39
|
+
function writeIfMissing(dir, relPath, content, created) {
|
|
40
|
+
const target = path.join(dir, relPath);
|
|
41
|
+
if (fs.existsSync(target))
|
|
42
|
+
return;
|
|
43
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
44
|
+
fs.writeFileSync(target, content, "utf-8");
|
|
45
|
+
created.push(relPath);
|
|
46
|
+
}
|
|
47
|
+
function renderPackageJson(name) {
|
|
48
|
+
const pkg = {
|
|
49
|
+
name: toPackageName(name),
|
|
50
|
+
version: "0.0.0",
|
|
51
|
+
private: true,
|
|
52
|
+
type: "module",
|
|
53
|
+
scripts: {
|
|
54
|
+
pack: `scenar pack ${TOUR_DIR}`,
|
|
55
|
+
},
|
|
56
|
+
dependencies: { ...BASE_DEPENDENCIES },
|
|
57
|
+
};
|
|
58
|
+
return JSON.stringify(pkg, null, 2) + "\n";
|
|
59
|
+
}
|
|
60
|
+
/** Coerce a directory name into a valid npm package name. */
|
|
61
|
+
function toPackageName(dirName) {
|
|
62
|
+
const slug = dirName
|
|
63
|
+
.trim()
|
|
64
|
+
.toLowerCase()
|
|
65
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
66
|
+
.replace(/^-+|-+$/g, "");
|
|
67
|
+
return slug.length > 0 ? slug : "scenar-demos";
|
|
68
|
+
}
|
|
69
|
+
/** Where the starter tour is scaffolded (also the default `pack` target). */
|
|
70
|
+
const TOUR_DIR = "tours/example-tour";
|
|
71
|
+
const TSCONFIG = `{
|
|
72
|
+
"compilerOptions": {
|
|
73
|
+
"target": "ES2022",
|
|
74
|
+
"module": "ESNext",
|
|
75
|
+
"moduleResolution": "Bundler",
|
|
76
|
+
"jsx": "react-jsx",
|
|
77
|
+
"strict": true,
|
|
78
|
+
"skipLibCheck": true,
|
|
79
|
+
"esModuleInterop": true,
|
|
80
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"]
|
|
81
|
+
},
|
|
82
|
+
"include": ["tours"]
|
|
83
|
+
}
|
|
84
|
+
`;
|
|
85
|
+
const GITIGNORE = `node_modules/
|
|
86
|
+
|
|
87
|
+
# Packed embeds — regenerate with \`scenar pack\`
|
|
88
|
+
*-bundle/
|
|
89
|
+
`;
|
|
90
|
+
const TOUR_STEPS = `import type { ScenarioStep } from "@scenar/core";
|
|
91
|
+
|
|
92
|
+
/** The screen shown at a given step (maps to a view in index.tsx). */
|
|
93
|
+
export type ExampleScreen = "login" | "dashboard";
|
|
94
|
+
|
|
95
|
+
/** Data snapshot for one step of the tour. */
|
|
96
|
+
export interface ExampleStepData {
|
|
97
|
+
/** Address-bar URL shown in the browser chrome (no scheme). */
|
|
98
|
+
readonly url: string;
|
|
99
|
+
/** Which screen is shown at this step. */
|
|
100
|
+
readonly screen: ExampleScreen;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* The tour timeline. \`delayMs\` is the dwell before each step (the first is
|
|
105
|
+
* shown immediately); \`caption\` renders under the player; \`narration\` is the
|
|
106
|
+
* spoken script synthesized by \`scenar narrate\`.
|
|
107
|
+
*/
|
|
108
|
+
export const steps: ScenarioStep<ExampleStepData>[] = [
|
|
109
|
+
{
|
|
110
|
+
delayMs: 0,
|
|
111
|
+
caption: "Sign in",
|
|
112
|
+
narration: "Sign in to your workspace.",
|
|
113
|
+
data: { url: "app.example.com/login", screen: "login" },
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
delayMs: 2400,
|
|
117
|
+
caption: "Your dashboard",
|
|
118
|
+
narration: "And you land on your dashboard.",
|
|
119
|
+
data: { url: "app.example.com/home", screen: "dashboard" },
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
`;
|
|
123
|
+
const TOUR_INDEX = `import type { ReactNode } from "react";
|
|
124
|
+
import {
|
|
125
|
+
BrowserView,
|
|
126
|
+
DashboardPage,
|
|
127
|
+
LoginCardPage,
|
|
128
|
+
type SideNavItem,
|
|
129
|
+
} from "@scenar/react";
|
|
130
|
+
import type { ExampleStepData } from "./steps";
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* renderStep: a pure (data, stepIndex) -> ReactNode. Both \`scenar pack\` (embed)
|
|
134
|
+
* and \`scenar render\` (video) consume this contract.
|
|
135
|
+
*
|
|
136
|
+
* This starter draws CSS-only @scenar/react shells so it packs with no extra
|
|
137
|
+
* setup. To show your REAL product UI, install your components
|
|
138
|
+
* (\`scenar install <your-pkg>\`), import and render them here, and wire any data
|
|
139
|
+
* they fetch in .scenar/providers.tsx.
|
|
140
|
+
*/
|
|
141
|
+
export function renderStep(data: ExampleStepData, stepIndex: number): ReactNode {
|
|
142
|
+
return (
|
|
143
|
+
<BrowserView url={"https://" + data.url} contentKey={String(stepIndex)}>
|
|
144
|
+
{data.screen === "login" ? <LoginScreen /> : <DashboardScreen />}
|
|
145
|
+
</BrowserView>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function LoginScreen(): ReactNode {
|
|
150
|
+
return (
|
|
151
|
+
<LoginCardPage
|
|
152
|
+
appName="Example"
|
|
153
|
+
subtitle="Sign in to your workspace"
|
|
154
|
+
fields={[
|
|
155
|
+
{ label: "Email", value: "you@example.com", type: "email" },
|
|
156
|
+
{ label: "Password", type: "password" },
|
|
157
|
+
]}
|
|
158
|
+
submitLabel="Sign in"
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const SIDEBAR: SideNavItem[] = [
|
|
164
|
+
{ label: "Workspace", isSection: true },
|
|
165
|
+
{ label: "Overview", active: true },
|
|
166
|
+
{ label: "Projects" },
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
function DashboardScreen(): ReactNode {
|
|
170
|
+
return (
|
|
171
|
+
<DashboardPage
|
|
172
|
+
appName="Example"
|
|
173
|
+
userName="You"
|
|
174
|
+
navLinks={[{ label: "Home", active: true }]}
|
|
175
|
+
sidebarItems={SIDEBAR}
|
|
176
|
+
>
|
|
177
|
+
<div style={{ padding: 20 }}>
|
|
178
|
+
<h2
|
|
179
|
+
style={{
|
|
180
|
+
margin: 0,
|
|
181
|
+
fontSize: 15,
|
|
182
|
+
fontWeight: 600,
|
|
183
|
+
color: "var(--scenar-foreground)",
|
|
184
|
+
}}
|
|
185
|
+
>
|
|
186
|
+
Welcome back
|
|
187
|
+
</h2>
|
|
188
|
+
</div>
|
|
189
|
+
</DashboardPage>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
`;
|
|
193
|
+
const TOUR_PROVIDERS = `/**
|
|
194
|
+
* .scenar/providers.tsx — wraps every step of THIS tour in \`scenar pack\` (embed)
|
|
195
|
+
* and \`scenar render\` (video).
|
|
196
|
+
*
|
|
197
|
+
* You only need this when your tour renders real, data-fetching components that
|
|
198
|
+
* need a client/provider to render in isolation (no backend). A tour built only
|
|
199
|
+
* from @scenar/react shells (like the starter) can leave this as a pass-through
|
|
200
|
+
* or delete it.
|
|
201
|
+
*
|
|
202
|
+
* Recommended pattern for Connect-RPC SDKs (e.g. @stigmer/react): mock data with
|
|
203
|
+
* an in-process router transport — no network, no service worker — and resolve
|
|
204
|
+
* the embed's light/dark mode from \`getEmbedColorMode()\`. Fill in your client,
|
|
205
|
+
* provider, and fixtures, then return the provider instead of the fragment:
|
|
206
|
+
*
|
|
207
|
+
* import "@your-org/react/styles.css";
|
|
208
|
+
* import { createRouterTransport } from "@connectrpc/connect";
|
|
209
|
+
* import { getEmbedColorMode } from "@scenar/react";
|
|
210
|
+
* import { YourClient } from "@your-org/sdk";
|
|
211
|
+
* import { YourProvider } from "@your-org/react";
|
|
212
|
+
* import { YourController } from "@your-org/protos/...";
|
|
213
|
+
*
|
|
214
|
+
* const transport = createRouterTransport((router) => {
|
|
215
|
+
* router.service(YourController, { get: () => yourFixtureObject });
|
|
216
|
+
* });
|
|
217
|
+
* const client = new YourClient({ baseUrl: "/", customTransport: transport });
|
|
218
|
+
*
|
|
219
|
+
* export function PreviewProviders({ children }: { readonly children: ReactNode }) {
|
|
220
|
+
* return (
|
|
221
|
+
* <YourProvider client={client} colorMode={getEmbedColorMode()}>
|
|
222
|
+
* {children}
|
|
223
|
+
* </YourProvider>
|
|
224
|
+
* );
|
|
225
|
+
* }
|
|
226
|
+
*/
|
|
227
|
+
import type { ReactNode } from "react";
|
|
228
|
+
|
|
229
|
+
export function PreviewProviders({ children }: { readonly children: ReactNode }) {
|
|
230
|
+
return <>{children}</>;
|
|
231
|
+
}
|
|
232
|
+
`;
|
|
233
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/install/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Base dependencies every Scenar demos project needs to author tours. The
|
|
6
|
+
* starter tour is built from `@scenar/react` shells, so `@scenar/react` is
|
|
7
|
+
* recorded as `"*"` (resolves to the latest published — pin it once you know
|
|
8
|
+
* the version you want). React is constrained to the major the `@scenar/*`
|
|
9
|
+
* packages target so the embed and the user's real components (added later)
|
|
10
|
+
* share a single React.
|
|
11
|
+
*/
|
|
12
|
+
export const BASE_DEPENDENCIES: Readonly<Record<string, string>> = {
|
|
13
|
+
"@scenar/react": "*",
|
|
14
|
+
react: "^19.0.0",
|
|
15
|
+
"react-dom": "^19.0.0",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/** Result of scaffolding a fresh demos project. */
|
|
19
|
+
export interface ScaffoldResult {
|
|
20
|
+
/** Files created, relative to the project directory. */
|
|
21
|
+
readonly created: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Scaffold a fresh Scenar demos project in `dir`.
|
|
26
|
+
*
|
|
27
|
+
* Creates a minimal `package.json`, a `tsconfig.json` tuned for JSX, a
|
|
28
|
+
* `.gitignore` that ignores build output, and a runnable **starter tour** under
|
|
29
|
+
* `tours/example-tour/` (a `steps.ts` timeline, an `index.tsx` that exports
|
|
30
|
+
* `renderStep`, and a `.scenar/providers.tsx`). The starter is built from
|
|
31
|
+
* `@scenar/react` shells so `scenar pack` works immediately; the author then
|
|
32
|
+
* swaps in their real components and wires data in `providers.tsx`.
|
|
33
|
+
*
|
|
34
|
+
* Existing files are never overwritten — this only fills in what is missing, so
|
|
35
|
+
* it is safe to re-run.
|
|
36
|
+
*/
|
|
37
|
+
export function scaffoldProject(dir: string): ScaffoldResult {
|
|
38
|
+
const created: string[] = [];
|
|
39
|
+
|
|
40
|
+
writeIfMissing(dir, "package.json", renderPackageJson(path.basename(dir)), created);
|
|
41
|
+
writeIfMissing(dir, "tsconfig.json", TSCONFIG, created);
|
|
42
|
+
writeIfMissing(dir, ".gitignore", GITIGNORE, created);
|
|
43
|
+
writeIfMissing(dir, path.join(TOUR_DIR, "steps.ts"), TOUR_STEPS, created);
|
|
44
|
+
writeIfMissing(dir, path.join(TOUR_DIR, "index.tsx"), TOUR_INDEX, created);
|
|
45
|
+
writeIfMissing(dir, path.join(TOUR_DIR, ".scenar", "providers.tsx"), TOUR_PROVIDERS, created);
|
|
46
|
+
|
|
47
|
+
return { created };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function writeIfMissing(
|
|
51
|
+
dir: string,
|
|
52
|
+
relPath: string,
|
|
53
|
+
content: string,
|
|
54
|
+
created: string[],
|
|
55
|
+
): void {
|
|
56
|
+
const target = path.join(dir, relPath);
|
|
57
|
+
if (fs.existsSync(target)) return;
|
|
58
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
59
|
+
fs.writeFileSync(target, content, "utf-8");
|
|
60
|
+
created.push(relPath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function renderPackageJson(name: string): string {
|
|
64
|
+
const pkg = {
|
|
65
|
+
name: toPackageName(name),
|
|
66
|
+
version: "0.0.0",
|
|
67
|
+
private: true,
|
|
68
|
+
type: "module",
|
|
69
|
+
scripts: {
|
|
70
|
+
pack: `scenar pack ${TOUR_DIR}`,
|
|
71
|
+
},
|
|
72
|
+
dependencies: { ...BASE_DEPENDENCIES },
|
|
73
|
+
};
|
|
74
|
+
return JSON.stringify(pkg, null, 2) + "\n";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Coerce a directory name into a valid npm package name. */
|
|
78
|
+
function toPackageName(dirName: string): string {
|
|
79
|
+
const slug = dirName
|
|
80
|
+
.trim()
|
|
81
|
+
.toLowerCase()
|
|
82
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
83
|
+
.replace(/^-+|-+$/g, "");
|
|
84
|
+
return slug.length > 0 ? slug : "scenar-demos";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Where the starter tour is scaffolded (also the default `pack` target). */
|
|
88
|
+
const TOUR_DIR = "tours/example-tour";
|
|
89
|
+
|
|
90
|
+
const TSCONFIG = `{
|
|
91
|
+
"compilerOptions": {
|
|
92
|
+
"target": "ES2022",
|
|
93
|
+
"module": "ESNext",
|
|
94
|
+
"moduleResolution": "Bundler",
|
|
95
|
+
"jsx": "react-jsx",
|
|
96
|
+
"strict": true,
|
|
97
|
+
"skipLibCheck": true,
|
|
98
|
+
"esModuleInterop": true,
|
|
99
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"]
|
|
100
|
+
},
|
|
101
|
+
"include": ["tours"]
|
|
102
|
+
}
|
|
103
|
+
`;
|
|
104
|
+
|
|
105
|
+
const GITIGNORE = `node_modules/
|
|
106
|
+
|
|
107
|
+
# Packed embeds — regenerate with \`scenar pack\`
|
|
108
|
+
*-bundle/
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
const TOUR_STEPS = `import type { ScenarioStep } from "@scenar/core";
|
|
112
|
+
|
|
113
|
+
/** The screen shown at a given step (maps to a view in index.tsx). */
|
|
114
|
+
export type ExampleScreen = "login" | "dashboard";
|
|
115
|
+
|
|
116
|
+
/** Data snapshot for one step of the tour. */
|
|
117
|
+
export interface ExampleStepData {
|
|
118
|
+
/** Address-bar URL shown in the browser chrome (no scheme). */
|
|
119
|
+
readonly url: string;
|
|
120
|
+
/** Which screen is shown at this step. */
|
|
121
|
+
readonly screen: ExampleScreen;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* The tour timeline. \`delayMs\` is the dwell before each step (the first is
|
|
126
|
+
* shown immediately); \`caption\` renders under the player; \`narration\` is the
|
|
127
|
+
* spoken script synthesized by \`scenar narrate\`.
|
|
128
|
+
*/
|
|
129
|
+
export const steps: ScenarioStep<ExampleStepData>[] = [
|
|
130
|
+
{
|
|
131
|
+
delayMs: 0,
|
|
132
|
+
caption: "Sign in",
|
|
133
|
+
narration: "Sign in to your workspace.",
|
|
134
|
+
data: { url: "app.example.com/login", screen: "login" },
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
delayMs: 2400,
|
|
138
|
+
caption: "Your dashboard",
|
|
139
|
+
narration: "And you land on your dashboard.",
|
|
140
|
+
data: { url: "app.example.com/home", screen: "dashboard" },
|
|
141
|
+
},
|
|
142
|
+
];
|
|
143
|
+
`;
|
|
144
|
+
|
|
145
|
+
const TOUR_INDEX = `import type { ReactNode } from "react";
|
|
146
|
+
import {
|
|
147
|
+
BrowserView,
|
|
148
|
+
DashboardPage,
|
|
149
|
+
LoginCardPage,
|
|
150
|
+
type SideNavItem,
|
|
151
|
+
} from "@scenar/react";
|
|
152
|
+
import type { ExampleStepData } from "./steps";
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* renderStep: a pure (data, stepIndex) -> ReactNode. Both \`scenar pack\` (embed)
|
|
156
|
+
* and \`scenar render\` (video) consume this contract.
|
|
157
|
+
*
|
|
158
|
+
* This starter draws CSS-only @scenar/react shells so it packs with no extra
|
|
159
|
+
* setup. To show your REAL product UI, install your components
|
|
160
|
+
* (\`scenar install <your-pkg>\`), import and render them here, and wire any data
|
|
161
|
+
* they fetch in .scenar/providers.tsx.
|
|
162
|
+
*/
|
|
163
|
+
export function renderStep(data: ExampleStepData, stepIndex: number): ReactNode {
|
|
164
|
+
return (
|
|
165
|
+
<BrowserView url={"https://" + data.url} contentKey={String(stepIndex)}>
|
|
166
|
+
{data.screen === "login" ? <LoginScreen /> : <DashboardScreen />}
|
|
167
|
+
</BrowserView>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function LoginScreen(): ReactNode {
|
|
172
|
+
return (
|
|
173
|
+
<LoginCardPage
|
|
174
|
+
appName="Example"
|
|
175
|
+
subtitle="Sign in to your workspace"
|
|
176
|
+
fields={[
|
|
177
|
+
{ label: "Email", value: "you@example.com", type: "email" },
|
|
178
|
+
{ label: "Password", type: "password" },
|
|
179
|
+
]}
|
|
180
|
+
submitLabel="Sign in"
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const SIDEBAR: SideNavItem[] = [
|
|
186
|
+
{ label: "Workspace", isSection: true },
|
|
187
|
+
{ label: "Overview", active: true },
|
|
188
|
+
{ label: "Projects" },
|
|
189
|
+
];
|
|
190
|
+
|
|
191
|
+
function DashboardScreen(): ReactNode {
|
|
192
|
+
return (
|
|
193
|
+
<DashboardPage
|
|
194
|
+
appName="Example"
|
|
195
|
+
userName="You"
|
|
196
|
+
navLinks={[{ label: "Home", active: true }]}
|
|
197
|
+
sidebarItems={SIDEBAR}
|
|
198
|
+
>
|
|
199
|
+
<div style={{ padding: 20 }}>
|
|
200
|
+
<h2
|
|
201
|
+
style={{
|
|
202
|
+
margin: 0,
|
|
203
|
+
fontSize: 15,
|
|
204
|
+
fontWeight: 600,
|
|
205
|
+
color: "var(--scenar-foreground)",
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
Welcome back
|
|
209
|
+
</h2>
|
|
210
|
+
</div>
|
|
211
|
+
</DashboardPage>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
const TOUR_PROVIDERS = `/**
|
|
217
|
+
* .scenar/providers.tsx — wraps every step of THIS tour in \`scenar pack\` (embed)
|
|
218
|
+
* and \`scenar render\` (video).
|
|
219
|
+
*
|
|
220
|
+
* You only need this when your tour renders real, data-fetching components that
|
|
221
|
+
* need a client/provider to render in isolation (no backend). A tour built only
|
|
222
|
+
* from @scenar/react shells (like the starter) can leave this as a pass-through
|
|
223
|
+
* or delete it.
|
|
224
|
+
*
|
|
225
|
+
* Recommended pattern for Connect-RPC SDKs (e.g. @stigmer/react): mock data with
|
|
226
|
+
* an in-process router transport — no network, no service worker — and resolve
|
|
227
|
+
* the embed's light/dark mode from \`getEmbedColorMode()\`. Fill in your client,
|
|
228
|
+
* provider, and fixtures, then return the provider instead of the fragment:
|
|
229
|
+
*
|
|
230
|
+
* import "@your-org/react/styles.css";
|
|
231
|
+
* import { createRouterTransport } from "@connectrpc/connect";
|
|
232
|
+
* import { getEmbedColorMode } from "@scenar/react";
|
|
233
|
+
* import { YourClient } from "@your-org/sdk";
|
|
234
|
+
* import { YourProvider } from "@your-org/react";
|
|
235
|
+
* import { YourController } from "@your-org/protos/...";
|
|
236
|
+
*
|
|
237
|
+
* const transport = createRouterTransport((router) => {
|
|
238
|
+
* router.service(YourController, { get: () => yourFixtureObject });
|
|
239
|
+
* });
|
|
240
|
+
* const client = new YourClient({ baseUrl: "/", customTransport: transport });
|
|
241
|
+
*
|
|
242
|
+
* export function PreviewProviders({ children }: { readonly children: ReactNode }) {
|
|
243
|
+
* return (
|
|
244
|
+
* <YourProvider client={client} colorMode={getEmbedColorMode()}>
|
|
245
|
+
* {children}
|
|
246
|
+
* </YourProvider>
|
|
247
|
+
* );
|
|
248
|
+
* }
|
|
249
|
+
*/
|
|
250
|
+
import type { ReactNode } from "react";
|
|
251
|
+
|
|
252
|
+
export function PreviewProviders({ children }: { readonly children: ReactNode }) {
|
|
253
|
+
return <>{children}</>;
|
|
254
|
+
}
|
|
255
|
+
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The loader artifact's name inside the bundle — a sibling of `index.html`. The
|
|
3
|
+
* enhanced `<scenar-embed>` snippet references it as `embed.js` relative to the
|
|
4
|
+
* embed URL, so `serve`/`publish` carry it automatically with no change to the
|
|
5
|
+
* publish-flow bundle contract.
|
|
6
|
+
*/
|
|
7
|
+
export declare const EMBED_LOADER_FILE = "embed.js";
|
|
8
|
+
/**
|
|
9
|
+
* Copy `@scenar/embed`'s prebuilt loader (its `./loader` export → the IIFE
|
|
10
|
+
* `embed.global.js`) into the bundle as {@link EMBED_LOADER_FILE}.
|
|
11
|
+
*
|
|
12
|
+
* The artifact is resolved through the package export rather than a hard-coded
|
|
13
|
+
* path, so it works the same in the workspace (symlinked) and in a published
|
|
14
|
+
* install. `@scenar/cli` depends on `@scenar/embed`, so it is always present and
|
|
15
|
+
* built before the CLI (and thus before `pack` runs).
|
|
16
|
+
*/
|
|
17
|
+
export declare function copyEmbedLoader(outDir: string): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=embed-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-loader.d.ts","sourceRoot":"","sources":["../../../src/pack/embed-loader.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAI5C;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { copyFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/**
|
|
5
|
+
* The loader artifact's name inside the bundle — a sibling of `index.html`. The
|
|
6
|
+
* enhanced `<scenar-embed>` snippet references it as `embed.js` relative to the
|
|
7
|
+
* embed URL, so `serve`/`publish` carry it automatically with no change to the
|
|
8
|
+
* publish-flow bundle contract.
|
|
9
|
+
*/
|
|
10
|
+
export const EMBED_LOADER_FILE = "embed.js";
|
|
11
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
12
|
+
/**
|
|
13
|
+
* Copy `@scenar/embed`'s prebuilt loader (its `./loader` export → the IIFE
|
|
14
|
+
* `embed.global.js`) into the bundle as {@link EMBED_LOADER_FILE}.
|
|
15
|
+
*
|
|
16
|
+
* The artifact is resolved through the package export rather than a hard-coded
|
|
17
|
+
* path, so it works the same in the workspace (symlinked) and in a published
|
|
18
|
+
* install. `@scenar/cli` depends on `@scenar/embed`, so it is always present and
|
|
19
|
+
* built before the CLI (and thus before `pack` runs).
|
|
20
|
+
*/
|
|
21
|
+
export async function copyEmbedLoader(outDir) {
|
|
22
|
+
const loaderPath = requireFromHere.resolve("@scenar/embed/loader");
|
|
23
|
+
await copyFile(loaderPath, join(outDir, EMBED_LOADER_FILE));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=embed-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-loader.js","sourceRoot":"","sources":["../../../src/pack/embed-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc;IAClD,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACnE,MAAM,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { copyFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The loader artifact's name inside the bundle — a sibling of `index.html`. The
|
|
7
|
+
* enhanced `<scenar-embed>` snippet references it as `embed.js` relative to the
|
|
8
|
+
* embed URL, so `serve`/`publish` carry it automatically with no change to the
|
|
9
|
+
* publish-flow bundle contract.
|
|
10
|
+
*/
|
|
11
|
+
export const EMBED_LOADER_FILE = "embed.js";
|
|
12
|
+
|
|
13
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Copy `@scenar/embed`'s prebuilt loader (its `./loader` export → the IIFE
|
|
17
|
+
* `embed.global.js`) into the bundle as {@link EMBED_LOADER_FILE}.
|
|
18
|
+
*
|
|
19
|
+
* The artifact is resolved through the package export rather than a hard-coded
|
|
20
|
+
* path, so it works the same in the workspace (symlinked) and in a published
|
|
21
|
+
* install. `@scenar/cli` depends on `@scenar/embed`, so it is always present and
|
|
22
|
+
* built before the CLI (and thus before `pack` runs).
|
|
23
|
+
*/
|
|
24
|
+
export async function copyEmbedLoader(outDir: string): Promise<void> {
|
|
25
|
+
const loaderPath = requireFromHere.resolve("@scenar/embed/loader");
|
|
26
|
+
await copyFile(loaderPath, join(outDir, EMBED_LOADER_FILE));
|
|
27
|
+
}
|
|
@@ -10,7 +10,7 @@ export interface PackFile {
|
|
|
10
10
|
/** Content type the server binds into the presign and the edge serves. */
|
|
11
11
|
readonly contentType: string;
|
|
12
12
|
}
|
|
13
|
-
/** The deploy instruction file
|
|
13
|
+
/** The deploy instruction file the upload backend consumes. */
|
|
14
14
|
export interface PackManifest {
|
|
15
15
|
readonly schemaVersion: number;
|
|
16
16
|
readonly scenarioId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack-manifest.d.ts","sourceRoot":"","sources":["../../../src/pack/pack-manifest.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,WAAW,QAAQ;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED
|
|
1
|
+
{"version":3,"file":"pack-manifest.d.ts","sourceRoot":"","sources":["../../../src/pack/pack-manifest.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,WAAW,QAAQ;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yBAAyB;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC;CAC5B;AAED,kFAAkF;AAClF,eAAO,MAAM,kBAAkB,uBAAuB,CAAC;AAEvD,mEAAmE;AACnE,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA+BjG;AAED,mDAAmD;AACnD,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAM7F;AAiBD,oFAAoF;AACpF,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAQpG"}
|
|
@@ -21,7 +21,7 @@ export interface PackFile {
|
|
|
21
21
|
readonly contentType: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/** The deploy instruction file
|
|
24
|
+
/** The deploy instruction file the upload backend consumes. */
|
|
25
25
|
export interface PackManifest {
|
|
26
26
|
readonly schemaVersion: number;
|
|
27
27
|
readonly scenarioId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-pack.d.ts","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-pack.d.ts","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAM5B,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,wCAAwC;AACxC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAyF1E"}
|
package/src/pack/run-pack.js
CHANGED
|
@@ -4,6 +4,7 @@ import { detectRenderExport } from "../render/detect-render-export.js";
|
|
|
4
4
|
import { resolveProvidersPath } from "../render/resolve-providers.js";
|
|
5
5
|
import { generateEmbedEntry, generateEmbedHtml } from "./generate-embed-entry.js";
|
|
6
6
|
import { runViteBuild } from "./build.js";
|
|
7
|
+
import { copyEmbedLoader } from "./embed-loader.js";
|
|
7
8
|
import { buildPackManifest, writePackManifest, writeScenarioJson, verifyManifestFilesExist, } from "./pack-manifest.js";
|
|
8
9
|
import { DEFAULT_VIEWPORT } from "./viewport.js";
|
|
9
10
|
/** Generator version stamped into scenario.json (kept in sync with the CLI). */
|
|
@@ -72,6 +73,11 @@ export async function runPack(options) {
|
|
|
72
73
|
width,
|
|
73
74
|
height: shellHeight,
|
|
74
75
|
});
|
|
76
|
+
// 4b. Copy the optional <scenar-embed> loader into the bundle as embed.js
|
|
77
|
+
// (sibling of index.html), so the enhanced snippet works on any static
|
|
78
|
+
// host (GitHub Pages, `serve`, the edge) with no extra setup. It lands
|
|
79
|
+
// before the manifest pass below so it ships as a first-class bundle file.
|
|
80
|
+
await copyEmbedLoader(outDir);
|
|
75
81
|
// 5. Compute + write the deploy-facing pack manifest (validates the bundle
|
|
76
82
|
// against the backend allowlist; throws on any violation).
|
|
77
83
|
const manifest = await buildPackManifest(outDir, scenarioId);
|
package/src/pack/run-pack.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-pack.js","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-pack.js","sourceRoot":"","sources":["../../../src/pack/run-pack.ts"],"names":[],"mappings":"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"}
|