@openelement/create 0.41.0-alpha.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/LICENSE +21 -0
- package/README.md +33 -0
- package/cli.d.ts +0 -0
- package/cli.js +397 -0
- package/package.json +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zhi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @openelement/create
|
|
2
|
+
|
|
3
|
+
Project scaffolding CLI for openElement applications.
|
|
4
|
+
|
|
5
|
+
> v0.39 surface: Framework product entry. This package is part of the
|
|
6
|
+
> first-run Framework story alongside `@openelement/app` and
|
|
7
|
+
> `@openelement/app/vite`.
|
|
8
|
+
|
|
9
|
+
`@openelement/create` generates a new openElement project with the recommended
|
|
10
|
+
directory structure, Deno configuration, Vite setup, and starter pages.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
deno run -A npm:@openelement/create my-app
|
|
16
|
+
cd my-app
|
|
17
|
+
deno task dev
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What It Creates
|
|
21
|
+
|
|
22
|
+
- `deno.json` - starter authoring imports and build tasks
|
|
23
|
+
- `vite.config.ts` - Vite build configuration with the openElement plugin
|
|
24
|
+
- `app/` - application directory with starter pages and islands
|
|
25
|
+
- `www/` - website output directory
|
|
26
|
+
|
|
27
|
+
The generated import map intentionally keeps protocol and build internals out of
|
|
28
|
+
the starter surface. Advanced contracts remain available through the published
|
|
29
|
+
workspace packages when a project needs them.
|
|
30
|
+
|
|
31
|
+
## License
|
|
32
|
+
|
|
33
|
+
MIT
|
package/cli.d.ts
ADDED
|
File without changes
|
package/cli.js
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
import { Deno } from "@deno/shim-deno";
|
|
2
|
+
/**
|
|
3
|
+
* @openelement/create - Minimal project scaffold for openElement framework.
|
|
4
|
+
*
|
|
5
|
+
* Usage: deno run -A npm:@openelement/create my-app
|
|
6
|
+
*
|
|
7
|
+
* openElement Architecture: Keep It Simple, Stupid.
|
|
8
|
+
* One template, zero prompts, instant start.
|
|
9
|
+
*/ import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { createLogger } from '@openelement/core/logger';
|
|
12
|
+
// ??? Package versions ??????????????????????????????????????????
|
|
13
|
+
// ADR 0016: Handle both local (workspace file://) and remote (npm registry) execution.
|
|
14
|
+
//
|
|
15
|
+
// - Local: read version from workspace deno.json (single source of truth)
|
|
16
|
+
// - Remote: query npm Registry API for latest version (zero hardcoding)
|
|
17
|
+
const NPM_SCOPE = '@openelement';
|
|
18
|
+
const log = createLogger('create');
|
|
19
|
+
const PKG_DIR_MAP = {
|
|
20
|
+
core: 'core',
|
|
21
|
+
adapterVite: 'adapter-vite',
|
|
22
|
+
app: 'app',
|
|
23
|
+
content: 'content',
|
|
24
|
+
ui: 'ui',
|
|
25
|
+
signal: 'signal',
|
|
26
|
+
element: 'element'
|
|
27
|
+
};
|
|
28
|
+
function loadWorkspaceVersion(pkg) {
|
|
29
|
+
const metaUrl = import.meta.url;
|
|
30
|
+
const selfPath = fileURLToPath(new URL('.', metaUrl));
|
|
31
|
+
const dir = PKG_DIR_MAP[pkg] || pkg;
|
|
32
|
+
const wsPath = resolve(selfPath, '..', '..', 'packages', dir, 'deno.json');
|
|
33
|
+
try {
|
|
34
|
+
const version = JSON.parse(Deno.readTextFileSync(wsPath)).version;
|
|
35
|
+
if (!version) throw new Error(`No version found in ${wsPath}`);
|
|
36
|
+
return version;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
throw new Error(`Failed to read version for @openelement/${dir} from ${wsPath}. ` + `Run this script from the openElement workspace or ensure deno.json is accessible.\n` + `Original error: ${e}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Detect whether cli.ts is being run from the openElement workspace. */ function isWorkspace() {
|
|
42
|
+
try {
|
|
43
|
+
const selfPath = fileURLToPath(new URL('.', import.meta.url));
|
|
44
|
+
Deno.readTextFileSync(resolve(selfPath, '..', '..', 'packages', 'core', 'deno.json'));
|
|
45
|
+
return true;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Fetch the latest version of an npm package from the Registry API. */ async function fetchNpmVersion(pkg) {
|
|
51
|
+
const resp = await fetch(`https://registry.npmjs.org/${NPM_SCOPE}/${pkg}`, {
|
|
52
|
+
headers: {
|
|
53
|
+
Accept: 'application/json'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (!resp.ok) {
|
|
57
|
+
throw new Error(`Failed to fetch version for ${NPM_SCOPE}/${pkg} from npm registry (HTTP ${resp.status})`);
|
|
58
|
+
}
|
|
59
|
+
const meta = await resp.json();
|
|
60
|
+
// npm registry response has dist-tags.latest
|
|
61
|
+
const version = meta?.['dist-tags']?.latest;
|
|
62
|
+
if (!version) {
|
|
63
|
+
throw new Error(`No version found for ${NPM_SCOPE}/${pkg} in npm registry response`);
|
|
64
|
+
}
|
|
65
|
+
return version;
|
|
66
|
+
}
|
|
67
|
+
/** Resolve all package versions: local from workspace, remote from npm registry. */ async function resolveVersions() {
|
|
68
|
+
const keys = Object.keys(PKG_DIR_MAP);
|
|
69
|
+
if (isWorkspace()) {
|
|
70
|
+
// Local: synchronous read from workspace
|
|
71
|
+
const v = {};
|
|
72
|
+
for (const k of keys)v[k] = loadWorkspaceVersion(k);
|
|
73
|
+
return v;
|
|
74
|
+
}
|
|
75
|
+
// Remote: fetch all versions from npm in parallel
|
|
76
|
+
console.info('Resolving package versions from npm...');
|
|
77
|
+
const entries = await Promise.all(keys.map(async (k)=>[
|
|
78
|
+
k,
|
|
79
|
+
await fetchNpmVersion(PKG_DIR_MAP[k])
|
|
80
|
+
]));
|
|
81
|
+
return Object.fromEntries(entries);
|
|
82
|
+
}
|
|
83
|
+
/** Build the template map with resolved version numbers. */ function buildTemplates(v) {
|
|
84
|
+
return {
|
|
85
|
+
'.gitignore': `dist/
|
|
86
|
+
node_modules/
|
|
87
|
+
`,
|
|
88
|
+
'public/openelement-mark.svg': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" role="img" aria-label="openElement mark">
|
|
89
|
+
<rect width="96" height="96" rx="18" fill="#212529"/>
|
|
90
|
+
<path d="M26 58V38l22-13 22 13v20L48 71 26 58Z" fill="none" stroke="#f8f9fa" stroke-width="6" stroke-linejoin="round"/>
|
|
91
|
+
<path d="M36 48h24" stroke="#7cc7ff" stroke-width="6" stroke-linecap="round"/>
|
|
92
|
+
</svg>
|
|
93
|
+
`,
|
|
94
|
+
'deno.json': `{
|
|
95
|
+
"imports": {
|
|
96
|
+
"@preact/signals-core": "npm:@preact/signals-core@^1.12.1",
|
|
97
|
+
"@deno/vite-plugin": "npm:@deno/vite-plugin",
|
|
98
|
+
"entities": "npm:entities@^4.5.0",
|
|
99
|
+
"hono": "npm:hono@4.12.23",
|
|
100
|
+
"hono/cors": "npm:hono@4.12.23/cors",
|
|
101
|
+
"hono/logger": "npm:hono@4.12.23/logger",
|
|
102
|
+
"hono/request-id": "npm:hono@4.12.23/request-id",
|
|
103
|
+
"hono/secure-headers": "npm:hono@4.12.23/secure-headers",
|
|
104
|
+
"marked": "npm:marked@15.0.12",
|
|
105
|
+
"@openelement/app": "npm:@openelement/app@^${v.app}",
|
|
106
|
+
"@openelement/app/vite": "npm:@openelement/app@^${v.app}/vite",
|
|
107
|
+
"@openelement/core": "npm:@openelement/core@^${v.core}",
|
|
108
|
+
"@openelement/core/jsx-runtime": "npm:@openelement/core@^${v.core}/jsx-runtime",
|
|
109
|
+
"@openelement/element": "npm:@openelement/element@^${v.element}",
|
|
110
|
+
"@openelement/ui": "npm:@openelement/ui@^${v.ui}",
|
|
111
|
+
"vite": "npm:vite@8.0.10"
|
|
112
|
+
},
|
|
113
|
+
"nodeModulesDir": "auto",
|
|
114
|
+
"tasks": {
|
|
115
|
+
"dev": "deno run --config deno.json -A npm:vite",
|
|
116
|
+
"build": "deno run --config deno.json -A npm:@openelement/adapter-vite@^${v.adapterVite}/cli/build",
|
|
117
|
+
"build:ssr": "deno run --config deno.json -A npm:vite build",
|
|
118
|
+
"build:client": "deno run --config deno.json -A npm:@openelement/adapter-vite@^${v.adapterVite}/cli/build-client",
|
|
119
|
+
"build:ssg": "deno run --config deno.json -A npm:@openelement/adapter-vite@^${v.adapterVite}/cli/build-ssg",
|
|
120
|
+
"preview": "deno run --config deno.json -A npm:vite preview"
|
|
121
|
+
},
|
|
122
|
+
"compilerOptions": { "lib": ["ES2022", "DOM", "DOM.Iterable"], "jsx": "react-jsx", "jsxImportSource": "@openelement/core" }
|
|
123
|
+
}
|
|
124
|
+
`,
|
|
125
|
+
'vite.config.ts': `import { openElement } from '@openelement/app/vite';
|
|
126
|
+
import { defineConfig } from 'vite';
|
|
127
|
+
import deno from '@deno/vite-plugin';
|
|
128
|
+
|
|
129
|
+
// Design tokens (from Open Props)
|
|
130
|
+
const colorTokensStyle =
|
|
131
|
+
'<style>' +
|
|
132
|
+
'--gray-0:#f8f9fa;--gray-1:#f1f3f5;--gray-3:#dee2e6;--gray-5:#adb5bd;--gray-7:#495057;--gray-9:#212529;' +
|
|
133
|
+
'--brand:#534ab7;--size-1:4px;--size-2:8px;--size-3:12px;--size-4:16px;--border-size-1:1px;--radius-2:8px;' +
|
|
134
|
+
'--font-sans:system-ui,-apple-system,sans-serif;--font-size-0:0.875rem;--font-weight-5:500;' +
|
|
135
|
+
'--shadow-1:0 1px 3px 0 rgb(0 0 0 / 0.1);' +
|
|
136
|
+
'body{margin:0;background:var(--gray-1);color:var(--gray-9);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}</style>';
|
|
137
|
+
|
|
138
|
+
export default defineConfig({
|
|
139
|
+
plugins: [
|
|
140
|
+
// SOP-015: Virtual module passthrough — @deno/vite-plugin doesn't
|
|
141
|
+
// support the "virtual:" scheme. This resolve hook intercepts virtual
|
|
142
|
+
// module IDs before @deno/vite-plugin, letting the openElement plugin handle them.
|
|
143
|
+
{ name: 'virtual-passthrough', resolveId(id) { if (id.startsWith('virtual:')) return '\0' + id; }, enforce: 'pre' },
|
|
144
|
+
deno(),
|
|
145
|
+
openElement({
|
|
146
|
+
html: { title: 'My openElement App' },
|
|
147
|
+
appShell: {
|
|
148
|
+
tagName: 'app-shell',
|
|
149
|
+
import: './app/components/app-shell.tsx',
|
|
150
|
+
props: {
|
|
151
|
+
siteName: 'My openElement App',
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
// Use pre-built UI components from @openelement/ui
|
|
155
|
+
// (npm distributes compiled JS - no decorator errors)
|
|
156
|
+
packageIslands: ['@openelement/ui'],
|
|
157
|
+
// SSR must bundle @openelement/ui (decorators need compilation)
|
|
158
|
+
ssr: {
|
|
159
|
+
noExternal: ['@openelement/ui'],
|
|
160
|
+
},
|
|
161
|
+
inject: {
|
|
162
|
+
headFragments: [
|
|
163
|
+
// Design tokens - DRY: values from @openelement/ui/open-props-tokens.ts
|
|
164
|
+
colorTokensStyle,
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
// Blog + Navigation + Sitemap (from @openelement/content)
|
|
168
|
+
content: {
|
|
169
|
+
blog: {
|
|
170
|
+
contentDir: 'content/blog',
|
|
171
|
+
basePath: '/blog',
|
|
172
|
+
},
|
|
173
|
+
nav: {
|
|
174
|
+
routesDir: 'app/routes',
|
|
175
|
+
headerNav: [
|
|
176
|
+
{ href: '/', label: 'Home' },
|
|
177
|
+
{ href: '/blog', label: 'Blog' },
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
})],
|
|
182
|
+
});
|
|
183
|
+
`,
|
|
184
|
+
'app/components/app-shell.tsx': `/** @jsxImportSource @openelement/core */
|
|
185
|
+
import { defineLayout } from '@openelement/app';
|
|
186
|
+
import { StyleSheet } from '@openelement/element';
|
|
187
|
+
|
|
188
|
+
export const tagName = 'app-shell';
|
|
189
|
+
|
|
190
|
+
const styles = new StyleSheet();
|
|
191
|
+
styles.replaceSync(\`
|
|
192
|
+
:host { display: block; min-height: 100vh; background: var(--gray-1); }
|
|
193
|
+
header, main, footer { max-width: 860px; margin: 0 auto; padding: 1rem; }
|
|
194
|
+
header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--gray-3); }
|
|
195
|
+
footer { color: var(--gray-7); font-size: 0.875rem; border-top: 1px solid var(--gray-3); }
|
|
196
|
+
a { color: var(--brand); text-decoration: none; font-weight: 600; }
|
|
197
|
+
\`);
|
|
198
|
+
|
|
199
|
+
export default defineLayout(tagName, {
|
|
200
|
+
styles,
|
|
201
|
+
render(props: { siteName?: string }) {
|
|
202
|
+
return (
|
|
203
|
+
<>
|
|
204
|
+
<header data-open-layout="app-shell">
|
|
205
|
+
<a href="/">{props.siteName ?? 'openElement'}</a>
|
|
206
|
+
<nav>
|
|
207
|
+
<a href="/freshness">Freshness</a>
|
|
208
|
+
<a href="/api/health">API health</a>
|
|
209
|
+
</nav>
|
|
210
|
+
</header>
|
|
211
|
+
<main>
|
|
212
|
+
<slot></slot>
|
|
213
|
+
</main>
|
|
214
|
+
<footer>Generated by @openelement/create.</footer>
|
|
215
|
+
</>
|
|
216
|
+
);
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
`,
|
|
220
|
+
'app/routes/index.tsx': `/** @jsxImportSource @openelement/core */
|
|
221
|
+
import { defineElement, definePage } from '@openelement/app';
|
|
222
|
+
import { StyleSheet } from '@openelement/element';
|
|
223
|
+
|
|
224
|
+
export const tagName = 'home-page';
|
|
225
|
+
|
|
226
|
+
const styles = new StyleSheet();
|
|
227
|
+
styles.replaceSync(\`
|
|
228
|
+
:host { display: block; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
|
|
229
|
+
h1 { font-size: 2rem; margin-bottom: 0.5rem; }
|
|
230
|
+
p { color: var(--text-secondary, #666); }
|
|
231
|
+
img { width: 64px; height: 64px; }
|
|
232
|
+
\`);
|
|
233
|
+
|
|
234
|
+
defineElement(tagName, {
|
|
235
|
+
styles,
|
|
236
|
+
render() {
|
|
237
|
+
return (
|
|
238
|
+
<>
|
|
239
|
+
<h1>Hello from openElement!</h1>
|
|
240
|
+
<p>
|
|
241
|
+
Your openElement app is running. Edit <code>app/routes/index.tsx</code> to
|
|
242
|
+
get started.
|
|
243
|
+
</p>
|
|
244
|
+
<img src="/openelement-mark.svg" alt="openElement mark" />
|
|
245
|
+
<my-counter></my-counter>
|
|
246
|
+
</>
|
|
247
|
+
);
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
export default definePage({
|
|
252
|
+
route: { path: '/' },
|
|
253
|
+
head: {
|
|
254
|
+
title: 'My openElement App',
|
|
255
|
+
description: 'Generated openElement starter app',
|
|
256
|
+
},
|
|
257
|
+
renderIntent: {
|
|
258
|
+
mode: 'static',
|
|
259
|
+
streaming: 'auto',
|
|
260
|
+
revalidate: false,
|
|
261
|
+
},
|
|
262
|
+
render() {
|
|
263
|
+
return <home-page />;
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
`,
|
|
267
|
+
'app/routes/freshness.tsx': `/** @jsxImportSource @openelement/core */
|
|
268
|
+
import { defineElement, definePage } from '@openelement/app';
|
|
269
|
+
import { StyleSheet } from '@openelement/element';
|
|
270
|
+
|
|
271
|
+
export const tagName = 'freshness-page';
|
|
272
|
+
|
|
273
|
+
const styles = new StyleSheet();
|
|
274
|
+
styles.replaceSync(\`
|
|
275
|
+
:host { display: block; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
|
|
276
|
+
p { color: var(--text-secondary, #666); }
|
|
277
|
+
\`);
|
|
278
|
+
|
|
279
|
+
defineElement(tagName, {
|
|
280
|
+
styles,
|
|
281
|
+
render() {
|
|
282
|
+
return (
|
|
283
|
+
<>
|
|
284
|
+
<h1>Freshness proof</h1>
|
|
285
|
+
<p>This page records ISR/cache intent with a 300 second revalidate window.</p>
|
|
286
|
+
</>
|
|
287
|
+
);
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
export default definePage({
|
|
292
|
+
route: { path: '/freshness' },
|
|
293
|
+
head: {
|
|
294
|
+
title: 'Freshness proof',
|
|
295
|
+
description: 'Generated openElement ISR intent route',
|
|
296
|
+
},
|
|
297
|
+
renderIntent: {
|
|
298
|
+
mode: 'static',
|
|
299
|
+
streaming: 'auto',
|
|
300
|
+
revalidate: 300,
|
|
301
|
+
},
|
|
302
|
+
render() {
|
|
303
|
+
return <freshness-page />;
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
`,
|
|
307
|
+
'app/routes/api/health.ts': `export default function health() {
|
|
308
|
+
return Response.json({
|
|
309
|
+
ok: true,
|
|
310
|
+
framework: 'openElement',
|
|
311
|
+
route: '/api/health',
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
`,
|
|
315
|
+
'app/islands/my-counter.tsx': `/** @jsxImportSource @openelement/core */
|
|
316
|
+
import { defineIsland, defineIslandConfig } from '@openelement/app';
|
|
317
|
+
import { signal, StyleSheet } from '@openelement/element';
|
|
318
|
+
|
|
319
|
+
export const tagName = 'my-counter';
|
|
320
|
+
export const openElement = defineIslandConfig({ hydrate: 'idle', ssr: true, dsd: true });
|
|
321
|
+
|
|
322
|
+
const styles = new StyleSheet();
|
|
323
|
+
styles.replaceSync(\`
|
|
324
|
+
:host { display: inline-flex; gap: 0.5rem; align-items: center; margin-top: 1rem; }
|
|
325
|
+
button { padding: 0.25rem 0.75rem; cursor: pointer; }
|
|
326
|
+
\`);
|
|
327
|
+
|
|
328
|
+
const count = signal(0);
|
|
329
|
+
|
|
330
|
+
export default defineIsland(tagName, {
|
|
331
|
+
styles,
|
|
332
|
+
render() {
|
|
333
|
+
return (
|
|
334
|
+
<>
|
|
335
|
+
<button onClick={() => count.value--}>-</button>
|
|
336
|
+
<span>{count.value}</span>
|
|
337
|
+
<button onClick={() => count.value++}>+</button>
|
|
338
|
+
</>
|
|
339
|
+
);
|
|
340
|
+
},
|
|
341
|
+
}, { hydrate: openElement.hydrate, dsd: openElement.dsd, ssr: openElement.ssr });
|
|
342
|
+
`
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
async function main() {
|
|
346
|
+
const name = Deno.args[0];
|
|
347
|
+
if (!name || name === '--help' || name === '-h') {
|
|
348
|
+
console.log('Usage: deno run -A npm:@openelement/create <project-name>');
|
|
349
|
+
Deno.exit(name ? 0 : 1);
|
|
350
|
+
}
|
|
351
|
+
// H-14 fix: Validate project name format to prevent path traversal
|
|
352
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
353
|
+
log.error(`Invalid project name: "${name}". Project name must only contain letters, numbers, underscores, and hyphens.`);
|
|
354
|
+
Deno.exit(1);
|
|
355
|
+
}
|
|
356
|
+
const cwd = Deno.cwd();
|
|
357
|
+
const targetDir = resolve(cwd, name);
|
|
358
|
+
const relativeTarget = relative(cwd, targetDir);
|
|
359
|
+
if (!relativeTarget || relativeTarget === '..' || relativeTarget.startsWith(`..${sep}`) || isAbsolute(relativeTarget)) {
|
|
360
|
+
log.error(`Refusing to create project outside the current directory: ${name}`);
|
|
361
|
+
Deno.exit(1);
|
|
362
|
+
}
|
|
363
|
+
try {
|
|
364
|
+
await Deno.stat(targetDir);
|
|
365
|
+
log.error(`Directory "${name}" already exists.`);
|
|
366
|
+
Deno.exit(1);
|
|
367
|
+
} catch (e) {
|
|
368
|
+
if (!(e instanceof Deno.errors.NotFound)) {
|
|
369
|
+
log.error(`Failed to inspect target directory "${name}": ${e}`);
|
|
370
|
+
Deno.exit(1);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Resolve package versions before generating templates
|
|
374
|
+
const v = await resolveVersions();
|
|
375
|
+
try {
|
|
376
|
+
await Deno.mkdir(targetDir, {
|
|
377
|
+
recursive: true
|
|
378
|
+
});
|
|
379
|
+
} catch (e) {
|
|
380
|
+
log.error(`Failed to create directory "${name}": ${e}`);
|
|
381
|
+
Deno.exit(1);
|
|
382
|
+
}
|
|
383
|
+
const TPL = buildTemplates(v);
|
|
384
|
+
for (const [path, content] of Object.entries(TPL)){
|
|
385
|
+
const fullPath = join(targetDir, path);
|
|
386
|
+
await Deno.mkdir(dirname(fullPath), {
|
|
387
|
+
recursive: true
|
|
388
|
+
});
|
|
389
|
+
await Deno.writeTextFile(fullPath, content);
|
|
390
|
+
console.info(` created ${path}`);
|
|
391
|
+
}
|
|
392
|
+
console.info(`\nopenElement project created at ./${relativeTarget}/`);
|
|
393
|
+
console.info(`\n cd ${relativeTarget}`);
|
|
394
|
+
console.info(' deno task dev');
|
|
395
|
+
}
|
|
396
|
+
main();
|
|
397
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jcmVhdGUvY2xpLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlbm8gfSBmcm9tIFwiQGRlbm8vc2hpbS1kZW5vXCI7XG4vKipcbiAqIEBvcGVuZWxlbWVudC9jcmVhdGUgLSBNaW5pbWFsIHByb2plY3Qgc2NhZmZvbGQgZm9yIG9wZW5FbGVtZW50IGZyYW1ld29yay5cbiAqXG4gKiBVc2FnZTogZGVubyBydW4gLUEgbnBtOkBvcGVuZWxlbWVudC9jcmVhdGUgbXktYXBwXG4gKlxuICogb3BlbkVsZW1lbnQgQXJjaGl0ZWN0dXJlOiBLZWVwIEl0IFNpbXBsZSwgU3R1cGlkLlxuICogT25lIHRlbXBsYXRlLCB6ZXJvIHByb21wdHMsIGluc3RhbnQgc3RhcnQuXG4gKi9cblxuaW1wb3J0IHsgZGlybmFtZSwgaXNBYnNvbHV0ZSwgam9pbiwgcmVsYXRpdmUsIHJlc29sdmUsIHNlcCB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnQG9wZW5lbGVtZW50L2NvcmUvbG9nZ2VyJztcblxuLy8gPz8/IFBhY2thZ2UgdmVyc2lvbnMgPz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/XG4vLyBBRFIgMDAxNjogSGFuZGxlIGJvdGggbG9jYWwgKHdvcmtzcGFjZSBmaWxlOi8vKSBhbmQgcmVtb3RlIChucG0gcmVnaXN0cnkpIGV4ZWN1dGlvbi5cbi8vXG4vLyAtIExvY2FsOiAgcmVhZCB2ZXJzaW9uIGZyb20gd29ya3NwYWNlIGRlbm8uanNvbiAoc2luZ2xlIHNvdXJjZSBvZiB0cnV0aClcbi8vIC0gUmVtb3RlOiBxdWVyeSBucG0gUmVnaXN0cnkgQVBJIGZvciBsYXRlc3QgdmVyc2lvbiAoemVybyBoYXJkY29kaW5nKVxuXG5jb25zdCBOUE1fU0NPUEUgPSAnQG9wZW5lbGVtZW50JztcbmNvbnN0IGxvZyA9IGNyZWF0ZUxvZ2dlcignY3JlYXRlJyk7XG5jb25zdCBQS0dfRElSX01BUDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgY29yZTogJ2NvcmUnLFxuICBhZGFwdGVyVml0ZTogJ2FkYXB0ZXItdml0ZScsXG4gIGFwcDogJ2FwcCcsXG4gIGNvbnRlbnQ6ICdjb250ZW50JyxcbiAgdWk6ICd1aScsXG4gIHNpZ25hbDogJ3NpZ25hbCcsXG4gIGVsZW1lbnQ6ICdlbGVtZW50Jyxcbn07XG5cbmZ1bmN0aW9uIGxvYWRXb3Jrc3BhY2VWZXJzaW9uKHBrZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbWV0YVVybCA9IGltcG9ydC5tZXRhLnVybDtcbiAgY29uc3Qgc2VsZlBhdGggPSBmaWxlVVJMVG9QYXRoKG5ldyBVUkwoJy4nLCBtZXRhVXJsKSk7XG4gIGNvbnN0IGRpciA9IFBLR19ESVJfTUFQW3BrZ10gfHwgcGtnO1xuICBjb25zdCB3c1BhdGggPSByZXNvbHZlKHNlbGZQYXRoLCAnLi4nLCAnLi4nLCAncGFja2FnZXMnLCBkaXIsICdkZW5vLmpzb24nKTtcbiAgdHJ5IHtcbiAgICBjb25zdCB2ZXJzaW9uID0gSlNPTi5wYXJzZShEZW5vLnJlYWRUZXh0RmlsZVN5bmMod3NQYXRoKSkudmVyc2lvbjtcbiAgICBpZiAoIXZlcnNpb24pIHRocm93IG5ldyBFcnJvcihgTm8gdmVyc2lvbiBmb3VuZCBpbiAke3dzUGF0aH1gKTtcbiAgICByZXR1cm4gdmVyc2lvbjtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gcmVhZCB2ZXJzaW9uIGZvciBAb3BlbmVsZW1lbnQvJHtkaXJ9IGZyb20gJHt3c1BhdGh9LiBgICtcbiAgICAgICAgYFJ1biB0aGlzIHNjcmlwdCBmcm9tIHRoZSBvcGVuRWxlbWVudCB3b3Jrc3BhY2Ugb3IgZW5zdXJlIGRlbm8uanNvbiBpcyBhY2Nlc3NpYmxlLlxcbmAgK1xuICAgICAgICBgT3JpZ2luYWwgZXJyb3I6ICR7ZX1gLFxuICAgICk7XG4gIH1cbn1cblxuLyoqIERldGVjdCB3aGV0aGVyIGNsaS50cyBpcyBiZWluZyBydW4gZnJvbSB0aGUgb3BlbkVsZW1lbnQgd29ya3NwYWNlLiAqL1xuZnVuY3Rpb24gaXNXb3Jrc3BhY2UoKTogYm9vbGVhbiB7XG4gIHRyeSB7XG4gICAgY29uc3Qgc2VsZlBhdGggPSBmaWxlVVJMVG9QYXRoKG5ldyBVUkwoJy4nLCBpbXBvcnQubWV0YS51cmwpKTtcbiAgICBEZW5vLnJlYWRUZXh0RmlsZVN5bmMocmVzb2x2ZShzZWxmUGF0aCwgJy4uJywgJy4uJywgJ3BhY2thZ2VzJywgJ2NvcmUnLCAnZGVuby5qc29uJykpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqIEZldGNoIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiBhbiBucG0gcGFja2FnZSBmcm9tIHRoZSBSZWdpc3RyeSBBUEkuICovXG5hc3luYyBmdW5jdGlvbiBmZXRjaE5wbVZlcnNpb24ocGtnOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCByZXNwID0gYXdhaXQgZmV0Y2goYGh0dHBzOi8vcmVnaXN0cnkubnBtanMub3JnLyR7TlBNX1NDT1BFfS8ke3BrZ31gLCB7XG4gICAgaGVhZGVyczogeyBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyB9LFxuICB9KTtcbiAgaWYgKCFyZXNwLm9rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEZhaWxlZCB0byBmZXRjaCB2ZXJzaW9uIGZvciAke05QTV9TQ09QRX0vJHtwa2d9IGZyb20gbnBtIHJlZ2lzdHJ5IChIVFRQICR7cmVzcC5zdGF0dXN9KWAsXG4gICAgKTtcbiAgfVxuICBjb25zdCBtZXRhID0gYXdhaXQgcmVzcC5qc29uKCk7XG4gIC8vIG5wbSByZWdpc3RyeSByZXNwb25zZSBoYXMgZGlzdC10YWdzLmxhdGVzdFxuICBjb25zdCB2ZXJzaW9uID0gbWV0YT8uWydkaXN0LXRhZ3MnXT8ubGF0ZXN0O1xuICBpZiAoIXZlcnNpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTm8gdmVyc2lvbiBmb3VuZCBmb3IgJHtOUE1fU0NPUEV9LyR7cGtnfSBpbiBucG0gcmVnaXN0cnkgcmVzcG9uc2VgLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHZlcnNpb247XG59XG5cbi8qKiBSZXNvbHZlIGFsbCBwYWNrYWdlIHZlcnNpb25zOiBsb2NhbCBmcm9tIHdvcmtzcGFjZSwgcmVtb3RlIGZyb20gbnBtIHJlZ2lzdHJ5LiAqL1xuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZVZlcnNpb25zKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4ge1xuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoUEtHX0RJUl9NQVApO1xuICBpZiAoaXNXb3Jrc3BhY2UoKSkge1xuICAgIC8vIExvY2FsOiBzeW5jaHJvbm91cyByZWFkIGZyb20gd29ya3NwYWNlXG4gICAgY29uc3QgdjogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICAgIGZvciAoY29uc3QgayBvZiBrZXlzKSB2W2tdID0gbG9hZFdvcmtzcGFjZVZlcnNpb24oayk7XG4gICAgcmV0dXJuIHY7XG4gIH1cblxuICAvLyBSZW1vdGU6IGZldGNoIGFsbCB2ZXJzaW9ucyBmcm9tIG5wbSBpbiBwYXJhbGxlbFxuICBjb25zb2xlLmluZm8oJ1Jlc29sdmluZyBwYWNrYWdlIHZlcnNpb25zIGZyb20gbnBtLi4uJyk7XG4gIGNvbnN0IGVudHJpZXMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICBrZXlzLm1hcChhc3luYyAoaykgPT4gW2ssIGF3YWl0IGZldGNoTnBtVmVyc2lvbihQS0dfRElSX01BUFtrXSldKSxcbiAgKTtcbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhlbnRyaWVzKTtcbn1cblxuLyoqIEJ1aWxkIHRoZSB0ZW1wbGF0ZSBtYXAgd2l0aCByZXNvbHZlZCB2ZXJzaW9uIG51bWJlcnMuICovXG5mdW5jdGlvbiBidWlsZFRlbXBsYXRlcyh2OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIHJldHVybiB7XG4gICAgJy5naXRpZ25vcmUnOiBgZGlzdC9cbm5vZGVfbW9kdWxlcy9cbmAsXG4gICAgJ3B1YmxpYy9vcGVuZWxlbWVudC1tYXJrLnN2Zyc6XG4gICAgICBgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgdmlld0JveD1cIjAgMCA5NiA5NlwiIHJvbGU9XCJpbWdcIiBhcmlhLWxhYmVsPVwib3BlbkVsZW1lbnQgbWFya1wiPlxuICA8cmVjdCB3aWR0aD1cIjk2XCIgaGVpZ2h0PVwiOTZcIiByeD1cIjE4XCIgZmlsbD1cIiMyMTI1MjlcIi8+XG4gIDxwYXRoIGQ9XCJNMjYgNThWMzhsMjItMTMgMjIgMTN2MjBMNDggNzEgMjYgNThaXCIgZmlsbD1cIm5vbmVcIiBzdHJva2U9XCIjZjhmOWZhXCIgc3Ryb2tlLXdpZHRoPVwiNlwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIvPlxuICA8cGF0aCBkPVwiTTM2IDQ4aDI0XCIgc3Ryb2tlPVwiIzdjYzdmZlwiIHN0cm9rZS13aWR0aD1cIjZcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIvPlxuPC9zdmc+XG5gLFxuICAgICdkZW5vLmpzb24nOiBge1xuICBcImltcG9ydHNcIjoge1xuICAgIFwiQHByZWFjdC9zaWduYWxzLWNvcmVcIjogXCJucG06QHByZWFjdC9zaWduYWxzLWNvcmVAXjEuMTIuMVwiLFxuICAgIFwiQGRlbm8vdml0ZS1wbHVnaW5cIjogXCJucG06QGRlbm8vdml0ZS1wbHVnaW5cIixcbiAgICBcImVudGl0aWVzXCI6IFwibnBtOmVudGl0aWVzQF40LjUuMFwiLFxuICAgIFwiaG9ub1wiOiBcIm5wbTpob25vQDQuMTIuMjNcIixcbiAgICBcImhvbm8vY29yc1wiOiBcIm5wbTpob25vQDQuMTIuMjMvY29yc1wiLFxuICAgIFwiaG9uby9sb2dnZXJcIjogXCJucG06aG9ub0A0LjEyLjIzL2xvZ2dlclwiLFxuICAgIFwiaG9uby9yZXF1ZXN0LWlkXCI6IFwibnBtOmhvbm9ANC4xMi4yMy9yZXF1ZXN0LWlkXCIsXG4gICAgXCJob25vL3NlY3VyZS1oZWFkZXJzXCI6IFwibnBtOmhvbm9ANC4xMi4yMy9zZWN1cmUtaGVhZGVyc1wiLFxuICAgIFwibWFya2VkXCI6IFwibnBtOm1hcmtlZEAxNS4wLjEyXCIsXG4gICAgXCJAb3BlbmVsZW1lbnQvYXBwXCI6IFwibnBtOkBvcGVuZWxlbWVudC9hcHBAXiR7di5hcHB9XCIsXG4gICAgXCJAb3BlbmVsZW1lbnQvYXBwL3ZpdGVcIjogXCJucG06QG9wZW5lbGVtZW50L2FwcEBeJHt2LmFwcH0vdml0ZVwiLFxuICAgIFwiQG9wZW5lbGVtZW50L2NvcmVcIjogXCJucG06QG9wZW5lbGVtZW50L2NvcmVAXiR7di5jb3JlfVwiLFxuICAgIFwiQG9wZW5lbGVtZW50L2NvcmUvanN4LXJ1bnRpbWVcIjogXCJucG06QG9wZW5lbGVtZW50L2NvcmVAXiR7di5jb3JlfS9qc3gtcnVudGltZVwiLFxuICAgIFwiQG9wZW5lbGVtZW50L2VsZW1lbnRcIjogXCJucG06QG9wZW5lbGVtZW50L2VsZW1lbnRAXiR7di5lbGVtZW50fVwiLFxuICAgIFwiQG9wZW5lbGVtZW50L3VpXCI6IFwibnBtOkBvcGVuZWxlbWVudC91aUBeJHt2LnVpfVwiLFxuICAgIFwidml0ZVwiOiBcIm5wbTp2aXRlQDguMC4xMFwiXG4gIH0sXG4gIFwibm9kZU1vZHVsZXNEaXJcIjogXCJhdXRvXCIsXG4gIFwidGFza3NcIjoge1xuICAgIFwiZGV2XCI6IFwiZGVubyBydW4gLS1jb25maWcgZGVuby5qc29uIC1BIG5wbTp2aXRlXCIsXG4gICAgXCJidWlsZFwiOiBcImRlbm8gcnVuIC0tY29uZmlnIGRlbm8uanNvbiAtQSBucG06QG9wZW5lbGVtZW50L2FkYXB0ZXItdml0ZUBeJHt2LmFkYXB0ZXJWaXRlfS9jbGkvYnVpbGRcIixcbiAgICBcImJ1aWxkOnNzclwiOiBcImRlbm8gcnVuIC0tY29uZmlnIGRlbm8uanNvbiAtQSBucG06dml0ZSBidWlsZFwiLFxuICAgIFwiYnVpbGQ6Y2xpZW50XCI6IFwiZGVubyBydW4gLS1jb25maWcgZGVuby5qc29uIC1BIG5wbTpAb3BlbmVsZW1lbnQvYWRhcHRlci12aXRlQF4ke3YuYWRhcHRlclZpdGV9L2NsaS9idWlsZC1jbGllbnRcIixcbiAgICBcImJ1aWxkOnNzZ1wiOiBcImRlbm8gcnVuIC0tY29uZmlnIGRlbm8uanNvbiAtQSBucG06QG9wZW5lbGVtZW50L2FkYXB0ZXItdml0ZUBeJHt2LmFkYXB0ZXJWaXRlfS9jbGkvYnVpbGQtc3NnXCIsXG4gICAgXCJwcmV2aWV3XCI6IFwiZGVubyBydW4gLS1jb25maWcgZGVuby5qc29uIC1BIG5wbTp2aXRlIHByZXZpZXdcIlxuICB9LFxuICBcImNvbXBpbGVyT3B0aW9uc1wiOiB7IFwibGliXCI6IFtcIkVTMjAyMlwiLCBcIkRPTVwiLCBcIkRPTS5JdGVyYWJsZVwiXSwgXCJqc3hcIjogXCJyZWFjdC1qc3hcIiwgXCJqc3hJbXBvcnRTb3VyY2VcIjogXCJAb3BlbmVsZW1lbnQvY29yZVwiIH1cbn1cbmAsXG4gICAgJ3ZpdGUuY29uZmlnLnRzJzogYGltcG9ydCB7IG9wZW5FbGVtZW50IH0gZnJvbSAnQG9wZW5lbGVtZW50L2FwcC92aXRlJztcbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gJ3ZpdGUnO1xuaW1wb3J0IGRlbm8gZnJvbSAnQGRlbm8vdml0ZS1wbHVnaW4nO1xuXG4vLyBEZXNpZ24gdG9rZW5zIChmcm9tIE9wZW4gUHJvcHMpXG5jb25zdCBjb2xvclRva2Vuc1N0eWxlID1cbiAgJzxzdHlsZT4nICtcbiAgJy0tZ3JheS0wOiNmOGY5ZmE7LS1ncmF5LTE6I2YxZjNmNTstLWdyYXktMzojZGVlMmU2Oy0tZ3JheS01OiNhZGI1YmQ7LS1ncmF5LTc6IzQ5NTA1NzstLWdyYXktOTojMjEyNTI5OycgK1xuICAnLS1icmFuZDojNTM0YWI3Oy0tc2l6ZS0xOjRweDstLXNpemUtMjo4cHg7LS1zaXplLTM6MTJweDstLXNpemUtNDoxNnB4Oy0tYm9yZGVyLXNpemUtMToxcHg7LS1yYWRpdXMtMjo4cHg7JyArXG4gICctLWZvbnQtc2FuczpzeXN0ZW0tdWksLWFwcGxlLXN5c3RlbSxzYW5zLXNlcmlmOy0tZm9udC1zaXplLTA6MC44NzVyZW07LS1mb250LXdlaWdodC01OjUwMDsnICtcbiAgJy0tc2hhZG93LTE6MCAxcHggM3B4IDAgcmdiKDAgMCAwIC8gMC4xKTsnICtcbiAgJ2JvZHl7bWFyZ2luOjA7YmFja2dyb3VuZDp2YXIoLS1ncmF5LTEpO2NvbG9yOnZhcigtLWdyYXktOSk7Zm9udC1mYW1pbHk6dmFyKC0tZm9udC1zYW5zKTstd2Via2l0LWZvbnQtc21vb3RoaW5nOmFudGlhbGlhc2VkOy1tb3otb3N4LWZvbnQtc21vb3RoaW5nOmdyYXlzY2FsZX08L3N0eWxlPic7XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHBsdWdpbnM6IFtcbiAgICAvLyBTT1AtMDE1OiBWaXJ0dWFsIG1vZHVsZSBwYXNzdGhyb3VnaCDigJQgQGRlbm8vdml0ZS1wbHVnaW4gZG9lc24ndFxuICAgIC8vIHN1cHBvcnQgdGhlIFwidmlydHVhbDpcIiBzY2hlbWUuIFRoaXMgcmVzb2x2ZSBob29rIGludGVyY2VwdHMgdmlydHVhbFxuICAgIC8vIG1vZHVsZSBJRHMgYmVmb3JlIEBkZW5vL3ZpdGUtcGx1Z2luLCBsZXR0aW5nIHRoZSBvcGVuRWxlbWVudCBwbHVnaW4gaGFuZGxlIHRoZW0uXG4gICAgeyBuYW1lOiAndmlydHVhbC1wYXNzdGhyb3VnaCcsIHJlc29sdmVJZChpZCkgeyBpZiAoaWQuc3RhcnRzV2l0aCgndmlydHVhbDonKSkgcmV0dXJuICdcXDAnICsgaWQ7IH0sIGVuZm9yY2U6ICdwcmUnIH0sXG4gICAgZGVubygpLFxuICAgIG9wZW5FbGVtZW50KHtcbiAgICBodG1sOiB7IHRpdGxlOiAnTXkgb3BlbkVsZW1lbnQgQXBwJyB9LFxuICAgIGFwcFNoZWxsOiB7XG4gICAgICB0YWdOYW1lOiAnYXBwLXNoZWxsJyxcbiAgICAgIGltcG9ydDogJy4vYXBwL2NvbXBvbmVudHMvYXBwLXNoZWxsLnRzeCcsXG4gICAgICBwcm9wczoge1xuICAgICAgICBzaXRlTmFtZTogJ015IG9wZW5FbGVtZW50IEFwcCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgLy8gVXNlIHByZS1idWlsdCBVSSBjb21wb25lbnRzIGZyb20gQG9wZW5lbGVtZW50L3VpXG4gICAgLy8gKG5wbSBkaXN0cmlidXRlcyBjb21waWxlZCBKUyAtIG5vIGRlY29yYXRvciBlcnJvcnMpXG4gICAgcGFja2FnZUlzbGFuZHM6IFsnQG9wZW5lbGVtZW50L3VpJ10sXG4gICAgLy8gU1NSIG11c3QgYnVuZGxlIEBvcGVuZWxlbWVudC91aSAoZGVjb3JhdG9ycyBuZWVkIGNvbXBpbGF0aW9uKVxuICAgIHNzcjoge1xuICAgICAgbm9FeHRlcm5hbDogWydAb3BlbmVsZW1lbnQvdWknXSxcbiAgICB9LFxuICAgIGluamVjdDoge1xuICAgICAgaGVhZEZyYWdtZW50czogW1xuICAgICAgICAvLyBEZXNpZ24gdG9rZW5zIC0gRFJZOiB2YWx1ZXMgZnJvbSBAb3BlbmVsZW1lbnQvdWkvb3Blbi1wcm9wcy10b2tlbnMudHNcbiAgICAgICAgY29sb3JUb2tlbnNTdHlsZSxcbiAgICAgIF0sXG4gICAgfSxcbiAgICAvLyBCbG9nICsgTmF2aWdhdGlvbiArIFNpdGVtYXAgKGZyb20gQG9wZW5lbGVtZW50L2NvbnRlbnQpXG4gICAgY29udGVudDoge1xuICAgICAgYmxvZzoge1xuICAgICAgICBjb250ZW50RGlyOiAnY29udGVudC9ibG9nJyxcbiAgICAgICAgYmFzZVBhdGg6ICcvYmxvZycsXG4gICAgICB9LFxuICAgICAgbmF2OiB7XG4gICAgICAgIHJvdXRlc0RpcjogJ2FwcC9yb3V0ZXMnLFxuICAgICAgICBoZWFkZXJOYXY6IFtcbiAgICAgICAgICB7IGhyZWY6ICcvJywgbGFiZWw6ICdIb21lJyB9LFxuICAgICAgICAgIHsgaHJlZjogJy9ibG9nJywgbGFiZWw6ICdCbG9nJyB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICB9LFxuICB9KV0sXG59KTtcbmAsXG4gICAgJ2FwcC9jb21wb25lbnRzL2FwcC1zaGVsbC50c3gnOiBgLyoqIEBqc3hJbXBvcnRTb3VyY2UgQG9wZW5lbGVtZW50L2NvcmUgKi9cbmltcG9ydCB7IGRlZmluZUxheW91dCB9IGZyb20gJ0BvcGVuZWxlbWVudC9hcHAnO1xuaW1wb3J0IHsgU3R5bGVTaGVldCB9IGZyb20gJ0BvcGVuZWxlbWVudC9lbGVtZW50JztcblxuZXhwb3J0IGNvbnN0IHRhZ05hbWUgPSAnYXBwLXNoZWxsJztcblxuY29uc3Qgc3R5bGVzID0gbmV3IFN0eWxlU2hlZXQoKTtcbnN0eWxlcy5yZXBsYWNlU3luYyhcXGBcbiAgOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgbWluLWhlaWdodDogMTAwdmg7IGJhY2tncm91bmQ6IHZhcigtLWdyYXktMSk7IH1cbiAgaGVhZGVyLCBtYWluLCBmb290ZXIgeyBtYXgtd2lkdGg6IDg2MHB4OyBtYXJnaW46IDAgYXV0bzsgcGFkZGluZzogMXJlbTsgfVxuICBoZWFkZXIgeyBkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGJvcmRlci1ib3R0b206IDFweCBzb2xpZCB2YXIoLS1ncmF5LTMpOyB9XG4gIGZvb3RlciB7IGNvbG9yOiB2YXIoLS1ncmF5LTcpOyBmb250LXNpemU6IDAuODc1cmVtOyBib3JkZXItdG9wOiAxcHggc29saWQgdmFyKC0tZ3JheS0zKTsgfVxuICBhIHsgY29sb3I6IHZhcigtLWJyYW5kKTsgdGV4dC1kZWNvcmF0aW9uOiBub25lOyBmb250LXdlaWdodDogNjAwOyB9XG5cXGApO1xuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVMYXlvdXQodGFnTmFtZSwge1xuICBzdHlsZXMsXG4gIHJlbmRlcihwcm9wczogeyBzaXRlTmFtZT86IHN0cmluZyB9KSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDw+XG4gICAgICAgIDxoZWFkZXIgZGF0YS1vcGVuLWxheW91dD1cImFwcC1zaGVsbFwiPlxuICAgICAgICAgIDxhIGhyZWY9XCIvXCI+e3Byb3BzLnNpdGVOYW1lID8/ICdvcGVuRWxlbWVudCd9PC9hPlxuICAgICAgICAgIDxuYXY+XG4gICAgICAgICAgICA8YSBocmVmPVwiL2ZyZXNobmVzc1wiPkZyZXNobmVzczwvYT5cbiAgICAgICAgICAgIDxhIGhyZWY9XCIvYXBpL2hlYWx0aFwiPkFQSSBoZWFsdGg8L2E+XG4gICAgICAgICAgPC9uYXY+XG4gICAgICAgIDwvaGVhZGVyPlxuICAgICAgICA8bWFpbj5cbiAgICAgICAgICA8c2xvdD48L3Nsb3Q+XG4gICAgICAgIDwvbWFpbj5cbiAgICAgICAgPGZvb3Rlcj5HZW5lcmF0ZWQgYnkgQG9wZW5lbGVtZW50L2NyZWF0ZS48L2Zvb3Rlcj5cbiAgICAgIDwvPlxuICAgICk7XG4gIH0sXG59KTtcbmAsXG4gICAgJ2FwcC9yb3V0ZXMvaW5kZXgudHN4JzogYC8qKiBAanN4SW1wb3J0U291cmNlIEBvcGVuZWxlbWVudC9jb3JlICovXG5pbXBvcnQgeyBkZWZpbmVFbGVtZW50LCBkZWZpbmVQYWdlIH0gZnJvbSAnQG9wZW5lbGVtZW50L2FwcCc7XG5pbXBvcnQgeyBTdHlsZVNoZWV0IH0gZnJvbSAnQG9wZW5lbGVtZW50L2VsZW1lbnQnO1xuXG5leHBvcnQgY29uc3QgdGFnTmFtZSA9ICdob21lLXBhZ2UnO1xuXG5jb25zdCBzdHlsZXMgPSBuZXcgU3R5bGVTaGVldCgpO1xuc3R5bGVzLnJlcGxhY2VTeW5jKFxcYFxuICA6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyBtYXgtd2lkdGg6IDgwMHB4OyBtYXJnaW46IDJyZW0gYXV0bzsgcGFkZGluZzogMCAxcmVtOyB9XG4gIGgxIHsgZm9udC1zaXplOiAycmVtOyBtYXJnaW4tYm90dG9tOiAwLjVyZW07IH1cbiAgcCB7IGNvbG9yOiB2YXIoLS10ZXh0LXNlY29uZGFyeSwgIzY2Nik7IH1cbiAgaW1nIHsgd2lkdGg6IDY0cHg7IGhlaWdodDogNjRweDsgfVxuXFxgKTtcblxuZGVmaW5lRWxlbWVudCh0YWdOYW1lLCB7XG4gIHN0eWxlcyxcbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgICA8PlxuICAgICAgICA8aDE+SGVsbG8gZnJvbSBvcGVuRWxlbWVudCE8L2gxPlxuICAgICAgICA8cD5cbiAgICAgICAgICBZb3VyIG9wZW5FbGVtZW50IGFwcCBpcyBydW5uaW5nLiBFZGl0IDxjb2RlPmFwcC9yb3V0ZXMvaW5kZXgudHN4PC9jb2RlPiB0b1xuICAgICAgICAgIGdldCBzdGFydGVkLlxuICAgICAgICA8L3A+XG4gICAgICAgIDxpbWcgc3JjPVwiL29wZW5lbGVtZW50LW1hcmsuc3ZnXCIgYWx0PVwib3BlbkVsZW1lbnQgbWFya1wiIC8+XG4gICAgICAgIDxteS1jb3VudGVyPjwvbXktY291bnRlcj5cbiAgICAgIDwvPlxuICAgICk7XG4gIH0sXG59KTtcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lUGFnZSh7XG4gIHJvdXRlOiB7IHBhdGg6ICcvJyB9LFxuICBoZWFkOiB7XG4gICAgdGl0bGU6ICdNeSBvcGVuRWxlbWVudCBBcHAnLFxuICAgIGRlc2NyaXB0aW9uOiAnR2VuZXJhdGVkIG9wZW5FbGVtZW50IHN0YXJ0ZXIgYXBwJyxcbiAgfSxcbiAgcmVuZGVySW50ZW50OiB7XG4gICAgbW9kZTogJ3N0YXRpYycsXG4gICAgc3RyZWFtaW5nOiAnYXV0bycsXG4gICAgcmV2YWxpZGF0ZTogZmFsc2UsXG4gIH0sXG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gPGhvbWUtcGFnZSAvPjtcbiAgfSxcbn0pO1xuYCxcbiAgICAnYXBwL3JvdXRlcy9mcmVzaG5lc3MudHN4JzogYC8qKiBAanN4SW1wb3J0U291cmNlIEBvcGVuZWxlbWVudC9jb3JlICovXG5pbXBvcnQgeyBkZWZpbmVFbGVtZW50LCBkZWZpbmVQYWdlIH0gZnJvbSAnQG9wZW5lbGVtZW50L2FwcCc7XG5pbXBvcnQgeyBTdHlsZVNoZWV0IH0gZnJvbSAnQG9wZW5lbGVtZW50L2VsZW1lbnQnO1xuXG5leHBvcnQgY29uc3QgdGFnTmFtZSA9ICdmcmVzaG5lc3MtcGFnZSc7XG5cbmNvbnN0IHN0eWxlcyA9IG5ldyBTdHlsZVNoZWV0KCk7XG5zdHlsZXMucmVwbGFjZVN5bmMoXFxgXG4gIDpob3N0IHsgZGlzcGxheTogYmxvY2s7IG1heC13aWR0aDogODAwcHg7IG1hcmdpbjogMnJlbSBhdXRvOyBwYWRkaW5nOiAwIDFyZW07IH1cbiAgcCB7IGNvbG9yOiB2YXIoLS10ZXh0LXNlY29uZGFyeSwgIzY2Nik7IH1cblxcYCk7XG5cbmRlZmluZUVsZW1lbnQodGFnTmFtZSwge1xuICBzdHlsZXMsXG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPD5cbiAgICAgICAgPGgxPkZyZXNobmVzcyBwcm9vZjwvaDE+XG4gICAgICAgIDxwPlRoaXMgcGFnZSByZWNvcmRzIElTUi9jYWNoZSBpbnRlbnQgd2l0aCBhIDMwMCBzZWNvbmQgcmV2YWxpZGF0ZSB3aW5kb3cuPC9wPlxuICAgICAgPC8+XG4gICAgKTtcbiAgfSxcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVQYWdlKHtcbiAgcm91dGU6IHsgcGF0aDogJy9mcmVzaG5lc3MnIH0sXG4gIGhlYWQ6IHtcbiAgICB0aXRsZTogJ0ZyZXNobmVzcyBwcm9vZicsXG4gICAgZGVzY3JpcHRpb246ICdHZW5lcmF0ZWQgb3BlbkVsZW1lbnQgSVNSIGludGVudCByb3V0ZScsXG4gIH0sXG4gIHJlbmRlckludGVudDoge1xuICAgIG1vZGU6ICdzdGF0aWMnLFxuICAgIHN0cmVhbWluZzogJ2F1dG8nLFxuICAgIHJldmFsaWRhdGU6IDMwMCxcbiAgfSxcbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiA8ZnJlc2huZXNzLXBhZ2UgLz47XG4gIH0sXG59KTtcbmAsXG4gICAgJ2FwcC9yb3V0ZXMvYXBpL2hlYWx0aC50cyc6IGBleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBoZWFsdGgoKSB7XG4gIHJldHVybiBSZXNwb25zZS5qc29uKHtcbiAgICBvazogdHJ1ZSxcbiAgICBmcmFtZXdvcms6ICdvcGVuRWxlbWVudCcsXG4gICAgcm91dGU6ICcvYXBpL2hlYWx0aCcsXG4gIH0pO1xufVxuYCxcbiAgICAnYXBwL2lzbGFuZHMvbXktY291bnRlci50c3gnOiBgLyoqIEBqc3hJbXBvcnRTb3VyY2UgQG9wZW5lbGVtZW50L2NvcmUgKi9cbmltcG9ydCB7IGRlZmluZUlzbGFuZCwgZGVmaW5lSXNsYW5kQ29uZmlnIH0gZnJvbSAnQG9wZW5lbGVtZW50L2FwcCc7XG5pbXBvcnQgeyBzaWduYWwsIFN0eWxlU2hlZXQgfSBmcm9tICdAb3BlbmVsZW1lbnQvZWxlbWVudCc7XG5cbmV4cG9ydCBjb25zdCB0YWdOYW1lID0gJ215LWNvdW50ZXInO1xuZXhwb3J0IGNvbnN0IG9wZW5FbGVtZW50ID0gZGVmaW5lSXNsYW5kQ29uZmlnKHsgaHlkcmF0ZTogJ2lkbGUnLCBzc3I6IHRydWUsIGRzZDogdHJ1ZSB9KTtcblxuY29uc3Qgc3R5bGVzID0gbmV3IFN0eWxlU2hlZXQoKTtcbnN0eWxlcy5yZXBsYWNlU3luYyhcXGBcbiAgOmhvc3QgeyBkaXNwbGF5OiBpbmxpbmUtZmxleDsgZ2FwOiAwLjVyZW07IGFsaWduLWl0ZW1zOiBjZW50ZXI7IG1hcmdpbi10b3A6IDFyZW07IH1cbiAgYnV0dG9uIHsgcGFkZGluZzogMC4yNXJlbSAwLjc1cmVtOyBjdXJzb3I6IHBvaW50ZXI7IH1cblxcYCk7XG5cbmNvbnN0IGNvdW50ID0gc2lnbmFsKDApO1xuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVJc2xhbmQodGFnTmFtZSwge1xuICBzdHlsZXMsXG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPD5cbiAgICAgICAgPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiBjb3VudC52YWx1ZS0tfT4tPC9idXR0b24+XG4gICAgICAgIDxzcGFuPntjb3VudC52YWx1ZX08L3NwYW4+XG4gICAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gY291bnQudmFsdWUrK30+KzwvYnV0dG9uPlxuICAgICAgPC8+XG4gICAgKTtcbiAgfSxcbn0sIHsgaHlkcmF0ZTogb3BlbkVsZW1lbnQuaHlkcmF0ZSwgZHNkOiBvcGVuRWxlbWVudC5kc2QsIHNzcjogb3BlbkVsZW1lbnQuc3NyIH0pO1xuYCxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFpbigpIHtcbiAgY29uc3QgbmFtZSA9IERlbm8uYXJnc1swXTtcbiAgaWYgKCFuYW1lIHx8IG5hbWUgPT09ICctLWhlbHAnIHx8IG5hbWUgPT09ICctaCcpIHtcbiAgICBjb25zb2xlLmxvZygnVXNhZ2U6IGRlbm8gcnVuIC1BIG5wbTpAb3BlbmVsZW1lbnQvY3JlYXRlIDxwcm9qZWN0LW5hbWU+Jyk7XG4gICAgRGVuby5leGl0KG5hbWUgPyAwIDogMSk7XG4gIH1cblxuICAvLyBILTE0IGZpeDogVmFsaWRhdGUgcHJvamVjdCBuYW1lIGZvcm1hdCB0byBwcmV2ZW50IHBhdGggdHJhdmVyc2FsXG4gIGlmICghL15bYS16QS1aMC05Xy1dKyQvLnRlc3QobmFtZSkpIHtcbiAgICBsb2cuZXJyb3IoXG4gICAgICBgSW52YWxpZCBwcm9qZWN0IG5hbWU6IFwiJHtuYW1lfVwiLiBQcm9qZWN0IG5hbWUgbXVzdCBvbmx5IGNvbnRhaW4gbGV0dGVycywgbnVtYmVycywgdW5kZXJzY29yZXMsIGFuZCBoeXBoZW5zLmAsXG4gICAgKTtcbiAgICBEZW5vLmV4aXQoMSk7XG4gIH1cblxuICBjb25zdCBjd2QgPSBEZW5vLmN3ZCgpO1xuICBjb25zdCB0YXJnZXREaXIgPSByZXNvbHZlKGN3ZCwgbmFtZSk7XG4gIGNvbnN0IHJlbGF0aXZlVGFyZ2V0ID0gcmVsYXRpdmUoY3dkLCB0YXJnZXREaXIpO1xuXG4gIGlmIChcbiAgICAhcmVsYXRpdmVUYXJnZXQgfHxcbiAgICByZWxhdGl2ZVRhcmdldCA9PT0gJy4uJyB8fFxuICAgIHJlbGF0aXZlVGFyZ2V0LnN0YXJ0c1dpdGgoYC4uJHtzZXB9YCkgfHxcbiAgICBpc0Fic29sdXRlKHJlbGF0aXZlVGFyZ2V0KVxuICApIHtcbiAgICBsb2cuZXJyb3IoXG4gICAgICBgUmVmdXNpbmcgdG8gY3JlYXRlIHByb2plY3Qgb3V0c2lkZSB0aGUgY3VycmVudCBkaXJlY3Rvcnk6ICR7bmFtZX1gLFxuICAgICk7XG4gICAgRGVuby5leGl0KDEpO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBEZW5vLnN0YXQodGFyZ2V0RGlyKTtcbiAgICBsb2cuZXJyb3IoYERpcmVjdG9yeSBcIiR7bmFtZX1cIiBhbHJlYWR5IGV4aXN0cy5gKTtcbiAgICBEZW5vLmV4aXQoMSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoIShlIGluc3RhbmNlb2YgRGVuby5lcnJvcnMuTm90Rm91bmQpKSB7XG4gICAgICBsb2cuZXJyb3IoYEZhaWxlZCB0byBpbnNwZWN0IHRhcmdldCBkaXJlY3RvcnkgXCIke25hbWV9XCI6ICR7ZX1gKTtcbiAgICAgIERlbm8uZXhpdCgxKTtcbiAgICB9XG4gIH1cblxuICAvLyBSZXNvbHZlIHBhY2thZ2UgdmVyc2lvbnMgYmVmb3JlIGdlbmVyYXRpbmcgdGVtcGxhdGVzXG4gIGNvbnN0IHYgPSBhd2FpdCByZXNvbHZlVmVyc2lvbnMoKTtcblxuICB0cnkge1xuICAgIGF3YWl0IERlbm8ubWtkaXIodGFyZ2V0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxvZy5lcnJvcihgRmFpbGVkIHRvIGNyZWF0ZSBkaXJlY3RvcnkgXCIke25hbWV9XCI6ICR7ZX1gKTtcbiAgICBEZW5vLmV4aXQoMSk7XG4gIH1cblxuICBjb25zdCBUUEwgPSBidWlsZFRlbXBsYXRlcyh2KTtcbiAgZm9yIChjb25zdCBbcGF0aCwgY29udGVudF0gb2YgT2JqZWN0LmVudHJpZXMoVFBMKSkge1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gam9pbih0YXJnZXREaXIsIHBhdGgpO1xuICAgIGF3YWl0IERlbm8ubWtkaXIoZGlybmFtZShmdWxsUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIGF3YWl0IERlbm8ud3JpdGVUZXh0RmlsZShmdWxsUGF0aCwgY29udGVudCk7XG4gICAgY29uc29sZS5pbmZvKGAgIGNyZWF0ZWQgJHtwYXRofWApO1xuICB9XG5cbiAgY29uc29sZS5pbmZvKGBcXG5vcGVuRWxlbWVudCBwcm9qZWN0IGNyZWF0ZWQgYXQgLi8ke3JlbGF0aXZlVGFyZ2V0fS9gKTtcbiAgY29uc29sZS5pbmZvKGBcXG4gIGNkICR7cmVsYXRpdmVUYXJnZXR9YCk7XG4gIGNvbnNvbGUuaW5mbygnICBkZW5vIHRhc2sgZGV2Jyk7XG59XG5cbm1haW4oKTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUFTLElBQUksUUFBUSxrQkFBa0I7QUFDdkM7Ozs7Ozs7Q0FPQyxHQUVELFNBQVMsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxHQUFHLFFBQVEsWUFBWTtBQUM5RSxTQUFTLGFBQWEsUUFBUSxXQUFXO0FBQ3pDLFNBQVMsWUFBWSxRQUFRLDJCQUEyQjtBQUV4RCxrRUFBa0U7QUFDbEUsdUZBQXVGO0FBQ3ZGLEVBQUU7QUFDRiwyRUFBMkU7QUFDM0Usd0VBQXdFO0FBRXhFLE1BQU0sWUFBWTtBQUNsQixNQUFNLE1BQU0sYUFBYTtBQUN6QixNQUFNLGNBQXNDO0VBQzFDLE1BQU07RUFDTixhQUFhO0VBQ2IsS0FBSztFQUNMLFNBQVM7RUFDVCxJQUFJO0VBQ0osUUFBUTtFQUNSLFNBQVM7QUFDWDtBQUVBLFNBQVMscUJBQXFCLEdBQVc7RUFDdkMsTUFBTSxVQUFVLFlBQVksR0FBRztFQUMvQixNQUFNLFdBQVcsY0FBYyxJQUFJLElBQUksS0FBSztFQUM1QyxNQUFNLE1BQU0sV0FBVyxDQUFDLElBQUksSUFBSTtFQUNoQyxNQUFNLFNBQVMsUUFBUSxVQUFV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
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openelement/create",
|
|
3
|
+
"version": "0.41.0-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./cli.js",
|
|
6
|
+
"types": "./cli.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./cli.d.ts",
|
|
10
|
+
"import": "./cli.js",
|
|
11
|
+
"default": "./cli.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@deno/shim-deno": "~0.19.0"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/open-element/openelement.git"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"openelement",
|
|
23
|
+
"web-components",
|
|
24
|
+
"ssg",
|
|
25
|
+
"framework",
|
|
26
|
+
"deno"
|
|
27
|
+
],
|
|
28
|
+
"bin": {
|
|
29
|
+
"openelement-create": "./cli.js",
|
|
30
|
+
"create-openelement": "./cli.js"
|
|
31
|
+
}
|
|
32
|
+
}
|