@lwc/engine-core 8.28.2 → 9.0.0

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.
@@ -1,20 +1,17 @@
1
1
  import type { LightningElement } from '../base-lightning-element';
2
- import type { ConfigValue, ContextValue, ReplaceReactiveValues, WireAdapterConstructor } from '../wiring';
2
+ import type { ConfigValue, ConfigWithReactiveProps, WireAdapterConstructor } from '../wiring';
3
3
  /**
4
4
  * The decorator returned by `@wire()`; not the `wire` function.
5
- *
6
- * For TypeScript users:
7
- * - If you are seeing an unclear error message, ensure that both the type of the decorated prop and
8
- * the config used match the types expected by the wire adapter.
9
- * - String literal types in the config are resolved to the corresponding prop on the component.
10
- * For example, a component with `id = 555` and `@wire(getBook, {id: "$id"} as const) book` will
11
- * have `"$id"` resolve to type `number`.
12
5
  */
13
6
  interface WireDecorator<Value, Class> {
14
7
  (target: unknown, context: ClassFieldDecoratorContext<Class, Value | undefined> | ClassMethodDecoratorContext<Class, Value extends (value: any) => any ? Value : (this: Class, value: Value) => void> | ClassGetterDecoratorContext<Class, Value | undefined> | ClassSetterDecoratorContext<Class, Value>): void;
15
8
  }
16
9
  /**
17
10
  * Decorator factory to wire a property or method to a wire adapter data source.
11
+ *
12
+ * TypeScript users: Due to limitations of the type system, some edge cases are
13
+ * not fully type checked. See the type definition for {@linkcode ConfigWithReactiveProps}
14
+ * for details.
18
15
  * @param adapter the adapter used to provision data
19
16
  * @param config configuration object for the adapter
20
17
  * @returns A decorator function
@@ -24,9 +21,9 @@ interface WireDecorator<Value, Class> {
24
21
  * \@wire(getBook, { id: '$bookId'}) book;
25
22
  * }
26
23
  */
27
- export default function wire<ReactiveConfig extends ConfigValue = ConfigValue, Value = any, Context extends ContextValue = ContextValue, Class = LightningElement>(adapter: WireAdapterConstructor<ReplaceReactiveValues<ReactiveConfig, Class>, Value, Context> | {
28
- adapter: WireAdapterConstructor<ReplaceReactiveValues<ReactiveConfig, Class>, Value, Context>;
29
- }, config?: ReactiveConfig): WireDecorator<Value, Class>;
24
+ export default function wire<const Config extends ConfigValue = ConfigValue, const Value = any, const Class = LightningElement>(adapter: WireAdapterConstructor<Config, Value> | {
25
+ adapter: WireAdapterConstructor<Config, Value>;
26
+ }, config?: ConfigWithReactiveProps<Config, Class>): WireDecorator<Value, Class>;
30
27
  export declare function internalWireFieldDecorator(key: string): PropertyDescriptor;
31
28
  export {};
32
29
  //# sourceMappingURL=wire.d.ts.map
@@ -1,4 +1,4 @@
1
1
  export { createContextProviderWithRegister, createContextWatcher } from './context';
2
- export { ConfigCallback, ConfigValue, ContextConsumer, ContextProvider, ContextProviderOptions, ContextValue, DataCallback, ReplaceReactiveValues, WireAdapter, WireAdapterConstructor, WireAdapterSchemaValue, WireContextSubscriptionPayload, WireContextSubscriptionCallback, } from './types';
2
+ export type { ConfigCallback, ConfigValue, ConfigWithReactiveProps, ContextConsumer, ContextProvider, ContextProviderOptions, ContextValue, DataCallback, WireAdapter, WireAdapterConstructor, WireAdapterSchemaValue, WireContextSubscriptionPayload, WireContextSubscriptionCallback, } from './types';
3
3
  export { connectWireAdapters, disconnectWireAdapters, installWireAdapters, storeWiredFieldMeta, storeWiredMethodMeta, } from './wiring';
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -50,19 +50,84 @@ export interface ContextProviderOptions {
50
50
  }
