License: Add new licensing mechanism #32946
License: Add new licensing mechanism #32946ajivanyandev wants to merge 25 commits intoDevExpress:26_1from
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a new DevExtreme licensing workflow that supports “product-only” LCP keys, adds tooling to resolve/convert license keys from standard DevExpress locations, and integrates a build-time placeholder replacement mechanism.
Changes:
- Add a
devextreme-license-verifyCLI that resolves LCX keys (env/file), converts them to LCP, and optionally writes a generated key file + updates.gitignore. - Add an
unplugin-based build plugin to replace alicenseKeyplaceholder in internal config during bundling. - Extend runtime license validation to parse/validate LCP product keys (plus new helper modules and Jest tests).
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds unplugin lock entry and updates some transitive snapshot versions. |
| packages/devextreme/package.json | Adds unplugin dependency and exposes devextreme-license-verify bin. |
| packages/devextreme/license/messages.js | Introduces shared licensing-related warning/error message strings. |
| packages/devextreme/license/dx-lcx-2-lcp.js | Adds LCX→LCP conversion and basic LCP parsing/warning helpers. |
| packages/devextreme/license/dx-get-lcx.js | Adds logic to resolve LCX keys from env vars and default OS paths. |
| packages/devextreme/license/devextreme-license.js | Implements the devextreme-license-verify CLI (stdout or file output). |
| packages/devextreme/license/devextreme-license-plugin.js | Adds an unplugin transform that patches the internal licenseKey placeholder. |
| packages/devextreme/license/devextreme-license-plugin.d.ts | Adds TypeScript typings for the licensing unplugin export. |
| packages/devextreme/js/__internal/core/m_config.ts | Adds a licenseKey field to internal config with a placeholder value. |
| packages/devextreme/js/__internal/core/license/types.ts | Refactors token typings and exports reusable error token constants. |
| packages/devextreme/js/__internal/core/license/rsa_bigint.ts | Reuses shared bigIntFromBytes helper instead of local implementation. |
| packages/devextreme/js/__internal/core/license/license_validation_internal.ts | Exposes an internal stub for isUnsupportedKeyFormat. |
| packages/devextreme/js/__internal/core/license/license_validation.ts | Adds LCP product-key parsing path + unsupported-format detection + constant refactor. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/utils.ts | Adds utilities for parsing/verifying LCP product-key payloads and signatures. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/types.ts | Adds ProductKind bigint flag definitions and composites. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/product_info.ts | Adds product info model + bit-flag checks. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/license_payload.test.ts | Adds Jest tests for payload-level product-kind/version selection logic. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/license_info.ts | Adds helpers to validate payload structure and find max allowed DevExtreme version. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/lcp_key_validator.ts | Implements product-only LCP key parsing and RSA signature verification. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/lcp_key_validation.test.ts | Adds smoke tests for malformed keys and optional fixture-based parsing. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/const.ts | Adds LCP constants (signature, decode map, RSA public key). |
| packages/devextreme/js/__internal/core/license/const.ts | Extracts shared license-validation constants (links, format, splitter, etc.). |
| packages/devextreme/js/__internal/core/license/byte_utils.ts | Adds bigIntFromBytes utility for RSA validation helpers. |
| packages/devextreme/eslint.config.mjs | Ignores the new license/ folder from linting. |
| packages/devextreme/build/npm-bin/devextreme-license-verify.js | Adds npm bin entrypoint shim for the new CLI in distribution. |
| packages/devextreme/build/gulp/npm.js | Copies license/** into the npm package distribution output. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
| useLegacyVisibleIndex: false, | ||
| versionAssertions: [], | ||
| copyStylesToShadowDom: true, | ||
| licenseKey: '/* ___$$$$$___devextreme___lcp___placeholder____$$$$$ */', |
| else if(a === '--cwd') out.cwd = args[++i] || process.cwd(); | ||
| else if(a.startsWith('--cwd=')) out.cwd = a.slice('--cwd='.length); |
| "inferno-create-element": "catalog:", | ||
| "inferno-hydrate": "catalog:", | ||
| "jszip": "^3.10.1", | ||
| "rrule": "^2.7.1" | ||
| "rrule": "^2.7.1", | ||
| "unplugin": "^3.0.0" |
| errors.log('W0000', 'config', 'licenseKey', 'LCXv1 is specified in the license key'); | ||
| return true; | ||
| } | ||
| if (hasLicensePrefix(licenseKey, 'egow')) { | ||
| errors.log('W0000', 'config', 'licenseKey', 'DevExtreme key is specified in the license key'); |
| } | ||
| validationPerformed = true; | ||
|
|
||
| if (isUnsupportedKeyFormat(licenseKey)) { |
|
|
||
| function fail(msg) { | ||
| process.stderr.write(msg.endsWith('\n') ? msg : msg + '\n'); | ||
| process.exit(0); |
| ignores: [ | ||
| 'artifacts/*', | ||
| 'js/viz/docs/*', | ||
| 'node_modules/*', | ||
| 'build/*', | ||
| 'license/*', | ||
| '**/*.j.tsx', | ||
| 'playground/*', |
| return { | ||
| name: 'devextreme-bundler-plugin', | ||
| enforce: 'pre', | ||
| transform(code, id) { |
| unplugin@3.0.0: | ||
| resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} | ||
| engines: {node: ^20.19.0 || >=22.12.0} | ||
|
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new DevExtreme licensing flow by adding a license key placeholder into runtime config, new validation logic for LCP (product-only) keys, and tooling (CLI + unplugin-based build-time patching) to inject/emit license keys during builds.
Changes:
- Add
devextreme-licenseCLI and anunpluginplugin to resolve and inject a license key into the build. - Extend internal license validation to support
LCPv1product-only keys and add Jest coverage for product-kind/version selection logic. - Package the new license assets into the npm distribution and wire up config placeholder replacement.
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds unplugin@3.0.0 and updates a transitive mapping dependency. |
| packages/devextreme/package.json | Adds unplugin dependency and exposes devextreme-license binary. |
| packages/devextreme/license/messages.js | Adds centralized user-facing licensing messages for CLI/plugin warnings. |
| packages/devextreme/license/dx-lcx-2-lcp.js | Adds LCX→LCP conversion + basic LCP parsing/version warning helper (Node-side). |
| packages/devextreme/license/dx-get-lcx.js | Adds env/file-based license key discovery logic. |
| packages/devextreme/license/devextreme-license.js | Adds CLI to output or generate a license-key file and optionally update .gitignore. |
| packages/devextreme/license/devextreme-license-plugin.js | Adds unplugin that patches the config placeholder during bundling. |
| packages/devextreme/license/devextreme-license-plugin.d.ts | Adds typings for the unplugin export. |
| packages/devextreme/js/__internal/core/m_config.ts | Introduces licenseKey placeholder to be replaced at build time. |
| packages/devextreme/js/__internal/core/license/types.ts | Refactors token types and exports reusable error-token constants (incl. product-kind). |
| packages/devextreme/js/__internal/core/license/rsa_bigint.ts | Reuses shared bigIntFromBytes helper instead of inlining it. |
| packages/devextreme/js/__internal/core/license/license_validation_internal.ts | Adds internal signature for isUnsupportedKeyFormat. |
| packages/devextreme/js/__internal/core/license/license_validation.ts | Adds support for product-only LCP keys + unsupported-format handling and refactors constants. |
| packages/devextreme/js/__internal/core/license/lcp_key_validation/* | Adds product-only key parsing, product-kind bitflag helpers, and Jest tests. |
| packages/devextreme/js/__internal/core/license/const.ts | Extracts shared license constants used by validation and UI. |
| packages/devextreme/js/__internal/core/license/byte_utils.ts | Adds bigIntFromBytes helper used by RSA/key parsing. |
| packages/devextreme/eslint.config.mjs | Excludes license/* from ESLint processing. |
| packages/devextreme/build/npm-bin/devextreme-license.js | Adds npm-distributed bin entrypoint for the CLI. |
| packages/devextreme/build/gulp/npm.js | Copies license/** into the npm dist output. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
|
|
||
| function fail(msg) { | ||
| process.stderr.write(msg.endsWith('\n') ? msg : msg + '\n'); | ||
| process.exit(0); |
| 'js/viz/docs/*', | ||
| 'node_modules/*', | ||
| 'build/*', | ||
| 'license/*', |
| unplugin@3.0.0: | ||
| resolution: {integrity: sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg==} | ||
| engines: {node: ^20.19.0 || >=22.12.0} | ||
|
|
No description provided.