nucleus-core-ts 0.9.882 → 0.9.884

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.
Files changed (23) hide show
  1. package/dist/.build-ok +1 -1
  2. package/dist/fe/components/ChatPanel/components/ConversationList.d.ts +1 -1
  3. package/dist/fe/components/ChatPanel/components/ConversationList.js +2 -2
  4. package/dist/fe/components/ChatPanel/components/MessageComposer.d.ts +1 -1
  5. package/dist/fe/components/ChatPanel/components/MessageComposer.js +2 -2
  6. package/dist/fe/components/ChatPanel/components/MessageThread.d.ts +1 -1
  7. package/dist/fe/components/ChatPanel/components/MessageThread.js +2 -2
  8. package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordForm.js +4 -4
  9. package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordPage.js +2 -2
  10. package/dist/fe/components/ForgotPasswordPage/labels.d.ts +4 -0
  11. package/dist/fe/components/ForgotPasswordPage/labels.js +3 -1
  12. package/dist/fe/components/IntegrationsPage/components/FieldMappingRows.js +6 -6
  13. package/dist/fe/components/ResetPasswordPage/components/ResetPasswordForm.js +9 -9
  14. package/dist/fe/components/ResetPasswordPage/components/ResetPasswordPage.js +2 -2
  15. package/dist/fe/components/ResetPasswordPage/labels.d.ts +9 -0
  16. package/dist/fe/components/ResetPasswordPage/labels.js +8 -1
  17. package/dist/fe/components/SetPasswordPage/components/SetPasswordForm.d.ts +2 -2
  18. package/dist/fe/components/SetPasswordPage/components/SetPasswordForm.js +148 -0
  19. package/dist/fe/components/SetPasswordPage/components/SetPasswordPage.js +2 -2
  20. package/dist/fe/components/SetPasswordPage/labels.d.ts +7 -0
  21. package/dist/fe/components/SetPasswordPage/labels.js +7 -1
  22. package/package.json +1 -1
  23. package/scripts/build.ts +44 -1
