@bleedingdev/modern-js-create 3.4.0-ultramodern.1 → 3.4.0-ultramodern.3
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/cjs/ultramodern-workspace/add-vertical.cjs +18 -0
- package/dist/cjs/ultramodern-workspace/contracts.cjs +5 -3
- package/dist/cjs/ultramodern-workspace/demo-components.cjs +9 -18
- package/dist/cjs/ultramodern-workspace/descriptors.cjs +2 -2
- package/dist/cjs/ultramodern-workspace/module-federation.cjs +10 -1
- package/dist/cjs/ultramodern-workspace/package-json.cjs +74 -13
- package/dist/cjs/ultramodern-workspace/versions.cjs +1 -5
- package/dist/cjs/ultramodern-workspace/workspace-scripts.cjs +7 -0
- package/dist/cjs/ultramodern-workspace/write-workspace.cjs +3 -7
- package/dist/esm/ultramodern-workspace/add-vertical.js +19 -1
- package/dist/esm/ultramodern-workspace/contracts.js +6 -4
- package/dist/esm/ultramodern-workspace/demo-components.js +9 -18
- package/dist/esm/ultramodern-workspace/descriptors.js +2 -2
- package/dist/esm/ultramodern-workspace/module-federation.js +10 -1
- package/dist/esm/ultramodern-workspace/package-json.js +62 -10
- package/dist/esm/ultramodern-workspace/versions.js +2 -3
- package/dist/esm/ultramodern-workspace/workspace-scripts.js +5 -1
- package/dist/esm/ultramodern-workspace/write-workspace.js +5 -9
- package/dist/esm-node/ultramodern-workspace/add-vertical.js +19 -1
- package/dist/esm-node/ultramodern-workspace/contracts.js +6 -4
- package/dist/esm-node/ultramodern-workspace/demo-components.js +9 -18
- package/dist/esm-node/ultramodern-workspace/descriptors.js +2 -2
- package/dist/esm-node/ultramodern-workspace/module-federation.js +10 -1
- package/dist/esm-node/ultramodern-workspace/package-json.js +62 -10
- package/dist/esm-node/ultramodern-workspace/versions.js +2 -3
- package/dist/esm-node/ultramodern-workspace/workspace-scripts.js +5 -1
- package/dist/esm-node/ultramodern-workspace/write-workspace.js +5 -9
- package/dist/types/ultramodern-workspace/package-json.d.ts +11 -2
- package/dist/types/ultramodern-workspace/versions.d.ts +1 -2
- package/dist/types/ultramodern-workspace/workspace-scripts.d.ts +1 -0
- package/package.json +4 -4
- package/template-workspace/AGENTS.md.handlebars +2 -1
- package/template-workspace/README.md.handlebars +7 -0
- package/template-workspace/oxfmt.config.ts +3 -1
- package/template-workspace/oxlint.config.ts +3 -1
- package/template-workspace/pnpm-workspace.yaml.handlebars +8 -0
- package/template-workspace/scripts/bootstrap-agent-skills.mjs +42 -10
- package/templates/app/shell-frame.tsx +1 -2
- package/templates/app/ultramodern-route-head.tsx.handlebars +23 -12
- package/templates/packages/shared-contracts-index.ts +206 -272
- package/templates/workspace-scripts/ultramodern-typecheck.mjs +197 -0
- package/templates/workspace-scripts/validate-ultramodern-workspace.mjs.handlebars +166 -2
|
@@ -16,7 +16,9 @@ export interface UltramodernPublicSitemapEntry {
|
|
|
16
16
|
/**
|
|
17
17
|
* Per-locale overrides when translated URLs use translated params.
|
|
18
18
|
*/
|
|
19
|
-
localeParams?: Partial<
|
|
19
|
+
localeParams?: Partial<
|
|
20
|
+
Record<'en' | 'cs', Record<string, string | number | boolean>>
|
|
21
|
+
>;
|
|
20
22
|
draft?: boolean;
|
|
21
23
|
indexable?: boolean;
|
|
22
24
|
lastModified?: string;
|
|
@@ -73,74 +75,64 @@ export const ultramodernWorkspaceContract = {
|
|
|
73
75
|
topology: 'topology/reference-topology.json',
|
|
74
76
|
} as const;
|
|
75
77
|
|
|
76
|
-
export
|
|
77
|
-
checkoutAddToCart: 'checkout:add-to-cart',
|
|
78
|
-
checkoutCartUpdated: 'checkout:cart-updated',
|
|
79
|
-
checkoutClearCart: 'checkout:clear-cart',
|
|
80
|
-
checkoutRemoveFromCart: 'checkout:remove-from-cart',
|
|
81
|
-
exploreSelectedShop: 'explore:selected-shop',
|
|
82
|
-
mfNavigate: 'mf:navigate',
|
|
83
|
-
} as const;
|
|
78
|
+
export type UltramodernWorkspaceLocale = 'en' | 'cs';
|
|
84
79
|
|
|
85
|
-
export type
|
|
86
|
-
|
|
80
|
+
export type UltramodernPerformanceReadinessSignalStatus =
|
|
81
|
+
| 'pass'
|
|
82
|
+
| 'warn'
|
|
83
|
+
| 'fail';
|
|
87
84
|
|
|
88
|
-
export
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface CheckoutCartLinePayload {
|
|
97
|
-
sku: string;
|
|
98
|
-
quantity: number;
|
|
99
|
-
name?: string;
|
|
100
|
-
unitPriceCents?: number;
|
|
101
|
-
}
|
|
85
|
+
export const ultramodernWorkspaceEventNames = {
|
|
86
|
+
navigate: 'ultramodern:navigate',
|
|
87
|
+
performanceSignal: 'ultramodern:performance-signal',
|
|
88
|
+
remoteReady: 'ultramodern:remote-ready',
|
|
89
|
+
routeSettled: 'ultramodern:route-settled',
|
|
90
|
+
} as const;
|
|
102
91
|
|
|
103
|
-
export
|
|
104
|
-
|
|
105
|
-
totalQuantity: number;
|
|
106
|
-
subtotalCents?: number;
|
|
107
|
-
}
|
|
92
|
+
export type UltramodernWorkspaceEventName =
|
|
93
|
+
(typeof ultramodernWorkspaceEventNames)[keyof typeof ultramodernWorkspaceEventNames];
|
|
108
94
|
|
|
109
|
-
export interface
|
|
110
|
-
|
|
95
|
+
export interface UltramodernNavigatePayload {
|
|
96
|
+
to: string;
|
|
97
|
+
replace?: boolean;
|
|
98
|
+
state?: Record<string, unknown>;
|
|
111
99
|
}
|
|
112
100
|
|
|
113
|
-
export interface
|
|
114
|
-
|
|
101
|
+
export interface UltramodernRouteSettledPayload {
|
|
102
|
+
pathname: string;
|
|
103
|
+
locale?: UltramodernWorkspaceLocale;
|
|
104
|
+
title?: string;
|
|
115
105
|
}
|
|
116
106
|
|
|
117
|
-
export interface
|
|
118
|
-
|
|
119
|
-
|
|
107
|
+
export interface UltramodernRemoteReadyPayload {
|
|
108
|
+
appId: string;
|
|
109
|
+
build?: string;
|
|
110
|
+
surface?: string;
|
|
111
|
+
version?: string;
|
|
120
112
|
}
|
|
121
113
|
|
|
122
|
-
export interface
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
114
|
+
export interface UltramodernPerformanceSignalPayload {
|
|
115
|
+
signalId: UltramodernPerformanceReadinessSignalId;
|
|
116
|
+
status: UltramodernPerformanceReadinessSignalStatus;
|
|
117
|
+
durationMs?: number;
|
|
118
|
+
detail?: Record<string, unknown>;
|
|
126
119
|
}
|
|
127
120
|
|
|
128
|
-
export interface
|
|
129
|
-
'
|
|
130
|
-
'
|
|
131
|
-
'
|
|
132
|
-
'
|
|
133
|
-
'explore:selected-shop': ExploreSelectedShopPayload;
|
|
134
|
-
'mf:navigate': MfNavigatePayload;
|
|
121
|
+
export interface UltramodernWorkspaceEventPayloadMap {
|
|
122
|
+
'ultramodern:navigate': UltramodernNavigatePayload;
|
|
123
|
+
'ultramodern:performance-signal': UltramodernPerformanceSignalPayload;
|
|
124
|
+
'ultramodern:remote-ready': UltramodernRemoteReadyPayload;
|
|
125
|
+
'ultramodern:route-settled': UltramodernRouteSettledPayload;
|
|
135
126
|
}
|
|
136
127
|
|
|
137
|
-
export class
|
|
138
|
-
readonly
|
|
128
|
+
export class UltramodernWorkspaceEventValidationError {
|
|
129
|
+
readonly message: string;
|
|
130
|
+
readonly name = 'UltramodernWorkspaceEventValidationError';
|
|
131
|
+
readonly eventName: UltramodernWorkspaceEventName;
|
|
139
132
|
readonly payload: unknown;
|
|
140
133
|
|
|
141
|
-
constructor(eventName:
|
|
142
|
-
|
|
143
|
-
this.name = 'TractorEventValidationError';
|
|
134
|
+
constructor(eventName: UltramodernWorkspaceEventName, payload: unknown) {
|
|
135
|
+
this.message = `Invalid payload for UltraModern workspace event "${eventName}"`;
|
|
144
136
|
this.eventName = eventName;
|
|
145
137
|
this.payload = payload;
|
|
146
138
|
}
|
|
@@ -152,11 +144,27 @@ const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
|
152
144
|
const isNonEmptyString = (value: unknown): value is string =>
|
|
153
145
|
typeof value === 'string' && value.trim().length > 0;
|
|
154
146
|
|
|
155
|
-
const
|
|
156
|
-
Number.
|
|
147
|
+
const isNonNegativeNumber = (value: unknown): value is number =>
|
|
148
|
+
typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
149
|
+
|
|
150
|
+
const isUltramodernWorkspaceLocale = (
|
|
151
|
+
value: unknown,
|
|
152
|
+
): value is UltramodernWorkspaceLocale => value === 'en' || value === 'cs';
|
|
157
153
|
|
|
158
|
-
const
|
|
159
|
-
|
|
154
|
+
const isPerformanceReadinessSignalId = (
|
|
155
|
+
value: unknown,
|
|
156
|
+
): value is UltramodernPerformanceReadinessSignalId =>
|
|
157
|
+
value === 'bfcache' ||
|
|
158
|
+
value === 'core-web-vitals-rum' ||
|
|
159
|
+
value === 'duplicate-prefetch-warmup' ||
|
|
160
|
+
value === 'cache-policy-sanity' ||
|
|
161
|
+
value === 'save-data-behavior' ||
|
|
162
|
+
value === 'cloudflare-ssr-cache-hints';
|
|
163
|
+
|
|
164
|
+
const isPerformanceReadinessSignalStatus = (
|
|
165
|
+
value: unknown,
|
|
166
|
+
): value is UltramodernPerformanceReadinessSignalStatus =>
|
|
167
|
+
value === 'pass' || value === 'warn' || value === 'fail';
|
|
160
168
|
|
|
161
169
|
const hasOptionalString = (value: Record<string, unknown>, key: string) =>
|
|
162
170
|
value[key] === undefined || isNonEmptyString(value[key]);
|
|
@@ -167,127 +175,128 @@ const hasOptionalBoolean = (value: Record<string, unknown>, key: string) =>
|
|
|
167
175
|
const hasOptionalRecord = (value: Record<string, unknown>, key: string) =>
|
|
168
176
|
value[key] === undefined || isRecord(value[key]);
|
|
169
177
|
|
|
170
|
-
const
|
|
178
|
+
const hasOptionalNonNegativeNumber = (
|
|
171
179
|
value: Record<string, unknown>,
|
|
172
180
|
key: string,
|
|
173
|
-
) => value[key] === undefined ||
|
|
181
|
+
) => value[key] === undefined || isNonNegativeNumber(value[key]);
|
|
174
182
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
): payload is CheckoutAddToCartPayload =>
|
|
178
|
-
isRecord(payload) &&
|
|
179
|
-
isNonEmptyString(payload['sku']) &&
|
|
180
|
-
isPositiveInteger(payload['quantity']) &&
|
|
181
|
-
hasOptionalString(payload, 'name') &&
|
|
182
|
-
hasOptionalString(payload, 'shopId') &&
|
|
183
|
-
hasOptionalNonNegativeInteger(payload, 'unitPriceCents');
|
|
183
|
+
const hasOptionalLocale = (value: Record<string, unknown>, key: string) =>
|
|
184
|
+
value[key] === undefined || isUltramodernWorkspaceLocale(value[key]);
|
|
184
185
|
|
|
185
|
-
export const
|
|
186
|
+
export const isUltramodernNavigatePayload = (
|
|
186
187
|
payload: unknown,
|
|
187
|
-
): payload is
|
|
188
|
+
): payload is UltramodernNavigatePayload =>
|
|
188
189
|
isRecord(payload) &&
|
|
189
|
-
isNonEmptyString(payload['
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
hasOptionalNonNegativeInteger(payload, 'unitPriceCents');
|
|
190
|
+
isNonEmptyString(payload['to']) &&
|
|
191
|
+
hasOptionalBoolean(payload, 'replace') &&
|
|
192
|
+
hasOptionalRecord(payload, 'state');
|
|
193
193
|
|
|
194
|
-
export const
|
|
194
|
+
export const isUltramodernRouteSettledPayload = (
|
|
195
195
|
payload: unknown,
|
|
196
|
-
): payload is
|
|
196
|
+
): payload is UltramodernRouteSettledPayload =>
|
|
197
197
|
isRecord(payload) &&
|
|
198
|
-
|
|
199
|
-
payload
|
|
200
|
-
|
|
201
|
-
hasOptionalNonNegativeInteger(payload, 'subtotalCents');
|
|
198
|
+
isNonEmptyString(payload['pathname']) &&
|
|
199
|
+
hasOptionalLocale(payload, 'locale') &&
|
|
200
|
+
hasOptionalString(payload, 'title');
|
|
202
201
|
|
|
203
|
-
export const
|
|
202
|
+
export const isUltramodernRemoteReadyPayload = (
|
|
204
203
|
payload: unknown,
|
|
205
|
-
): payload is
|
|
206
|
-
isRecord(payload) && isNonEmptyString(payload['sku']);
|
|
207
|
-
|
|
208
|
-
export const isCheckoutClearCartPayload = (
|
|
209
|
-
payload: unknown,
|
|
210
|
-
): payload is CheckoutClearCartPayload =>
|
|
211
|
-
isRecord(payload) && hasOptionalString(payload, 'reason');
|
|
212
|
-
|
|
213
|
-
export const isExploreSelectedShopPayload = (
|
|
214
|
-
payload: unknown,
|
|
215
|
-
): payload is ExploreSelectedShopPayload =>
|
|
204
|
+
): payload is UltramodernRemoteReadyPayload =>
|
|
216
205
|
isRecord(payload) &&
|
|
217
|
-
isNonEmptyString(payload['
|
|
218
|
-
hasOptionalString(payload, '
|
|
206
|
+
isNonEmptyString(payload['appId']) &&
|
|
207
|
+
hasOptionalString(payload, 'build') &&
|
|
208
|
+
hasOptionalString(payload, 'surface') &&
|
|
209
|
+
hasOptionalString(payload, 'version');
|
|
219
210
|
|
|
220
|
-
export const
|
|
211
|
+
export const isUltramodernPerformanceSignalPayload = (
|
|
221
212
|
payload: unknown,
|
|
222
|
-
): payload is
|
|
213
|
+
): payload is UltramodernPerformanceSignalPayload =>
|
|
223
214
|
isRecord(payload) &&
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
215
|
+
isPerformanceReadinessSignalId(payload['signalId']) &&
|
|
216
|
+
isPerformanceReadinessSignalStatus(payload['status']) &&
|
|
217
|
+
hasOptionalNonNegativeNumber(payload, 'durationMs') &&
|
|
218
|
+
hasOptionalRecord(payload, 'detail');
|
|
227
219
|
|
|
228
|
-
const
|
|
229
|
-
[
|
|
230
|
-
[tractorEventNames.checkoutCartUpdated]: isCheckoutCartUpdatedPayload,
|
|
231
|
-
[tractorEventNames.checkoutClearCart]: isCheckoutClearCartPayload,
|
|
232
|
-
[tractorEventNames.checkoutRemoveFromCart]: isCheckoutRemoveFromCartPayload,
|
|
233
|
-
[tractorEventNames.exploreSelectedShop]: isExploreSelectedShopPayload,
|
|
234
|
-
[tractorEventNames.mfNavigate]: isMfNavigatePayload,
|
|
235
|
-
} satisfies {
|
|
236
|
-
[Name in TractorEventName]: (
|
|
220
|
+
const ultramodernWorkspaceEventValidators: {
|
|
221
|
+
[Name in UltramodernWorkspaceEventName]: (
|
|
237
222
|
payload: unknown,
|
|
238
|
-
) => payload is
|
|
223
|
+
) => payload is UltramodernWorkspaceEventPayloadMap[Name];
|
|
224
|
+
} = {
|
|
225
|
+
[ultramodernWorkspaceEventNames.navigate]: isUltramodernNavigatePayload,
|
|
226
|
+
[ultramodernWorkspaceEventNames.performanceSignal]:
|
|
227
|
+
isUltramodernPerformanceSignalPayload,
|
|
228
|
+
[ultramodernWorkspaceEventNames.remoteReady]:
|
|
229
|
+
isUltramodernRemoteReadyPayload,
|
|
230
|
+
[ultramodernWorkspaceEventNames.routeSettled]:
|
|
231
|
+
isUltramodernRouteSettledPayload,
|
|
239
232
|
};
|
|
240
233
|
|
|
241
|
-
export const
|
|
234
|
+
export const isUltramodernWorkspaceEventPayload = <
|
|
235
|
+
Name extends UltramodernWorkspaceEventName,
|
|
236
|
+
>(
|
|
242
237
|
eventName: Name,
|
|
243
238
|
payload: unknown,
|
|
244
|
-
): payload is
|
|
245
|
-
|
|
239
|
+
): payload is UltramodernWorkspaceEventPayloadMap[Name] =>
|
|
240
|
+
ultramodernWorkspaceEventValidators[eventName](payload);
|
|
246
241
|
|
|
247
|
-
export const
|
|
242
|
+
export const assertUltramodernWorkspaceEventPayload = <
|
|
243
|
+
Name extends UltramodernWorkspaceEventName,
|
|
244
|
+
>(
|
|
248
245
|
eventName: Name,
|
|
249
246
|
payload: unknown,
|
|
250
|
-
):
|
|
251
|
-
if (!
|
|
252
|
-
throw new
|
|
247
|
+
): UltramodernWorkspaceEventPayloadMap[Name] => {
|
|
248
|
+
if (!isUltramodernWorkspaceEventPayload(eventName, payload)) {
|
|
249
|
+
throw new UltramodernWorkspaceEventValidationError(eventName, payload);
|
|
253
250
|
}
|
|
254
251
|
|
|
255
252
|
return payload;
|
|
256
253
|
};
|
|
257
254
|
|
|
258
|
-
export const
|
|
255
|
+
export const createUltramodernWorkspaceEvent = <
|
|
256
|
+
Name extends UltramodernWorkspaceEventName,
|
|
257
|
+
>(
|
|
259
258
|
eventName: Name,
|
|
260
|
-
payload:
|
|
261
|
-
): CustomEvent<
|
|
259
|
+
payload: UltramodernWorkspaceEventPayloadMap[Name],
|
|
260
|
+
): CustomEvent<UltramodernWorkspaceEventPayloadMap[Name]> =>
|
|
262
261
|
new CustomEvent(eventName, {
|
|
263
262
|
bubbles: true,
|
|
264
263
|
composed: true,
|
|
265
|
-
detail:
|
|
264
|
+
detail: assertUltramodernWorkspaceEventPayload(eventName, payload),
|
|
266
265
|
});
|
|
267
266
|
|
|
268
|
-
export const
|
|
267
|
+
export const dispatchUltramodernWorkspaceEvent = <
|
|
268
|
+
Name extends UltramodernWorkspaceEventName,
|
|
269
|
+
>(
|
|
269
270
|
target: EventTarget,
|
|
270
271
|
eventName: Name,
|
|
271
|
-
payload:
|
|
272
|
-
) =>
|
|
272
|
+
payload: UltramodernWorkspaceEventPayloadMap[Name],
|
|
273
|
+
) =>
|
|
274
|
+
target.dispatchEvent(
|
|
275
|
+
createUltramodernWorkspaceEvent(eventName, payload),
|
|
276
|
+
);
|
|
273
277
|
|
|
274
|
-
export const
|
|
278
|
+
export const onUltramodernWorkspaceEvent = <
|
|
279
|
+
Name extends UltramodernWorkspaceEventName,
|
|
280
|
+
>(
|
|
275
281
|
target: EventTarget,
|
|
276
282
|
eventName: Name,
|
|
277
283
|
handler: (
|
|
278
|
-
payload:
|
|
279
|
-
event: CustomEvent<
|
|
284
|
+
payload: UltramodernWorkspaceEventPayloadMap[Name],
|
|
285
|
+
event: CustomEvent<UltramodernWorkspaceEventPayloadMap[Name]>,
|
|
280
286
|
) => void,
|
|
281
287
|
) => {
|
|
282
288
|
const listener = (event: Event) => {
|
|
283
289
|
if (!('detail' in event)) {
|
|
284
|
-
throw new
|
|
290
|
+
throw new UltramodernWorkspaceEventValidationError(
|
|
291
|
+
eventName,
|
|
292
|
+
undefined,
|
|
293
|
+
);
|
|
285
294
|
}
|
|
286
295
|
|
|
287
296
|
const customEvent = event as CustomEvent<unknown>;
|
|
288
297
|
handler(
|
|
289
|
-
|
|
290
|
-
customEvent as CustomEvent<
|
|
298
|
+
assertUltramodernWorkspaceEventPayload(eventName, customEvent.detail),
|
|
299
|
+
customEvent as CustomEvent<UltramodernWorkspaceEventPayloadMap[Name]>,
|
|
291
300
|
);
|
|
292
301
|
};
|
|
293
302
|
|
|
@@ -298,169 +307,94 @@ export const onTractorEvent = <Name extends TractorEventName>(
|
|
|
298
307
|
};
|
|
299
308
|
};
|
|
300
309
|
|
|
301
|
-
const
|
|
302
|
-
line: CheckoutCartLinePayload,
|
|
303
|
-
): CheckoutCartLinePayload => {
|
|
304
|
-
if (!isCheckoutCartLinePayload(line)) {
|
|
305
|
-
throw new TractorEventValidationError('checkout:cart-updated', line);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
return {
|
|
309
|
-
quantity: line.quantity,
|
|
310
|
-
sku: line.sku,
|
|
311
|
-
...(line.name === undefined ? {} : { name: line.name }),
|
|
312
|
-
...(line.unitPriceCents === undefined
|
|
313
|
-
? {}
|
|
314
|
-
: { unitPriceCents: line.unitPriceCents }),
|
|
315
|
-
};
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
export const createCheckoutCartSnapshot = (
|
|
319
|
-
lines: readonly CheckoutCartLinePayload[],
|
|
320
|
-
): CheckoutCartUpdatedPayload => {
|
|
321
|
-
const normalizedLines = lines.map(line => normalizeCheckoutLine(line));
|
|
322
|
-
const subtotalCents = normalizedLines.reduce(
|
|
323
|
-
(total, line) => total + (line.unitPriceCents ?? 0) * line.quantity,
|
|
324
|
-
0,
|
|
325
|
-
);
|
|
326
|
-
|
|
327
|
-
return {
|
|
328
|
-
lines: normalizedLines,
|
|
329
|
-
totalQuantity: normalizedLines.reduce(
|
|
330
|
-
(total, line) => total + line.quantity,
|
|
331
|
-
0,
|
|
332
|
-
),
|
|
333
|
-
...(subtotalCents === 0 ? {} : { subtotalCents }),
|
|
334
|
-
};
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
export const applyCheckoutCartEvent = (
|
|
338
|
-
cart: CheckoutCartUpdatedPayload,
|
|
339
|
-
eventName:
|
|
340
|
-
| 'checkout:add-to-cart'
|
|
341
|
-
| 'checkout:remove-from-cart'
|
|
342
|
-
| 'checkout:clear-cart',
|
|
343
|
-
payload:
|
|
344
|
-
| CheckoutAddToCartPayload
|
|
345
|
-
| CheckoutRemoveFromCartPayload
|
|
346
|
-
| CheckoutClearCartPayload,
|
|
347
|
-
): CheckoutCartUpdatedPayload => {
|
|
348
|
-
if (eventName === 'checkout:clear-cart') {
|
|
349
|
-
assertTractorEventPayload(eventName, payload);
|
|
350
|
-
return createCheckoutCartSnapshot([]);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
if (eventName === 'checkout:remove-from-cart') {
|
|
354
|
-
const removePayload = assertTractorEventPayload(eventName, payload);
|
|
355
|
-
return createCheckoutCartSnapshot(
|
|
356
|
-
cart.lines.filter(line => line.sku !== removePayload.sku),
|
|
357
|
-
);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
const addPayload = assertTractorEventPayload(eventName, payload);
|
|
361
|
-
const lines = cart.lines.map(normalizeCheckoutLine);
|
|
362
|
-
const existingIndex = lines.findIndex(line => line.sku === addPayload.sku);
|
|
363
|
-
const nextLine = normalizeCheckoutLine({
|
|
364
|
-
quantity: addPayload.quantity,
|
|
365
|
-
sku: addPayload.sku,
|
|
366
|
-
...(addPayload.name === undefined ? {} : { name: addPayload.name }),
|
|
367
|
-
...(addPayload.unitPriceCents === undefined
|
|
368
|
-
? {}
|
|
369
|
-
: { unitPriceCents: addPayload.unitPriceCents }),
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
if (existingIndex === -1) {
|
|
373
|
-
return createCheckoutCartSnapshot([...lines, nextLine]);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const existing = lines[existingIndex];
|
|
377
|
-
return createCheckoutCartSnapshot(
|
|
378
|
-
lines.map((line, index) =>
|
|
379
|
-
index === existingIndex
|
|
380
|
-
? normalizeCheckoutLine({
|
|
381
|
-
...line,
|
|
382
|
-
...nextLine,
|
|
383
|
-
quantity: existing.quantity + addPayload.quantity,
|
|
384
|
-
})
|
|
385
|
-
: line,
|
|
386
|
-
),
|
|
387
|
-
);
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
export const dispatchCheckoutAddToCart = (
|
|
391
|
-
target: EventTarget,
|
|
392
|
-
payload: CheckoutAddToCartPayload,
|
|
393
|
-
) => dispatchTractorEvent(target, 'checkout:add-to-cart', payload);
|
|
394
|
-
|
|
395
|
-
export const dispatchCheckoutCartUpdated = (
|
|
310
|
+
export const dispatchUltramodernNavigate = (
|
|
396
311
|
target: EventTarget,
|
|
397
|
-
payload:
|
|
398
|
-
) =>
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
export const dispatchCheckoutClearCart = (
|
|
406
|
-
target: EventTarget,
|
|
407
|
-
payload: CheckoutClearCartPayload = {},
|
|
408
|
-
) => dispatchTractorEvent(target, 'checkout:clear-cart', payload);
|
|
409
|
-
|
|
410
|
-
export const dispatchExploreSelectedShop = (
|
|
411
|
-
target: EventTarget,
|
|
412
|
-
payload: ExploreSelectedShopPayload,
|
|
413
|
-
) => dispatchTractorEvent(target, 'explore:selected-shop', payload);
|
|
312
|
+
payload: UltramodernNavigatePayload,
|
|
313
|
+
) =>
|
|
314
|
+
dispatchUltramodernWorkspaceEvent(
|
|
315
|
+
target,
|
|
316
|
+
ultramodernWorkspaceEventNames.navigate,
|
|
317
|
+
payload,
|
|
318
|
+
);
|
|
414
319
|
|
|
415
|
-
export const
|
|
320
|
+
export const dispatchUltramodernRouteSettled = (
|
|
416
321
|
target: EventTarget,
|
|
417
|
-
payload:
|
|
418
|
-
) =>
|
|
322
|
+
payload: UltramodernRouteSettledPayload,
|
|
323
|
+
) =>
|
|
324
|
+
dispatchUltramodernWorkspaceEvent(
|
|
325
|
+
target,
|
|
326
|
+
ultramodernWorkspaceEventNames.routeSettled,
|
|
327
|
+
payload,
|
|
328
|
+
);
|
|
419
329
|
|
|
420
|
-
export const
|
|
330
|
+
export const dispatchUltramodernRemoteReady = (
|
|
421
331
|
target: EventTarget,
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
332
|
+
payload: UltramodernRemoteReadyPayload,
|
|
333
|
+
) =>
|
|
334
|
+
dispatchUltramodernWorkspaceEvent(
|
|
335
|
+
target,
|
|
336
|
+
ultramodernWorkspaceEventNames.remoteReady,
|
|
337
|
+
payload,
|
|
338
|
+
);
|
|
427
339
|
|
|
428
|
-
export const
|
|
340
|
+
export const dispatchUltramodernPerformanceSignal = (
|
|
429
341
|
target: EventTarget,
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
342
|
+
payload: UltramodernPerformanceSignalPayload,
|
|
343
|
+
) =>
|
|
344
|
+
dispatchUltramodernWorkspaceEvent(
|
|
345
|
+
target,
|
|
346
|
+
ultramodernWorkspaceEventNames.performanceSignal,
|
|
347
|
+
payload,
|
|
348
|
+
);
|
|
435
349
|
|
|
436
|
-
export const
|
|
350
|
+
export const onUltramodernNavigate = (
|
|
437
351
|
target: EventTarget,
|
|
438
352
|
handler: (
|
|
439
|
-
payload:
|
|
440
|
-
event: CustomEvent<
|
|
353
|
+
payload: UltramodernNavigatePayload,
|
|
354
|
+
event: CustomEvent<UltramodernNavigatePayload>,
|
|
441
355
|
) => void,
|
|
442
|
-
) =>
|
|
356
|
+
) =>
|
|
357
|
+
onUltramodernWorkspaceEvent(
|
|
358
|
+
target,
|
|
359
|
+
ultramodernWorkspaceEventNames.navigate,
|
|
360
|
+
handler,
|
|
361
|
+
);
|
|
443
362
|
|
|
444
|
-
export const
|
|
363
|
+
export const onUltramodernRouteSettled = (
|
|
445
364
|
target: EventTarget,
|
|
446
365
|
handler: (
|
|
447
|
-
payload:
|
|
448
|
-
event: CustomEvent<
|
|
366
|
+
payload: UltramodernRouteSettledPayload,
|
|
367
|
+
event: CustomEvent<UltramodernRouteSettledPayload>,
|
|
449
368
|
) => void,
|
|
450
|
-
) =>
|
|
369
|
+
) =>
|
|
370
|
+
onUltramodernWorkspaceEvent(
|
|
371
|
+
target,
|
|
372
|
+
ultramodernWorkspaceEventNames.routeSettled,
|
|
373
|
+
handler,
|
|
374
|
+
);
|
|
451
375
|
|
|
452
|
-
export const
|
|
376
|
+
export const onUltramodernRemoteReady = (
|
|
453
377
|
target: EventTarget,
|
|
454
378
|
handler: (
|
|
455
|
-
payload:
|
|
456
|
-
event: CustomEvent<
|
|
379
|
+
payload: UltramodernRemoteReadyPayload,
|
|
380
|
+
event: CustomEvent<UltramodernRemoteReadyPayload>,
|
|
457
381
|
) => void,
|
|
458
|
-
) =>
|
|
382
|
+
) =>
|
|
383
|
+
onUltramodernWorkspaceEvent(
|
|
384
|
+
target,
|
|
385
|
+
ultramodernWorkspaceEventNames.remoteReady,
|
|
386
|
+
handler,
|
|
387
|
+
);
|
|
459
388
|
|
|
460
|
-
export const
|
|
389
|
+
export const onUltramodernPerformanceSignal = (
|
|
461
390
|
target: EventTarget,
|
|
462
391
|
handler: (
|
|
463
|
-
payload:
|
|
464
|
-
event: CustomEvent<
|
|
392
|
+
payload: UltramodernPerformanceSignalPayload,
|
|
393
|
+
event: CustomEvent<UltramodernPerformanceSignalPayload>,
|
|
465
394
|
) => void,
|
|
466
|
-
) =>
|
|
395
|
+
) =>
|
|
396
|
+
onUltramodernWorkspaceEvent(
|
|
397
|
+
target,
|
|
398
|
+
ultramodernWorkspaceEventNames.performanceSignal,
|
|
399
|
+
handler,
|
|
400
|
+
);
|