@svgrid/enterprise 2.5.2 → 2.5.3

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>SvGrid Studio - Designer</title>
7
- <script type="module" crossorigin src="./assets/index-CM5xvaOy.js"></script>
7
+ <script type="module" crossorigin src="./assets/index-CBYU-KNn.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-Dd_uD5pT.js">
9
9
  <link rel="modulepreload" crossorigin href="./assets/disclose-version-CIm4S9xS.js">
10
10
  <link rel="modulepreload" crossorigin href="./assets/export-format-DwjuTfrQ.js">
@@ -16,7 +16,7 @@
16
16
  <link rel="modulepreload" crossorigin href="./assets/easing-zaypKrr0.js">
17
17
  <link rel="modulepreload" crossorigin href="./assets/chart-DHEgt4lN.js">
18
18
  <link rel="modulepreload" crossorigin href="./assets/SvGridChart-BEDNTdc5.js">
19
- <link rel="modulepreload" crossorigin href="./assets/src-D-ET9Mmo.js">
19
+ <link rel="modulepreload" crossorigin href="./assets/src-i309BeJb.js">
20
20
  <link rel="modulepreload" crossorigin href="./assets/SvListBox-BVzVfCG3.js">
21
21
  <link rel="stylesheet" crossorigin href="./assets/dismissable-BF-9TJSd.css">
22
22
  <link rel="stylesheet" crossorigin href="./assets/SvDateTimePicker-Cygij-dr.css">
