@svgrid/enterprise 1.2.0 → 2.0.0

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.
Files changed (159) hide show
  1. package/dist/cdn/svgrid-enterprise.svelte-external.js +26039 -805
  2. package/dist/designer/assets/index-Dp44bTid.js +939 -0
  3. package/dist/designer/assets/index-RJp6x8tw.css +1 -0
  4. package/dist/designer/assets/jszip.min-CjMo-QGg.js +2 -0
  5. package/dist/designer/index.html +13 -0
  6. package/dist/node/studio.js +22554 -0
  7. package/package.json +10 -3
  8. package/src/SvAuthGate.svelte +115 -0
  9. package/src/SvBoard.dom.test.ts +67 -0
  10. package/src/SvBoard.svelte +192 -0
  11. package/src/SvExportMenu.svelte +553 -0
  12. package/src/SvFileInput.svelte +113 -0
  13. package/src/SvGridEditPanel.dom.test.ts +146 -0
  14. package/src/SvGridEditPanel.svelte +793 -0
  15. package/src/SvGridMasterDetail.svelte +95 -0
  16. package/src/SvImportDialog.svelte +1020 -0
  17. package/src/SvLookupInput.svelte +180 -0
  18. package/src/SvRecordDetail.dom.test.ts +137 -0
  19. package/src/SvRecordDetail.svelte +288 -0
  20. package/src/SvSchedule.dom.test.ts +57 -0
  21. package/src/SvSchedule.svelte +156 -0
  22. package/src/SvSchemaChart.svelte +233 -0
  23. package/src/SvSchemaDashboard.svelte +130 -0
  24. package/src/ai-export-pdf.test.ts +74 -0
  25. package/src/ai-export-xlsx.test.ts +87 -0
  26. package/src/ai-export.test.ts +110 -0
  27. package/src/ai.ts +1188 -782
  28. package/src/edit-panel.test.ts +213 -0
  29. package/src/edit-panel.ts +228 -0
  30. package/src/export-conditional.test.ts +60 -0
  31. package/src/export-conditional.ts +94 -0
  32. package/src/export-ooxml.test.ts +152 -0
  33. package/src/export-ooxml.ts +485 -0
  34. package/src/export-pdf.test.ts +138 -0
  35. package/src/export-pdf.ts +245 -0
  36. package/src/export-print.test.ts +66 -0
  37. package/src/export-print.ts +132 -0
  38. package/src/export-serialize.test.ts +56 -0
  39. package/src/export-serialize.ts +24 -0
  40. package/src/export-xls.ts +196 -0
  41. package/src/export-xlsx-roundtrip.test.ts +120 -0
  42. package/src/export-xlsx.test.ts +150 -0
  43. package/src/export.test.ts +349 -0
  44. package/src/export.ts +1452 -549
  45. package/src/import-automap.test.ts +131 -0
  46. package/src/import-hardening.test.ts +158 -0
  47. package/src/import.ts +1042 -648
  48. package/src/index.ts +282 -0
  49. package/src/install.ts +134 -114
  50. package/src/license-core.test.ts +23 -0
  51. package/src/license-core.ts +35 -0
  52. package/src/license.ts +103 -90
  53. package/src/master-detail.test.ts +61 -0
  54. package/src/master-detail.ts +42 -0
  55. package/src/print.ts +107 -127
  56. package/src/schema-designer.test.ts +121 -0
  57. package/src/schema-designer.ts +142 -0
  58. package/src/schema.test.ts +268 -0
  59. package/src/schema.ts +499 -0
  60. package/src/smart-shim.ts +107 -105
  61. package/src/sources/aggregate.test.ts +79 -0
  62. package/src/sources/aggregate.ts +102 -0
  63. package/src/sources/auth-supabase.test.ts +80 -0
  64. package/src/sources/auth-supabase.ts +87 -0
  65. package/src/sources/dashboard.kpi.test.ts +50 -0
  66. package/src/sources/dashboard.test.ts +61 -0
  67. package/src/sources/dashboard.ts +136 -0
  68. package/src/sources/field-inference.test.ts +60 -0
  69. package/src/sources/field-inference.ts +63 -0
  70. package/src/sources/filters.test.ts +58 -0
  71. package/src/sources/filters.ts +64 -0
  72. package/src/sources/index.ts +67 -0
  73. package/src/sources/introspect-supabase.test.ts +100 -0
  74. package/src/sources/introspect-supabase.ts +119 -0
  75. package/src/sources/realtime-supabase.test.ts +93 -0
  76. package/src/sources/realtime-supabase.ts +99 -0
  77. package/src/sources/relation-lookup.test.ts +99 -0
  78. package/src/sources/relation-lookup.ts +128 -0
  79. package/src/sources/rest-adapters.test.ts +95 -0
  80. package/src/sources/rest-adapters.ts +120 -0
  81. package/src/sources/rest.test.ts +104 -0
  82. package/src/sources/rest.ts +129 -0
  83. package/src/sources/schema-from-columns.test.ts +106 -0
  84. package/src/sources/schema-from-columns.ts +88 -0
  85. package/src/sources/supabase.test.ts +110 -0
  86. package/src/sources/supabase.ts +99 -0
  87. package/src/sources/with-entity-rules.test.ts +104 -0
  88. package/src/sources/with-entity-rules.ts +78 -0
  89. package/src/sources/with-relation-labels.test.ts +75 -0
  90. package/src/sources/with-relation-labels.ts +73 -0
  91. package/src/studio/bug-report.test.ts +101 -0
  92. package/src/studio/bug-report.ts +165 -0
  93. package/src/studio/cli.test.ts +187 -0
  94. package/src/studio/cli.ts +112 -0
  95. package/src/studio/csv.test.ts +90 -0
  96. package/src/studio/csv.ts +165 -0
  97. package/src/studio/db-connect-string.test.ts +94 -0
  98. package/src/studio/db-connect-string.ts +128 -0
  99. package/src/studio/emit-project.test.ts +923 -0
  100. package/src/studio/emit-project.ts +1273 -0
  101. package/src/studio/emit-schema.test.ts +94 -0
  102. package/src/studio/emit-schema.ts +920 -0
  103. package/src/studio/index.ts +195 -0
  104. package/src/studio/introspect-db.test.ts +186 -0
  105. package/src/studio/introspect-db.ts +312 -0
  106. package/src/studio/introspect-prisma.test.ts +99 -0
  107. package/src/studio/introspect-prisma.ts +175 -0
  108. package/src/studio/introspect.test.ts +172 -0
  109. package/src/studio/introspect.ts +310 -0
  110. package/src/studio/pipeline.test.ts +42 -0
  111. package/src/studio/project-robust.test.ts +157 -0
  112. package/src/studio/project.test.ts +473 -0
  113. package/src/studio/project.ts +916 -0
  114. package/src/studio/sample-data.test.ts +58 -0
  115. package/src/studio/sample-data.ts +200 -0
  116. package/src/studio/samples/ats.ts +202 -0
  117. package/src/studio/samples/clinic.ts +177 -0
  118. package/src/studio/samples/crm.ts +250 -0
  119. package/src/studio/samples/ecommerce.ts +187 -0
  120. package/src/studio/samples/events.ts +199 -0
  121. package/src/studio/samples/fleet.ts +184 -0
  122. package/src/studio/samples/gym.ts +213 -0
  123. package/src/studio/samples/hr.ts +193 -0
  124. package/src/studio/samples/index.ts +55 -0
  125. package/src/studio/samples/insurance.ts +195 -0
  126. package/src/studio/samples/inventory.ts +182 -0
  127. package/src/studio/samples/invoicing.ts +162 -0
  128. package/src/studio/samples/library.ts +180 -0
  129. package/src/studio/samples/live-data.test.ts +98 -0
  130. package/src/studio/samples/live-data.ts +308 -0
  131. package/src/studio/samples/projects.ts +190 -0
  132. package/src/studio/samples/realestate.ts +196 -0
  133. package/src/studio/samples/restaurant.ts +187 -0
  134. package/src/studio/samples/samples.test.ts +208 -0
  135. package/src/studio/samples/school.ts +197 -0
  136. package/src/studio/samples/seed-floor.test.ts +25 -0
  137. package/src/studio/samples/shared.ts +305 -0
  138. package/src/studio/samples/subscriptions.ts +183 -0
  139. package/src/studio/samples/support.ts +182 -0
  140. package/src/studio/scaffold-app.test.ts +91 -0
  141. package/src/studio/scaffold-app.ts +161 -0
  142. package/src/studio/scaffold.test.ts +178 -0
  143. package/src/studio/scaffold.ts +374 -0
  144. package/src/studio/themes.ts +172 -0
  145. package/src/studio/verify.test.ts +47 -0
  146. package/src/studio/verify.ts +79 -0
  147. package/src/sveltekit/in-memory.test.ts +104 -0
  148. package/src/sveltekit/in-memory.ts +129 -0
  149. package/src/sveltekit/index.ts +23 -0
  150. package/src/sveltekit/query-plan.test.ts +109 -0
  151. package/src/sveltekit/query-plan.ts +125 -0
  152. package/src/sveltekit/sql-source.test.ts +185 -0
  153. package/src/sveltekit/sql-source.ts +166 -0
  154. package/src/sveltekit/sql.test.ts +80 -0
  155. package/src/sveltekit/sql.ts +131 -0
  156. package/src/sveltekit/transport.test.ts +175 -0
  157. package/src/sveltekit/transport.ts +254 -0
  158. package/src/sveltekit/types.ts +11 -0
  159. package/src/upgrade-prompt.ts +149 -148
