@unchainedshop/core 5.0.0-alpha.3 → 5.0.0-alpha.5

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.
@@ -15,7 +15,7 @@ export declare const ProductCreateSpecificationSchema: z.ZodMiniObject<{
15
15
  readonly ACTIVE: "ACTIVE";
16
16
  readonly DELETED: "DELETED";
17
17
  }>>>;
18
- published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
18
+ published: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
19
19
  tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
20
20
  commerce: z.ZodMiniOptional<z.ZodMiniObject<{
21
21
  pricing: z.ZodMiniArray<z.ZodMiniObject<{
@@ -76,7 +76,7 @@ export declare const ProductCreatePayloadSchema: z.ZodMiniObject<{
76
76
  readonly ACTIVE: "ACTIVE";
77
77
  readonly DELETED: "DELETED";
78
78
  }>>>;
79
- published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
79
+ published: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
80
80
  tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
81
81
  commerce: z.ZodMiniOptional<z.ZodMiniObject<{
82
82
  pricing: z.ZodMiniArray<z.ZodMiniObject<{
@@ -183,7 +183,7 @@ declare namespace createProduct {
183
183
  readonly ACTIVE: "ACTIVE";
184
184
  readonly DELETED: "DELETED";
185
185
  }>>>;
186
- published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
186
+ published: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
187
187
  tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
188
188
  commerce: z.ZodMiniOptional<z.ZodMiniObject<{
189
189
  pricing: z.ZodMiniArray<z.ZodMiniObject<{
@@ -8,7 +8,7 @@ export const ProductCreateSpecificationSchema = z.object({
8
8
  type: z.enum(ProductType),
9
9
  sequence: z.optional(z.number()),
10
10
  status: z.nullish(z.enum(ProductStatus)),
11
- published: z.nullish(z.iso.datetime()),
11
+ published: z.nullish(z.string().check(z.refine((value) => !Number.isNaN(new Date(value).getTime()), 'Invalid date'))),
12
12
  tags: z.optional(z.array(z.string())),
13
13
  commerce: z.optional(z.object({
14
14
  pricing: z.array(z.object({
@@ -9,7 +9,7 @@ export declare const ProductUpdateSpecificationSchema: z.ZodMiniObject<{
9
9
  readonly ACTIVE: "ACTIVE";
10
10
  readonly DELETED: "DELETED";
11
11
  }>>>;
12
- published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
12
+ published: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
13
13
  tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
14
14
  commerce: z.ZodMiniOptional<z.ZodMiniObject<{
15
15
  pricing: z.ZodMiniArray<z.ZodMiniObject<{
@@ -64,7 +64,7 @@ export declare const ProductUpdatePayloadSchema: z.ZodMiniObject<{
64
64
  readonly ACTIVE: "ACTIVE";
65
65
  readonly DELETED: "DELETED";
66
66
  }>>>;
67
- published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
67
+ published: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
68
68
  tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
69
69
  commerce: z.ZodMiniOptional<z.ZodMiniObject<{
70
70
  pricing: z.ZodMiniArray<z.ZodMiniObject<{
@@ -165,7 +165,7 @@ declare namespace updateProduct {
165
165
  readonly ACTIVE: "ACTIVE";
166
166
  readonly DELETED: "DELETED";
167
167
  }>>>;
168
- published: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
168
+ published: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
169
169
  tags: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
170
170
  commerce: z.ZodMiniOptional<z.ZodMiniObject<{
171
171
  pricing: z.ZodMiniArray<z.ZodMiniObject<{
@@ -8,7 +8,7 @@ export const ProductUpdateSpecificationSchema = z.object({
8
8
  type: z.optional(z.string()),
9
9
  sequence: z.optional(z.number()),
10
10
  status: z.nullish(z.enum(ProductStatus)),
11
- published: z.nullish(z.iso.datetime()),
11
+ published: z.nullish(z.string().check(z.refine((value) => !Number.isNaN(new Date(value).getTime()), 'Invalid date'))),
12
12
  tags: z.optional(z.array(z.string())),
13
13
  commerce: z.optional(z.object({
14
14
  pricing: z.array(z.object({
@@ -48,9 +48,10 @@ export const BaseWorker = {
48
48
  retries: workConfig.retries || 0,
49
49
  };
50
50
  if (workConfig.input) {
51
- workData.input = (await workConfig.input(workData)) || {};
52
- if (!workData.input)
51
+ const input = await workConfig.input(workData);
52
+ if (!input)
53
53
  return null;
54
+ workData.input = input;
54
55
  }
55
56
  return unchainedAPI.modules.worker.ensureOneWork(workData);
56
57
  }));
@@ -18,6 +18,12 @@ export type IWorkerDirector = IBaseDirector<IWorkerAdapter<any, any>> & {
18
18
  configureAutoscheduling: (workScheduleConfiguration: WorkScheduleConfiguration) => void;
19
19
  getAutoSchedules: () => [string, WorkScheduleConfiguration][];
20
20
  doWork: (work: Work, unchainedAPI: any) => Promise<WorkResult>;
21
+ allocateWork: (unchainedAPI: {
22
+ modules: Modules;
23
+ }, options?: {
24
+ types?: string[] | null;
25
+ worker?: string;
26
+ }) => Promise<Work | null>;
21
27
  processNextWork: (unchainedAPI: {
22
28
  modules: Modules;
23
29
  }, workerId?: string) => Promise<Work | null>;
@@ -57,22 +57,34 @@ export const WorkerDirector = {
57
57
  return errorOutput;
58
58
  }
59
59
  },
60
+ allocateWork: async (unchainedAPI, { types: requestedTypes, worker = unchainedAPI.modules.worker.workerId } = {}) => {
61
+ const lock = await unchainedAPI.modules.orders.acquireLock('allocation', 'worker');
62
+ try {
63
+ const adapters = WorkerDirector.getAdapters();
64
+ const allocationMap = await unchainedAPI.modules.worker.allocationMap();
65
+ const types = adapters
66
+ .filter((adapter) => {
67
+ if (requestedTypes && !requestedTypes.includes(adapter.type))
68
+ return false;
69
+ if (adapter.maxParallelAllocations &&
70
+ adapter.maxParallelAllocations <= allocationMap[adapter.type])
71
+ return false;
72
+ return true;
73
+ })
74
+ .map((adapter) => adapter.type);
75
+ return await unchainedAPI.modules.worker.allocateWork({
76
+ types,
77
+ worker,
78
+ });
79
+ }
80
+ finally {
81
+ await lock.release();
82
+ }
83
+ },
60
84
  processNextWork: async (unchainedAPI, workerId) => {
61
- const adapters = WorkerDirector.getAdapters();
62
- const allocationMap = await unchainedAPI.modules.worker.allocationMap();
63
- const types = adapters
64
- .filter((adapter) => {
65
- if (adapter.external)
66
- return false;
67
- if (adapter.maxParallelAllocations &&
68
- adapter.maxParallelAllocations <= allocationMap[adapter.type])
69
- return false;
70
- return true;
71
- })
72
- .map((adapter) => adapter.type);
73
85
  const worker = workerId ?? unchainedAPI.modules.worker.workerId;
74
- const work = await unchainedAPI.modules.worker.allocateWork({
75
- types,
86
+ const work = await WorkerDirector.allocateWork(unchainedAPI, {
87
+ types: WorkerDirector.getActivePluginTypes({ external: false }),
76
88
  worker,
77
89
  });
78
90
  if (work) {
@@ -93,13 +93,15 @@ class PluginRegistry {
93
93
  for (const plugin of this.plugins.values()) {
94
94
  if (!plugin.adapters)
95
95
  continue;
96
+ if (this.skippedPlugins.has(plugin.key))
97
+ continue;
96
98
  for (const adapter of plugin.adapters) {
97
99
  if (adapter.adapterType === adapterType) {
98
100
  result.push(adapter);
99
101
  }
100
102
  }
101
103
  }
102
- return result;
104
+ return result.toSorted((left, right) => (left.orderIndex ?? 0) - (right.orderIndex ?? 0));
103
105
  }
104
106
  hasPlugin(key) {
105
107
  return this.plugins.has(key);
@@ -0,0 +1,8 @@
1
+ import type { Modules } from '../modules.ts';
2
+ export declare function bulkAssignProductsToAssortmentService(this: Modules, { assortmentId, productIds }: {
3
+ assortmentId: string;
4
+ productIds: string[];
5
+ }): Promise<{
6
+ successIds: string[];
7
+ failedIds: string[];
8
+ }>;
@@ -0,0 +1,11 @@
1
+ import { executeBulkOperation } from '@unchainedshop/utils';
2
+ export async function bulkAssignProductsToAssortmentService({ assortmentId, productIds }) {
3
+ const result = await executeBulkOperation(productIds, async (productId) => {
4
+ if (!(await this.products.productExists({ productId })))
5
+ throw new Error('not-found');
6
+ const assignment = await this.assortments.products.create({ assortmentId, productId });
7
+ if (!assignment)
8
+ throw new Error('create-failed');
9
+ });
10
+ return result;
11
+ }
@@ -0,0 +1,7 @@
1
+ import type { Modules } from '../modules.ts';
2
+ export declare function bulkDeleteUsersService(this: Modules, { userIds }: {
3
+ userIds: string[];
4
+ }): Promise<{
5
+ successIds: string[];
6
+ failedIds: string[];
7
+ }>;
@@ -0,0 +1,11 @@
1
+ import { executeBulkOperation } from '@unchainedshop/utils';
2
+ import { deleteUserService } from "./deleteUser.js";
3
+ export async function bulkDeleteUsersService({ userIds }) {
4
+ return executeBulkOperation(userIds, async (userId) => {
5
+ if (!(await this.users.userExists({ userId })))
6
+ throw new Error('not-found');
7
+ const result = await deleteUserService.call(this, { userId });
8
+ if (!result)
9
+ throw new Error('delete-failed');
10
+ });
11
+ }
@@ -0,0 +1,7 @@
1
+ import type { Modules } from '../modules.ts';
2
+ export declare function bulkRemoveFiltersService(this: Modules, { filterIds }: {
3
+ filterIds: string[];
4
+ }): Promise<{
5
+ successIds: string[];
6
+ failedIds: string[];
7
+ }>;
@@ -0,0 +1,10 @@
1
+ import { executeBulkOperation } from '@unchainedshop/utils';
2
+ import { removeFilterService } from "./removeFilter.js";
3
+ export async function bulkRemoveFiltersService({ filterIds }) {
4
+ return executeBulkOperation(filterIds, async (filterId) => {
5
+ const filter = await this.filters.findFilter({ filterId });
6
+ if (!filter)
7
+ throw new Error('not-found');
8
+ await removeFilterService.call(this, { filter });
9
+ });
10
+ }
@@ -0,0 +1,7 @@
1
+ import type { Modules } from '../modules.ts';
2
+ export declare function bulkRemoveProductsService(this: Modules, { productIds }: {
3
+ productIds: string[];
4
+ }): Promise<{
5
+ successIds: string[];
6
+ failedIds: string[];
7
+ }>;
@@ -0,0 +1,23 @@
1
+ import { executeBulkOperation } from '@unchainedshop/utils';
2
+ import { removeProductService } from "./removeProduct.js";
3
+ export async function bulkRemoveProductsService({ productIds }) {
4
+ return executeBulkOperation(productIds, async (productId) => {
5
+ if (!(await this.products.productExists({ productId })))
6
+ throw new Error('not-found');
7
+ if (await this.products.firstActiveProductBundle(productId)) {
8
+ throw new Error('linked-to-active-bundle');
9
+ }
10
+ if (await this.products.firstActiveProductProxy(productId)) {
11
+ throw new Error('linked-to-active-variation');
12
+ }
13
+ if (await this.quotations.openQuotationWithProduct({ productId })) {
14
+ throw new Error('linked-to-quotation');
15
+ }
16
+ if (await this.enrollments.openEnrollmentWithProduct({ productId })) {
17
+ throw new Error('linked-to-enrollment');
18
+ }
19
+ const result = await removeProductService.call(this, { productId });
20
+ if (!result)
21
+ throw new Error('already-deleted');
22
+ });
23
+ }
@@ -0,0 +1,8 @@
1
+ import type { Modules } from '../modules.ts';
2
+ export declare function bulkSetFilterActiveService(this: Modules, { filterIds, isActive }: {
3
+ filterIds: string[];
4
+ isActive: boolean;
5
+ }): Promise<{
6
+ successIds: string[];
7
+ failedIds: string[];
8
+ }>;
@@ -0,0 +1,12 @@
1
+ import { executeBulkOperation } from '@unchainedshop/utils';
2
+ import { updateFilterService } from "./updateFilter.js";
3
+ export async function bulkSetFilterActiveService({ filterIds, isActive }) {
4
+ return executeBulkOperation(filterIds, async (filterId) => {
5
+ const filter = await this.filters.findFilter({ filterId });
6
+ if (!filter)
7
+ throw new Error('not-found');
8
+ if (!(await updateFilterService.call(this, filterId, { isActive }))) {
9
+ throw new Error('update-failed');
10
+ }
11
+ });
12
+ }
@@ -62,6 +62,11 @@ import { simulateConfigurablePriceRangeService } from './simulateConfigurablePri
62
62
  import { createFileDownloadURLService } from './createFileDownloadURL.ts';
63
63
  import { resolveTokenStatusService } from './resolveTokenStatus.ts';
64
64
  import { isTokenInvalidateableService } from './isTokenInvalidateable.ts';
65
+ import { bulkRemoveProductsService } from './bulkRemoveProducts.ts';
66
+ import { bulkRemoveFiltersService } from './bulkRemoveFilters.ts';
67
+ import { bulkDeleteUsersService } from './bulkDeleteUsers.ts';
68
+ import { bulkSetFilterActiveService } from './bulkSetFilterActive.ts';
69
+ import { bulkAssignProductsToAssortmentService } from './bulkAssignProductsToAssortment.ts';
65
70
  export type ServiceInterface = (this: Modules, ...args: any[]) => Promise<any> | any;
66
71
  export type Bound<T extends ServiceInterface> = OmitThisParameter<T>;
67
72
  export type CustomServices = Record<string, ServiceInterface | Record<string, ServiceInterface>>;
@@ -105,13 +110,18 @@ export default function initServices(modules: Modules, customServices?: CustomSe
105
110
  simulateProductDispatching: Bound<typeof simulateProductDispatchingService>;
106
111
  simulateProductInventory: Bound<typeof simulateProductInventoryService>;
107
112
  removeProduct: Bound<typeof removeProductService>;
113
+ bulkRemoveProducts: Bound<typeof bulkRemoveProductsService>;
108
114
  findProductSiblings: Bound<typeof findProductSiblingsService>;
109
115
  simulateConfigurablePriceRange: Bound<typeof simulateConfigurablePriceRangeService>;
110
116
  };
117
+ assortments: {
118
+ bulkAssignProductsToAssortment: Bound<typeof bulkAssignProductsToAssortmentService>;
119
+ };
111
120
  users: {
112
121
  migrateUserData: Bound<typeof migrateUserDataService>;
113
122
  updateUserAvatarAfterUpload: Bound<typeof updateUserAvatarAfterUploadService>;
114
123
  deleteUser: Bound<typeof deleteUserService>;
124
+ bulkDeleteUsers: Bound<typeof bulkDeleteUsersService>;
115
125
  };
116
126
  enrollments: {
117
127
  createEnrollmentFromCheckout: Bound<typeof createEnrollmentFromCheckoutService>;
@@ -139,6 +149,8 @@ export default function initServices(modules: Modules, customServices?: CustomSe
139
149
  updateFilter: Bound<typeof updateFilterService>;
140
150
  createFilterOption: Bound<typeof createFilterOptionService>;
141
151
  removeFilterOption: Bound<typeof removeFilterOptionService>;
152
+ bulkRemoveFilters: Bound<typeof bulkRemoveFiltersService>;
153
+ bulkSetFilterActive: Bound<typeof bulkSetFilterActiveService>;
142
154
  };
143
155
  warehousing: {
144
156
  ercMetadata: Bound<typeof ercMetadataService>;
@@ -61,6 +61,11 @@ import { simulateConfigurablePriceRangeService } from "./simulateConfigurablePri
61
61
  import { createFileDownloadURLService } from "./createFileDownloadURL.js";
62
62
  import { resolveTokenStatusService } from "./resolveTokenStatus.js";
63
63
  import { isTokenInvalidateableService } from "./isTokenInvalidateable.js";
64
+ import { bulkRemoveProductsService } from "./bulkRemoveProducts.js";
65
+ import { bulkRemoveFiltersService } from "./bulkRemoveFilters.js";
66
+ import { bulkDeleteUsersService } from "./bulkDeleteUsers.js";
67
+ import { bulkSetFilterActiveService } from "./bulkSetFilterActive.js";
68
+ import { bulkAssignProductsToAssortmentService } from "./bulkAssignProductsToAssortment.js";
64
69
  function bindMethodsToModules(modules) {
65
70
  return {
66
71
  get(target, prop, receiver) {
@@ -116,13 +121,18 @@ export default function initServices(modules, customServices = {}) {
116
121
  simulateProductDispatching: simulateProductDispatchingService,
117
122
  simulateProductInventory: simulateProductInventoryService,
118
123
  removeProduct: removeProductService,
124
+ bulkRemoveProducts: bulkRemoveProductsService,
119
125
  findProductSiblings: findProductSiblingsService,
120
126
  simulateConfigurablePriceRange: simulateConfigurablePriceRangeService,
121
127
  },
128
+ assortments: {
129
+ bulkAssignProductsToAssortment: bulkAssignProductsToAssortmentService,
130
+ },
122
131
  users: {
123
132
  migrateUserData: migrateUserDataService,
124
133
  updateUserAvatarAfterUpload: updateUserAvatarAfterUploadService,
125
134
  deleteUser: deleteUserService,
135
+ bulkDeleteUsers: bulkDeleteUsersService,
126
136
  },
127
137
  enrollments: {
128
138
  createEnrollmentFromCheckout: createEnrollmentFromCheckoutService,
@@ -150,6 +160,8 @@ export default function initServices(modules, customServices = {}) {
150
160
  updateFilter: updateFilterService,
151
161
  createFilterOption: createFilterOptionService,
152
162
  removeFilterOption: removeFilterOptionService,
163
+ bulkRemoveFilters: bulkRemoveFiltersService,
164
+ bulkSetFilterActive: bulkSetFilterActiveService,
153
165
  },
154
166
  warehousing: {
155
167
  ercMetadata: ercMetadataService,
@@ -39,6 +39,7 @@ export async function initCartProvidersService(order) {
39
39
  const paymentCredentials = await this.payment.paymentCredentials.findPaymentCredentials({ userId: updatedOrder.userId, isPreferred: true }, {
40
40
  sort: {
41
41
  created: -1,
42
+ _id: -1,
42
43
  },
43
44
  });
44
45
  const defaultOrderPaymentProvider = await paymentSettings.determineDefaultProvider({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unchainedshop/core",
3
3
  "description": "Core orchestration package for the Unchained Engine with business services and directors",
4
- "version": "5.0.0-alpha.3",
4
+ "version": "5.0.0-alpha.5",
5
5
  "main": "lib/core-index.js",
6
6
  "types": "lib/core-index.d.ts",
7
7
  "type": "module",
@@ -35,32 +35,32 @@
35
35
  },
36
36
  "homepage": "https://github.com/unchainedshop/unchained#readme",
37
37
  "dependencies": {
38
- "@unchainedshop/core-assortments": "^5.0.0-alpha.1",
39
- "@unchainedshop/core-bookmarks": "^5.0.0-alpha.1",
40
- "@unchainedshop/core-countries": "^5.0.0-alpha.1",
41
- "@unchainedshop/core-currencies": "^5.0.0-alpha.1",
42
- "@unchainedshop/core-delivery": "^5.0.0-alpha.1",
43
- "@unchainedshop/core-enrollments": "^5.0.0-alpha.1",
44
- "@unchainedshop/core-events": "^5.0.0-alpha.1",
45
- "@unchainedshop/core-files": "^5.0.0-alpha.1",
46
- "@unchainedshop/core-filters": "^5.0.0-alpha.1",
47
- "@unchainedshop/core-languages": "^5.0.0-alpha.1",
48
- "@unchainedshop/core-orders": "^5.0.0-alpha.1",
49
- "@unchainedshop/core-payment": "^5.0.0-alpha.1",
50
- "@unchainedshop/core-products": "^5.0.0-alpha.1",
51
- "@unchainedshop/core-quotations": "^5.0.0-alpha.1",
52
- "@unchainedshop/core-users": "^5.0.0-alpha.1",
53
- "@unchainedshop/core-warehousing": "^5.0.0-alpha.1",
54
- "@unchainedshop/core-worker": "^5.0.0-alpha.1",
55
- "@unchainedshop/events": "^5.0.0-alpha.1",
56
- "@unchainedshop/logger": "^5.0.0-alpha.1",
57
- "@unchainedshop/mongodb": "^5.0.0-alpha.1",
58
- "@unchainedshop/utils": "^5.0.0-alpha.1",
38
+ "@unchainedshop/core-assortments": "^5.0.0-alpha.5",
39
+ "@unchainedshop/core-bookmarks": "^5.0.0-alpha.5",
40
+ "@unchainedshop/core-countries": "^5.0.0-alpha.5",
41
+ "@unchainedshop/core-currencies": "^5.0.0-alpha.5",
42
+ "@unchainedshop/core-delivery": "^5.0.0-alpha.5",
43
+ "@unchainedshop/core-enrollments": "^5.0.0-alpha.5",
44
+ "@unchainedshop/core-events": "^5.0.0-alpha.5",
45
+ "@unchainedshop/core-files": "^5.0.0-alpha.5",
46
+ "@unchainedshop/core-filters": "^5.0.0-alpha.5",
47
+ "@unchainedshop/core-languages": "^5.0.0-alpha.5",
48
+ "@unchainedshop/core-orders": "^5.0.0-alpha.5",
49
+ "@unchainedshop/core-payment": "^5.0.0-alpha.5",
50
+ "@unchainedshop/core-products": "^5.0.0-alpha.5",
51
+ "@unchainedshop/core-quotations": "^5.0.0-alpha.5",
52
+ "@unchainedshop/core-users": "^5.0.0-alpha.5",
53
+ "@unchainedshop/core-warehousing": "^5.0.0-alpha.5",
54
+ "@unchainedshop/core-worker": "^5.0.0-alpha.5",
55
+ "@unchainedshop/events": "^5.0.0-alpha.5",
56
+ "@unchainedshop/logger": "^5.0.0-alpha.5",
57
+ "@unchainedshop/mongodb": "^5.0.0-alpha.5",
58
+ "@unchainedshop/utils": "^5.0.0-alpha.5",
59
59
  "minipass-json-stream": "^1.0.2",
60
60
  "zod": "^4.2.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/node": "^26.2.0",
64
- "typescript": "^5.8.3"
64
+ "typescript": "^6.0.3"
65
65
  }
66
66
  }