51
51
  export type ContextProvider = (elmOrComponent: EventTarget, options: ContextProviderOptions) => void;
52
52
  export type RegisterContextProviderFn = (element: HostElement, adapterContextToken: string, onContextSubscription: WireContextSubscriptionCallback) => void;
53
- /** Resolves a property chain to the corresponding value on the target type. */
54
- type ResolveReactiveValue<
55
- /** The object to search for properties; initially the component. */
56
- Target,
57
- /** A string representing a chain of of property keys, e.g. "data.user.name". */
58
- Keys extends string> = Keys extends `${infer FirstKey}.${infer Rest}` ? FirstKey extends keyof Target ? ResolveReactiveValue<Target[FirstKey], Rest> : undefined : Keys extends keyof Target ? Target[Keys] : undefined;
59
53
  /**
60
- * Detects if the `Value` type is a property chain starting with "$". If so, it resolves the
61
- * properties to the corresponding value on the target type.
54
+ * Gets the property keys that can be used in a reactive string. Excludes symbols and string props
55
+ * with `.` (`$foo.bar` maps to `Class["foo"]["bar"]`; `Class["foo.bar"]` can never be used).
62
56
  */
63
- type ResolveValueIfReactive<Value, Target> = Value extends string ? string extends Value ? any : Value extends `$${infer Keys}` ? ResolveReactiveValue<Target, Keys> : Value : Value;
64
- export type ReplaceReactiveValues<Config extends ConfigValue, Component> = {
65
- [K in keyof Config]: ResolveValueIfReactive<Config[K], Component>;
57
+ type ReactivePropsOnly<K extends PropertyKey> = Exclude<K, symbol | `${string}.${string}`>;
58
+ /** The string keys of an object that match the target type. */
59
+ type PropsOfType<Class, Target> = ReactivePropsOnly<{
60
+ [K in keyof Class]-?: NonNullable<Class[K]> extends Target ? K : never;
61
+ }[keyof Class]>;
62
+ /** Gets the property keys that can be used in a reactive property chain. */
63
+ type ChainableObjectProps<Class> = ReactivePropsOnly<{
64
+ [K in keyof Class]-?: NonNullable<Class[K]> extends object ? keyof NonNullable<Class[K]> extends never ? never : K : never;
65
+ }[keyof Class]>;
66
+ /**
67
+ * Extends a given wire adapter config with reactive property strings
68
+ * (for example, `$prop`) for values on the given class that match the config.
69
+ *
70
+ * Due to limitations of the type system, and to limit the size of the
71
+ * resulting type union, a number of restrictions apply to this type that can
72
+ * result in false positives or false negatives.
73
+ *
74
+ * - Config values with a `string` type inherently permit _any_ string,
75
+ * even reactive strings that resolve to the wrong type.
76
+ * - Only top-level props are validated. Type checking is _not_ done on nested
77
+ * property chains.
78
+ * - Property chains are allowed only if the top-level property is an object.
79
+ * - Property chains from `LightningElement` props are excluded.
80
+ *
81
+ * For property chains, a getter can be used to avoid incorrect error reporting,
82
+ * as top-level properties are always validated. Alternatively, a type assertion
83
+ * can be used to suppress the error.
84
+ *
85
+ * @example
86
+ * // Wire adapter with a required number prop and optional string prop
87
+ * declare const Adapter: WireAdapterConstructor<{ num: number; str?: string }>;
88
+ * declare class Component extends LightningElement {
89
+ * numberProp = 6_7;
90
+ * stringProp = '🙌';
91
+ * objectProp?: { nestedStringProp: string };
92
+
93
+ * \@wire(Adapter, { num: 123 }) validNumberValue?: unknown;
94
+ * \@wire(Adapter, { num: "$numberProp" }) validNumberProp?: unknown;
95
+ * \@wire(Adapter, { num: "bad value" }) invalidNumberValue?: unknown;
96
+ * \@wire(Adapter, { num: "$stringProp" }) invalidNumberProp?: unknown;
97
+ *
98
+ * \@wire(Adapter, { str: "valid string", num: 0 }) validStringValue?: unknown;
99
+ * \@wire(Adapter, { str: "$stringProp", num: 0 }) validStringProp?: unknown;
100
+
101
+ * // `"$numberProp"` is a string, and therefore satisfies the type,
102
+ * // despite resolving to a number at runtime
103
+ * \@wire(Adapter, { str: "$numberProp", num: 0 }) falseNegativeString?: unknown;
104
+ *
105
+ * // Nested props aren't checked to avoid crashing on recursive types
106
+ * \@wire(Adapter, { num: "$objectProp.nestedStringProp" }) falseNegativeNested?: unknown;
107
+ *
108
+ * // Any value can have properties accessed at runtime, but property chains using
109
+ * // non-objects are uncommon, and are excluded for simplicity
110
+ * \@wire(Adapter, { num: "$stringProp.length" }) falsePositiveString?: unknown;
111
+ *
112
+ * // Using props inherited from `LightningElement` for property chains is uncommon,
113
+ * // and are excluded for simplicity
114
+ * \@wire(Adapter, { num: "$hostElement.childElementCount" }) falsePositiveLightningElement?: unknown;
115
+ *
116
+ * get propertyChainWorkaround(): string {
117
+ * return this.objectProp.nestedStringProp;
118
+ * }
119
+ *
120
+ * // Top-level prop is type checked and correctly reports an error
121
+ * \@wire(Adapter, { num: "$propertyChainWorkaround" }) truePositiveGetter?: unknown;
122
+ *
123
+ * // Type assertion is used and correctly reports an error
124
+ * \@wire(Adapter, {
125
+ * num: "$objectProp.nestedStringProp" as unknown as Component["objectProp"]["nestedStringProp"]
126
+ * }) truePositiveTypeAssertion?: unknown;
127
+ * }
128
+ */
129
+ export type ConfigWithReactiveProps<Config extends ConfigValue, Class> = {
130
+ [K in keyof Config]: Config[K] | `$${PropsOfType<Class, Config[K]>}` | `$${ChainableObjectProps<Class>}.${string}`;
66
131
  };
67
132
  export {};
68
133
  //# sourceMappingURL=types.d.ts.map
package/dist/index.js CHANGED
@@ -2452,10 +2452,7 @@ function api$1(
2452
2452
  value,
2453
2453
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2454
2454
  context) {
2455
- if (process.env.NODE_ENV !== 'production') {
2456
- assert.fail(`@api decorator can only be used as a decorator function.`);
2457
- }
2458
- throw new Error();
2455
+ assert.fail(`@api decorator can only be used as a decorator function.`);
2459
2456
  }
2460
2457
  function createPublicPropertyDescriptor(key) {
2461
2458
  return {
@@ -2535,10 +2532,7 @@ context) {
2535
2532
  if (arguments.length === 1) {
2536
2533
  return getReactiveProxy(target);
2537
2534
  }
2538
- if (process.env.NODE_ENV !== 'production') {
2539
- assert.fail(`@track decorator can only be used with one argument to return a trackable object, or as a decorator function.`);
2540
- }
2541
- throw new Error();
2535
+ assert.fail(`@track decorator can only be used with one argument to return a trackable object, or as a decorator function.`);
2542
2536
  }
2543
2537
  function internalTrackDecorator(key) {
2544
2538
  return {
@@ -2578,6 +2572,10 @@ function internalTrackDecorator(key) {
2578
2572
  */
2579
2573
  /**
2580
2574
  * Decorator factory to wire a property or method to a wire adapter data source.
2575
+ *
2576
+ * TypeScript users: Due to limitations of the type system, some edge cases are
2577
+ * not fully type checked. See the type definition for {@linkcode ConfigWithReactiveProps}
2578
+ * for details.
2581
2579
  * @param adapter the adapter used to provision data
2582
2580
  * @param config configuration object for the adapter
2583
2581
  * @returns A decorator function
@@ -2592,10 +2590,7 @@ function wire(
2592
2590
  adapter,
2593
2591
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2594
2592
  config) {
2595
- if (process.env.NODE_ENV !== 'production') {
2596
- assert.fail('@wire(adapter, config?) may only be used as a decorator.');
2597
- }
2598
- throw new Error();
2593
+ assert.fail('@wire(adapter, config?) may only be used as a decorator.');
2599
2594
  }
2600
2595
  function internalWireFieldDecorator(key) {
2601
2596
  return {
@@ -2641,7 +2636,7 @@ function validateObservedField(Ctor, fieldName, descriptor) {
2641
2636
  if (!isUndefined$1(descriptor)) {
2642
2637
  const type = getClassDescriptorType(descriptor);
2643
2638
  const message = `Invalid observed ${fieldName} field. Found a duplicate ${type} with the same name.`;
2644
- // TODO [#3408]: this should throw, not log
2639
+ // TODO [#4450]: this should throw, not log
2645
2640
  logError(message);
2646
2641
  }
2647
2642
  }
@@ -2649,7 +2644,7 @@ function validateFieldDecoratedWithTrack(Ctor, fieldName, descriptor) {
2649
2644
  assertNotProd(); // this method should never leak to prod
2650
2645
  if (!isUndefined$1(descriptor)) {
2651
2646
  const type = getClassDescriptorType(descriptor);
2652
- // TODO [#3408]: this should throw, not log
2647
+ // TODO [#4450]: this should throw, not log
2653
2648
  logError(`Invalid @track ${fieldName} field. Found a duplicate ${type} with the same name.`);
2654
2649
  }
2655
2650
  }
@@ -2657,14 +2652,14 @@ function validateFieldDecoratedWithWire(Ctor, fieldName, descriptor) {
2657
2652
  assertNotProd(); // this method should never leak to prod
2658
2653
  if (!isUndefined$1(descriptor)) {
2659
2654
  const type = getClassDescriptorType(descriptor);
2660
- // TODO [#3408]: this should throw, not log
2655
+ // TODO [#4450]: this should throw, not log
2661
2656
  logError(`Invalid @wire ${fieldName} field. Found a duplicate ${type} with the same name.`);
2662
2657
  }
2663
2658
  }
2664
2659
  function validateMethodDecoratedWithWire(Ctor, methodName, descriptor) {
2665
2660
  assertNotProd(); // this method should never leak to prod
2666
2661
  if (isUndefined$1(descriptor) || !isFunction$1(descriptor.value) || isFalse(descriptor.writable)) {
2667
- // TODO [#3441]: This line of code does not seem possible to reach.
2662
+ // TODO [#4450]: This line of code does not seem possible to reach.
2668
2663
  logError(`Invalid @wire ${methodName} field. The field should have a valid writable descriptor.`);
2669
2664
  }
2670
2665
  }
@@ -2673,7 +2668,7 @@ function validateFieldDecoratedWithApi(Ctor, fieldName, descriptor) {
2673
2668
  if (!isUndefined$1(descriptor)) {
2674
2669
  const type = getClassDescriptorType(descriptor);
2675
2670
  const message = `Invalid @api ${fieldName} field. Found a duplicate ${type} with the same name.`;
2676
- // TODO [#3408]: this should throw, not log
2671
+ // TODO [#4450]: this should throw, not log
2677
2672
  logError(message);
2678
2673
  }
2679
2674
  }
@@ -2681,7 +2676,7 @@ function validateAccessorDecoratedWithApi(Ctor, fieldName, descriptor) {
2681
2676
  assertNotProd(); // this method should never leak to prod
2682
2677
  if (isFunction$1(descriptor.set)) {
2683
2678
  if (!isFunction$1(descriptor.get)) {
2684
- // TODO [#3441]: This line of code does not seem possible to reach.
2679
+ // TODO [#4450]: This line of code does not seem possible to reach.
2685
2680
  logError(`Missing getter for property ${fieldName} decorated with @api in ${Ctor}. You cannot have a setter without the corresponding getter.`);
2686
2681
  }
2687
2682
  }
@@ -2767,7 +2762,7 @@ function registerDecorators(Ctor, meta) {
2767
2762
  if (method === 1) {
2768
2763
  if (process.env.NODE_ENV !== 'production') {
2769
2764
  if (!adapter) {
2770
- // TODO [#3408]: this should throw, not log
2765
+ // TODO [#4450]: this should throw, not log
2771
2766
  logError(`@wire on method "${fieldOrMethodName}": adapter id must be truthy.`);
2772
2767
  }
2773
2768
  validateMethodDecoratedWithWire(Ctor, fieldOrMethodName, descriptor);
@@ -2781,7 +2776,7 @@ function registerDecorators(Ctor, meta) {
2781
2776
  else {
2782
2777
  if (process.env.NODE_ENV !== 'production') {
2783
2778
  if (!adapter) {
2784
- // TODO [#3408]: this should throw, not log
2779
+ // TODO [#4450]: this should throw, not log
2785
2780
  logError(`@wire on field "${fieldOrMethodName}": adapter id must be truthy.`);
2786
2781
  }
2787
2782
  validateFieldDecoratedWithWire(Ctor, fieldOrMethodName, descriptor);
@@ -5237,7 +5232,6 @@ function hasDynamicChildren(children) {
5237
5232
  }
5238
5233
  function createKeyToOldIdx(children, beginIdx, endIdx) {
5239
5234
  const map = {};
5240
- // TODO [#1637]: simplify this by assuming that all vnodes has keys
5241
5235
  for (let j = beginIdx; j <= endIdx; ++j) {
5242
5236
  const ch = children[j];
5243
5237
  if (isVNode(ch)) {
@@ -8769,5 +8763,5 @@ function readonly(obj) {
8769
8763
  }
8770
8764
 
8771
8765
  export { BaseBridgeElement, LightningElement, profilerControl as __unstable__ProfilerControl, reportingControl as __unstable__ReportingControl, api$1 as api, computeShadowAndRenderMode, connectRootElement, createContextProviderWithRegister, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentAPIVersion, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, registerComponent, registerDecorators, registerTemplate, runFormAssociatedCallback, runFormDisabledCallback, runFormResetCallback, runFormStateRestoreCallback, sanitizeAttribute, shouldBeFormAssociated, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
8772
- /** version: 8.28.2 */
8766
+ /** version: 9.0.0 */
8773
8767
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
5
5
  ],
6
6
  "name": "@lwc/engine-core",
7
- "version": "8.28.2",
7
+ "version": "9.0.0",
8
8
  "description": "Core LWC engine APIs.",
9
9
  "keywords": [
10
10
  "lwc"
@@ -19,13 +19,17 @@
19
19
  "url": "https://github.com/salesforce/lwc/issues"
20
20
  },
21
21
  "license": "MIT",
22
+ "type": "module",
22
23
  "publishConfig": {
23
24
  "access": "public"
24
25
  },
26
+ "engines": {
27
+ "node": ">=16.6.0"
28
+ },
25
29
  "volta": {
26
30
  "extends": "../../../package.json"
27
31
  },
28
- "main": "dist/index.cjs.js",
32
+ "main": "dist/index.js",
29
33
  "module": "dist/index.js",
30
34
  "types": "dist/index.d.ts",
31
35
  "files": [
@@ -46,9 +50,9 @@
46
50
  }
47
51
  },
48
52
  "dependencies": {
49
- "@lwc/features": "8.28.2",
50
- "@lwc/shared": "8.28.2",
51
- "@lwc/signals": "8.28.2"
53
+ "@lwc/features": "9.0.0",
54
+ "@lwc/shared": "9.0.0",
55
+ "@lwc/signals": "9.0.0"
52
56
  },
53
57
  "devDependencies": {
54
58
  "observable-membrane": "2.0.0"