nucleus-core-ts 0.9.165 → 0.9.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fe/components/ChatPanel/components/ChatPanel.d.ts +1 -1
- package/dist/fe/components/ChatPanel/components/ChatPanel.js +22 -2
- package/dist/fe/components/ChatPanel/components/NewConversationModal.d.ts +17 -0
- package/dist/fe/components/ChatPanel/components/NewConversationModal.js +107 -0
- package/dist/fe/components/ChatPanel/index.d.ts +2 -1
- package/dist/fe/components/ChatPanel/index.js +1 -0
- package/dist/fe/components/ChatPanel/theme/index.d.ts +15 -0
- package/dist/fe/components/ChatPanel/theme/index.js +16 -1
- package/dist/fe/components/ChatPanel/types/index.d.ts +14 -0
- package/dist/fe/index.d.ts +2 -2
- package/dist/fe/index.js +1 -1
- package/dist/src/Client/ApiCaller/types.d.ts +10 -2
- package/package.json +1 -1
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
3
4
|
import { cn } from '../../../utils/cn';
|
|
4
5
|
import { useChat } from '../hooks/useChat';
|
|
5
6
|
import { chatPanelTheme } from '../theme';
|
|
6
7
|
import { ConversationList } from './ConversationList';
|
|
7
8
|
import { MessageComposer } from './MessageComposer';
|
|
8
9
|
import { MessageThread } from './MessageThread';
|
|
10
|
+
import { NewConversationModal } from './NewConversationModal';
|
|
9
11
|
export function ChatPanel(props) {
|
|
10
12
|
const theme = chatPanelTheme;
|
|
11
13
|
const chat = useChat(props);
|
|
12
14
|
const { store } = chat;
|
|
15
|
+
const [pickerOpen, setPickerOpen] = useState(false);
|
|
13
16
|
const active = store.conversations.find((c)=>c.id === store.activeConversationId) ?? null;
|
|
17
|
+
const handleNewConversation = ()=>{
|
|
18
|
+
if (props.directory) setPickerOpen(true);
|
|
19
|
+
else props.onNewConversation?.();
|
|
20
|
+
};
|
|
21
|
+
const handleStartDirect = (userId)=>{
|
|
22
|
+
chat.startDirect(userId);
|
|
23
|
+
setPickerOpen(false);
|
|
24
|
+
};
|
|
14
25
|
const handleSendFiles = (files, text)=>{
|
|
15
26
|
const conversationId = store.activeConversationId;
|
|
16
27
|
if (!conversationId) return;
|
|
@@ -51,10 +62,10 @@ export function ChatPanel(props) {
|
|
|
51
62
|
className: theme.sidebar.title,
|
|
52
63
|
children: props.title ?? 'Messages'
|
|
53
64
|
}),
|
|
54
|
-
props.onNewConversation && /*#__PURE__*/ _jsx("button", {
|
|
65
|
+
(props.directory || props.onNewConversation) && /*#__PURE__*/ _jsx("button", {
|
|
55
66
|
type: "button",
|
|
56
67
|
className: theme.sidebar.newButton,
|
|
57
|
-
onClick:
|
|
68
|
+
onClick: handleNewConversation,
|
|
58
69
|
"aria-label": "New conversation",
|
|
59
70
|
children: /*#__PURE__*/ _jsxs("svg", {
|
|
60
71
|
className: "h-4 w-4",
|
|
@@ -106,6 +117,15 @@ export function ChatPanel(props) {
|
|
|
106
117
|
className: theme.error,
|
|
107
118
|
children: store.error
|
|
108
119
|
}),
|
|
120
|
+
props.directory && /*#__PURE__*/ _jsx(NewConversationModal, {
|
|
121
|
+
open: pickerOpen,
|
|
122
|
+
directory: props.directory,
|
|
123
|
+
currentUserId: props.currentUserId,
|
|
124
|
+
theme: theme,
|
|
125
|
+
isCreating: props.actions.createConversation.state.isPending,
|
|
126
|
+
onClose: ()=>setPickerOpen(false),
|
|
127
|
+
onStartDirect: handleStartDirect
|
|
128
|
+
}),
|
|
109
129
|
active && /*#__PURE__*/ _jsx(MessageComposer, {
|
|
110
130
|
theme: theme,
|
|
111
131
|
value: store.composerText,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { ChatPanelTheme } from '../theme';
|
|
3
|
+
import type { ChatDirectoryUser } from '../types';
|
|
4
|
+
type NewConversationModalProps = {
|
|
5
|
+
open: boolean;
|
|
6
|
+
directory: ChatDirectoryUser[];
|
|
7
|
+
currentUserId: string;
|
|
8
|
+
theme: ChatPanelTheme;
|
|
9
|
+
isCreating: boolean;
|
|
10
|
+
title?: string;
|
|
11
|
+
searchPlaceholder?: string;
|
|
12
|
+
emptyLabel?: string;
|
|
13
|
+
onClose: () => void;
|
|
14
|
+
onStartDirect: (userId: string) => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function NewConversationModal({ open, directory, currentUserId, theme, isCreating, title, searchPlaceholder, emptyLabel, onClose, onStartDirect, }: NewConversationModalProps): ReactElement | null;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { cn } from '../../../utils/cn';
|
|
5
|
+
import { initialsOf } from '../helpers';
|
|
6
|
+
export function NewConversationModal({ open, directory, currentUserId, theme, isCreating, title = 'New message', searchPlaceholder = 'Search people...', emptyLabel = 'No people found', onClose, onStartDirect }) {
|
|
7
|
+
const [query, setQuery] = useState('');
|
|
8
|
+
if (!open) return null;
|
|
9
|
+
const normalized = query.trim().toLowerCase();
|
|
10
|
+
const people = directory.filter((person)=>person.userId !== currentUserId).filter((person)=>normalized ? person.name.toLowerCase().includes(normalized) || (person.subtitle?.toLowerCase().includes(normalized) ?? false) : true);
|
|
11
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
12
|
+
className: theme.picker.overlay,
|
|
13
|
+
children: [
|
|
14
|
+
/*#__PURE__*/ _jsx("button", {
|
|
15
|
+
type: "button",
|
|
16
|
+
"aria-label": "Close",
|
|
17
|
+
className: "absolute inset-0 h-full w-full cursor-default",
|
|
18
|
+
onClick: onClose
|
|
19
|
+
}),
|
|
20
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
21
|
+
className: cn('relative', theme.picker.panel),
|
|
22
|
+
role: "dialog",
|
|
23
|
+
"aria-modal": "true",
|
|
24
|
+
"aria-label": title,
|
|
25
|
+
children: [
|
|
26
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
27
|
+
className: theme.picker.header,
|
|
28
|
+
children: [
|
|
29
|
+
/*#__PURE__*/ _jsx("span", {
|
|
30
|
+
className: theme.picker.title,
|
|
31
|
+
children: title
|
|
32
|
+
}),
|
|
33
|
+
/*#__PURE__*/ _jsx("button", {
|
|
34
|
+
type: "button",
|
|
35
|
+
className: theme.picker.closeButton,
|
|
36
|
+
onClick: onClose,
|
|
37
|
+
"aria-label": "Close",
|
|
38
|
+
children: /*#__PURE__*/ _jsxs("svg", {
|
|
39
|
+
className: "h-4 w-4",
|
|
40
|
+
fill: "none",
|
|
41
|
+
viewBox: "0 0 24 24",
|
|
42
|
+
stroke: "currentColor",
|
|
43
|
+
children: [
|
|
44
|
+
/*#__PURE__*/ _jsx("title", {
|
|
45
|
+
children: "Close"
|
|
46
|
+
}),
|
|
47
|
+
/*#__PURE__*/ _jsx("path", {
|
|
48
|
+
strokeLinecap: "round",
|
|
49
|
+
strokeLinejoin: "round",
|
|
50
|
+
strokeWidth: 2,
|
|
51
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
52
|
+
})
|
|
53
|
+
]
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
}),
|
|
58
|
+
/*#__PURE__*/ _jsx("div", {
|
|
59
|
+
className: theme.picker.searchWrap,
|
|
60
|
+
children: /*#__PURE__*/ _jsx("input", {
|
|
61
|
+
type: "text",
|
|
62
|
+
className: theme.picker.search,
|
|
63
|
+
placeholder: searchPlaceholder,
|
|
64
|
+
value: query,
|
|
65
|
+
onChange: (event)=>setQuery(event.target.value)
|
|
66
|
+
})
|
|
67
|
+
}),
|
|
68
|
+
/*#__PURE__*/ _jsx("div", {
|
|
69
|
+
className: theme.picker.list,
|
|
70
|
+
children: people.length === 0 ? /*#__PURE__*/ _jsx("div", {
|
|
71
|
+
className: theme.picker.empty,
|
|
72
|
+
children: emptyLabel
|
|
73
|
+
}) : people.map((person)=>/*#__PURE__*/ _jsxs("button", {
|
|
74
|
+
type: "button",
|
|
75
|
+
className: theme.picker.item,
|
|
76
|
+
disabled: isCreating,
|
|
77
|
+
onClick: ()=>onStartDirect(person.userId),
|
|
78
|
+
children: [
|
|
79
|
+
/*#__PURE__*/ _jsx("span", {
|
|
80
|
+
className: theme.picker.avatar,
|
|
81
|
+
children: person.avatarUrl ? /*#__PURE__*/ _jsx("img", {
|
|
82
|
+
src: person.avatarUrl,
|
|
83
|
+
alt: person.name,
|
|
84
|
+
className: "h-full w-full rounded-full object-cover"
|
|
85
|
+
}) : initialsOf(person.name)
|
|
86
|
+
}),
|
|
87
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
88
|
+
className: "min-w-0 flex-1",
|
|
89
|
+
children: [
|
|
90
|
+
/*#__PURE__*/ _jsx("span", {
|
|
91
|
+
className: cn('block', theme.picker.name),
|
|
92
|
+
children: person.name
|
|
93
|
+
}),
|
|
94
|
+
person.subtitle && /*#__PURE__*/ _jsx("span", {
|
|
95
|
+
className: cn('block', theme.picker.subtitle),
|
|
96
|
+
children: person.subtitle
|
|
97
|
+
})
|
|
98
|
+
]
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
}, person.userId))
|
|
102
|
+
})
|
|
103
|
+
]
|
|
104
|
+
})
|
|
105
|
+
]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
@@ -2,7 +2,8 @@ export { ChatPanel } from './components/ChatPanel';
|
|
|
2
2
|
export { ConversationList } from './components/ConversationList';
|
|
3
3
|
export { MessageComposer } from './components/MessageComposer';
|
|
4
4
|
export { MessageThread } from './components/MessageThread';
|
|
5
|
+
export { NewConversationModal } from './components/NewConversationModal';
|
|
5
6
|
export { type UseChatReturn, useChat } from './hooks/useChat';
|
|
6
7
|
export { useChatStore } from './store';
|
|
7
8
|
export { type ChatPanelTheme, chatPanelTheme, extendChatPanelTheme } from './theme';
|
|
8
|
-
export type { ChatAttachmentDTO, ChatConversationDTO, ChatMessageDTO, ChatPanelActions, ChatPanelProps, ChatPanelState, ChatParticipantDTO, TypingIndicator, } from './types';
|
|
9
|
+
export type { ChatAttachmentDTO, ChatConversationDTO, ChatDirectoryUser, ChatMessageDTO, ChatPanelActions, ChatPanelProps, ChatPanelState, ChatParticipantDTO, TypingIndicator, } from './types';
|
|
@@ -2,6 +2,7 @@ export { ChatPanel } from './components/ChatPanel';
|
|
|
2
2
|
export { ConversationList } from './components/ConversationList';
|
|
3
3
|
export { MessageComposer } from './components/MessageComposer';
|
|
4
4
|
export { MessageThread } from './components/MessageThread';
|
|
5
|
+
export { NewConversationModal } from './components/NewConversationModal';
|
|
5
6
|
export { useChat } from './hooks/useChat';
|
|
6
7
|
export { useChatStore } from './store';
|
|
7
8
|
export { chatPanelTheme, extendChatPanelTheme } from './theme';
|
|
@@ -57,6 +57,21 @@ export declare const chatPanelTheme: {
|
|
|
57
57
|
readonly pendingChip: "inline-flex items-center gap-1 rounded-lg bg-zinc-100 px-2 py-1 text-xs text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300";
|
|
58
58
|
};
|
|
59
59
|
readonly error: "border-t border-red-200 bg-red-50 px-4 py-2 text-xs text-red-600 dark:border-red-900 dark:bg-red-950/40 dark:text-red-300";
|
|
60
|
+
readonly picker: {
|
|
61
|
+
readonly overlay: "fixed inset-0 z-50 flex items-start justify-center bg-black/50 p-4 backdrop-blur-sm sm:items-center";
|
|
62
|
+
readonly panel: "flex max-h-[80vh] w-full max-w-md flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-950";
|
|
63
|
+
readonly header: "flex items-center justify-between gap-2 border-b border-zinc-200 px-4 py-3 dark:border-zinc-800";
|
|
64
|
+
readonly title: "text-sm font-semibold";
|
|
65
|
+
readonly closeButton: "inline-flex h-8 w-8 items-center justify-center rounded-lg text-zinc-500 transition hover:bg-zinc-100 dark:hover:bg-zinc-800";
|
|
66
|
+
readonly searchWrap: "border-b border-zinc-200 p-3 dark:border-zinc-800";
|
|
67
|
+
readonly search: "w-full rounded-xl border border-zinc-200 bg-zinc-50 px-3 py-2 text-sm outline-none focus:border-zinc-400 dark:border-zinc-800 dark:bg-zinc-900";
|
|
68
|
+
readonly list: "flex-1 overflow-y-auto p-1.5";
|
|
69
|
+
readonly item: "flex w-full items-center gap-3 rounded-xl px-2.5 py-2 text-left transition hover:bg-zinc-100 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-zinc-900";
|
|
70
|
+
readonly avatar: "flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-full bg-zinc-200 text-sm font-semibold text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300";
|
|
71
|
+
readonly name: "truncate text-sm font-medium";
|
|
72
|
+
readonly subtitle: "truncate text-xs text-zinc-500 dark:text-zinc-400";
|
|
73
|
+
readonly empty: "px-4 py-8 text-center text-sm text-zinc-400";
|
|
74
|
+
};
|
|
60
75
|
};
|
|
61
76
|
export declare function extendChatPanelTheme(overrides: Partial<{
|
|
62
77
|
[K in keyof ChatPanelTheme]: Partial<ChatPanelTheme[K]>;
|
|
@@ -55,7 +55,22 @@ export const chatPanelTheme = {
|
|
|
55
55
|
pendingFiles: 'flex flex-wrap gap-1.5 px-4 pb-2',
|
|
56
56
|
pendingChip: 'inline-flex items-center gap-1 rounded-lg bg-zinc-100 px-2 py-1 text-xs text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300'
|
|
57
57
|
},
|
|
58
|
-
error: 'border-t border-red-200 bg-red-50 px-4 py-2 text-xs text-red-600 dark:border-red-900 dark:bg-red-950/40 dark:text-red-300'
|
|
58
|
+
error: 'border-t border-red-200 bg-red-50 px-4 py-2 text-xs text-red-600 dark:border-red-900 dark:bg-red-950/40 dark:text-red-300',
|
|
59
|
+
picker: {
|
|
60
|
+
overlay: 'fixed inset-0 z-50 flex items-start justify-center bg-black/50 p-4 backdrop-blur-sm sm:items-center',
|
|
61
|
+
panel: 'flex max-h-[80vh] w-full max-w-md flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-950',
|
|
62
|
+
header: 'flex items-center justify-between gap-2 border-b border-zinc-200 px-4 py-3 dark:border-zinc-800',
|
|
63
|
+
title: 'text-sm font-semibold',
|
|
64
|
+
closeButton: 'inline-flex h-8 w-8 items-center justify-center rounded-lg text-zinc-500 transition hover:bg-zinc-100 dark:hover:bg-zinc-800',
|
|
65
|
+
searchWrap: 'border-b border-zinc-200 p-3 dark:border-zinc-800',
|
|
66
|
+
search: 'w-full rounded-xl border border-zinc-200 bg-zinc-50 px-3 py-2 text-sm outline-none focus:border-zinc-400 dark:border-zinc-800 dark:bg-zinc-900',
|
|
67
|
+
list: 'flex-1 overflow-y-auto p-1.5',
|
|
68
|
+
item: 'flex w-full items-center gap-3 rounded-xl px-2.5 py-2 text-left transition hover:bg-zinc-100 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-zinc-900',
|
|
69
|
+
avatar: 'flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-full bg-zinc-200 text-sm font-semibold text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300',
|
|
70
|
+
name: 'truncate text-sm font-medium',
|
|
71
|
+
subtitle: 'truncate text-xs text-zinc-500 dark:text-zinc-400',
|
|
72
|
+
empty: 'px-4 py-8 text-center text-sm text-zinc-400'
|
|
73
|
+
}
|
|
59
74
|
};
|
|
60
75
|
export function extendChatPanelTheme(overrides) {
|
|
61
76
|
const merged = {};
|
|
@@ -43,11 +43,25 @@ export type ChatPanelActions = {
|
|
|
43
43
|
id: string;
|
|
44
44
|
}, ChatActionResponse>;
|
|
45
45
|
};
|
|
46
|
+
/** A selectable person for the built-in "new conversation" people picker. */
|
|
47
|
+
export type ChatDirectoryUser = {
|
|
48
|
+
userId: string;
|
|
49
|
+
name: string;
|
|
50
|
+
avatarUrl?: string;
|
|
51
|
+
/** Secondary line, e.g. job title or department. */
|
|
52
|
+
subtitle?: string;
|
|
53
|
+
};
|
|
46
54
|
export type ChatPanelProps = {
|
|
47
55
|
/** The authenticated user's id (must match the verified session). */
|
|
48
56
|
currentUserId: string;
|
|
49
57
|
/** Generated API actions wired by the consumer. */
|
|
50
58
|
actions: ChatPanelActions;
|
|
59
|
+
/**
|
|
60
|
+
* People the current user can start a conversation with. When provided, the
|
|
61
|
+
* "new conversation" button opens a built-in searchable people picker
|
|
62
|
+
* (Facebook/LinkedIn style). The current user is filtered out automatically.
|
|
63
|
+
*/
|
|
64
|
+
directory?: ChatDirectoryUser[];
|
|
51
65
|
/** Absolute WebSocket origin, e.g. "wss://api.example.com". Defaults to current host. */
|
|
52
66
|
wsUrl?: string;
|
|
53
67
|
/** WebSocket path (default: "/api/events/subscribe"). */
|
package/dist/fe/index.d.ts
CHANGED
|
@@ -9,8 +9,8 @@ export { Captcha, captchaTheme } from './components/Captcha';
|
|
|
9
9
|
export type { ChangePasswordAction, ChangePasswordFormProps, ChangePasswordHeaderProps, ChangePasswordPageConfig, ChangePasswordStep, } from './components/ChangePasswordPage';
|
|
10
10
|
export { ChangePasswordPage, useChangePasswordStore, } from './components/ChangePasswordPage';
|
|
11
11
|
export { Checkbox } from './components/Checkbox';
|
|
12
|
-
export { ChatPanel, chatPanelTheme, extendChatPanelTheme, useChat, useChatStore } from './components/ChatPanel';
|
|
13
|
-
export type { ChatPanelActions, ChatPanelProps, ChatPanelState, ChatPanelTheme, TypingIndicator as ChatTypingIndicator, UseChatReturn, } from './components/ChatPanel';
|
|
12
|
+
export { ChatPanel, chatPanelTheme, extendChatPanelTheme, NewConversationModal, useChat, useChatStore, } from './components/ChatPanel';
|
|
13
|
+
export type { ChatDirectoryUser, ChatPanelActions, ChatPanelProps, ChatPanelState, ChatPanelTheme, TypingIndicator as ChatTypingIndicator, UseChatReturn, } from './components/ChatPanel';
|
|
14
14
|
export { DataTable } from './components/DataTable';
|
|
15
15
|
export { DatePicker } from './components/DatePicker';
|
|
16
16
|
export type { ComponentCategory, ComponentEntry, ComponentExample, DesignSystemMethods, DesignSystemPageProps, DesignSystemState, PropControl, PropControlOption, PropControlType, ThemeMode, ViewportSize, } from './components/DesignSystem';
|
package/dist/fe/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export { Captcha, captchaTheme } from './components/Captcha';
|
|
|
8
8
|
export { ChangePasswordPage, useChangePasswordStore } from './components/ChangePasswordPage';
|
|
9
9
|
export { Checkbox } from './components/Checkbox';
|
|
10
10
|
// Chat
|
|
11
|
-
export { ChatPanel, chatPanelTheme, extendChatPanelTheme, useChat, useChatStore } from './components/ChatPanel';
|
|
11
|
+
export { ChatPanel, chatPanelTheme, extendChatPanelTheme, NewConversationModal, useChat, useChatStore } from './components/ChatPanel';
|
|
12
12
|
export { DataTable } from './components/DataTable';
|
|
13
13
|
export { DatePicker } from './components/DatePicker';
|
|
14
14
|
export { ComponentCanvas, ComponentSidebar, createDefaultRegistry, DesignSystemPage, designSystemTheme, extendDesignSystemTheme, PropsPanel, useDesignSystemStore } from './components/DesignSystem';
|
|
@@ -2322,17 +2322,25 @@ export type AllGeneratedEndpoints<TEntities extends readonly {
|
|
|
2322
2322
|
}[], TExtra extends Record<string, EndpointDefinition> = Record<string, never>> = GeneratedEndpointsFromConfig<TEntities> & AuthEndpointDefinitions & MonitoringEndpointDefinitions & TExtra;
|
|
2323
2323
|
type NucleusColumnTypeToTS<T extends string> = T extends 'integer' | 'smallint' | 'bigint' | 'serial' | 'smallserial' | 'bigserial' | 'real' | 'doublePrecision' | 'numeric' | 'decimal' ? number : T extends 'text' | 'varchar' | 'char' | 'uuid' ? string : T extends 'boolean' ? boolean : T extends 'date' | 'time' | 'timestamp' | 'timestamptz' ? Date | string : T extends 'json' | 'jsonb' ? unknown : unknown;
|
|
2324
2324
|
type SnakeToCamelCase<S extends string> = S extends `${infer T}_${infer U}` ? `${T}${Capitalize<SnakeToCamelCase<U>>}` : S;
|
|
2325
|
+
/** Maps a column to its TS type, wrapping `array: true` columns as `T[]`. */
|
|
2326
|
+
type ColumnTsType<C extends {
|
|
2327
|
+
type: string;
|
|
2328
|
+
array?: boolean;
|
|
2329
|
+
}> = C extends {
|
|
2330
|
+
array: true;
|
|
2331
|
+
} ? NucleusColumnTypeToTS<C['type']>[] : NucleusColumnTypeToTS<C['type']>;
|
|
2325
2332
|
type ColumnsToEntity<TColumns extends readonly {
|
|
2326
2333
|
name: string;
|
|
2327
2334
|
type: string;
|
|
2335
|
+
array?: boolean;
|
|
2328
2336
|
}[]> = {
|
|
2329
2337
|
[C in Extract<TColumns[number], {
|
|
2330
2338
|
notNull: true;
|
|
2331
|
-
}> as SnakeToCamelCase<C['name']>]:
|
|
2339
|
+
}> as SnakeToCamelCase<C['name']>]: ColumnTsType<C>;
|
|
2332
2340
|
} & {
|
|
2333
2341
|
[C in Exclude<TColumns[number], {
|
|
2334
2342
|
notNull: true;
|
|
2335
|
-
}> as SnakeToCamelCase<C['name']>]:
|
|
2343
|
+
}> as SnakeToCamelCase<C['name']>]: ColumnTsType<C> | null;
|
|
2336
2344
|
};
|
|
2337
2345
|
type BaseEntityFields = {
|
|
2338
2346
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nucleus-core-ts",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.167",
|
|
4
4
|
"description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
|
|
5
5
|
"author": "Hidayet Can Özcan <hidayetcan@gmail.com>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|