@arcgis/lumina-compiler 4.31.0-next.100

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 (142) hide show
  1. package/LICENSE.md +13 -0
  2. package/README.md +21 -0
  3. package/dist/chunk-BQ4U6HQL.js +1 -0
  4. package/dist/chunk-JFKSI6I7.js +1 -0
  5. package/dist/context/index.d.ts +241 -0
  6. package/dist/context/types.d.ts +34 -0
  7. package/dist/context/utils.d.ts +23 -0
  8. package/dist/context/utils.spec.d.ts +1 -0
  9. package/dist/defaultAssetsUrl.d.ts +21 -0
  10. package/dist/defaultAssetsUrl.spec.d.ts +1 -0
  11. package/dist/dependencies/arcgisCore.d.ts +30 -0
  12. package/dist/dependencies/discover.d.ts +62 -0
  13. package/dist/dependencies/index.d.ts +11 -0
  14. package/dist/dependencies/lit.d.ts +2 -0
  15. package/dist/dependencies/loaders.d.ts +8 -0
  16. package/dist/dependencies/stencil.d.ts +6 -0
  17. package/dist/dependencies/testSetupFiles.d.ts +21 -0
  18. package/dist/dependencies/updateLumina.d.ts +8 -0
  19. package/dist/dependencies/updateLumina.spec.d.ts +1 -0
  20. package/dist/dependencies/utils.d.ts +23 -0
  21. package/dist/entrypoints/addNonLazyImports.d.ts +13 -0
  22. package/dist/entrypoints/config.d.ts +23 -0
  23. package/dist/entrypoints/dtsUtils.d.ts +22 -0
  24. package/dist/entrypoints/dtsUtils.spec.d.ts +1 -0
  25. package/dist/entrypoints/findUtils.d.ts +21 -0
  26. package/dist/entrypoints/findUtils.spec.d.ts +1 -0
  27. package/dist/entrypoints/handleComponentImports.d.ts +13 -0
  28. package/dist/entrypoints/pathMapping.d.ts +25 -0
  29. package/dist/entrypoints/resolveTagName.d.ts +14 -0
  30. package/dist/entrypoints/resolveTagName.spec.d.ts +1 -0
  31. package/dist/frameworkTypes/index.d.ts +15 -0
  32. package/dist/frameworkTypes/lumina.d.ts +5 -0
  33. package/dist/frameworkTypes/preact.d.ts +6 -0
  34. package/dist/frameworkTypes/react.d.ts +6 -0
  35. package/dist/frameworkTypes/stencil.d.ts +5 -0
  36. package/dist/frameworkTypes/utils.d.ts +8 -0
  37. package/dist/frameworkTypes/vanilla.d.ts +3 -0
  38. package/dist/index.d.ts +29 -0
  39. package/dist/index.js +248 -0
  40. package/dist/jsxToLitHtml/autoAddNothing.d.ts +8 -0
  41. package/dist/jsxToLitHtml/comments.d.ts +19 -0
  42. package/dist/jsxToLitHtml/config.d.ts +148 -0
  43. package/dist/jsxToLitHtml/convertProps.d.ts +10 -0
  44. package/dist/jsxToLitHtml/escapeForTemplateLiteral.d.ts +45 -0
  45. package/dist/jsxToLitHtml/imports.d.ts +32 -0
  46. package/dist/jsxToLitHtml/index.d.ts +17 -0
  47. package/dist/jsxToLitHtml/inferPropType.d.ts +40 -0
  48. package/dist/jsxToLitHtml/insertRepeatCall.d.ts +49 -0
  49. package/dist/jsxToLitHtml/jsxVisitor.d.ts +11 -0
  50. package/dist/jsxToLitHtml/templateParts.d.ts +17 -0
  51. package/dist/jsxToLitHtml/throwOnImportingExternalized.d.ts +10 -0
  52. package/dist/jsxToLitHtml/types.d.ts +80 -0
  53. package/dist/jsxToLitHtml/utils.d.ts +14 -0
  54. package/dist/jsxToLitHtml/utils.spec.d.ts +1 -0
  55. package/dist/manifests/complexTypes/addComponentMetadata.d.ts +5 -0
  56. package/dist/manifests/complexTypes/addMethodMetadata.d.ts +6 -0
  57. package/dist/manifests/complexTypes/addPropMetadata.d.ts +8 -0
  58. package/dist/manifests/complexTypes/docsUtils.d.ts +18 -0
  59. package/dist/manifests/complexTypes/event.d.ts +9 -0
  60. package/dist/manifests/complexTypes/getComplexPropertyType.d.ts +11 -0
  61. package/dist/manifests/complexTypes/transformUtils.d.ts +130 -0
  62. package/dist/manifests/complexTypes/transformUtils.spec.d.ts +1 -0
  63. package/dist/manifests/complexTypes/typeToEnum.d.ts +14 -0
  64. package/dist/manifests/complexTypes/typeToEnum.spec.d.ts +1 -0
  65. package/dist/manifests/complexTypes/types.d.ts +135 -0
  66. package/dist/manifests/config.d.ts +2 -0
  67. package/dist/manifests/createManifest.d.ts +39 -0
  68. package/dist/manifests/customElementDecoratorPlugins.d.ts +58 -0
  69. package/dist/manifests/customElementDecoratorPlugins.spec.d.ts +1 -0
  70. package/dist/manifests/hideUntilHydrated.d.ts +15 -0
  71. package/dist/manifests/index.d.ts +12 -0
  72. package/dist/manifests/kebabCaseAttributes.d.ts +18 -0
  73. package/dist/manifests/lazy.d.ts +22 -0
  74. package/dist/manifests/lazy.spec.d.ts +1 -0
  75. package/dist/manifests/stencilManifest.d.ts +17 -0
  76. package/dist/manifests/storybookManifest.d.ts +6 -0
  77. package/dist/manifests/types.d.ts +1 -0
  78. package/dist/manifests/utils.d.ts +17 -0
  79. package/dist/plugins/buildCdn.d.ts +14 -0
  80. package/dist/plugins/buildStencilHydrate.d.ts +16 -0
  81. package/dist/plugins/buildWrappers.d.ts +3 -0
  82. package/dist/plugins/configureVite.d.ts +19 -0
  83. package/dist/plugins/externalizeDependencies.d.ts +34 -0
  84. package/dist/plugins/externalizeDependencies.spec.d.ts +1 -0
  85. package/dist/plugins/generateDocs.d.ts +10 -0
  86. package/dist/plugins/handleDynamicAssets.d.ts +3 -0
  87. package/dist/plugins/handleStaticAssets.d.ts +9 -0
  88. package/dist/plugins/loadLitCss.d.ts +89 -0
  89. package/dist/plugins/printTotalBuildSize.d.ts +7 -0
  90. package/dist/plugins/provideAssets.d.ts +53 -0
  91. package/dist/plugins/provideAssets.spec.d.ts +1 -0
  92. package/dist/plugins/setAssetsPath.d.ts +10 -0
  93. package/dist/plugins/updatePackageJson.d.ts +9 -0
  94. package/dist/plugins/updatePackageJson.spec.d.ts +1 -0
  95. package/dist/publicTypes.d.ts +626 -0
  96. package/dist/puppeteer-testing/globalSetup.d.ts +72 -0
  97. package/dist/puppeteer-testing/globalSetup.js +11 -0
  98. package/dist/puppeteer-testing/index.d.ts +9 -0
  99. package/dist/puppeteer-testing/index.js +6 -0
  100. package/dist/puppeteer-testing/injected.d.ts +8 -0
  101. package/dist/puppeteer-testing/puppeteer/browser.d.ts +6 -0
  102. package/dist/puppeteer-testing/puppeteer/element.d.ts +219 -0
  103. package/dist/puppeteer-testing/puppeteer/events.d.ts +21 -0
  104. package/dist/puppeteer-testing/puppeteer/page.d.ts +5 -0
  105. package/dist/puppeteer-testing/puppeteer/types.d.ts +124 -0
  106. package/dist/puppeteer-testing/vitest/matchers/attributes.d.ts +4 -0
  107. package/dist/puppeteer-testing/vitest/matchers/classList.d.ts +4 -0
  108. package/dist/puppeteer-testing/vitest/matchers/events.d.ts +7 -0
  109. package/dist/puppeteer-testing/vitest/matchers/index.d.ts +38 -0
  110. package/dist/puppeteer-testing/vitest/matchers/text.d.ts +2 -0
  111. package/dist/puppeteer-testing/vitest/matchers/utils.d.ts +1 -0
  112. package/dist/puppeteer-testing/vitest/runner.d.ts +15 -0
  113. package/dist/puppeteer-testing/vitest/setupFile.d.ts +1 -0
  114. package/dist/testing/index.d.ts +11 -0
  115. package/dist/testing/index.js +1 -0
  116. package/dist/testing/mount.d.ts +106 -0
  117. package/dist/testing/setupFile.d.ts +1 -0
  118. package/dist/testing/snapshotSerializer.d.ts +12 -0
  119. package/dist/testing/wrapController.d.ts +33 -0
  120. package/dist/tests/utils.d.ts +4 -0
  121. package/dist/transformers/guardAgainstInternalJsDoc.d.ts +11 -0
  122. package/dist/transformers/index.d.ts +22 -0
  123. package/dist/transformers/injectRuntimeOptions.d.ts +3 -0
  124. package/dist/transformers/internalTypeScriptApis.d.ts +29 -0
  125. package/dist/transformers/liftDecorators.d.ts +21 -0
  126. package/dist/transformers/members.d.ts +12 -0
  127. package/dist/transformers/property.d.ts +9 -0
  128. package/dist/transformers/propertyOptions.d.ts +111 -0
  129. package/dist/transformers/updateOriginalFile.d.ts +20 -0
  130. package/dist/transformers/utils.d.ts +14 -0
  131. package/dist/types/astTransformers.d.ts +3 -0
  132. package/dist/types/hideInternalLitElement.d.ts +9 -0
  133. package/dist/types/index.d.ts +18 -0
  134. package/dist/types/liftSetterTypes.d.ts +33 -0
  135. package/dist/types/textTransformers.d.ts +4 -0
  136. package/dist/types/transformComponentMembers.d.ts +10 -0
  137. package/dist/useLumina.d.ts +13 -0
  138. package/dist/utils/error.d.ts +4 -0
  139. package/dist/utils/packageJson.d.ts +24 -0
  140. package/dist/utils/path.d.ts +25 -0
  141. package/dist/utils/path.spec.d.ts +1 -0
  142. package/package.json +80 -0
