@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.
- package/LICENSE.md +13 -0
- package/README.md +21 -0
- package/dist/chunk-BQ4U6HQL.js +1 -0
- package/dist/chunk-JFKSI6I7.js +1 -0
- package/dist/context/index.d.ts +241 -0
- package/dist/context/types.d.ts +34 -0
- package/dist/context/utils.d.ts +23 -0
- package/dist/context/utils.spec.d.ts +1 -0
- package/dist/defaultAssetsUrl.d.ts +21 -0
- package/dist/defaultAssetsUrl.spec.d.ts +1 -0
- package/dist/dependencies/arcgisCore.d.ts +30 -0
- package/dist/dependencies/discover.d.ts +62 -0
- package/dist/dependencies/index.d.ts +11 -0
- package/dist/dependencies/lit.d.ts +2 -0
- package/dist/dependencies/loaders.d.ts +8 -0
- package/dist/dependencies/stencil.d.ts +6 -0
- package/dist/dependencies/testSetupFiles.d.ts +21 -0
- package/dist/dependencies/updateLumina.d.ts +8 -0
- package/dist/dependencies/updateLumina.spec.d.ts +1 -0
- package/dist/dependencies/utils.d.ts +23 -0
- package/dist/entrypoints/addNonLazyImports.d.ts +13 -0
- package/dist/entrypoints/config.d.ts +23 -0
- package/dist/entrypoints/dtsUtils.d.ts +22 -0
- package/dist/entrypoints/dtsUtils.spec.d.ts +1 -0
- package/dist/entrypoints/findUtils.d.ts +21 -0
- package/dist/entrypoints/findUtils.spec.d.ts +1 -0
- package/dist/entrypoints/handleComponentImports.d.ts +13 -0
- package/dist/entrypoints/pathMapping.d.ts +25 -0
- package/dist/entrypoints/resolveTagName.d.ts +14 -0
- package/dist/entrypoints/resolveTagName.spec.d.ts +1 -0
- package/dist/frameworkTypes/index.d.ts +15 -0
- package/dist/frameworkTypes/lumina.d.ts +5 -0
- package/dist/frameworkTypes/preact.d.ts +6 -0
- package/dist/frameworkTypes/react.d.ts +6 -0
- package/dist/frameworkTypes/stencil.d.ts +5 -0
- package/dist/frameworkTypes/utils.d.ts +8 -0
- package/dist/frameworkTypes/vanilla.d.ts +3 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +248 -0
- package/dist/jsxToLitHtml/autoAddNothing.d.ts +8 -0
- package/dist/jsxToLitHtml/comments.d.ts +19 -0
- package/dist/jsxToLitHtml/config.d.ts +148 -0
- package/dist/jsxToLitHtml/convertProps.d.ts +10 -0
- package/dist/jsxToLitHtml/escapeForTemplateLiteral.d.ts +45 -0
- package/dist/jsxToLitHtml/imports.d.ts +32 -0
- package/dist/jsxToLitHtml/index.d.ts +17 -0
- package/dist/jsxToLitHtml/inferPropType.d.ts +40 -0
- package/dist/jsxToLitHtml/insertRepeatCall.d.ts +49 -0
- package/dist/jsxToLitHtml/jsxVisitor.d.ts +11 -0
- package/dist/jsxToLitHtml/templateParts.d.ts +17 -0
- package/dist/jsxToLitHtml/throwOnImportingExternalized.d.ts +10 -0
- package/dist/jsxToLitHtml/types.d.ts +80 -0
- package/dist/jsxToLitHtml/utils.d.ts +14 -0
- package/dist/jsxToLitHtml/utils.spec.d.ts +1 -0
- package/dist/manifests/complexTypes/addComponentMetadata.d.ts +5 -0
- package/dist/manifests/complexTypes/addMethodMetadata.d.ts +6 -0
- package/dist/manifests/complexTypes/addPropMetadata.d.ts +8 -0
- package/dist/manifests/complexTypes/docsUtils.d.ts +18 -0
- package/dist/manifests/complexTypes/event.d.ts +9 -0
- package/dist/manifests/complexTypes/getComplexPropertyType.d.ts +11 -0
- package/dist/manifests/complexTypes/transformUtils.d.ts +130 -0
- package/dist/manifests/complexTypes/transformUtils.spec.d.ts +1 -0
- package/dist/manifests/complexTypes/typeToEnum.d.ts +14 -0
- package/dist/manifests/complexTypes/typeToEnum.spec.d.ts +1 -0
- package/dist/manifests/complexTypes/types.d.ts +135 -0
- package/dist/manifests/config.d.ts +2 -0
- package/dist/manifests/createManifest.d.ts +39 -0
- package/dist/manifests/customElementDecoratorPlugins.d.ts +58 -0
- package/dist/manifests/customElementDecoratorPlugins.spec.d.ts +1 -0
- package/dist/manifests/hideUntilHydrated.d.ts +15 -0
- package/dist/manifests/index.d.ts +12 -0
- package/dist/manifests/kebabCaseAttributes.d.ts +18 -0
- package/dist/manifests/lazy.d.ts +22 -0
- package/dist/manifests/lazy.spec.d.ts +1 -0
- package/dist/manifests/stencilManifest.d.ts +17 -0
- package/dist/manifests/storybookManifest.d.ts +6 -0
- package/dist/manifests/types.d.ts +1 -0
- package/dist/manifests/utils.d.ts +17 -0
- package/dist/plugins/buildCdn.d.ts +14 -0
- package/dist/plugins/buildStencilHydrate.d.ts +16 -0
- package/dist/plugins/buildWrappers.d.ts +3 -0
- package/dist/plugins/configureVite.d.ts +19 -0
- package/dist/plugins/externalizeDependencies.d.ts +34 -0
- package/dist/plugins/externalizeDependencies.spec.d.ts +1 -0
- package/dist/plugins/generateDocs.d.ts +10 -0
- package/dist/plugins/handleDynamicAssets.d.ts +3 -0
- package/dist/plugins/handleStaticAssets.d.ts +9 -0
- package/dist/plugins/loadLitCss.d.ts +89 -0
- package/dist/plugins/printTotalBuildSize.d.ts +7 -0
- package/dist/plugins/provideAssets.d.ts +53 -0
- package/dist/plugins/provideAssets.spec.d.ts +1 -0
- package/dist/plugins/setAssetsPath.d.ts +10 -0
- package/dist/plugins/updatePackageJson.d.ts +9 -0
- package/dist/plugins/updatePackageJson.spec.d.ts +1 -0
- package/dist/publicTypes.d.ts +626 -0
- package/dist/puppeteer-testing/globalSetup.d.ts +72 -0
- package/dist/puppeteer-testing/globalSetup.js +11 -0
- package/dist/puppeteer-testing/index.d.ts +9 -0
- package/dist/puppeteer-testing/index.js +6 -0
- package/dist/puppeteer-testing/injected.d.ts +8 -0
- package/dist/puppeteer-testing/puppeteer/browser.d.ts +6 -0
- package/dist/puppeteer-testing/puppeteer/element.d.ts +219 -0
- package/dist/puppeteer-testing/puppeteer/events.d.ts +21 -0
- package/dist/puppeteer-testing/puppeteer/page.d.ts +5 -0
- package/dist/puppeteer-testing/puppeteer/types.d.ts +124 -0
- package/dist/puppeteer-testing/vitest/matchers/attributes.d.ts +4 -0
- package/dist/puppeteer-testing/vitest/matchers/classList.d.ts +4 -0
- package/dist/puppeteer-testing/vitest/matchers/events.d.ts +7 -0
- package/dist/puppeteer-testing/vitest/matchers/index.d.ts +38 -0
- package/dist/puppeteer-testing/vitest/matchers/text.d.ts +2 -0
- package/dist/puppeteer-testing/vitest/matchers/utils.d.ts +1 -0
- package/dist/puppeteer-testing/vitest/runner.d.ts +15 -0
- package/dist/puppeteer-testing/vitest/setupFile.d.ts +1 -0
- package/dist/testing/index.d.ts +11 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/mount.d.ts +106 -0
- package/dist/testing/setupFile.d.ts +1 -0
- package/dist/testing/snapshotSerializer.d.ts +12 -0
- package/dist/testing/wrapController.d.ts +33 -0
- package/dist/tests/utils.d.ts +4 -0
- package/dist/transformers/guardAgainstInternalJsDoc.d.ts +11 -0
- package/dist/transformers/index.d.ts +22 -0
- package/dist/transformers/injectRuntimeOptions.d.ts +3 -0
- package/dist/transformers/internalTypeScriptApis.d.ts +29 -0
- package/dist/transformers/liftDecorators.d.ts +21 -0
- package/dist/transformers/members.d.ts +12 -0
- package/dist/transformers/property.d.ts +9 -0
- package/dist/transformers/propertyOptions.d.ts +111 -0
- package/dist/transformers/updateOriginalFile.d.ts +20 -0
- package/dist/transformers/utils.d.ts +14 -0
- package/dist/types/astTransformers.d.ts +3 -0
- package/dist/types/hideInternalLitElement.d.ts +9 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/liftSetterTypes.d.ts +33 -0
- package/dist/types/textTransformers.d.ts +4 -0
- package/dist/types/transformComponentMembers.d.ts +10 -0
- package/dist/useLumina.d.ts +13 -0
- package/dist/utils/error.d.ts +4 -0
- package/dist/utils/packageJson.d.ts +24 -0
- package/dist/utils/path.d.ts +25 -0
- package/dist/utils/path.spec.d.ts +1 -0
- 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,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,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,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,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 {};
|