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 +1 -1
- package/dist/fe/components/ChatPanel/components/ConversationList.d.ts +1 -1
- package/dist/fe/components/ChatPanel/components/ConversationList.js +2 -2
- package/dist/fe/components/ChatPanel/components/MessageComposer.d.ts +1 -1
- package/dist/fe/components/ChatPanel/components/MessageComposer.js +2 -2
- package/dist/fe/components/ChatPanel/components/MessageThread.d.ts +1 -1
- package/dist/fe/components/ChatPanel/components/MessageThread.js +2 -2
- package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordForm.js +2 -2
- package/dist/fe/components/ForgotPasswordPage/components/ForgotPasswordPage.js +2 -2
- package/dist/fe/components/IntegrationsPage/components/FieldMappingRows.js +6 -6
- package/dist/fe/components/ResetPasswordPage/components/ResetPasswordForm.js +2 -2
- package/dist/fe/components/ResetPasswordPage/components/ResetPasswordPage.js +2 -2
- package/dist/fe/components/SetPasswordPage/components/SetPasswordForm.d.ts +2 -2
- package/dist/fe/components/SetPasswordPage/components/SetPasswordForm.js +148 -0
- package/dist/fe/components/SetPasswordPage/components/SetPasswordPage.js +2 -2
- package/package.json +1 -1
- package/scripts/build.ts +44 -1
package/dist/.build-ok
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
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,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
|
-
|
|
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.
|
|
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
|
-
|
|
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[]> {
|