@@ -0,0 +1,106 @@
1
+ import type { TemplateResult } from "lit-html";
2
+ import type { JsxNode, LitElement, ToElement } from "@arcgis/lumina";
3
+ export type RenderResult<Component extends HTMLElement> = {
4
+ /**
5
+ * The custom element proxy that is attached to the DOM.
6
+ *
7
+ * This element will contain all the public properties and public methods of
8
+ * your custom element, but it will not contain any internal members.
9
+ */
10
+ readonly el: ToElement<Component> & {
11
+ shadowRoot: ShadowRoot;
12
+ };
13
+ /**
14
+ * This is the actual LitElement that you authored in the code.
15
+ *
16
+ * It is not directly connected to the DOM (instead, a proxy element is used
17
+ * to facilitate lazy-loading).
18
+ *
19
+ * All public and private members of your custom element are available here.
20
+ */
21
+ readonly component: Component;
22
+ /**
23
+ * A callback for triggering component re-render. Optionally, if the first
24
+ * argument to `mount()` was a function, that function will be called
25
+ * again to get a new template.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * let someValue = 1;
30
+ * const { el, component, reRender } = await mount<ArcgisCounter>(
31
+ * ()=><arcgis-counter someProp={someValue} />
32
+ * );
33
+ *
34
+ * someValue = 2;
35
+ * await reRender();
36
+ * ```
37
+ *
38
+ * The above is roughly equivalent to manually setting `el.someProp = 2`.
39
+ */
40
+ readonly reRender: () => Promise<boolean>;
41
+ };
42
+ export type RenderOptions<Component extends HTMLElement = HTMLElement> = {
43
+ /**
44
+ * The parent to attach this component to.
45
+ *
46
+ * @default document.body
47
+ */
48
+ readonly parent?: DocumentFragment | HTMLElement;
49
+ /**
50
+ * `mount()` will return a promise that resolves after the element
51
+ * is connected to the DOM, fully loaded and rendered.
52
+ *
53
+ * This callback is for executing code right after the element is connected to
54
+ * the DOM, but before it is fully loaded and rendered.
55
+ */
56
+ readonly afterConnect?: (el: ToElement<Component> & {
57
+ shadowRoot: ShadowRoot;
58
+ }) => Promise<void> | void;
59
+ /**
60
+ * This option only needs to be used if you created the custom element
61
+ * dynamically (inside the test file), rather than in a separate .tsx file.
62
+ * Also, if you already passed the dynamic custom element class as the first
63
+ * argument to `mount()`, you don't need to provide it again here.
64
+ */
65
+ readonly dynamicComponents?: (typeof LitElement)[];
66
+ /**
67
+ * Whether to cleanup the document body after the test. Set this to false if
68
+ * you wish to reuse the same component between different test() blocks.
69
+ *
70
+ * @default true
71
+ */
72
+ readonly cleanupAfterTest?: boolean;
73
+ };
74
+ /**
75
+ * Render Lit Element in a test environment.
76
+ *
77
+ * See documentation:
78
+ * https://qawebgis.esri.com/arcgis-components/?path=/docs/references-lumina-testing--docs
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * // Create component based on a tag name
83
+ * const { el, component } = await mount("arcgis-counter");
84
+ * // Create component based on JSX (explicit type annotation necessary)
85
+ * const { el, component } = await mount<"arcgis-counter">(<arcgis-counter />);
86
+ * // You can also use the component class as the explicit type annotation:
87
+ * const { el, component } = await mount<ArcgisCounter>(<arcgis-counter />);
88
+ * ```
89
+ *
90
+ * @remarks
91
+ * In it's simplest form, what this function is doing is the following:
92
+ *
93
+ * ```tsx
94
+ * import { render } from "lit-html";
95
+ * render(<arcgis-counter />, document.body);
96
+ * const el = document.querySelector("arcgis-counter")!;
97
+ * await el.componentOnReady();
98
+ * ```
99
+ */
100
+ export declare function mount<const TagName extends keyof HTMLElementTagNameMap>(tagName: TagName, options?: RenderOptions<HTMLElementTagNameMap[TagName]>): Promise<RenderResult<HTMLElementTagNameMap[TagName]>>;
101
+ export declare function mount<Class extends typeof LitElement>(template: TemplateResult | (() => JsxNode), options?: RenderOptions<InstanceType<Class>> & {
102
+ dynamicComponents: [Class];
103
+ }): Promise<RenderResult<InstanceType<Class>>>;
104
+ export declare function mount<TagName extends keyof HTMLElementTagNameMap = "wbr">(jsx: TemplateResult | (() => JsxNode), options?: RenderOptions<TagName extends "wbr" ? LitElement : HTMLElementTagNameMap[TagName]>): Promise<RenderResult<TagName extends "wbr" ? LitElement : HTMLElementTagNameMap[TagName]>>;
105
+ export declare function mount<Class extends typeof LitElement>(template: Class | TemplateResult | (() => JsxNode), options?: RenderOptions<InstanceType<Class>>): Promise<RenderResult<InstanceType<Class>>>;
106
+ export declare function mount<Component extends LitElement>(template: TemplateResult | (() => JsxNode) | (new () => Component), options?: RenderOptions<Component>): Promise<RenderResult<Component>>;
@@ -0,0 +1 @@
1
+ export declare function setupLuminaTest(): void;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Adds a vitest serializer for Shadow DOM.
3
+ * You do not need to call this function directly - `@arcgis/lumina-compiler` will
4
+ * configure Vitest to use this serializer automatically.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * const { el, component } = await mount("arcgis-test1");
9
+ * expect(el.shadowRoot).toMatchInlineSnapshot(`<p>1</p>`);
10
+ * ```
11
+ */
12
+ export declare function addShadowDomSerializer(): void;
@@ -0,0 +1,33 @@
1
+ import type { BaseComponent, ControllerHost } from "@arcgis/components-controllers";
2
+ import { LitElement } from "@arcgis/lumina";
3
+ /**
4
+ * Wrap a controller in a small component - useful when you are interested in
5
+ * only testing the controller behavior.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const testController = (): string => makeController(()=>'a');
10
+ * const { component } = await mount(wrapController(testController));
11
+ * expect(component.controller).toEqual("a");
12
+ * ```
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * class TestController extends Controller {
17
+ * a = "a";
18
+ * }
19
+ * const {
20
+ * component: { controller }
21
+ * } = await mount(wrapController(TestController));
22
+ * expect(controller.a).toEqual("a");
23
+ * ```
24
+ */
25
+ export declare function wrapController<T>(controller: ((component: BaseComponent & ControllerHost) => T) | (new (component: BaseComponent & ControllerHost) => T),
26
+ /**
27
+ * An optional callback to call right after controller constructor
28
+ */
29
+ afterConstruct?: (component: LitElement & {
30
+ controller: T;
31
+ }) => Promise<void> | void): typeof LitElement & (new () => LitElement & {
32
+ controller: T;
33
+ });
@@ -0,0 +1,4 @@
1
+ import type { ContextDirectories } from "../context/types";
2
+ import type { CompilerContext } from "../context";
3
+ export declare const testDir: ContextDirectories;
4
+ export declare const testContext: Pick<CompilerContext, "dir" | "documentationFileNames">;
@@ -0,0 +1,11 @@
1
+ import type { FileTransformer } from "../publicTypes";
2
+ /**
3
+ * Custom-elements-manifest excludes `@internal` things from the
4
+ * manifest, without letting us do much about it. We still want these
5
+ * to appear in the manifest so that they are included in the lazy
6
+ * component meta - without that, lazy-loading won't work correctly
7
+ *
8
+ * Opened an issue:
9
+ * https://github.com/open-wc/custom-elements-manifest/issues/263
10
+ */
11
+ export declare const guardAgainstInternalJsDoc: FileTransformer;
@@ -0,0 +1,22 @@
1
+ import type { Plugin } from "vite";
2
+ import type { CompilerContext } from "../context";
3
+ import ts from "typescript";
4
+ /**
5
+ * A pipeline of transformers for .tsx files.
6
+ * Only .tsx files are touched as all transformations deal with components and
7
+ * components should be defined in .tsx files.
8
+ *
9
+ * Instead of having separate transform() vite plugins, and each plugin having
10
+ * to generate a source map (or forgetting to do so and breaking DX) and then
11
+ * having Vite merge those source maps (Vite's source map merging can loose
12
+ * precision), the pipeline is just a list of TypeScript transformers
13
+ * efficiently applied one after another.
14
+ *
15
+ * And at the end, TypeScript will generate the source map for us - it does it
16
+ * in a smart way - if we re-use the original typescript node during
17
+ * transformation, then that node has original position information attached to
18
+ * it - thus, even if transformer moves things around a lot, TypeScript can
19
+ * still create a great source map.
20
+ */
21
+ export declare const componentTransformPipeline: (context: CompilerContext) => Plugin;
22
+ export declare function getCompilerOptionsForPrinter(context: CompilerContext): ts.CompilerOptions;
@@ -0,0 +1,3 @@
1
+ import type { SourceDescription } from "rollup";
2
+ import type { CompilerContext } from "../context";
3
+ export declare function injectRuntimeOptions(runtimeTsCode: string, context: CompilerContext): SourceDescription;
@@ -0,0 +1,29 @@
1
+ import type { SourceMap } from "rollup";
2
+ import ts from "typescript";
3
+ export type UndocumentedTypeScript = {
4
+ readonly createSourceMapGenerator?: (host: ts.CompilerHost, basename: string, sourceRoot: string, dirname: string, compilerOptions: ts.CompilerOptions) => SourceMapGenerator;
5
+ readonly createTextWriter?: (newLine: string) => EmitTextWriter;
6
+ readonly getNewLineCharacter?: (options: ts.CompilerOptions) => string;
7
+ readonly createPrinter: (
8
+ /**
9
+ * Printer has undocumented options for printing source maps:
10
+ * https://github.com/microsoft/TypeScript/blob/7319968e90600102892a79142fb804bcbe384160/src/compiler/types.ts#L9689C18-L9707
11
+ */
12
+ options: ts.CompilerOptions & ts.PrinterOptions) => ReturnType<typeof ts.createPrinter> & UndocumentedPrinter;
13
+ };
14
+ type SourceMapGenerator = {
15
+ readonly toJSON: () => SourceMap;
16
+ };
17
+ type UndocumentedPrinter = {
18
+ readonly writeFile?: (writeFile: ts.SourceFile, writer: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) => void;
19
+ writeNode?(hint: ts.EmitHint, node: ts.TypeNode, sourceFile: undefined, output: EmitTextWriter): void;
20
+ writeNode?(hint: ts.EmitHint, node: Node, sourceFile: ts.SourceFile, output: EmitTextWriter): void;
21
+ };
22
+ type EmitTextWriter = {
23
+ readonly getText: () => string;
24
+ readonly clear: () => void;
25
+ };
26
+ export declare const undocumentedTs: Required<UndocumentedTypeScript>;
27
+ export declare function getPrinter(compilerOptions: ts.CompilerOptions): ReturnType<typeof createPrinter>;
28
+ declare function createPrinter(compilerOptions: ts.CompilerOptions): ReturnType<typeof ts.createPrinter> & UndocumentedPrinter;
29
+ export {};
@@ -0,0 +1,21 @@
1
+ import ts from "typescript";
2
+ export type LiftedDecorators = Map<string, ts.ObjectLiteralExpression>;
3
+ /**
4
+ * Using decorators in a file means shipping TypeScript's decorator polyfill.
5
+ * Plus, the decorator polyfill is meant to be generic and so adds more code
6
+ * than needed.
7
+ *
8
+ * Fortunately, Lit supports a static "properties" property (mainly for
9
+ * non-TypeScript users) that can be used to define properties in a more
10
+ * build size efficient way, without the need for `@property()` or `@state()`
11
+ * decorators.
12
+ *
13
+ * @remarks
14
+ * Without this, map-components CDN build is 398kb.
15
+ * With lifted decorator, it is 364kb (34kb smaller).
16
+ * AND, with compact property options it's 354kb (7kb smaller).
17
+ *
18
+ * For comparison, map-components Stencil CDN build is 370kb (and they
19
+ * lift all decorators too).
20
+ */
21
+ export declare function liftDecorators(members: readonly ts.ClassElement[], liftedDecorators: LiftedDecorators, minifyFlags: boolean): readonly ts.ClassElement[];
@@ -0,0 +1,12 @@
1
+ import ts from "typescript";
2
+ import type { FileTransformContext, FileTransformer } from "../publicTypes";
3
+ /**
4
+ * - Remove `@Method()` decorators from the code. `@Method()` decorators are
5
+ * only needed for the docs extraction.
6
+ * - Add `{ type: Number }` or `{ type: Boolean }` to `@property()` where
7
+ * necessary
8
+ * - Replace `@property()` decorators with `static properties = {}` to reduce
9
+ * bundle size.
10
+ */
11
+ export declare const transformMembers: FileTransformer;
12
+ export declare function visitComponentMembers<T extends ts.Node>(memberVisitor: (member: ts.ClassElement, className: string | undefined) => ts.ClassElement, node: T, context: FileTransformContext, beforeMembers?: () => void, afterMembers?: (node: ts.ClassElement[]) => readonly ts.ClassElement[]): T;
@@ -0,0 +1,9 @@
1
+ import ts from "typescript";
2
+ import type { FileTransformContext } from "../publicTypes";
3
+ import type { LiftedDecorators } from "./liftDecorators";
4
+ export declare function transformProperty(context: FileTransformContext, property: ts.AccessorDeclaration | ts.PropertyDeclaration, className: string | undefined, sourceFile: ts.SourceFile, makeOriginalSourceFileEdit: (from: number, to: number, replaceWith: string) => void, liftedDecorators?: LiftedDecorators): ts.ClassElement;
5
+ export type ParsedPropertyDecorator = {
6
+ decorator: ts.Decorator;
7
+ callExpression: ts.CallExpression;
8
+ options: ts.ObjectLiteralExpression | undefined;
9
+ };
@@ -0,0 +1,111 @@
1
+ import ts from "typescript";
2
+ import type { FileTransformContext } from "../publicTypes";
3
+ import type { ExtendedManifestField } from "../manifests/complexTypes/types";
4
+ import type { ParsedPropertyDecorator } from "./property";
5
+ /**
6
+ * In Stencil, the compiler uses type checking to determine if the inferred
7
+ * property type is number or boolean, and if so, would make sure to cast the
8
+ * string attribute value to number or boolean. Even in development mode type
9
+ * checking is used for that - which is not ideal as it slows down the dev server.
10
+ *
11
+ * That is why in Lumina we are no doing type checking at all (not even
12
+ * creating a TypeScript program) in the dev server. That of course puts some
13
+ * constraints on us.
14
+ *
15
+ * In Lit, since there is no compiler, Lit relies on the `{type: Number}` or
16
+ * `{type: Boolean}` property being passed to the `@property` decorator to
17
+ * determine if the property should be cast.
18
+ *
19
+ * Looking at all usages of number and boolean properties in Calcite and
20
+ * map-components, I see a few patterns:
21
+ *
22
+ * - In Calcite:
23
+ *
24
+ * - all boolean properties either explicitly have "false" as a default value,
25
+ * or explicitly have `boolean` type in TypeScript - in this case the AST
26
+ * contains enough information for lumina-compiler to insert `{type: Boolean}`
27
+ * in the code at build-time.
28
+ * - most number properties either have `number` type in TypeScript or numeric
29
+ * default value. This however is not always the case as there are a few
30
+ * exceptions:
31
+ *
32
+ * - calcite-action-group.columns: uses `Columns` number enum as it's type
33
+ * - calcite-block.headingLevel: uses `HeadingLevel` number enum as it's
34
+ * type
35
+ * - calcite-pagination.maxItems, calcite-popover.offsetDistance and
36
+ * calcite-tooltip.offsetDistance: use a const variable of numeric type as
37
+ * their default value
38
+ *
39
+ * These cases can't be inferred from the AST alone
40
+ *
41
+ * - In Map Components:
42
+ *
43
+ * - here the story is complicated by the fact that we use the following
44
+ * Controllers syntax in a lot of places:
45
+ *
46
+ * ```tsx
47
+ * \@Prop() hideCreateFeaturesSection = this.widget.visibleElements.createFeaturesSection;
48
+ * ```
49
+ *
50
+ * In the above, the type is boolean, but we can't know that from the AST.
51
+ *
52
+ * Since we can use the type checker during build, I am considering solving the
53
+ * issue like this:
54
+ *
55
+ * - both in serve and build mode, look at the AST to see if we can trivially
56
+ * infer whether the property type is number or boolean
57
+ * - in build mode:
58
+ * - if has a custom converter specified, don't do anything
59
+ * - else, if trivially inferred that property is boolean and number:
60
+ * - if has explicit type annotation:
61
+ * - if type annotation is of type number or boolean:
62
+ * - edit the source code to automatically remove the useless type
63
+ * annotation, and add a small log message to notify dev about what
64
+ * happened
65
+ * - warn about mismatching type annotation
66
+ * - add {type:Number} or {type:Boolean} to the .js output code, not source
67
+ * code
68
+ * - else, use the type checker, with an algorithm similar to Stencil to
69
+ * detect if property type is number or boolean
70
+ * - if detected that property type is not number or boolean
71
+ * - don't do anything
72
+ * - else, if property type is number or boolean
73
+ * - edit the source file to automatically add the type annotation
74
+ * and add a small log message to notify dev about what happened
75
+ * - add `{type:Number}` or `{type:Boolean}` to the .js output code
76
+ * - else, don't do anything
77
+ * - in dev mode:
78
+ * - if type or converter is explicitly present
79
+ * - don't do anything
80
+ * - if inferred that property type is number or boolean
81
+ * - add `{type:Number}` or `{type:Boolean}` to the .js output code, not
82
+ * source code
83
+ *
84
+ * The benefits of the above:
85
+ *
86
+ * - dev build is fast as no type checking is happening
87
+ * - source code is clean as type annotations are not present, unless ambiguous
88
+ * - in ambiguous cases, the source code has an explicit annotation, which
89
+ * ensures the serve mode has the same behavior as build for all properties
90
+ * - ambiguous newly added properties in serve mode won't yet have an explicit
91
+ * type annotation, but that is okay as ambiguous number/boolean properties
92
+ * are not that common, and in development mode properties are often set as
93
+ * JavaScript properties rather than HTML attributes, thus bypassing the
94
+ * need to cast the property
95
+ * - when converting a codebase from Stencil to Lit (either manually or using
96
+ * the codemod), the type annotations in ambiguous places would be inserted
97
+ * automatically if not yet present
98
+ * - when converting wrapped map-components widget to native, most usages of a
99
+ * code style like this will be removed, to be replaced with unambiguous
100
+ * `false` default value:
101
+ *
102
+ * ```tsx
103
+ * \@Prop() hideCreateFeaturesSection = this.widget.visibleElements.createFeaturesSection;
104
+ * ```
105
+ *
106
+ * In such cases, the above algorithm will automatically remove the now
107
+ * useless type annotation.
108
+ *
109
+ * See also https://github.com/runem/lit-analyzer/blob/master/packages/lit-analyzer/src/lib/rules/no-incompatible-property-type.ts
110
+ */
111
+ export declare function transformPropertyOptions(property: ts.AccessorDeclaration | ts.PropertyDeclaration, decorator: ParsedPropertyDecorator, context: FileTransformContext, sourceFile: ts.SourceFile, makeOriginalSourceFileEdit: (from: number, to: number, replaceWith: string) => void, propertyManifest: ExtendedManifestField | undefined): ts.ObjectLiteralExpression | undefined;
@@ -0,0 +1,20 @@
1
+ import type { FileTransformContext } from "../publicTypes";
2
+ /**
3
+ * Update the original source file to add `{ type : Number }` or
4
+ * `{ type : Boolean }`.
5
+ *
6
+ * We can't simply reuse the result from the transformer because other
7
+ * transformers may have modified this file beforehand. Instead, we create a new
8
+ * ts.SourceFile from the file system source file, and re-run just this single
9
+ * transformer on it.
10
+ *
11
+ * @remarks
12
+ * Using synchronous fs in this file because:
13
+ * - most of the time this function will not be called, so the performance
14
+ * impact is negligible
15
+ * - the transformer pipeline is sync, so having async functions in it is only
16
+ * possible if we don't await the result
17
+ * - async fs may interfere with another plugin reading/writing the source code
18
+ * file at the same time
19
+ */
20
+ export declare function updateSourceFilePropertyTypes(context: FileTransformContext, filePath: string): void;
@@ -0,0 +1,14 @@
1
+ import ts from "typescript";
2
+ import type { FileTransformer } from "../publicTypes";
3
+ import type { CompilerContext } from "../context";
4
+ /**
5
+ * Run a chain of transformers on a TypeScript .tsx or .d.ts file and return
6
+ * the resulting source file
7
+ */
8
+ export declare function runTransformers(context: CompilerContext, transformationContext: ts.TransformationContext, sourceFile: ts.SourceFile, transformers: readonly FileTransformer[]): ts.SourceFile;
9
+ /**
10
+ * For performance reasons, to avoid the need to re-create the source map
11
+ * after this change, replace the given code string with a comment string of
12
+ * equal length :)
13
+ */
14
+ export declare const commentOutCode: (match: string) => string;
@@ -0,0 +1,3 @@
1
+ import type { CompilerContext } from "../context";
2
+ import type { PluginOptions } from "vite-plugin-dts";
3
+ export declare function runAstDtsTransformers(context: CompilerContext): NonNullable<PluginOptions["resolvers"]>[number];
@@ -0,0 +1,9 @@
1
+ import type { FileTransformer } from "../publicTypes";
2
+ /**
3
+ * Modify the .d.ts to make it appear that components extend the
4
+ * PublicLitElement rather than LitElement
5
+ *
6
+ * This will hide internal methods like addController() and connectedCallback()
7
+ * from the public typings
8
+ */
9
+ export declare const hideInternalLitElement: FileTransformer;
@@ -0,0 +1,18 @@
1
+ import type { Plugin } from "vite";
2
+ import type { CompilerContext } from "../context";
3
+ /**
4
+ * Generate TypeScript definition files for the files in the project.
5
+ * There is a corresponding .d.ts file emitted for each source .ts and .tsx file.
6
+ *
7
+ * Separately, in ./frameworkTypes typings we produce typings for framework and
8
+ * vanilla JavaScript users
9
+ *
10
+ * @remarks
11
+ * Because vite-plugin-dts creates ts.SourceFile instances during
12
+ * buildStart(), any changes to files in any of our transform() hooks won't be
13
+ * reflected in the final .d.ts files (unless we create new ts.SourceFile
14
+ * objects but that may be computationally expensive).
15
+ * Thus for now we are using beforeWriteFile() hook that vite-plugin-dts
16
+ * provides to modify the files before they are output.
17
+ */
18
+ export declare function generateTypes(context: CompilerContext): Plugin;
@@ -0,0 +1,33 @@
1
+ import type { PropertyDeclaration } from "typescript";
2
+ import ts from "typescript";
3
+ import type { CompilerContext } from "../context";
4
+ export type LiftedSetter = {
5
+ name: ts.PropertyName;
6
+ type: ts.TypeNode;
7
+ isRequired: boolean;
8
+ };
9
+ export declare const setterTypesPropertyName = "_setterTypes";
10
+ /**
11
+ * In TypeScript, if getter and setter have different types, there is no way
12
+ * to get the setter type - you can only get the getter type.
13
+ *
14
+ * For JSX typings, we need the setter types. As a workaround, we create a
15
+ * types-only property on the component class that contains the types for the
16
+ * setter properties. Then, the JSX typings retrieve the type from this
17
+ * property.
18
+ *
19
+ * @see https://github.com/microsoft/TypeScript/issues/43729
20
+ */
21
+ export declare function addLiftedSettersProperty(setters: LiftedSetter[], sourceFile: ts.SourceFile, context: CompilerContext): PropertyDeclaration;
22
+ /**
23
+ * Despite the fact that TypeScript AST nodes are immutable, we can not have the
24
+ * same node in two places in the AST. Cloning nodes is also quite tricky.
25
+ *
26
+ * There is a gigantic library for this (that is also unmaintained and does not
27
+ * support TypeScript 5): https://github.com/wessberg/ts-clone-node
28
+ *
29
+ * The other option is to print the node and parse it again, which is what we
30
+ * are doing here. TypeScript does not expose the APIs to parse individual
31
+ * nodes, so we must parse the entire source file.
32
+ */
33
+ export declare function clonePropertyParts(name: ts.PropertyName, type: ts.TypeNode, printer: ts.Printer, sourceFile: ts.SourceFile): readonly [name: ts.PropertyName, type: ts.TypeNode];
@@ -0,0 +1,4 @@
1
+ import type { CompilerContext } from "../context";
2
+ import type { PluginOptions } from "vite-plugin-dts";
3
+ export declare const runTextDtsTransformers: (context: CompilerContext) => PluginOptions["beforeWriteFile"];
4
+ export declare const isTestFile: (id: string) => boolean;
@@ -0,0 +1,10 @@
1
+ import type { FileTransformer } from "../publicTypes";
2
+ /**
3
+ * Cleanup public component typings:
4
+ * - Hide all non-property, non-events, non-methods from public typings
5
+ * - Add `readonly` modifier for readonly properties
6
+ * - Remove internal emit() method from event typings
7
+ * - Make all event properties readonly
8
+ * - Remove all static members
9
+ */
10
+ export declare const transformComponentMembers: FileTransformer;
@@ -0,0 +1,13 @@
1
+ import type { LuminaPlugins, LuminaOptions } from "./publicTypes";
2
+ /**
3
+ * Auto-configure Vite for a Lit web component project.
4
+ *
5
+ * Main features:
6
+ * - Main entrypoint lazy-loads all components on demand
7
+ * - Allow you to author your components in JSX for great developer experience,
8
+ * and convert JSX to lit-html templates at build time for maximum efficiency
9
+ * - Separate bundle for each component to bundle only the necessary code
10
+ * - Generates types, docs, and manifests for web components
11
+ * - Generates a CDN build
12
+ */
13
+ export declare function useLumina(options?: LuminaOptions): LuminaPlugins;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Throw if trying to access a property that was not provided, or set any property
3
+ */
4
+ export declare const throwOnUnknown: (base: Record<string, unknown>) => unknown;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * A subset of the package.json typing that is interesting to Lumina.
3
+ *
4
+ * The full package.json type is insanely large (20k lines):
5
+ * https://github.com/ffflorian/schemastore-updater/blob/main/schemas/package/index.d.ts#L20067
6
+ */
7
+ export type MiniPackageJson = {
8
+ "name": string;
9
+ "version": string;
10
+ "dependencies"?: Record<string, string>;
11
+ "devDependencies"?: Record<string, string>;
12
+ "peerDependencies"?: Record<string, string>;
13
+ "css.customData"?: string[];
14
+ "customElements"?: string;
15
+ "html.customData"?: string[];
16
+ "web-types"?: string;
17
+ };
18
+ export declare function retrievePackageJson(location?: string): MiniPackageJson;
19
+ export declare function asyncRetrievePackageJson(location?: string): Promise<MiniPackageJson>;
20
+ /**
21
+ * Returns an absolute path to the root of a package in node_modules, without
22
+ * trailing slash.
23
+ */
24
+ export declare function fetchPackageLocation(packageName: string, cwd?: string): Promise<string>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * See ../path.md for details about our path handling.
3
+ */
4
+ /// <reference types="node" />
5
+ import posix from "path/posix";
6
+ /**
7
+ * This is called "isPosix" rather than "isNotWindows" because even if we are
8
+ * on Windows, we could be running in a POSIX environment (e.g. WSL2)
9
+ */
10
+ export declare const isPosix: boolean;
11
+ export declare const toPosixPathSeparators: (relativePath: string) => string;
12
+ /**
13
+ * On Windows, replace all `/` in the path back with `\\`. Do this only if you
14
+ * wish to output the path in the console or error message.
15
+ * On POSIX system (macOS, Linux, ...), this does not change the path (because
16
+ * inside the compiler we use `/` everywhere).
17
+ */
18
+ export declare const toSystemPathSeparators: (relativePath: string) => string;
19
+ export declare const getCwd: () => string;
20
+ export declare const path: typeof posix & {
21
+ sep: "/";
22
+ };
23
+ export declare const exportsForTests: {
24
+ toWin32PathSeparators: (relativePath: string) => string;
25
+ };
@@ -0,0 +1 @@
1
+ export {};