fix(@lexical/utils): fix #5918 by re-exporting shared/* constants with explicit types (#5920)

This commit is contained in:
Bob Ippolito
2024-04-19 15:10:53 -07:00
committed by GitHub
parent 3a440491c2
commit 8fda1b4da9
3 changed files with 116 additions and 15 deletions

View File

@ -19,10 +19,11 @@
"dev": "npm run dev --prefix packages/lexical-playground",
"start-test-server": "npm run preview --prefix packages/lexical-playground -- --port 4000",
"build": "node scripts/build.js",
"build-prod": "npm run clean && npm run build -- --prod",
"build-prod": "npm run clean && npm run build -- --prod && node ./scripts/validate-tsc-types.js",
"build-playground-prod": "npm run build-prod && npm run build-prod --prefix packages/lexical-playground",
"build-release": "npm run build-prod -- --release",
"build-release": "npm run build-prod -- --release && node ./scripts/validate-tsc-types.js",
"build-www": "npm run clean && npm run build -- --www && npm run build -- --www --prod && npm run prepare-www",
"build-types": "tsc -p ./tsconfig.build.json && node ./scripts/validate-tsc-types.js",
"clean": "node scripts/clean.js",
"extract-codes": "node scripts/build.js --codes",
"flow": "node ./scripts/check-flow-types.js",

View File

@ -24,7 +24,20 @@ import {
LexicalEditor,
LexicalNode,
} from 'lexical';
import {IS_FIREFOX} from 'shared/environment';
// This underscore postfixing is used as a hotfix so we do not
// export shared types from this module #5918
import {CAN_USE_DOM as CAN_USE_DOM_} from 'shared/canUseDOM';
import {
CAN_USE_BEFORE_INPUT as CAN_USE_BEFORE_INPUT_,
IS_ANDROID as IS_ANDROID_,
IS_ANDROID_CHROME as IS_ANDROID_CHROME_,
IS_APPLE as IS_APPLE_,
IS_APPLE_WEBKIT as IS_APPLE_WEBKIT_,
IS_CHROME as IS_CHROME_,
IS_FIREFOX as IS_FIREFOX_,
IS_IOS as IS_IOS_,
IS_SAFARI as IS_SAFARI_,
} from 'shared/environment';
import invariant from 'shared/invariant';
import normalizeClassNames from 'shared/normalizeClassNames';
@ -32,18 +45,17 @@ export {default as markSelection} from './markSelection';
export {default as mergeRegister} from './mergeRegister';
export {default as positionNodeOnRange} from './positionNodeOnRange';
export {$splitNode, isHTMLAnchorElement, isHTMLElement} from 'lexical';
export {CAN_USE_DOM} from 'shared/canUseDOM';
export {
CAN_USE_BEFORE_INPUT,
IS_ANDROID,
IS_ANDROID_CHROME,
IS_APPLE,
IS_APPLE_WEBKIT,
IS_CHROME,
IS_FIREFOX,
IS_IOS,
IS_SAFARI,
} from 'shared/environment';
// Hotfix to export these with inlined types #5918
export const CAN_USE_BEFORE_INPUT: boolean = CAN_USE_BEFORE_INPUT_;
export const CAN_USE_DOM: boolean = CAN_USE_DOM_;
export const IS_ANDROID: boolean = IS_ANDROID_;
export const IS_ANDROID_CHROME: boolean = IS_ANDROID_CHROME_;
export const IS_APPLE: boolean = IS_APPLE_;
export const IS_APPLE_WEBKIT: boolean = IS_APPLE_WEBKIT_;
export const IS_CHROME: boolean = IS_CHROME_;
export const IS_FIREFOX: boolean = IS_FIREFOX_;
export const IS_IOS: boolean = IS_IOS_;
export const IS_SAFARI: boolean = IS_SAFARI_;
export type DFSNode = Readonly<{
depth: number;

View File

@ -0,0 +1,88 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
// @ts-check
'use strict';
const fs = require('fs-extra');
const glob = require('glob');
const ts = require('typescript');
const pretty = process.env.CI !== 'true';
/** @type {ts.FormatDiagnosticsHost} */
const diagnosticsHost = {
getCanonicalFileName: (fn) => fn,
getCurrentDirectory: () => './',
getNewLine: () => '\n',
};
/**
* Validate that the published .d.ts types do not have dependencies
* on any private module (currently shared/*).
*
* `process.exit(1)` on failure.
*/
function validateTscTypes() {
const dtsFilesPattern = './.ts-temp/{lexical,lexical-*}/**/*.d.ts';
const dtsFiles = glob.sync(dtsFilesPattern);
if (dtsFiles.length === 0) {
console.error(
`Missing ${dtsFilesPattern}, \`npm run build-prod\` or \`npm run build-release\` first`,
);
process.exit(1);
}
/** @type {ts.Diagnostic[]} */
const diagnostics = [];
for (const fn of dtsFiles) {
// console.log(fn);
const ast = ts.createSourceFile(
fn,
fs.readFileSync(fn, 'utf-8'),
ts.ScriptTarget.Latest,
);
const checkSpecifier = (/** @type {ts.Node | undefined} */ node) => {
if (!node || node.kind !== ts.SyntaxKind.StringLiteral) {
return;
}
const specifier = /** @type {import('typescript').StringLiteral} */ (
node
);
if (/^shared(\/|$)/.test(specifier.text)) {
const start = specifier.getStart(ast);
diagnostics.push({
category: ts.DiagnosticCategory.Error,
code: Infinity,
file: ast,
length: specifier.getEnd() - start,
messageText: `Published .d.ts files must not import private module '${specifier.text}'.`,
start,
});
}
};
ast.forEachChild((node) => {
if (node.kind === ts.SyntaxKind.ExportDeclaration) {
const exportNode =
/** @type {import('typescript').ExportDeclaration} */ (node);
checkSpecifier(exportNode.moduleSpecifier);
} else if (node.kind === ts.SyntaxKind.ImportDeclaration) {
const importNode =
/** @type {import('typescript').ImportDeclaration} */ (node);
checkSpecifier(importNode.moduleSpecifier);
}
});
}
if (diagnostics.length > 0) {
const msg = (
pretty ? ts.formatDiagnosticsWithColorAndContext : ts.formatDiagnostics
)(diagnostics, diagnosticsHost);
console.error(msg.replace(/ TSInfinity:/g, ':'));
process.exit(1);
}
}
validateTscTypes();