create-aiaui-module 0.0.0-stage → 0.1.1-TEST
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -2
- package/bin/create-aiaui-module.js +137 -0
- package/package.json +30 -4
- package/runtime/__init__.py +82 -0
- package/runtime/_runtime/__init__.py +40 -0
- package/runtime/_runtime/host.py +88 -0
- package/runtime/_runtime/loader.py +39 -0
- package/runtime/_runtime/registry.py +93 -0
- package/src/errors.js +6 -0
- package/src/generator.js +194 -0
- package/src/protocol.js +98 -0
- package/templates/HelloWorld/README.md +13 -0
- package/templates/HelloWorld/contractVersion +1 -0
- package/templates/HelloWorld/resources/build.mjs +9 -0
- package/templates/HelloWorld/resources/dist/manifest.json +6 -0
- package/templates/HelloWorld/resources/dist/modules.js +3753 -0
- package/templates/HelloWorld/resources/package.json +12 -0
- package/templates/HelloWorld/resources/src/Hello.ce.vue +25 -0
- package/templates/HelloWorld/resources/src/index.ts +32 -0
- package/templates/HelloWorld/resources/vite.config.mjs +13 -0
- package/templates/JobInformation/CUSTOMIZATION.md +173 -0
- package/templates/JobInformation/README.md +114 -0
- package/templates/JobInformation/api.py +53 -0
- package/templates/JobInformation/contractVersion +1 -0
- package/templates/JobInformation/resources/build.mjs +9 -0
- package/templates/JobInformation/resources/dist/manifest.json +6 -0
- package/templates/JobInformation/resources/dist/modules.js +2919 -0
- package/templates/JobInformation/resources/package-lock.json +1032 -0
- package/templates/JobInformation/resources/package.json +15 -0
- package/templates/JobInformation/resources/src/bus.ts +38 -0
- package/templates/JobInformation/resources/src/contract.ts +74 -0
- package/templates/JobInformation/resources/src/customization.ts +25 -0
- package/templates/JobInformation/resources/src/defaults/DefaultPanel.vue +22 -0
- package/templates/JobInformation/resources/src/defaults/Header.vue +12 -0
- package/templates/JobInformation/resources/src/defaults/InputCarriers.vue +15 -0
- package/templates/JobInformation/resources/src/defaults/OutputCarriers.vue +14 -0
- package/templates/JobInformation/resources/src/defaults/Recipe.vue +18 -0
- package/templates/JobInformation/resources/src/defaults/Timeline.vue +22 -0
- package/templates/JobInformation/resources/src/defaults/slots.ts +16 -0
- package/templates/JobInformation/resources/src/defaults/styles.css +90 -0
- package/templates/JobInformation/resources/src/index.ts +45 -0
- package/templates/JobInformation/resources/src/vite-env.d.ts +1 -0
- package/templates/JobInformation/resources/vite.config.mjs +27 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aiaui-job-information-template",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "node build.mjs",
|
|
7
|
+
"dev": "vite build --watch"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": { "vue": "^3.5.0" },
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@vitejs/plugin-vue": "^6.0.0",
|
|
12
|
+
"typescript": "^5.9.0",
|
|
13
|
+
"vite": "^8.0.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ModuleBus, ModuleBusListener } from "./contract";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create a per-mount communication bus.
|
|
5
|
+
*
|
|
6
|
+
* Not a singleton: `index.ts` creates one bus per `mount`, so it dies with
|
|
7
|
+
* unmount and is re-born on the next mount of the same module (for example
|
|
8
|
+
* when the user switches Instance in the UI).
|
|
9
|
+
*/
|
|
10
|
+
export function createBus(): ModuleBus {
|
|
11
|
+
const listeners = new Map<string, Set<ModuleBusListener>>();
|
|
12
|
+
const handles = new Map<string, object>();
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
emit(event, payload) {
|
|
16
|
+
for (const listener of [...(listeners.get(event) ?? [])]) {
|
|
17
|
+
listener(payload);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
on(event, listener) {
|
|
21
|
+
const current = listeners.get(event) ?? new Set<ModuleBusListener>();
|
|
22
|
+
current.add(listener);
|
|
23
|
+
listeners.set(event, current);
|
|
24
|
+
},
|
|
25
|
+
off(event, listener) {
|
|
26
|
+
listeners.get(event)?.delete(listener);
|
|
27
|
+
},
|
|
28
|
+
expose(name, handle) {
|
|
29
|
+
handles.set(name, handle);
|
|
30
|
+
},
|
|
31
|
+
release(name) {
|
|
32
|
+
handles.delete(name);
|
|
33
|
+
},
|
|
34
|
+
peer(name) {
|
|
35
|
+
return handles.get(name);
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Component } from "vue";
|
|
2
|
+
|
|
3
|
+
export type ModuleApi = {
|
|
4
|
+
call<T>(
|
|
5
|
+
method: string,
|
|
6
|
+
path: string,
|
|
7
|
+
options?: { query?: Record<string, unknown>; body?: unknown },
|
|
8
|
+
): Promise<T>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/** Bus listener signature. Payload is deliberately loose; type it at the use site. */
|
|
12
|
+
export type ModuleBusListener = (payload?: any) => void;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A tiny communication bus shared by every slot component of one mount.
|
|
16
|
+
*
|
|
17
|
+
* - `emit` / `on` / `off` — decoupled events between slots
|
|
18
|
+
* - `expose` / `peer` — imperative handles published by one slot and called by another
|
|
19
|
+
*
|
|
20
|
+
* The bus is created per `mount` by `index.ts`. It never crosses module or
|
|
21
|
+
* Instance boundaries: switching an Instance mounts a fresh bus.
|
|
22
|
+
*/
|
|
23
|
+
export type ModuleBus = {
|
|
24
|
+
emit(event: string, payload?: unknown): void;
|
|
25
|
+
on(event: string, listener: ModuleBusListener): void;
|
|
26
|
+
off(event: string, listener: ModuleBusListener): void;
|
|
27
|
+
expose<T extends object>(name: string, handle: T): void;
|
|
28
|
+
release(name: string): void;
|
|
29
|
+
peer<T extends object>(name: string): T | undefined;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type ModuleContext = {
|
|
33
|
+
module: string;
|
|
34
|
+
instanceId: string;
|
|
35
|
+
api: ModuleApi;
|
|
36
|
+
signal: AbortSignal;
|
|
37
|
+
/** Sibling-slot communication; created per mount. See CUSTOMIZATION.md. */
|
|
38
|
+
bus: ModuleBus;
|
|
39
|
+
place: (spec: {
|
|
40
|
+
kind: "route" | "slot";
|
|
41
|
+
path?: string;
|
|
42
|
+
slot?: string;
|
|
43
|
+
label?: string;
|
|
44
|
+
order?: number;
|
|
45
|
+
}) => void;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* What the host platform actually passes into `mount`. The module enriches
|
|
50
|
+
* it with `bus` before slot components ever see it; slots always receive the
|
|
51
|
+
* full `ModuleContext` (with `bus`).
|
|
52
|
+
*/
|
|
53
|
+
export type HostModuleContext = Omit<ModuleContext, "bus">;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A replaceable UI box. Slot components receive `context` as their only prop,
|
|
57
|
+
* so a developer can swap any box while keeping access to the module API.
|
|
58
|
+
*/
|
|
59
|
+
export type SlotComponent = Component;
|
|
60
|
+
|
|
61
|
+
export type SlotMap = Record<string, SlotComponent>;
|
|
62
|
+
|
|
63
|
+
export type SlotCustomization = {
|
|
64
|
+
mode?: "slots";
|
|
65
|
+
slots?: SlotMap;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type FullCustomization = {
|
|
69
|
+
mode: "full";
|
|
70
|
+
mount: (container: HTMLElement, context: ModuleContext) => void | Promise<void>;
|
|
71
|
+
unmount: () => void;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type Customization = SlotCustomization | FullCustomization;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Customization } from "./contract";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Developer customization entry point.
|
|
5
|
+
*
|
|
6
|
+
* Default (no change): keeps the built-in panel.
|
|
7
|
+
*
|
|
8
|
+
* Partial (replace individual boxes):
|
|
9
|
+
* import MyHeader from "./custom/MyHeader.vue";
|
|
10
|
+
* export const customization: Customization = {
|
|
11
|
+
* mode: "slots",
|
|
12
|
+
* slots: { header: MyHeader },
|
|
13
|
+
* };
|
|
14
|
+
*
|
|
15
|
+
* Full (replace the entire module):
|
|
16
|
+
* export const customization: Customization = {
|
|
17
|
+
* mode: "full",
|
|
18
|
+
* mount(container, context) { ... },
|
|
19
|
+
* unmount() { ... },
|
|
20
|
+
* };
|
|
21
|
+
*/
|
|
22
|
+
export const customization: Customization = {
|
|
23
|
+
mode: "slots",
|
|
24
|
+
slots: {},
|
|
25
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { Component } from "vue";
|
|
3
|
+
import type { ModuleContext } from "../contract";
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
context: ModuleContext;
|
|
7
|
+
slots: Record<string, Component>;
|
|
8
|
+
slotOrder: string[];
|
|
9
|
+
}>();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<main class="aia-job-information">
|
|
14
|
+
<component
|
|
15
|
+
v-for="name in props.slotOrder"
|
|
16
|
+
v-if="props.slots[name]"
|
|
17
|
+
:key="name"
|
|
18
|
+
:is="props.slots[name]"
|
|
19
|
+
:context="props.context"
|
|
20
|
+
/>
|
|
21
|
+
</main>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ModuleContext } from "../contract";
|
|
3
|
+
|
|
4
|
+
defineProps<{ context: ModuleContext }>();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<section class="aiaji-slot aiaji-header">
|
|
9
|
+
<div class="aiaji-crumb">OB-260920-014 <span aria-hidden="true">></span> LOT-A3471</div>
|
|
10
|
+
<div class="aiaji-state">WaitingForStart</div>
|
|
11
|
+
</section>
|
|
12
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ModuleContext } from "../contract";
|
|
3
|
+
|
|
4
|
+
defineProps<{ context: ModuleContext }>();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<section class="aiaji-slot aiaji-carriers aiaji-carriers-input">
|
|
9
|
+
<h3>INPUT CARRIER(S)</h3>
|
|
10
|
+
<ul>
|
|
11
|
+
<li>CR-01</li>
|
|
12
|
+
<li>CR-02</li>
|
|
13
|
+
</ul>
|
|
14
|
+
</section>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ModuleContext } from "../contract";
|
|
3
|
+
|
|
4
|
+
defineProps<{ context: ModuleContext }>();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<section class="aiaji-slot aiaji-carriers aiaji-carriers-output">
|
|
9
|
+
<h3>OUTPUT CARRIER(S)</h3>
|
|
10
|
+
<ul>
|
|
11
|
+
<li>—</li>
|
|
12
|
+
</ul>
|
|
13
|
+
</section>
|
|
14
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ModuleContext } from "../contract";
|
|
3
|
+
|
|
4
|
+
defineProps<{ context: ModuleContext }>();
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<section class="aiaji-slot aiaji-recipe">
|
|
9
|
+
<div class="aiaji-meta">
|
|
10
|
+
<span>WO1 WO2 WO3 W17</span>
|
|
11
|
+
<span>42.6 Pa / 620W</span>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="aiaji-recipe-row">
|
|
14
|
+
<span class="aiaji-recipe-name">RCP-CU-ETCH-O7</span>
|
|
15
|
+
<button type="button">View all</button>
|
|
16
|
+
</div>
|
|
17
|
+
</section>
|
|
18
|
+
</template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { ModuleContext } from "../contract";
|
|
3
|
+
|
|
4
|
+
defineProps<{ context: ModuleContext }>();
|
|
5
|
+
|
|
6
|
+
const steps = ["Waiting for Start", "Start", "Executing", "Finished"];
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<section class="aiaji-slot aiaji-timeline">
|
|
11
|
+
<h3>Progress</h3>
|
|
12
|
+
<ol>
|
|
13
|
+
<li
|
|
14
|
+
v-for="(step, index) in steps"
|
|
15
|
+
:key="step"
|
|
16
|
+
:class="{ 'aiaji-active': index === 0 }"
|
|
17
|
+
>
|
|
18
|
+
{{ step }}
|
|
19
|
+
</li>
|
|
20
|
+
</ol>
|
|
21
|
+
</section>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SlotMap } from "../contract";
|
|
2
|
+
import Header from "./Header.vue";
|
|
3
|
+
import InputCarriers from "./InputCarriers.vue";
|
|
4
|
+
import OutputCarriers from "./OutputCarriers.vue";
|
|
5
|
+
import Timeline from "./Timeline.vue";
|
|
6
|
+
import Recipe from "./Recipe.vue";
|
|
7
|
+
|
|
8
|
+
export const defaultSlots: SlotMap = {
|
|
9
|
+
header: Header,
|
|
10
|
+
inputCarriers: InputCarriers,
|
|
11
|
+
outputCarriers: OutputCarriers,
|
|
12
|
+
timeline: Timeline,
|
|
13
|
+
recipe: Recipe,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const slotOrder = ["header", "inputCarriers", "outputCarriers", "timeline", "recipe"];
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
.aia-job-information {
|
|
2
|
+
display: grid;
|
|
3
|
+
gap: 16px;
|
|
4
|
+
padding: 20px;
|
|
5
|
+
color: var(--aia-text, #222);
|
|
6
|
+
font: inherit;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.aiaji-slot h3 {
|
|
10
|
+
margin: 0 0 8px;
|
|
11
|
+
font-size: 0.85rem;
|
|
12
|
+
letter-spacing: 0.04em;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.aiaji-slot button {
|
|
16
|
+
font: inherit;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.aiaji-header {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
justify-content: space-between;
|
|
24
|
+
gap: 12px;
|
|
25
|
+
border-bottom: 1px solid var(--aia-border, #e5e7eb);
|
|
26
|
+
padding-bottom: 12px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.aiaji-crumb {
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.aiaji-state {
|
|
34
|
+
border: 1px solid var(--aia-border, #e5e7eb);
|
|
35
|
+
border-radius: 999px;
|
|
36
|
+
padding: 4px 12px;
|
|
37
|
+
color: var(--aia-accent, #2563eb);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.aiaji-carriers {
|
|
41
|
+
border: 1px solid var(--aia-border, #e5e7eb);
|
|
42
|
+
border-radius: 8px;
|
|
43
|
+
padding: 12px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.aiaji-carriers ul {
|
|
47
|
+
margin: 0;
|
|
48
|
+
padding-left: 20px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.aiaji-timeline ol {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-wrap: wrap;
|
|
54
|
+
gap: 8px;
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 0;
|
|
57
|
+
list-style: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.aiaji-timeline li {
|
|
61
|
+
border: 1px solid var(--aia-border, #e5e7eb);
|
|
62
|
+
border-radius: 999px;
|
|
63
|
+
padding: 6px 12px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.aiaji-timeline li.aiaji-active {
|
|
67
|
+
border-color: var(--aia-accent, #2563eb);
|
|
68
|
+
color: var(--aia-accent, #2563eb);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.aiaji-recipe {
|
|
72
|
+
display: grid;
|
|
73
|
+
gap: 10px;
|
|
74
|
+
border: 1px solid var(--aia-border, #e5e7eb);
|
|
75
|
+
border-radius: 8px;
|
|
76
|
+
padding: 12px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.aiaji-meta,
|
|
80
|
+
.aiaji-recipe-row {
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-wrap: wrap;
|
|
83
|
+
gap: 12px;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: space-between;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.aiaji-recipe-name {
|
|
89
|
+
font-weight: 600;
|
|
90
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { createApp, type App } from "vue";
|
|
2
|
+
import DefaultPanel from "./defaults/DefaultPanel.vue";
|
|
3
|
+
import { defaultSlots, slotOrder } from "./defaults/slots";
|
|
4
|
+
import { customization } from "./customization";
|
|
5
|
+
import { createBus } from "./bus";
|
|
6
|
+
import type { HostModuleContext, ModuleContext } from "./contract";
|
|
7
|
+
import defaultStyles from "./defaults/styles.css?inline";
|
|
8
|
+
|
|
9
|
+
let app: App | null = null;
|
|
10
|
+
let styleElement: HTMLStyleElement | null = null;
|
|
11
|
+
|
|
12
|
+
function ensureStyles() {
|
|
13
|
+
if (styleElement) return;
|
|
14
|
+
styleElement = document.createElement("style");
|
|
15
|
+
styleElement.textContent = defaultStyles;
|
|
16
|
+
document.head.appendChild(styleElement);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function mount(container: HTMLElement, context: HostModuleContext) {
|
|
20
|
+
context.place({ kind: "route", path: "/jobs", label: "Jobs", order: 20 });
|
|
21
|
+
|
|
22
|
+
// One bus per mount: every slot component of this mount (built-in, custom,
|
|
23
|
+
// or full-mode) shares it via `context.bus`, and it dies on unmount.
|
|
24
|
+
const moduleContext: ModuleContext = { ...context, bus: createBus() };
|
|
25
|
+
|
|
26
|
+
if (customization.mode === "full") {
|
|
27
|
+
return customization.mount(container, moduleContext);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
ensureStyles();
|
|
31
|
+
const slots = { ...defaultSlots, ...(customization.slots ?? {}) };
|
|
32
|
+
app = createApp(DefaultPanel, { context: moduleContext, slots, slotOrder });
|
|
33
|
+
app.mount(container);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function unmount() {
|
|
37
|
+
if (customization.mode === "full") {
|
|
38
|
+
customization.unmount();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
app?.unmount();
|
|
42
|
+
app = null;
|
|
43
|
+
styleElement?.remove();
|
|
44
|
+
styleElement = null;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
import vue from "@vitejs/plugin-vue";
|
|
4
|
+
|
|
5
|
+
const manifest = { entry: "modules.js", files: ["modules.js"] };
|
|
6
|
+
|
|
7
|
+
// Write manifest on every emit, including `vite build --watch`, so running
|
|
8
|
+
// `npm run dev` never leaves `dist/` without a valid manifest.json.
|
|
9
|
+
function manifestPlugin() {
|
|
10
|
+
return {
|
|
11
|
+
name: "aiaui-module-manifest",
|
|
12
|
+
writeBundle() {
|
|
13
|
+
writeFileSync("dist/manifest.json", JSON.stringify(manifest, null, 2) + "\n");
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
plugins: [vue(), manifestPlugin()],
|
|
20
|
+
// Browser builds must never reference Node's `process` global.
|
|
21
|
+
// Collapse Vue's process.env.NODE_ENV guards at build time.
|
|
22
|
+
define: { "process.env.NODE_ENV": JSON.stringify("production") },
|
|
23
|
+
build: {
|
|
24
|
+
emptyOutDir: true,
|
|
25
|
+
lib: { entry: "src/index.ts", formats: ["es"], fileName: "modules" },
|
|
26
|
+
},
|
|
27
|
+
});
|