package/src/index.ts CHANGED
@@ -5,10 +5,15 @@ export {
5
5
  isLicenseKeySet,
6
6
  hasValidLicense,
7
7
  assertEnterpriseLicensed,
8
+ nudgeEnterprise,
9
+ checkLicenseKey,
10
+ type LicenseInfo,
11
+ type LicenseStatus,
8
12
  } from './license'
9
13
 
10
14
  export {
11
15
  exportGrid,
16
+ copyExportToClipboard,
12
17
  type ExportFormat,
13
18
  type ExportOptions,
14
19
  type ExportColumn,
@@ -16,19 +21,34 @@ export {
16
21
  type ExportStyles,
17
22
  type ExportHeaderFooterLine,
18
23
  type ExportSheet,
24
+ type ExportRowSource,
25
+ type ExportProgress,
26
+ type ExportResult,
27
+ type ClipboardFormat,
28
+ type ClipboardExportOptions,
19
29
  } from './export'
30
+ export { default as SvExportMenu } from './SvExportMenu.svelte'
31
+ export { buildPdfDocDefinition, type PdfExportOptions, type PdfPageSize } from './export-pdf'
20
32
  export { printGrid, type PrintOptions } from './print'
21
33
  export {
22
34
  importData,
35
+ readImportMatrix,
36
+ mapImportMatrix,
37
+ mapImportMatrixAsync,
38
+ autoMapColumns,
39
+ inferImportColumnTypes,
23
40
  type ImportFormat,
24
41
  type ImportFieldType,
25
42
  type ImportOptions,
26
43
  type ImportResult,
44
+ type ImportProgress,
27
45
  type ImportColumnMap,
28
46
  type ImportColumnTypes,
47
+ type ImportGridColumn,
29
48
  type ImportRowError,
30
49
  type ImportValidator,
31
50
  } from './import'
51
+ export { default as SvImportDialog } from './SvImportDialog.svelte'
32
52
  export { installEnterprise, type EnterpriseGridApi, type EnterpriseAIApi, type EnterprisePivotApi } from './install'
33
53
  export {
34
54
  createStagedEditing,
@@ -56,6 +76,259 @@ export {
56
76
  type PivotValueConfig,
57
77
  } from './pivot'
58
78
 
79
+ export {
80
+ titleCase,
81
+ resolveIdField,
82
+ schemaToColumns,
83
+ schemaToFormFields,
84
+ validateField,
85
+ applyComputed,
86
+ validateEntity,
87
+ type EntitySchema,
88
+ type EntityField,
89
+ type EntityFieldType,
90
+ type EntityHooks,
91
+ type FormFieldDescriptor,
92
+ type StudioEditorType,
93
+ type StandardSchemaV1,
94
+ type StandardSchemaResult,
95
+ type ValidationOp,
96
+ type ValidationRuleSpec,
97
+ } from './schema'
98
+
99
+ export {
100
+ planQuery,
101
+ coerce,
102
+ createInMemoryDataSource,
103
+ createKitDataSource,
104
+ createKitHandlers,
105
+ createSqlDataSource,
106
+ planToSql,
107
+ type QueryPlan,
108
+ type PlanPredicate,
109
+ type PlanOp,
110
+ type KitDataSourceOptions,
111
+ type KitHandlerOptions,
112
+ type KitHandlers,
113
+ type KitMessage,
114
+ type SqlDialect,
115
+ type SqlPlan,
116
+ type SqlExecutor,
117
+ type SqlDataSourceConfig,
118
+ type WritableDataSource,
119
+ } from './sveltekit'
120
+
121
+ export {
122
+ createSupabaseDataSource,
123
+ createRestDataSource,
124
+ offsetLimitAdapter,
125
+ dummyJsonAdapter,
126
+ jsonServerAdapter,
127
+ introspectSupabaseTable,
128
+ createSupabaseRealtime,
129
+ createRelationLookup,
130
+ createSupabaseAuth,
131
+ aggregateRows,
132
+ chartFieldsFromSchema,
133
+ normalizeFilters,
134
+ buildEntitySchema,
135
+ pickLabelField,
136
+ linkRelationLabels,
137
+ type SupabaseDataSourceConfig,
138
+ type SupabaseClientLike,
139
+ type RestDataSourceConfig,
140
+ type RestAdapter,
141
+ type OffsetLimitOptions,
142
+ type IntrospectSupabaseOptions,
143
+ type IntrospectedColumn,
144
+ type ColumnReference,
145
+ type NormalizedFilter,
146
+ type NormalizedPredicate,
147
+ type SupabaseRealtimeConfig,
148
+ type SupabaseRealtimeClientLike,
149
+ type SupabaseRealtimeHandle,
150
+ type RealtimeChannelLike,
151
+ type RealtimeChange,
152
+ type RelationLookup,
153
+ type RelationLookupConfig,
154
+ type RelationOption,
155
+ type SupabaseAuthConfig,
156
+ type SupabaseAuthController,
157
+ type SupabaseAuthClientLike,
158
+ type AuthState,
159
+ type AuthUser,
160
+ withEntityRules,
161
+ withRelationLabels,
162
+ reduceValue,
163
+ kpiSeries,
164
+ sparklinePoints,
165
+ seriesDelta,
166
+ formatKpiValue,
167
+ dashboardFromSchema,
168
+ type AggregateReduce,
169
+ type AggregateRequest,
170
+ type AggregateBucket,
171
+ type AggregateSource,
172
+ type DashboardSpec,
173
+ type DashboardWidget,
174
+ type KpiWidget,
175
+ type ChartWidget,
176
+ type RelationLabelConfig,
177
+ } from './sources'
178
+
179
+ export {
180
+ buildInitialValues,
181
+ controlKind,
182
+ editMode,
183
+ rowId,
184
+ toSubmitValues,
185
+ validateAll,
186
+ type EditMode,
187
+ type ControlKind,
188
+ } from './edit-panel'
189
+ export { default as SvGridEditPanel } from './SvGridEditPanel.svelte'
190
+ export { default as SvLookupInput } from './SvLookupInput.svelte'
191
+ export { default as SvFileInput } from './SvFileInput.svelte'
192
+ export { default as SvAuthGate } from './SvAuthGate.svelte'
193
+ export { default as SvSchemaChart } from './SvSchemaChart.svelte'
194
+ export { default as SvSchemaDashboard } from './SvSchemaDashboard.svelte'
195
+ export { default as SvBoard } from './SvBoard.svelte'
196
+ export { default as SvSchedule } from './SvSchedule.svelte'
197
+ export { default as SvRecordDetail } from './SvRecordDetail.svelte'
198
+
199
+ export {
200
+ FIELD_TYPES,
201
+ blankField,
202
+ addField,
203
+ removeField,
204
+ updateField,
205
+ moveField,
206
+ validateSchema,
207
+ isSchemaValid,
208
+ sampleRows,
209
+ type SchemaIssue,
210
+ type SchemaIssueLevel,
211
+ } from './schema-designer'
212
+ // NOTE: The visual designer components (SvSchemaDesigner, SvStudioDesigner) are
213
+ // the commercial "SvGrid Studio" seller. They live entirely in the PRIVATE
214
+ // website repo (website/src/lib/designer), NOT in this public package - they
215
+ // import the public API below. The Studio *codegen* below stays public because
216
+ // the MCP server depends on it.
217
+ // The Studio project model + codegen (also on the pure `@svgrid/enterprise/studio`
218
+ // subpath) - re-exported so the designer and its model come from one import.
219
+ export {
220
+ createProject,
221
+ defaultScreenFor,
222
+ emitStudioProject,
223
+ emitStudioAppBundle,
224
+ emitStudioApp,
225
+ sampleApps,
226
+ getSampleApp,
227
+ liveDataSamples,
228
+ getLiveDataSample,
229
+ type SampleApp,
230
+ sanitizeStudioProject,
231
+ buildStudioBugReport,
232
+ type BugReport,
233
+ type BugReportInput,
234
+ addBlock,
235
+ addBlockAt,
236
+ removeBlock,
237
+ moveBlock,
238
+ reorderBlock,
239
+ updateBlock,
240
+ addScreen,
241
+ removeScreen,
242
+ updateScreen,
243
+ duplicateScreen,
244
+ reorderScreen,
245
+ insertBlock,
246
+ addEntity,
247
+ removeEntity,
248
+ updateEntity,
249
+ setDataSource,
250
+ defaultEntitySource,
251
+ setEntityDataSource,
252
+ entityDataSource,
253
+ setTheme,
254
+ setThemePreset,
255
+ setShell,
256
+ sanitizeProject,
257
+ screenFromTemplate,
258
+ addScreenFromTemplate,
259
+ serializeProject,
260
+ parseProject,
261
+ blockPalette,
262
+ validateProject,
263
+ isProjectValid,
264
+ entityOf,
265
+ studioThemes,
266
+ defaultStudioTheme,
267
+ getStudioTheme,
268
+ resolveThemeTokens,
269
+ isDarkTheme,
270
+ themeStyleString,
271
+ type StudioTheme,
272
+ type StudioProject,
273
+ type Screen,
274
+ type ScreenNav,
275
+ type Block,
276
+ type BlockKind,
277
+ type BlockConfig,
278
+ type GridConfig,
279
+ type GridEditing,
280
+ type GridDensity,
281
+ type GridAlign,
282
+ type PagerPosition,
283
+ type GridColumnConfig,
284
+ type ChartConfig,
285
+ type KpiConfig,
286
+ type KpiFormat,
287
+ type DashboardConfig,
288
+ type MasterDetailConfig,
289
+ type LookupConfig,
290
+ type Reduce,
291
+ type DataSourceKind,
292
+ type EntityDataSource,
293
+ type MemorySource,
294
+ type RestSource,
295
+ type SqlSource,
296
+ type SupabaseSource,
297
+ type RestMethod,
298
+ type ParamLocation,
299
+ type ParamType,
300
+ type RequestParam,
301
+ type SqlDialectKind,
302
+ type ProjectTheme,
303
+ type ShellConfig,
304
+ type ShellStyle,
305
+ type ScreenTemplate,
306
+ type PaletteItem,
307
+ type ProjectIssue,
308
+ type GeneratedFile,
309
+ } from './studio'
310
+ export {
311
+ buildConnectionString,
312
+ parseConnectionString,
313
+ redactConnectionString,
314
+ isFileDialect,
315
+ DRIVER_PACKAGE,
316
+ DEFAULT_PORT,
317
+ countTableRows,
318
+ probeConnection,
319
+ type SqlConnectionParts,
320
+ type TableRowCount,
321
+ type SqlDialectName,
322
+ } from './studio'
323
+
324
+ export {
325
+ buildDisplayRows,
326
+ isDetailRow,
327
+ toggleExpanded,
328
+ type DetailRow,
329
+ } from './master-detail'
330
+ export { default as SvGridMasterDetail } from './SvGridMasterDetail.svelte'
331
+
59
332
  export { default as SvPivotDesigner } from './SvPivotDesigner.svelte'
60
333
  export {
61
334
  ALL_AGGREGATORS,
@@ -99,4 +372,13 @@ export {
99
372
  aiClassify,
100
373
  type AIClassifyOptions,
101
374
  type AIClassifyResult,
375
+ // Natural-language export
376
+ aiExport,
377
+ type AIExportOptions,
378
+ type AIExportPlan,
379
+ // Anomaly detection
380
+ aiFindAnomalies,
381
+ type AIAnomaly,
382
+ type AIAnomalyOptions,
383
+ type AIAnomalyResult,
102
384
  } from './ai'
package/src/install.ts CHANGED
@@ -1,114 +1,134 @@
1
- import type { RowData, TableFeatures, SvGridApi } from '@svgrid/grid'
2
- import { exportGrid, type ExportOptions } from './export'
3
- import { printGrid, type PrintOptions } from './print'
4
- import { importData, type ImportOptions, type ImportResult } from './import'
5
- import { isLicenseKeySet } from './license'
6
- import { emitUnlicensedNudge } from './watermark'
7
- import {
8
- aiFilter, aiSmartFill, aiSummarize, aiClassify,
9
- type AIFilterOptions, type AIFilterResult,
10
- type AISmartFillOptions, type AISmartFillResult,
11
- type AISummarizeOptions, type AISummary,
12
- type AIClassifyOptions, type AIClassifyResult,
13
- } from './ai'
14
- import {
15
- createPivotModel,
16
- type PivotConfig,
17
- type PivotResult,
18
- } from './pivot'
19
-
20
- export type EnterpriseAIApi<TData extends RowData> = {
21
- /** Natural-language -> filter + sort plan (and optionally apply it). */
22
- filter(query: string, opts?: AIFilterOptions): Promise<AIFilterResult>
23
- /** Propose values for empty cells based on a few worked examples. */
24
- smartFill<TValue = unknown>(opts: AISmartFillOptions): Promise<AISmartFillResult<TValue>>
25
- /** One-paragraph + bullets summary of a row, selection, group, or the whole view. */
26
- summarize(opts: AISummarizeOptions): Promise<AISummary>
27
- /** Classify free-text cells into one of a known set of labels. */
28
- classify(opts: AIClassifyOptions): Promise<AIClassifyResult>
29
- // TData is referenced so the type stays bound to the row shape even
30
- // though the helpers all read through `api.getData()`. Lets callers
31
- // get correct inference downstream without explicit generics.
32
- readonly _rowType?: TData
33
- }
34
-
35
- export type EnterprisePivotApi<
36
- TFeatures extends TableFeatures,
37
- TData extends RowData,
38
- > = {
39
- /**
40
- * Build a pivot row/column model from the grid's current data. Returns
41
- * `{ rows, columns }` you can feed to a separate `<SvGrid>` instance
42
- * (the typical pattern - the source grid stays unmodified). Pure: no
43
- * mutation, no DOM access.
44
- */
45
- build(config: PivotConfig<TData>): PivotResult<TFeatures>
46
- /**
47
- * Build a pivot from an arbitrary array (not necessarily the grid's
48
- * data). Useful for previewing a designer's config against a sample
49
- * before committing.
50
- */
51
- buildFrom<TIn extends RowData>(
52
- data: ReadonlyArray<TIn>,
53
- config: PivotConfig<TIn>,
54
- ): PivotResult<TFeatures>
55
- }
56
-
57
- export type EnterpriseGridApi<
58
- TFeatures extends TableFeatures,
59
- TData extends RowData,
60
- > = SvGridApi<TFeatures, TData> & {
61
- /** Export the current visible rows to the chosen format. */
62
- exportData(opts: ExportOptions<TData>): Promise<void>
63
- /** Open a printable view of the current visible rows in a new window. */
64
- print(opts?: PrintOptions<TData>): Promise<void>
65
- /** Read an Excel / CSV / TSV / JSON file (or inline text) into typed
66
- * rows. Caller decides whether to commit into the grid or preview
67
- * the parsed result first via the returned `ImportResult`. */
68
- importData(opts: ImportOptions<TData>): Promise<ImportResult<TData>>
69
- /** AI helpers (Pro). All calls route through a consumer-registered
70
- * AIProvider via setAIProvider(); no model client is bundled. */
71
- ai: EnterpriseAIApi<TData>
72
- /** Pivot table builder (Pro). Pure - returns `{ rows, columns }` you
73
- * hand to a separate `<SvGrid>` instance. */
74
- pivot: EnterprisePivotApi<TFeatures, TData>
75
- }
76
-
77
- /**
78
- * Augment a SvGridApi instance with Pro methods (`exportData`, `print`,
79
- * `ai.*`). Mutates and returns the same object so existing references
80
- * keep working.
81
- *
82
- * If no license key has been set, the Pro methods still function but the
83
- * grid shows a small "unlicensed" watermark linking to jqwidgets.com and
84
- * the console emits a one-time nudge. Revoked or malformed keys throw on
85
- * first call.
86
- */
87
- export function installEnterprise<
88
- TFeatures extends TableFeatures,
89
- TData extends RowData,
90
- >(api: SvGridApi<TFeatures, TData>): EnterpriseGridApi<TFeatures, TData> {
91
- const pro = api as EnterpriseGridApi<TFeatures, TData>
92
- pro.exportData = (opts) => exportGrid(pro, opts)
93
- pro.print = (opts) => printGrid(pro, opts)
94
- pro.importData = (opts) => importData(pro, opts)
95
- pro.ai = {
96
- filter: (query, opts) => aiFilter(pro, query, opts),
97
- smartFill: (opts) => aiSmartFill(pro, opts),
98
- summarize: (opts) => aiSummarize(pro, opts),
99
- classify: (opts) => aiClassify(pro, opts),
100
- }
101
- pro.pivot = {
102
- build: (config) =>
103
- createPivotModel<TFeatures, TData>(pro.getData(), config),
104
- buildFrom: <TIn extends RowData>(data: ReadonlyArray<TIn>, config: PivotConfig<TIn>) =>
105
- // PivotConfig is variance-strict in TIn; the runtime call only needs
106
- // the row shape to match config.rows / config.cols field names, which
107
- // the caller-side generic enforces.
108
- createPivotModel<TFeatures, TIn>(data, config),
109
- }
110
- // Surface the soft-gate state at install time so the watermark appears
111
- // alongside the grid, not just after the user clicks Export.
112
- if (!isLicenseKeySet()) emitUnlicensedNudge()
113
- return pro
114
- }
1
+ import type { RowData, TableFeatures, SvGridApi } from '@svgrid/grid'
2
+ import {
3
+ exportGrid,
4
+ copyExportToClipboard,
5
+ type ExportOptions,
6
+ type ExportResult,
7
+ type ClipboardExportOptions,
8
+ } from './export'
9
+ import { printGrid, type PrintOptions } from './print'
10
+ import { importData, type ImportOptions, type ImportResult } from './import'
11
+ import { isLicenseKeySet } from './license'
12
+ import { emitUnlicensedNudge } from './watermark'
13
+ import {
14
+ aiFilter, aiSmartFill, aiSummarize, aiClassify, aiExport, aiFindAnomalies,
15
+ type AIFilterOptions, type AIFilterResult,
16
+ type AISmartFillOptions, type AISmartFillResult,
17
+ type AISummarizeOptions, type AISummary,
18
+ type AIClassifyOptions, type AIClassifyResult,
19
+ type AIExportOptions, type AIExportPlan,
20
+ type AIAnomalyOptions, type AIAnomalyResult,
21
+ } from './ai'
22
+ import {
23
+ createPivotModel,
24
+ type PivotConfig,
25
+ type PivotResult,
26
+ } from './pivot'
27
+
28
+ export type EnterpriseAIApi<TData extends RowData> = {
29
+ /** Natural-language -> filter + sort plan (and optionally apply it). */
30
+ filter(query: string, opts?: AIFilterOptions): Promise<AIFilterResult>
31
+ /** Propose values for empty cells based on a few worked examples. */
32
+ smartFill<TValue = unknown>(opts: AISmartFillOptions): Promise<AISmartFillResult<TValue>>
33
+ /** One-paragraph + bullets summary of a row, selection, group, or the whole view. */
34
+ summarize(opts: AISummarizeOptions): Promise<AISummary>
35
+ /** Classify free-text cells into one of a known set of labels. */
36
+ classify(opts: AIClassifyOptions): Promise<AIClassifyResult>
37
+ /** Natural-language export: "export EU orders from Q2 as a grouped PDF". */
38
+ export(query: string, opts?: AIExportOptions): Promise<AIExportPlan>
39
+ /** Scan a slice for anomalies / outliers, returning a structured list. */
40
+ findAnomalies(opts?: AIAnomalyOptions): Promise<AIAnomalyResult>
41
+ // TData is referenced so the type stays bound to the row shape even
42
+ // though the helpers all read through `api.getData()`. Lets callers
43
+ // get correct inference downstream without explicit generics.
44
+ readonly _rowType?: TData
45
+ }
46
+
47
+ export type EnterprisePivotApi<
48
+ TFeatures extends TableFeatures,
49
+ TData extends RowData,
50
+ > = {
51
+ /**
52
+ * Build a pivot row/column model from the grid's current data. Returns
53
+ * `{ rows, columns }` you can feed to a separate `<SvGrid>` instance
54
+ * (the typical pattern - the source grid stays unmodified). Pure: no
55
+ * mutation, no DOM access.
56
+ */
57
+ build(config: PivotConfig<TData>): PivotResult<TFeatures>
58
+ /**
59
+ * Build a pivot from an arbitrary array (not necessarily the grid's
60
+ * data). Useful for previewing a designer's config against a sample
61
+ * before committing.
62
+ */
63
+ buildFrom<TIn extends RowData>(
64
+ data: ReadonlyArray<TIn>,
65
+ config: PivotConfig<TIn>,
66
+ ): PivotResult<TFeatures>
67
+ }
68
+
69
+ export type EnterpriseGridApi<
70
+ TFeatures extends TableFeatures,
71
+ TData extends RowData,
72
+ > = SvGridApi<TFeatures, TData> & {
73
+ /** Export the current visible rows to the chosen format. Returns the built
74
+ * file ({@link ExportResult}) for the dependency-free paths (undefined for
75
+ * the vendored-writer xlsx paths, which download directly). */
76
+ exportData(opts: ExportOptions<TData>): Promise<ExportResult | undefined>
77
+ /** Copy the grid (view / selection / all) to the clipboard in a native text
78
+ * format (default `tsv`, pastes into Excel / Sheets as columns). */
79
+ copyExport(opts?: ClipboardExportOptions<TData>): Promise<void>
80
+ /** Open a printable view of the current visible rows in a new window. */
81
+ print(opts?: PrintOptions<TData>): Promise<void>
82
+ /** Read an Excel / CSV / TSV / JSON file (or inline text) into typed
83
+ * rows. Caller decides whether to commit into the grid or preview
84
+ * the parsed result first via the returned `ImportResult`. */
85
+ importData(opts: ImportOptions<TData>): Promise<ImportResult<TData>>
86
+ /** AI helpers (Pro). All calls route through a consumer-registered
87
+ * AIProvider via setAIProvider(); no model client is bundled. */
88
+ ai: EnterpriseAIApi<TData>
89
+ /** Pivot table builder (Pro). Pure - returns `{ rows, columns }` you
90
+ * hand to a separate `<SvGrid>` instance. */
91
+ pivot: EnterprisePivotApi<TFeatures, TData>
92
+ }
93
+
94
+ /**
95
+ * Augment a SvGridApi instance with Pro methods (`exportData`, `print`,
96
+ * `ai.*`). Mutates and returns the same object so existing references
97
+ * keep working.
98
+ *
99
+ * If no license key has been set, the Pro methods still function but the
100
+ * grid shows a small "unlicensed" watermark linking to jqwidgets.com and
101
+ * the console emits a one-time nudge. Revoked or malformed keys throw on
102
+ * first call.
103
+ */
104
+ export function installEnterprise<
105
+ TFeatures extends TableFeatures,
106
+ TData extends RowData,
107
+ >(api: SvGridApi<TFeatures, TData>): EnterpriseGridApi<TFeatures, TData> {
108
+ const pro = api as EnterpriseGridApi<TFeatures, TData>
109
+ pro.exportData = (opts) => exportGrid(pro, opts)
110
+ pro.copyExport = (opts) => copyExportToClipboard(pro, opts)
111
+ pro.print = (opts) => printGrid(pro, opts)
112
+ pro.importData = (opts) => importData(pro, opts)
113
+ pro.ai = {
114
+ filter: (query, opts) => aiFilter(pro, query, opts),
115
+ smartFill: (opts) => aiSmartFill(pro, opts),
116
+ summarize: (opts) => aiSummarize(pro, opts),
117
+ classify: (opts) => aiClassify(pro, opts),
118
+ export: (query, opts) => aiExport(pro, query, opts),
119
+ findAnomalies: (opts) => aiFindAnomalies(pro, opts),
120
+ }
121
+ pro.pivot = {
122
+ build: (config) =>
123
+ createPivotModel<TFeatures, TData>(pro.getData(), config),
124
+ buildFrom: <TIn extends RowData>(data: ReadonlyArray<TIn>, config: PivotConfig<TIn>) =>
125
+ // PivotConfig is variance-strict in TIn; the runtime call only needs
126
+ // the row shape to match config.rows / config.cols field names, which
127
+ // the caller-side generic enforces.
128
+ createPivotModel<TFeatures, TIn>(data, config),
129
+ }
130
+ // Surface the soft-gate state at install time so the watermark appears
131
+ // alongside the grid, not just after the user clicks Export.
132
+ if (!isLicenseKeySet()) emitUnlicensedNudge()
133
+ return pro
134
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { checkLicenseKey } from './license-core'
3
+
4
+ describe('checkLicenseKey', () => {
5
+ it('unset for null / empty', () => {
6
+ expect(checkLicenseKey(null)).toEqual({ status: 'unset', valid: false })
7
+ expect(checkLicenseKey(undefined)).toEqual({ status: 'unset', valid: false })
8
+ expect(checkLicenseKey('')).toEqual({ status: 'unset', valid: false })
9
+ })
10
+
11
+ it('invalid for a wrong prefix', () => {
12
+ expect(checkLicenseKey('nope-123')).toEqual({ status: 'invalid', valid: false })
13
+ })
14
+
15
+ it('dev / eval keys are valid but flagged', () => {
16
+ expect(checkLicenseKey('SVENTERPRISE-DEV-abc')).toEqual({ status: 'dev', valid: true })
17
+ expect(checkLicenseKey('SVENTERPRISE-EVAL-acme-2026')).toEqual({ status: 'eval', valid: true })
18
+ })
19
+
20
+ it('any other SVENTERPRISE- key is licensed', () => {
21
+ expect(checkLicenseKey('SVENTERPRISE-ACME-2026-9XYZ')).toEqual({ status: 'licensed', valid: true })
22
+ })
23
+ })
@@ -0,0 +1,35 @@
1
+ // Pure license classification - no DOM, no Svelte, no module state. Shared by
2
+ // the browser gate (license.ts, via setLicenseKey) AND the Node/MCP generator
3
+ // (which reads the key from the SVGRID_LICENSE_KEY env var). One definition of
4
+ // "what a valid key is," so the two contexts can never drift.
5
+ //
6
+ // This is deliberately NOT crypto (see license.ts). It classifies a key string;
7
+ // callers decide what to do with the result. The Studio is soft-gate only:
8
+ // unlicensed use still works, it just nudges.
9
+ import { REVOKED_KEYS } from './revoked.js'
10
+
11
+ export const VALID_PREFIX = 'SVENTERPRISE-'
12
+
13
+ export type LicenseStatus =
14
+ | 'unset' // no key provided
15
+ | 'invalid' // present but wrong prefix (usually a typo)
16
+ | 'revoked' // valid prefix but on the revoked list
17
+ | 'dev' // SVENTERPRISE-DEV... - works, not for production
18
+ | 'eval' // SVENTERPRISE-EVAL... - works, not for production
19
+ | 'licensed' // any other SVENTERPRISE-... - paid production
20
+
21
+ export type LicenseInfo = {
22
+ status: LicenseStatus
23
+ /** True when the key permits use (dev / eval / licensed). */
24
+ valid: boolean
25
+ }
26
+
27
+ /** Classify a license key string. Pure and side-effect-free. */
28
+ export function checkLicenseKey(key: string | null | undefined): LicenseInfo {
29
+ if (key == null || key === '') return { status: 'unset', valid: false }
30
+ if (!key.startsWith(VALID_PREFIX)) return { status: 'invalid', valid: false }
31
+ if (REVOKED_KEYS.has(key)) return { status: 'revoked', valid: false }
32
+ if (key.startsWith('SVENTERPRISE-DEV')) return { status: 'dev', valid: true }
33
+ if (key.startsWith('SVENTERPRISE-EVAL')) return { status: 'eval', valid: true }
34
+ return { status: 'licensed', valid: true }
35
+ }