Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x, 20.x, 22.x]
# monaco-editor 0.56 (and the modernized toolchain: jest 30, eslint 8 with
# a TypeScript 5 parser) no longer support the older runtimes this matrix
# used to cover, and `engines` now requires >=24.
node-version: [24.x]

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: yarn install
cache: yarn
- run: yarn install --frozen-lockfile
- run: yarn lint
- run: yarn test
- run: yarn build
16 changes: 8 additions & 8 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '24.x'
registry-url: 'https://registry.npmjs.org'

- run: yarn
Expand All @@ -26,18 +26,18 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '24.x'
registry-url: ${{ secrets.PRIVATE_REGISTRY }}

- run: yarn publish --non-interactive
env:
NODE_AUTH_TOKEN: ${{ secrets.PRIVATE_REGISTRY_TOKEN }}

- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '24.x'
registry-url: 'https://registry.npmjs.org'

- name: install example dependencies
Expand All @@ -51,7 +51,7 @@ jobs:
PUBLIC_URL: '/monaco-sql-languages'

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./example/build
3 changes: 0 additions & 3 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
10 changes: 9 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
module.exports = {
plugins: [
// monaco-editor 0.56 locates its web workers with
// `new URL('...', import.meta.url)`. Jest transforms these files to CJS,
// where `import.meta` is a syntax error, so the whole editor.api import chain
// fails to load. This rewrites it to a `require`-based equivalent, which is
// enough for tests: they only tokenize strings and never start a worker.
'babel-plugin-transform-import-meta',
],
presets: [
['@babel/preset-env', {targets: {node: 'current'}}],
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
};
4 changes: 2 additions & 2 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"private": true,
"dependencies": {
"@popsql/monaco-sql-languages": "file:../",
"monaco-editor": "^0.38.0",
"monaco-editor": "^0.56.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-monaco-editor": "^0.52.0",
"react-monaco-editor": "^0.59.0",
"react-scripts": "5.0.1"
},
"scripts": {
Expand Down
7 changes: 7 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ module.exports = {
'^(\\.{1,2}/.*)\\.js$': '$1',
'^monaco-editor$':
'<rootDir>/node_modules/monaco-editor/esm/vs/editor/editor.api.js',
// Mirror monaco-editor 0.56's exports map, which resolves
// `monaco-editor/<path>` to `esm/vs/<path>`. Jest does not consult `exports`,
// so deep imports have to be rewritten here to match what bundlers and Node
// do for consumers. Keep this above the generic rule below, which stays for
// paths that are already `esm/...` (`transformIgnorePatterns` relies on it).
'^monaco-editor/((?!esm/|min/|dev/).*)$':
'<rootDir>/node_modules/monaco-editor/esm/vs/$1',
'monaco-editor/(.*)': '<rootDir>/node_modules/monaco-editor/$1',
},
setupFilesAfterEnv: ['<rootDir>/test/mocks.ts'],
Expand Down
63 changes: 35 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,59 @@
"module": "./lib/esm/index.js",
"types": "./lib/types/index.d.ts",
"exports": {
"require": "./lib/cjs/index.js",
"import": "./lib/esm/index.js",
"types": "./lib/types/index.d.ts"
".": {
"types": "./lib/types/index.d.ts",
"import": "./lib/esm/index.js",
"require": "./lib/cjs/index.js"
},
"./package.json": "./package.json"
},
"files": [
"lib"
],
"scripts": {
"build": "rimraf lib && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
"prepare": "husky install",
"prepare": "husky",
"lint": "eslint . --ext .ts",
"test": "jest"
},
"devDependencies": {
"@babel/core": "^7.21.8",
"@babel/preset-env": "^7.21.5",
"@babel/preset-typescript": "^7.21.5",
"@jest/globals": "^29.5.0",
"@types/jest": "^29.5.1",
"@babel/core": "^7.28.4",
"@babel/preset-env": "^7.28.3",
"@babel/preset-typescript": "^7.27.1",
"@jest/globals": "^30.4.1",
"@types/jest": "^30.0.0",
"@types/lodash.clonedeep": "^4.5.9",
"@typescript-eslint/eslint-plugin": "^5.31.0",
"@typescript-eslint/parser": "^5.31.0",
"babel-jest": "^29.5.0",
"eslint": "^8.40.0",
"@typescript-eslint/eslint-plugin": "^8.66.0",
"@typescript-eslint/parser": "^8.66.0",
"babel-jest": "^30.4.1",
"babel-plugin-transform-import-meta": "^2.3.3",
"eslint": "^8.57.1",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-jest": "^26.6.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-sort-destructure-keys": "^1.4.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^28.14.0",
"eslint-plugin-prettier": "^5.5.6",
"eslint-plugin-sort-destructure-keys": "^2.0.0",
"eslint-plugin-sort-keys-fix": "^1.1.2",
"eslint-plugin-typescript-sort-keys": "^2.1.0",
"husky": "^8.0.3",
"jest": "^29.5.0",
"eslint-plugin-typescript-sort-keys": "^3.3.0",
"husky": "^9.1.7",
"jest": "^30.4.2",
"jest-css-modules-transform": "^4.4.2",
"jest-environment-jsdom": "^29.5.0",
"lint-staged": "^13.2.2",
"monaco-editor": "^0.38.0",
"prettier": "^2.8.8",
"rimraf": "^5.0.0",
"typescript": "^4.9"
"jest-environment-jsdom": "^30.4.1",
"lint-staged": "^17.3.0",
"monaco-editor": "^0.56.0",
"prettier": "^3.9.6",
"rimraf": "^6.1.3",
"typescript": "^5.9.3"
},
"peerDependencies": {
"monaco-editor": "*"
"monaco-editor": ">=0.56.0"
},
"dependencies": {
"lodash.clonedeep": "^4.5.0"
},
"engines": {
"node": ">=24"
}
}
7 changes: 6 additions & 1 deletion src/monaco-pgsql.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
declare module 'monaco-editor/esm/vs/basic-languages/pgsql/pgsql' {
// monaco-editor ships no type declarations for its monarch language definitions,
// so declare the shape we consume. The specifier must match the import in
// src/pgsql/pgsql.ts exactly: TypeScript is configured with
// `moduleResolution: node`, which ignores `exports` maps, so this declaration is
// also what lets that import typecheck at all.
declare module 'monaco-editor/languages/definitions/pgsql/pgsql.js' {
export const conf: import('monaco-editor').languages.LanguageConfiguration;
export const language: import('monaco-editor').languages.IMonarchLanguage;
}
13 changes: 12 additions & 1 deletion src/pgsql/pgsql.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
// Documented for pg 17

import cloneDeep from 'lodash.clonedeep';
// monaco-editor 0.56 reorganized its ESM tree, moving the monarch language
// definitions from `basic-languages/<lang>/<lang>` to
// `languages/definitions/<lang>/<lang>`, and added an `exports` map. Both parts
// matter here:
//
// - The exports map is the only supported way in; `monaco-editor/esm/vs/...`
// specifiers no longer resolve at all, because the map's wildcards rewrite
// `./<path>` to `./esm/vs/<path>.js`.
// - Because the mapped target is matched literally, the `.js` suffix is
// required rather than stylistic. Without it this resolves to a file that
// does not exist.
import {
conf as oldConf,
language as oldLanguage,
} from 'monaco-editor/esm/vs/basic-languages/pgsql/pgsql';
} from 'monaco-editor/languages/definitions/pgsql/pgsql.js';

const conf = cloneDeep(oldConf);
const language = cloneDeep(oldLanguage);
Expand Down
12 changes: 12 additions & 0 deletions test/mocks.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
// monaco-editor 0.56 builds its icon stylesheet through `CSS.escape`, which jsdom
// does not implement. Without it, `setMonarchTokensProvider` throws before any
// tokenization happens. The real escaping rules don't matter here (nothing
// asserts on CSS), so a minimal identifier escape is enough.
Object.defineProperty(window, 'CSS', {
value: {
escape: (value: string) =>
String(value).replace(/[^\w-]/g, (c) => `\\${c}`),
},
writable: true,
});

Object.defineProperty(window, 'matchMedia', {
value: jest.fn().mockImplementation((query) => ({
// Deprecated
Expand Down
24 changes: 13 additions & 11 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
{
"compilerOptions": {
"compilerOptions": {
"esModuleInterop": true,
"isolatedModules": true,
"module": "ESNext",
"moduleResolution": "node",
"module": "ESNext",
// `bundler` resolution honors package `exports` maps, which monaco-editor
// 0.56 relies on: its declarations live at ./esm/vs/index.d.ts and are only
// reachable through `exports` (the legacy `typings` field still points at a
// file the package no longer ships). Under the older `node` resolution
// TypeScript fell back to the untyped ./min bundle and every
// `import ... from 'monaco-editor'` degraded to an implicit any.
"moduleResolution": "bundler",
"strict": true,
"target": "ESNext",
},
"include": [
"src/**/*"
],
"exclude": [
"src/**/*.test.ts"
]
"target": "ESNext"
},
"include": ["src/**/*"],
"exclude": ["src/**/*.test.ts"]
}
10 changes: 8 additions & 2 deletions tsconfig.cjs.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "CommonJS",
// `node16` rather than `CommonJS`/`node10`: monaco-editor 0.56 exposes its
// declarations only through its `exports` map, and the classic resolver
// cannot see them (it falls back to the untyped ./min bundle). `node16`
// understands `exports` while still emitting CommonJS. `bundler` resolution
// from the base config is not an option here, as it requires an ES module.
"module": "node16",
"moduleResolution": "node16",
"outDir": "lib/cjs",
"sourceMap": true,
"target": "ES2016",
"target": "ES2016"
}
}
Loading
Loading