nucleus-core-ts 0.9.882 → 0.9.883

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/.build-ok CHANGED
@@ -1 +1 @@
1
- 0.9.882
1
+ 0.9.883
@@ -1,5 +1,5 @@
1
- import { type ChatPanelLabels } from '../labels';
2
1
  import type { ReactElement } from 'react';
2
+ import { type ChatPanelLabels } from '../labels';
3
3
  import type { ChatPanelTheme } from '../theme';
4
4
  import type { ChatConversationDTO } from '../types';
5
5
  type ConversationListProps = {
@@ -1,8 +1,8 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DEFAULT_CHAT_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
3
  import { cn } from '../../../utils/cn';
5
4
  import { conversationTitle, formatRelativeTime, initialsOf, otherParticipantId } from '../helpers';
5
+ import { DEFAULT_CHAT_LABELS } from '../labels';
6
6
  export function ConversationList({ conversations, activeId, currentUserId, isLoading, theme, onSelect, resolveUserName, resolveUserAvatar, labels }) {
7
7
  const say = {
8
8
  ...DEFAULT_CHAT_LABELS,
@@ -1,5 +1,5 @@
1
- import { type ChatPanelLabels } from '../labels';
2
1
  import type { ReactElement } from 'react';
2
+ import { type ChatPanelLabels } from '../labels';
3
3
  import type { ChatPanelTheme } from '../theme';
4
4
  type MessageComposerProps = {
5
5
  labels?: Partial<ChatPanelLabels>;
@@ -1,7 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { DEFAULT_CHAT_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
3
  import { useRef, useState } from 'react';
4
+ import { DEFAULT_CHAT_LABELS } from '../labels';
5
5
  export function MessageComposer({ theme, value, disabled, uploadEnabled, onChange, onSendText, onSendFiles, labels }) {
6
6
  const say = {
7
7
  ...DEFAULT_CHAT_LABELS,
@@ -1,5 +1,5 @@
1
- import { type ChatPanelLabels } from '../labels';
2
1
  import type { ReactElement } from 'react';
2
+ import { type ChatPanelLabels } from '../labels';
3
3
  import type { ChatPanelTheme } from '../theme';
4
4
  import type { ChatConversationDTO, ChatMessageDTO, TypingIndicator } from '../types';
5
5
  type MessageThreadProps = {
@@ -1,9 +1,9 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { DEFAULT_CHAT_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
3
  import { useEffect, useRef } from 'react';
5
4
  import { cn } from '../../../utils/cn';
6
5
  import { conversationTitle, formatClockTime } from '../helpers';
6
+ import { DEFAULT_CHAT_LABELS } from '../labels';
7
7
  function Attachments({ message, theme }) {
8
8
  if (message.attachments.length === 0) return null;
9
9
  return /*#__PURE__*/ _jsx("span", {
@@ -1,12 +1,12 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DEFAULT_FORGOT_PASSWORD_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
3
  import { useGSAP } from '@gsap/react';
5
4
  import gsap from 'gsap';
6
5
  import { useRef } from 'react';
7
6
  import { cn } from '../../../utils/cn';
8
7
  import { Button } from '../../Button';
9
8
  import { NucleusTextInput } from '../../NucleusTextInput';
9
+ import { DEFAULT_FORGOT_PASSWORD_LABELS } from '../labels';
10
10
  import { useForgotPasswordStore } from '../store';
11
11
  import { forgotPasswordPageTheme } from '../theme';
12
12
  gsap.registerPlugin(useGSAP);
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DEFAULT_FORGOT_PASSWORD_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
3
  import { useGSAP } from '@gsap/react';
5
4
  import gsap from 'gsap';
6
5
  import { useRef } from 'react';
7
6
  import { cn } from '../../../utils/cn';
8
7
  import { AbstractAnimatedBackground } from '../../AbstractAnimatedBackground';
8
+ import { DEFAULT_FORGOT_PASSWORD_LABELS } from '../labels';
9
9
  import { forgotPasswordPageTheme } from '../theme';
10
10
  import { ForgotPasswordForm } from './ForgotPasswordForm';
11
11
  import { ForgotPasswordHeader } from './ForgotPasswordHeader';
@@ -120,21 +120,21 @@ export function FieldMappingRows({ rows, sourceFields, targetFields, disabled, o
120
120
  /*#__PURE__*/ _jsxs("p", {
121
121
  className: theme.field.hint,
122
122
  children: [
123
- "A single field inside the braces can be shaped on its own with",
124
- ' ',
123
+ "A single field inside the braces can be shaped on its own with ",
125
124
  /*#__PURE__*/ _jsx("strong", {
126
125
  children: '|'
127
126
  }),
128
- ": ",
127
+ ":",
128
+ ' ',
129
129
  /*#__PURE__*/ _jsx("strong", {
130
130
  children: '{companyCode}-{departmentCode|pathLeaf}'
131
131
  }),
132
- ' ',
133
- "turns ",
132
+ " turns ",
134
133
  /*#__PURE__*/ _jsx("em", {
135
134
  children: "TAT"
136
135
  }),
137
- " and ",
136
+ " and",
137
+ ' ',
138
138
  /*#__PURE__*/ _jsx("em", {
139
139
  children: "050/285/204"
140
140
  }),
@@ -1,6 +1,5 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DEFAULT_RESET_PASSWORD_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
3
  import { useGSAP } from '@gsap/react';
5
4
  import gsap from 'gsap';
6
5
  import { useMemo, useRef } from 'react';
@@ -8,6 +7,7 @@ import { cn } from '../../../utils/cn';
8
7
  import { Button } from '../../Button';
9
8
  import { NucleusTextInput } from '../../NucleusTextInput';
10
9
  import { DEFAULT_PASSWORD_POLICY } from '../../SetPasswordPage/types';
10
+ import { DEFAULT_RESET_PASSWORD_LABELS } from '../labels';
11
11
  import { useResetPasswordStore } from '../store';
12
12
  import { resetPasswordPageTheme } from '../theme';
13
13
  gsap.registerPlugin(useGSAP);
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DEFAULT_RESET_PASSWORD_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
3
  import { useGSAP } from '@gsap/react';
5
4
  import gsap from 'gsap';
6
5
  import { useRef } from 'react';
7
6
  import { cn } from '../../../utils/cn';
8
7
  import { AbstractAnimatedBackground } from '../../AbstractAnimatedBackground';
8
+ import { DEFAULT_RESET_PASSWORD_LABELS } from '../labels';
9
9
  import { resetPasswordPageTheme } from '../theme';
10
10
  import { ResetPasswordForm } from './ResetPasswordForm';
11
11
  import { ResetPasswordHeader } from './ResetPasswordHeader';
@@ -1,3 +1,3 @@
1
- import { type SetPasswordLabels } from '../labels';
2
1
  import type { ReactElement } from 'react';
3
- export declare function SetPasswordForm({ labels }?: Partial<SetPasswordLabels>, labels: any, passwordChangeAction: any, passwordSetAction: any, isInvite: boolean | undefined, onSuccess: any, onBackToLogin: any, backToLoginHref: any, passwordPolicy: {} | undefined, SetPasswordFormProps: any): ReactElement;
2
+ import { type SetPasswordFormProps } from '../types';
3
+ export declare function SetPasswordForm({ labels, passwordChangeAction, passwordSetAction, isInvite, onSuccess, onBackToLogin, backToLoginHref, passwordPolicy, }: SetPasswordFormProps): ReactElement;
@@ -0,0 +1,148 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { NucleusTextInput } from '../../NucleusTextInput';
4
+ import { DEFAULT_SET_PASSWORD_LABELS } from '../labels';
5
+ import { useSetPasswordStore } from '../store';
6
+ import { setPasswordPageTheme } from '../theme';
7
+ import { DEFAULT_PASSWORD_POLICY } from '../types';
8
+ export function SetPasswordForm({ labels, passwordChangeAction, passwordSetAction, isInvite = false, onSuccess, onBackToLogin, backToLoginHref, passwordPolicy = {} }) {
9
+ const say = {
10
+ ...DEFAULT_SET_PASSWORD_LABELS,
11
+ ...labels
12
+ };
13
+ const theme = setPasswordPageTheme;
14
+ const store = useSetPasswordStore();
15
+ const policy = {
16
+ ...DEFAULT_PASSWORD_POLICY,
17
+ ...passwordPolicy
18
+ };
19
+ const activeAction = isInvite && passwordSetAction ? passwordSetAction : passwordChangeAction;
20
+ const validateForm = ()=>{
21
+ if (!store.newPassword) {
22
+ return 'Password is required';
23
+ }
24
+ if (store.newPassword.length < policy.minLength) {
25
+ return `Password must be at least ${policy.minLength} characters`;
26
+ }
27
+ if (policy.maxLength && store.newPassword.length > policy.maxLength) {
28
+ return `Password must be at most ${policy.maxLength} characters`;
29
+ }
30
+ if (policy.requireUppercase && !/[A-Z]/.test(store.newPassword)) {
31
+ return 'Password must contain at least one uppercase letter';
32
+ }
33
+ if (policy.requireLowercase && !/[a-z]/.test(store.newPassword)) {
34
+ return 'Password must contain at least one lowercase letter';
35
+ }
36
+ if (policy.requireNumber && !/[0-9]/.test(store.newPassword)) {
37
+ return 'Password must contain at least one number';
38
+ }
39
+ if (policy.requireSpecialChar) {
40
+ const specialCharsRegex = new RegExp(`[${policy.specialChars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')}]`);
41
+ if (!specialCharsRegex.test(store.newPassword)) {
42
+ return 'Password must contain at least one special character';
43
+ }
44
+ }
45
+ if (!store.confirmPassword) {
46
+ return 'Please confirm your password';
47
+ }
48
+ if (store.newPassword !== store.confirmPassword) {
49
+ return 'Passwords do not match';
50
+ }
51
+ return null;
52
+ };
53
+ const handleSubmit = (e)=>{
54
+ e.preventDefault();
55
+ const validationError = validateForm();
56
+ if (validationError) {
57
+ store.setError(validationError);
58
+ return;
59
+ }
60
+ store.setError(null);
61
+ if (!activeAction) {
62
+ store.setError('No action configured');
63
+ return;
64
+ }
65
+ const onAfterHandle = ()=>{
66
+ store.setStep('success');
67
+ if (onSuccess) {
68
+ setTimeout(onSuccess, 2000);
69
+ } else if (onBackToLogin) {
70
+ setTimeout(onBackToLogin, 2000);
71
+ }
72
+ };
73
+ const onErrorHandle = (error)=>{
74
+ store.setError(error?.message || 'Failed to set password');
75
+ };
76
+ if (isInvite && passwordSetAction && store.userId) {
77
+ passwordSetAction.start({
78
+ payload: {
79
+ newPassword: store.newPassword,
80
+ userId: store.userId
81
+ },
82
+ onAfterHandle,
83
+ onErrorHandle
84
+ });
85
+ } else if (passwordChangeAction) {
86
+ passwordChangeAction.start({
87
+ payload: {
88
+ currentPassword: '',
89
+ newPassword: store.newPassword,
90
+ confirmPassword: store.confirmPassword
91
+ },
92
+ onAfterHandle,
93
+ onErrorHandle
94
+ });
95
+ }
96
+ };
97
+ return /*#__PURE__*/ _jsxs("form", {
98
+ onSubmit: handleSubmit,
99
+ className: theme.form.wrapper,
100
+ children: [
101
+ store.error && /*#__PURE__*/ _jsx("div", {
102
+ className: theme.alert.error,
103
+ role: "alert",
104
+ children: store.error
105
+ }),
106
+ /*#__PURE__*/ _jsx(NucleusTextInput, {
107
+ type: "password",
108
+ label: "New Password",
109
+ value: store.newPassword,
110
+ onChange: (val)=>store.setNewPassword(val, policy.minLength),
111
+ placeholder: say.newPasswordPlaceholder,
112
+ isNewPassword: true,
113
+ showPasswordStrength: policy.showStrengthIndicator,
114
+ maxInputLength: policy.maxLength,
115
+ enableValidation: false
116
+ }),
117
+ /*#__PURE__*/ _jsx(NucleusTextInput, {
118
+ type: "password",
119
+ label: "Confirm Password",
120
+ value: store.confirmPassword,
121
+ onChange: store.setConfirmPassword,
122
+ placeholder: say.confirmPasswordPlaceholder,
123
+ isNewPassword: true,
124
+ confirmValue: store.newPassword,
125
+ enableValidation: false
126
+ }),
127
+ /*#__PURE__*/ _jsx("button", {
128
+ type: "submit",
129
+ disabled: activeAction?.state.isPending,
130
+ className: theme.form.submitButton,
131
+ children: activeAction?.state.isPending ? 'Setting Password...' : 'Set Password'
132
+ }),
133
+ /*#__PURE__*/ _jsx("div", {
134
+ className: theme.form.backLink,
135
+ children: backToLoginHref ? /*#__PURE__*/ _jsx("a", {
136
+ href: backToLoginHref,
137
+ className: theme.form.backLinkText,
138
+ children: "Back to login"
139
+ }) : onBackToLogin ? /*#__PURE__*/ _jsx("button", {
140
+ type: "button",
141
+ onClick: onBackToLogin,
142
+ className: theme.form.backLinkText,
143
+ children: "Back to login"
144
+ }) : null
145
+ })
146
+ ]
147
+ });
148
+ }
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { DEFAULT_SET_PASSWORD_LABELS } from '../labels';
3
1
  'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
3
  import { useGSAP } from '@gsap/react';
5
4
  import gsap from 'gsap';
6
5
  import { useEffect, useEffectEvent, useRef } from 'react';
7
6
  import { cn } from '../../../utils/cn';
8
7
  import { AbstractAnimatedBackground } from '../../AbstractAnimatedBackground';
8
+ import { DEFAULT_SET_PASSWORD_LABELS } from '../labels';
9
9
  import { useSetPasswordStore } from '../store';
10
10
  import { setPasswordPageTheme } from '../theme';
11
11
  import { SetPasswordForm } from './SetPasswordForm';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nucleus-core-ts",
3
- "version": "0.9.882",
3
+ "version": "0.9.883",
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",
package/scripts/build.ts CHANGED
@@ -249,7 +249,50 @@ async function verifyPackageShape() {
249
249
  }
250
250
  }
251
251
 
252
- log.success(`Package shape verified (${shipped.length} files, no tests)`)
252
+ /*
253
+ * A declaration with no JavaScript beside it.
254
+ *
255
+ * `SetPasswordForm.d.ts` shipped without `SetPasswordForm.js`: a stray
256
+ * character above the `'use client'` directive made swc skip the file, and
257
+ * nothing here noticed — the package published, the types resolved, and the
258
+ * customer's Next build was the thing that failed, with
259
+ * "Can't resolve './SetPasswordForm'". The types are emitted by tsc and the
260
+ * code by swc, so one can silently go missing while the other does not, and
261
+ * that gap is exactly what a consumer trips over.
262
+ */
263
+ const declarations: string[] = []
264
+ const walkTypes = async (dir: string) => {
265
+ for (const entry of await readdir(dir, { withFileTypes: true })) {
266
+ const full = join(dir, entry.name)
267
+ if (entry.isDirectory()) await walkTypes(full)
268
+ else if (entry.name.endsWith('.d.ts')) declarations.push(full)
269
+ }
270
+ }
271
+
272
+ /*
273
+ * Only the TRANSPILED trees, where a module is emitted one-for-one.
274
+ *
275
+ * `src/` is bundled into `dist/index.js`, so its declarations legitimately
276
+ * have no file of their own beside them, and `bin/` ships as TypeScript. The
277
+ * frontend is the one that maps file to file, and it is where the consumer's
278
+ * import resolves to a path rather than to a bundle.
279
+ */
280
+ const oneForOne = ['fe', ...(config.transpileDirs || []).map((d) => d.replace('./', ''))]
281
+ for (const dir of new Set(oneForOne)) {
282
+ const full = join(config.build.outDir, dir)
283
+ if (await Bun.file(join(full, 'index.js')).exists()) await walkTypes(full)
284
+ }
285
+
286
+ const emitted = new Set(shipped)
287
+ const orphans = declarations
288
+ .map((file) => file.replace(/\.d\.ts$/, '.js'))
289
+ .filter((expected) => !emitted.has(expected))
290
+ if (orphans.length > 0) {
291
+ log.error(`${orphans.length} declaration(s) shipped with no JavaScript, e.g. ${orphans[0]}`)
292
+ throw new Error('a module was typed but never emitted — the consumer cannot import it')
293
+ }
294
+
295
+ log.success(`Package shape verified (${shipped.length} files, no tests, no orphan types)`)
253
296
  }
254
297
 
255
298
  async function getJsFiles(dir: string): Promise<string[]> {