@mashkovd/pelican-vue 0.2.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/README.md +100 -0
- package/dist/index.d.ts +162 -0
- package/dist/pelican-libertex-social.mjs +1530 -0
- package/dist/pelican-libertex-social.mjs.map +1 -0
- package/dist/pelican-libertex-social.umd.cjs +2 -0
- package/dist/pelican-libertex-social.umd.cjs.map +1 -0
- package/dist/style.css +1 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# @mashkovd/pelican-vue
|
|
2
|
+
|
|
3
|
+
Vue 3 component for browsing Libertex Social copy-trading strategies via a
|
|
4
|
+
[`pelican-libertex-social`](../README.md) proxy. Drop it into any Vue 3 app
|
|
5
|
+
that can reach a running proxy (the proxy handles OIDC token refresh and
|
|
6
|
+
upstream rate-limiting; this component only consumes its REST surface).
|
|
7
|
+
|
|
8
|
+
A live proxy is hosted at `https://labs-pelican-proxy.mctl.ai` — point
|
|
9
|
+
`api-base` at it to skip running your own.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npm install @mashkovd/pelican-vue
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`vue@^3.4` is a peer dependency — make sure it's already in your host app.
|
|
18
|
+
|
|
19
|
+
## Use
|
|
20
|
+
|
|
21
|
+
```vue
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { PelicanLibertexSocial } from '@mashkovd/pelican-vue';
|
|
24
|
+
import '@mashkovd/pelican-vue/style.css';
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<PelicanLibertexSocial api-base="https://labs-pelican-proxy.mctl.ai" />
|
|
29
|
+
</template>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
That's it. The component handles everything else — fetching the catalog,
|
|
33
|
+
filters, sort, lazy enrichment, trade panels, theme toggle.
|
|
34
|
+
|
|
35
|
+
### CORS / dev-server proxy
|
|
36
|
+
|
|
37
|
+
If your host app and the Pelican proxy live on different origins, the
|
|
38
|
+
browser will block the cross-origin fetch unless the proxy explicitly
|
|
39
|
+
allows your origin (it does not, by default).
|
|
40
|
+
|
|
41
|
+
The cleanest workaround is to proxy `/api` through your own dev/prod
|
|
42
|
+
server:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// vite.config.ts
|
|
46
|
+
export default defineConfig({
|
|
47
|
+
server: {
|
|
48
|
+
proxy: {
|
|
49
|
+
'/api': 'https://labs-pelican-proxy.mctl.ai',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
…and pass an empty `api-base` so the component issues relative requests:
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<PelicanLibertexSocial api-base="" />
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For Nuxt, declare a `routeRules` proxy. For Quasar, set `devServer.proxy`
|
|
62
|
+
in `quasar.config.js`.
|
|
63
|
+
|
|
64
|
+
## Props
|
|
65
|
+
|
|
66
|
+
| prop | type | default | notes |
|
|
67
|
+
| ---------------- | --------------------------------- | ---------------- | ---------------------------------------- |
|
|
68
|
+
| `apiBase` | `string` (required) | — | Base URL of the pelican proxy |
|
|
69
|
+
| `theme` | `'auto' \| 'dark' \| 'light'` | `'auto'` | Persists in `localStorage['pelican-theme']` |
|
|
70
|
+
| `defaultSort` | `SortKey` | `'return-desc'` | One of 20 sort modes |
|
|
71
|
+
| `defaultFilters` | `Partial<FiltersState>` | `{}` | Initial filter values |
|
|
72
|
+
| `locale` | `string` | `'en-US'` | Used for number/date formatting |
|
|
73
|
+
| `pageSize` | `number` | `20` | Rows per page |
|
|
74
|
+
|
|
75
|
+
## Emits
|
|
76
|
+
|
|
77
|
+
| event | payload | when |
|
|
78
|
+
| ------------------ | ---------------------------------------------------------------------- | --------------------------------- |
|
|
79
|
+
| `update:theme` | `'auto' \| 'dark' \| 'light'` | User cycled the theme toggle |
|
|
80
|
+
| `select-strategy` | `Strategy` | A row was expanded |
|
|
81
|
+
| `error` | `{ code: 'no_token' \| 'fetch_failed' \| 'http_error' \| string, message }` | Network / proxy error |
|
|
82
|
+
|
|
83
|
+
## Slots
|
|
84
|
+
|
|
85
|
+
- `#brand` — replace the default header/brand block.
|
|
86
|
+
- `#empty` — replace the empty-state copy when filters match nothing.
|
|
87
|
+
- `#row-actions` — append controls to each row (`{ strategy }` slot scope).
|
|
88
|
+
|
|
89
|
+
## Dev
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
cd vue
|
|
93
|
+
npm install
|
|
94
|
+
npm run dev # Vite playground at :5173, proxies /api → :8787
|
|
95
|
+
npm run build # produces dist/ (ESM + UMD + style.css + .d.ts)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## License
|
|
99
|
+
|
|
100
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { ComponentOptionsMixin } from 'vue';
|
|
2
|
+
import { ComponentProvideOptions } from 'vue';
|
|
3
|
+
import { DefineComponent } from 'vue';
|
|
4
|
+
import { PublicProps } from 'vue';
|
|
5
|
+
|
|
6
|
+
declare const __VLS_component: DefineComponent<__VLS_Props, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {} & {
|
|
7
|
+
error: (err: PelicanError) => any;
|
|
8
|
+
"update:theme": (m: ThemeMode) => any;
|
|
9
|
+
"select-strategy": (s: Strategy) => any;
|
|
10
|
+
}, string, PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
11
|
+
onError?: ((err: PelicanError) => any) | undefined;
|
|
12
|
+
"onUpdate:theme"?: ((m: ThemeMode) => any) | undefined;
|
|
13
|
+
"onSelect-strategy"?: ((s: Strategy) => any) | undefined;
|
|
14
|
+
}>, {
|
|
15
|
+
locale: string;
|
|
16
|
+
theme: ThemeMode;
|
|
17
|
+
defaultSort: SortKey;
|
|
18
|
+
pageSize: number;
|
|
19
|
+
}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
20
|
+
|
|
21
|
+
declare type __VLS_Props = {
|
|
22
|
+
apiBase: string;
|
|
23
|
+
theme?: ThemeMode;
|
|
24
|
+
defaultSort?: SortKey;
|
|
25
|
+
defaultFilters?: Partial<FiltersState>;
|
|
26
|
+
columns?: ColumnKey[];
|
|
27
|
+
locale?: string;
|
|
28
|
+
pageSize?: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
declare function __VLS_template(): {
|
|
32
|
+
attrs: Partial<{}>;
|
|
33
|
+
slots: {
|
|
34
|
+
brand?(_: {}): any;
|
|
35
|
+
empty?(_: {}): any;
|
|
36
|
+
'row-actions'?(_: {
|
|
37
|
+
strategy: Strategy;
|
|
38
|
+
}): any;
|
|
39
|
+
};
|
|
40
|
+
refs: {};
|
|
41
|
+
rootEl: HTMLDivElement;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
declare type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
|
|
45
|
+
|
|
46
|
+
declare type __VLS_WithTemplateSlots<T, S> = T & {
|
|
47
|
+
new (): {
|
|
48
|
+
$slots: S;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export declare type ColumnKey = 'name' | 'spark' | 'return' | 'copiers' | 'aum' | 'dd' | 'age' | 'balance' | 'fee' | 'link';
|
|
53
|
+
|
|
54
|
+
export declare function defaultFilters(): FiltersState;
|
|
55
|
+
|
|
56
|
+
export declare interface FiltersState {
|
|
57
|
+
risk: Set<RiskLevel>;
|
|
58
|
+
retMin: number | null;
|
|
59
|
+
retMax: number | null;
|
|
60
|
+
ddMax: number | null;
|
|
61
|
+
aumMin: number | null;
|
|
62
|
+
copiersMin: number | null;
|
|
63
|
+
ageMin: number | null;
|
|
64
|
+
tradesMin: number | null;
|
|
65
|
+
winrateMin: number | null;
|
|
66
|
+
feeMax: number | null;
|
|
67
|
+
balanceMin: number | null;
|
|
68
|
+
balanceMax: number | null;
|
|
69
|
+
search: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export declare interface HistoryPoint {
|
|
73
|
+
Timestamp: string;
|
|
74
|
+
AccountReturn: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export declare interface MarketSlice {
|
|
78
|
+
n: string;
|
|
79
|
+
c: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export declare interface PelicanError extends Error {
|
|
83
|
+
code: 'no_token' | 'fetch_failed' | 'http_error';
|
|
84
|
+
status?: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export declare const PelicanLibertexSocial: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
|
|
88
|
+
|
|
89
|
+
export declare interface ProgressResponse {
|
|
90
|
+
ready: boolean;
|
|
91
|
+
building: boolean;
|
|
92
|
+
loaded: number;
|
|
93
|
+
total: number;
|
|
94
|
+
built_at: number | null;
|
|
95
|
+
schedule?: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export declare type RiskLevel = 'Low' | 'Medium' | 'High' | 'Unsuitable';
|
|
99
|
+
|
|
100
|
+
export declare type SignalKind = 'open' | 'closed';
|
|
101
|
+
|
|
102
|
+
export declare const SORT_KEYS: readonly ["return-desc", "return-asc", "copiers-desc", "copiers-asc", "aum-desc", "aum-asc", "dd-asc", "dd-desc", "fee-asc", "fee-desc", "age-desc", "age-asc", "balance-desc", "balance-asc", "winrate-desc", "winrate-asc", "trades-desc", "trades-asc", "monthly-desc", "monthly-asc"];
|
|
103
|
+
|
|
104
|
+
export declare const SORT_LABELS: Record<SortKey, string>;
|
|
105
|
+
|
|
106
|
+
export declare const SORT_TOGGLE: Record<SortColumn, [SortKey, SortKey]>;
|
|
107
|
+
|
|
108
|
+
export declare type SortColumn = 'return' | 'copiers' | 'aum' | 'dd' | 'fee' | 'age' | 'balance';
|
|
109
|
+
|
|
110
|
+
export declare type SortKey = (typeof SORT_KEYS)[number];
|
|
111
|
+
|
|
112
|
+
export declare interface Strategy {
|
|
113
|
+
Id: number;
|
|
114
|
+
Name: string | null;
|
|
115
|
+
ImageUploaded?: boolean | null;
|
|
116
|
+
Profile: StrategyProfile | null;
|
|
117
|
+
NumCopiers: number | null;
|
|
118
|
+
Fee: number | null;
|
|
119
|
+
RiskProfile: RiskLevel | null;
|
|
120
|
+
IsSimulated: boolean;
|
|
121
|
+
IsEnabled: boolean | null;
|
|
122
|
+
Inception: string | null;
|
|
123
|
+
Currency: string | null;
|
|
124
|
+
Return: number | null;
|
|
125
|
+
MaxDD: number | null;
|
|
126
|
+
RealisedPnl: number | null;
|
|
127
|
+
UnrealisedPnl: number | null;
|
|
128
|
+
History: HistoryPoint[];
|
|
129
|
+
TradesTotal: number;
|
|
130
|
+
Wins: number;
|
|
131
|
+
Losses: number;
|
|
132
|
+
Markets: MarketSlice[];
|
|
133
|
+
AccountBalance: number | null;
|
|
134
|
+
CopiersAUM: number | null;
|
|
135
|
+
MonthlyProfit: number | null;
|
|
136
|
+
YearlyProfit: number | null;
|
|
137
|
+
_stats?: boolean;
|
|
138
|
+
_meta?: boolean;
|
|
139
|
+
_enrichAttempted?: boolean;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
declare interface StrategyProfile {
|
|
143
|
+
Id?: number | string;
|
|
144
|
+
Name?: string | null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export declare type ThemeMode = 'auto' | 'dark' | 'light';
|
|
148
|
+
|
|
149
|
+
export declare interface Trade {
|
|
150
|
+
Id?: number;
|
|
151
|
+
MarketName?: string;
|
|
152
|
+
OpenTimestamp?: string;
|
|
153
|
+
CloseTimestamp?: string | null;
|
|
154
|
+
Direction?: 'Buy' | 'Sell' | string;
|
|
155
|
+
Pnl?: number;
|
|
156
|
+
Volume?: number;
|
|
157
|
+
Multiplier?: number;
|
|
158
|
+
OpenPrice?: number;
|
|
159
|
+
ClosePrice?: number;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { }
|