@@ -15130,7 +15130,7 @@ function hasFieldConditions(schema) {
15130
15130
  *
15131
15131
  * `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
15132
15132
  */
15133
- var SVGRID_VERSION = "2.5.2";
15133
+ var SVGRID_VERSION = "2.5.3";
15134
15134
  //#endregion
15135
15135
  //#region src/studio/emit-project.ts
15136
15136
  var has = (blocks, kind) => blocks.some((b) => b.config.kind === kind);
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "commercial",
5
5
  "url": "https://svgrid.com/pricing"
6
6
  },
7
- "version": "2.5.2",
7
+ "version": "2.5.3",
8
8
  "description": "Enterprise feature pack for SvGrid: Excel (xlsx), PDF, CSV, TSV and HTML export, Excel/CSV/JSON import, pivot tables with a drag-and-drop designer, paginated print, Kanban board and scheduler views. Requires a paid license key.",
9
9
  "license": "SEE LICENSE IN LICENSE",
10
10
  "author": "jQWidgets <sales@jqwidgets.com>",
@@ -97,16 +97,33 @@ describe('what happens after the trial ends', () => {
97
97
  expect(getLicenseExpiry()?.toISOString()).toBe('2026-09-04T23:59:59.999Z')
98
98
  })
99
99
 
100
- it('a lapsed trial gets the card but NOT the watermark', () => {
100
+ it('a lapsed trial gets the watermark, the console notice AND the card', () => {
101
101
  vi.useFakeTimers({ now: new Date('2026-09-20T10:00:00Z') })
102
+ const info = vi.spyOn(console, 'info').mockImplementation(() => {})
102
103
  setLicenseKey(KEY)
103
104
  assertEnterpriseLicensed('Export')
104
105
 
106
+ // The evaluation is over, so the app stops looking licensed on every
107
+ // surface - it just keeps working.
105
108
  expect(document.querySelector(CARD)).not.toBeNull()
106
- // Someone who evaluated and let the clock run out is a prospect mid-
107
- // conversation; stamping their UI is the wrong pressure. An app with no
108
- // key at all still gets both surfaces - covered below.
109
- expect(watermarkCalls()).toBe(0)
109
+ expect(watermarkCalls()).toBeGreaterThan(0)
110
+ expect(info.mock.calls.flat().join(' ')).toMatch(/evaluation license expired on 2026-09-04/)
111
+ info.mockRestore()
112
+ })
113
+
114
+ it('the expiry console notice fires once, not on every Pro call', () => {
115
+ vi.useFakeTimers({ now: new Date('2026-09-20T10:00:00Z') })
116
+ const info = vi.spyOn(console, 'info').mockImplementation(() => {})
117
+ setLicenseKey(KEY)
118
+ assertEnterpriseLicensed('Export')
119
+ assertEnterpriseLicensed('Export')
120
+ assertEnterpriseLicensed('Print')
121
+
122
+ const expiryNotices = info.mock.calls
123
+ .flat()
124
+ .filter((m) => typeof m === 'string' && m.includes('evaluation license expired'))
125
+ expect(expiryNotices).toHaveLength(1)
126
+ info.mockRestore()
110
127
  })
111
128
 
112
129
  it('an app with no key at all still gets the watermark', () => {
package/src/license.ts CHANGED
@@ -12,11 +12,11 @@
12
12
  // in REVOKED_KEYS -> throws (revoked / leaked / expired)
13
13
  // starts with "SVENTERPRISE-DEV" or
14
14
  // "SVENTERPRISE-EVAL" -> works; one-time console.info notice
15
- // an EXPIRED dev/eval key -> still works, but shows the upgrade
16
- // card each session. No watermark: a
17
- // lapsed trial is a prospect, not an
18
- // unlicensed app. Stays a soft gate so a
19
- // trial ending cannot break a build.
15
+ // an EXPIRED dev/eval key -> still works, but stops looking
16
+ // licensed: watermark + a one-time
17
+ // console notice naming the expiry date
18
+ // + the upgrade card. Stays a soft gate
19
+ // so a trial ending cannot break a build.
20
20
  // any other "SVENTERPRISE-..." -> works silently (paid production)
21
21
 
22
22
  import { checkLicenseKey, VALID_PREFIX, type LicenseInfo } from './license-core'
@@ -27,6 +27,22 @@ export { checkLicenseKey, type LicenseInfo, type LicenseStatus } from './license
27
27
 
28
28
  let currentKey: string | null = null
29
29
  let noticedDev = false
30
+ let noticedExpired = false
31
+
32
+ /** One-time console notice for a trial that has run out. Separate from the
33
+ * dev/eval notice: that one says "not for production", this one says the
34
+ * evaluation is over and names the date, which is the actionable part. */
35
+ function noticeExpired(info: LicenseInfo): void {
36
+ if (noticedExpired) return
37
+ noticedExpired = true
38
+ const on = info.expiresAt ? ` on ${info.expiresAt.toISOString().slice(0, 10)}` : ''
39
+ // eslint-disable-next-line no-console
40
+ console.info(
41
+ `@svgrid/enterprise: your evaluation license expired${on}. Everything still ` +
42
+ 'works, but the watermark and upgrade notice stay until a license key is set. ' +
43
+ 'Contact sales@jqwidgets.com or see https://svgrid.com/pricing',
44
+ )
45
+ }
30
46
 
31
47
  export function setLicenseKey(key: string): void {
32
48
  if (typeof key !== 'string' || key.length === 0) {
@@ -34,11 +50,13 @@ export function setLicenseKey(key: string): void {
34
50
  }
35
51
  currentKey = key
36
52
  noticedDev = false
53
+ noticedExpired = false
37
54
  }
38
55
 
39
56
  export function clearLicenseKey(): void {
40
57
  currentKey = null
41
58
  noticedDev = false
59
+ noticedExpired = false
42
60
  }
43
61
 
44
62
  export function getLicenseKey(): string | null {
@@ -86,11 +104,11 @@ export function nudgeEnterprise(feature?: EnterpriseFeatureLabel): void {
86
104
  // checking it alone would let a lapsed trial through silently forever.
87
105
  if (info.valid && !info.expired) return
88
106
  const lapsedTrial = info.valid && info.expired === true
89
- // A lapsed trial gets the card but NOT the watermark. Someone who evaluated
90
- // and let the clock run out is a prospect mid-conversation, not an app that
91
- // never had a licence - stamping their UI is the wrong pressure. An app with
92
- // no key at all still gets both.
93
- if (!lapsedTrial) emitUnlicensedNudge()
107
+ // A lapsed trial gets the same treatment as an unlicensed app - watermark,
108
+ // console notice and card. The evaluation is over; the app keeps running,
109
+ // but it stops looking licensed.
110
+ emitUnlicensedNudge()
111
+ if (lapsedTrial) noticeExpired(info)
94
112
  showUpgradePrompt(feature, { expired: lapsedTrial })
95
113
  }
96
114
 
@@ -118,8 +136,10 @@ export function assertEnterpriseLicensed(feature?: EnterpriseFeatureLabel): void
118
136
  case 'eval':
119
137
  if (info.expired) {
120
138
  // The trial is over. Deliberately NOT a throw: the app keeps working,
121
- // so the developer sees the nudge without their users hitting a broken
122
- // build. Card only - no watermark; see nudgeEnterprise() for why.
139
+ // so the developer sees the nudges without their users hitting a broken
140
+ // build. Watermark + console notice + card, same as an unlicensed app.
141
+ emitUnlicensedNudge()
142
+ noticeExpired(info)
123
143
  showUpgradePrompt(feature, { expired: true })
124
144
  return
125
145
  }
package/src/version.ts CHANGED
@@ -10,4 +10,4 @@
10
10
  *
11
11
  * `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
12
12
  */
13
- export const SVGRID_VERSION = '2.5.2'
13
+ export const SVGRID_VERSION = '2.5.3'