package/dist/.build-ok CHANGED
@@ -1 +1 @@
1
- 0.9.882
1
+ 0.9.884
@@ -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);
@@ -56,7 +56,7 @@ export function ForgotPasswordForm({ labels, forgotPasswordAction, onBackToLogin
56
56
  const handleSubmit = contextSafe((e)=>{
57
57
  e.preventDefault();
58
58
  if (!store.email) {
59
- store.setError('Please enter your email address');
59
+ store.setError(say.emailRequired);
60
60
  shakeForm();
61
61
  return;
62
62
  }
@@ -197,7 +197,7 @@ export function ForgotPasswordForm({ labels, forgotPasswordAction, onBackToLogin
197
197
  fullWidth: true,
198
198
  loading: isLoading,
199
199
  disabled: isLoading,
200
- children: "Send Reset Link"
200
+ children: say.submit
201
201
  })
202
202
  }),
203
203
  /*#__PURE__*/ _jsx("div", {
@@ -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';
@@ -15,5 +15,9 @@ export type ForgotPasswordLabels = {
15
15
  sentTo: string;
16
16
  backToLogin: string;
17
17
  pageLabel: string;
18
+ /** The button that sends the link. */
19
+ submit: string;
20
+ /** Said when the box is empty. */
21
+ emailRequired: string;
18
22
  };
19
23
  export declare const DEFAULT_FORGOT_PASSWORD_LABELS: ForgotPasswordLabels;
@@ -12,5 +12,7 @@
12
12
  checkYourEmail: 'Check your email',
13
13
  sentTo: "We've sent a password reset link to {email}. Please check your inbox and follow the instructions.",
14
14
  backToLogin: 'Back to login',
15
- pageLabel: 'Forgot password page'
15
+ pageLabel: 'Forgot password page',
16
+ submit: 'Send Reset Link',
17
+ emailRequired: 'Please enter your email address'
16
18
  };
@@ -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);
@@ -95,28 +95,28 @@ export function ResetPasswordForm({ labels, token, resetPasswordAction, onBackTo
95
95
  if (policy.requireUppercase) {
96
96
  reqs.push({
97
97
  key: 'uppercase',
98
- label: 'One uppercase letter',
98
+ label: say.ruleUppercase,
99
99
  test: (p)=>/[A-Z]/.test(p)
100
100
  });
101
101
  }
102
102
  if (policy.requireLowercase) {
103
103
  reqs.push({
104
104
  key: 'lowercase',
105
- label: 'One lowercase letter',
105
+ label: say.ruleLowercase,
106
106
  test: (p)=>/[a-z]/.test(p)
107
107
  });
108
108
  }
109
109
  if (policy.requireNumber) {
110
110
  reqs.push({
111
111
  key: 'number',
112
- label: 'One number',
112
+ label: say.ruleNumber,
113
113
  test: (p)=>/\d/.test(p)
114
114
  });
115
115
  }
116
116
  if (policy.requireSpecialChar) {
117
117
  reqs.push({
118
118
  key: 'special',
119
- label: 'One special character',
119
+ label: say.ruleSpecial,
120
120
  test: (p)=>{
121
121
  const escapedChars = policy.specialChars.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
122
122
  return new RegExp(`[${escapedChars}]`).test(p);
@@ -139,18 +139,18 @@ export function ResetPasswordForm({ labels, token, resetPasswordAction, onBackTo
139
139
  const handleSubmit = contextSafe((e)=>{
140
140
  e.preventDefault();
141
141
  if (!store.newPassword || !store.confirmPassword) {
142
- store.setError('Please fill in all fields');
142
+ store.setError(say.fillAllFields);
143
143
  shakeForm();
144
144
  return;
145
145
  }
146
146
  if (store.newPassword !== store.confirmPassword) {
147
- store.setError('Passwords do not match');
147
+ store.setError(say.passwordsDoNotMatch);
148
148
  shakeForm();
149
149
  return;
150
150
  }
151
151
  const allRequirementsMet = passwordRequirements.every((req)=>req.test(store.newPassword));
152
152
  if (!allRequirementsMet) {
153
- store.setError('Password does not meet all requirements');
153
+ store.setError(say.requirementsNotMet);
154
154
  shakeForm();
155
155
  return;
156
156
  }
@@ -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';
@@ -10,5 +10,14 @@ export type ResetPasswordLabels = {
10
10
  success: string;
11
11
  backToLogin: string;
12
12
  pageLabel: string;
13
+ /** The rules listed under the box, one line each. */
14
+ ruleUppercase: string;
15
+ ruleLowercase: string;
16
+ ruleNumber: string;
17
+ ruleSpecial: string;
18
+ /** Said when something is wrong, at the moment it is wrong. */
19
+ fillAllFields: string;
20
+ passwordsDoNotMatch: string;
21
+ requirementsNotMet: string;
13
22
  };
14
23
  export declare const DEFAULT_RESET_PASSWORD_LABELS: ResetPasswordLabels;
@@ -8,5 +8,12 @@
8
8
  passwordRequirements: 'Password requirements:',
9
9
  success: 'Password Reset Successful',
10
10
  backToLogin: 'Back to login',
11
- pageLabel: 'Reset password page'
11
+ pageLabel: 'Reset password page',
12
+ ruleUppercase: 'One uppercase letter',
13
+ ruleLowercase: 'One lowercase letter',
14
+ ruleNumber: 'One number',
15
+ ruleSpecial: 'One special character',
16
+ fillAllFields: 'Please fill in all fields',
17
+ passwordsDoNotMatch: 'Passwords do not match',
18
+ requirementsNotMet: 'Password does not meet all requirements'
12
19
  };
@@ -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 say.passwordRequired;
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 say.passwordNeedsNumber;
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 say.confirmRequired;
47
+ }
48
+ if (store.newPassword !== store.confirmPassword) {
49
+ return say.passwordsDoNotMatch;
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(say.noActionConfigured);
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 || say.failed);
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';
@@ -21,5 +21,12 @@ export type SetPasswordLabels = {
21
21
  passwordStrength: string;
22
22
  passwordRequirements: string;
23
23
  pageLabel: string;
24
+ /** Said when something is wrong, at the moment it is wrong. */
25
+ passwordRequired: string;
26
+ passwordNeedsNumber: string;
27
+ confirmRequired: string;
28
+ passwordsDoNotMatch: string;
29
+ noActionConfigured: string;
30
+ failed: string;
24
31
  };
25
32
  export declare const DEFAULT_SET_PASSWORD_LABELS: SetPasswordLabels;
@@ -19,5 +19,11 @@
19
19
  confirmPasswordPlaceholder: 'Confirm your new password',
20
20
  passwordStrength: 'Password strength',
21
21
  passwordRequirements: 'Password requirements',
22
- pageLabel: 'Set password page'
22
+ pageLabel: 'Set password page',
23
+ passwordRequired: 'Password is required',
24
+ passwordNeedsNumber: 'Password must contain at least one number',
25
+ confirmRequired: 'Please confirm your password',
26
+ passwordsDoNotMatch: 'Passwords do not match',
27
+ noActionConfigured: 'No action configured',
28
+ failed: 'Failed to set password'
23
29
  };
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.884",
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[]> {