@dbx-tools/shared-generator 0.0.0-stage → 0.9.136

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.
package/src/kpi.ts ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Browser-safe KPI research contracts.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { z } from "zod";
8
+
9
+ const nonBlankString = z.string().trim().min(1);
10
+ const identifier = z.string().regex(/^[a-z][a-z0-9_]*$/);
11
+
12
+ /** One evidence-backed KPI used to shape generated data and presentation. */
13
+ export const ResearchedKpiSchema = z
14
+ .object({
15
+ name: identifier.describe("Stable snake_case KPI identifier."),
16
+ label: nonBlankString.describe("Human-readable KPI label."),
17
+ definition: nonBlankString.describe("Business definition supported by cited research."),
18
+ unit: z
19
+ .enum(["number", "currency", "percent", "duration"])
20
+ .describe("Display unit and formatting family."),
21
+ targetDirection: z
22
+ .enum(["higher", "lower", "neutral"])
23
+ .describe("Whether higher or lower values represent improvement."),
24
+ sourceUrls: z
25
+ .array(z.string().url())
26
+ .describe("Research sources supporting the KPI definition."),
27
+ })
28
+ .strict()
29
+ .describe("Evidence-backed KPI selected for generated demo data.");
30
+
31
+ /** Evidence-backed KPI. */
32
+ export type ResearchedKpi = z.infer<typeof ResearchedKpiSchema>;
33
+
34
+ /** KPI research request independent of any mutation workflow. */
35
+ export const KpiResearchRequestSchema = z
36
+ .object({
37
+ company: nonBlankString.max(200).describe("Company or brand being modeled."),
38
+ purpose: nonBlankString.max(200).describe("Purpose of the generated demonstration."),
39
+ queries: z
40
+ .array(nonBlankString.max(500))
41
+ .min(1)
42
+ .max(10)
43
+ .describe("Natural-language questions the generated data should answer."),
44
+ })
45
+ .strict()
46
+ .describe("Request for web-researched KPIs that shape generated demo data.");
47
+
48
+ /** KPI research request. */
49
+ export type KpiResearchRequest = z.infer<typeof KpiResearchRequestSchema>;
50
+
51
+ /** KPI research result and its source provenance. */
52
+ export const KpiResearchResultSchema = z
53
+ .object({
54
+ kpis: z.array(ResearchedKpiSchema).min(1).max(8).describe("Selected KPI definitions."),
55
+ sources: z
56
+ .array(
57
+ z
58
+ .object({
59
+ url: z.string().url().describe("Research source URL."),
60
+ title: nonBlankString.optional().describe("Source title, when available."),
61
+ fetched: z.boolean().describe("Whether page content was read."),
62
+ })
63
+ .strict(),
64
+ )
65
+ .describe("Deduplicated KPI research sources."),
66
+ })
67
+ .strict()
68
+ .describe("Evidence-backed KPI research output.");
69
+
70
+ /** KPI research result. */
71
+ export type KpiResearchResult = z.infer<typeof KpiResearchResultSchema>;
@@ -0,0 +1,303 @@
1
+ /**
2
+ * Browser-safe contracts for generated Databricks demo assets.
3
+ *
4
+ * @module
5
+ */
6
+
7
+ import { z } from "zod";
8
+ import { BrandPackageSchema } from "./brand.ts";
9
+ import { KpiResearchResultSchema, ResearchedKpiSchema } from "./kpi.ts";
10
+
11
+ const nonBlankString = z.string().trim().min(1);
12
+ const identifier = z.string().regex(/^[a-z][a-z0-9_]*$/, "Expected a lowercase SQL identifier.");
13
+
14
+ /** Presentation created after generated data is validated. */
15
+ export const PresentationModeSchema = z.enum(["dashboard", "genie"]);
16
+
17
+ /** Presentation mode. */
18
+ export type PresentationMode = z.infer<typeof PresentationModeSchema>;
19
+
20
+ /** Complete input for the governed generator workflow. */
21
+ export const GeneratorRequestSchema = z
22
+ .object({
23
+ company: nonBlankString.max(200).describe("Company or brand represented by the demo."),
24
+ purpose: nonBlankString.max(200).describe("Short purpose used in schema and asset names."),
25
+ queries: z
26
+ .array(nonBlankString.max(500))
27
+ .min(1)
28
+ .max(10)
29
+ .describe("Business questions that shape KPI research and generated data."),
30
+ website: z
31
+ .string()
32
+ .url()
33
+ .optional()
34
+ .describe("Known company website for brand disambiguation."),
35
+ presentation: PresentationModeSchema.default("dashboard").describe(
36
+ "Dashboard with automatic companion Genie, or standalone Genie without a dashboard.",
37
+ ),
38
+ rowCount: z
39
+ .number()
40
+ .int()
41
+ .min(1_000)
42
+ .max(100_000)
43
+ .default(50_000)
44
+ .describe("Rows generated in the primary fact table."),
45
+ })
46
+ .strict()
47
+ .describe("Request for a per-user Databricks demo data environment.");
48
+
49
+ /** Generator workflow input after defaults. */
50
+ export type GeneratorRequest = z.output<typeof GeneratorRequestSchema>;
51
+
52
+ /** Supported deterministic column generators. */
53
+ export const GeneratedColumnSchema = z.discriminatedUnion("generator", [
54
+ z
55
+ .object({
56
+ name: identifier.describe("Column name."),
57
+ generator: z.literal("id"),
58
+ description: nonBlankString.describe("Column business meaning."),
59
+ })
60
+ .strict(),
61
+ z
62
+ .object({
63
+ name: identifier.describe("Column name."),
64
+ generator: z.literal("date"),
65
+ description: nonBlankString.describe("Column business meaning."),
66
+ days: z.number().int().min(30).max(1_095).describe("Generated history window in days."),
67
+ })
68
+ .strict(),
69
+ z
70
+ .object({
71
+ name: identifier.describe("Column name."),
72
+ generator: z.literal("category"),
73
+ description: nonBlankString.describe("Column business meaning."),
74
+ values: z.array(nonBlankString.max(80)).min(2).max(12).describe("Skewed category values."),
75
+ })
76
+ .strict(),
77
+ z
78
+ .object({
79
+ name: identifier.describe("Column name."),
80
+ generator: z.literal("number"),
81
+ description: nonBlankString.describe("Column business meaning."),
82
+ minimum: z.number().describe("Minimum generated value."),
83
+ maximum: z.number().describe("Maximum generated value."),
84
+ decimals: z.number().int().min(0).max(4).default(2).describe("Decimal precision."),
85
+ })
86
+ .strict(),
87
+ z
88
+ .object({
89
+ name: identifier.describe("Column name."),
90
+ generator: z.literal("boolean"),
91
+ description: nonBlankString.describe("Column business meaning."),
92
+ trueProbability: z.number().min(0.01).max(0.99).describe("Share of true rows."),
93
+ })
94
+ .strict(),
95
+ ]);
96
+
97
+ /** Deterministic generated column specification. */
98
+ export type GeneratedColumn = z.infer<typeof GeneratedColumnSchema>;
99
+
100
+ /** KPI binding compiled into validation SQL and dashboard measures. */
101
+ export const GeneratedMetricSchema = ResearchedKpiSchema.extend({
102
+ aggregation: z
103
+ .enum(["count", "sum", "average"])
104
+ .describe("Safe aggregate compiled by the generator."),
105
+ column: identifier.optional().describe("Numeric source column; omitted for count."),
106
+ }).strict();
107
+
108
+ /** KPI binding. */
109
+ export type GeneratedMetric = z.infer<typeof GeneratedMetricSchema>;
110
+
111
+ /** Structured plan compiled into SQL and presentation assets. */
112
+ export const GeneratorPlanSchema = z
113
+ .object({
114
+ table: identifier.describe("Primary generated Delta table name."),
115
+ rowCount: z.number().int().min(1_000).max(100_000).describe("Rows to generate."),
116
+ columns: z
117
+ .array(GeneratedColumnSchema)
118
+ .min(4)
119
+ .max(16)
120
+ .describe("Typed deterministic column generators."),
121
+ metrics: z.array(GeneratedMetricSchema).min(1).max(6).describe("Dashboard and Genie KPIs."),
122
+ story: nonBlankString.describe("Business anomaly and impact represented in the data."),
123
+ sampleQuestions: z
124
+ .array(nonBlankString.max(300))
125
+ .min(3)
126
+ .max(8)
127
+ .describe("Questions supported by the generated table."),
128
+ })
129
+ .strict()
130
+ .superRefine((value, ctx) => {
131
+ const names = new Set<string>();
132
+ for (const [index, column] of value.columns.entries()) {
133
+ if (names.has(column.name)) {
134
+ ctx.addIssue({
135
+ code: "custom",
136
+ path: ["columns", index, "name"],
137
+ message: "Generated column names must be unique.",
138
+ });
139
+ }
140
+ names.add(column.name);
141
+ }
142
+ if (!value.columns.some(({ generator }) => generator === "id")) {
143
+ ctx.addIssue({ code: "custom", path: ["columns"], message: "An id column is required." });
144
+ }
145
+ if (!value.columns.some(({ generator }) => generator === "date")) {
146
+ ctx.addIssue({ code: "custom", path: ["columns"], message: "A date column is required." });
147
+ }
148
+ if (!value.columns.some(({ generator }) => generator === "category")) {
149
+ ctx.addIssue({
150
+ code: "custom",
151
+ path: ["columns"],
152
+ message: "A category column is required.",
153
+ });
154
+ }
155
+ const numeric = new Set(
156
+ value.columns.filter(({ generator }) => generator === "number").map(({ name }) => name),
157
+ );
158
+ for (const [index, metric] of value.metrics.entries()) {
159
+ if (metric.aggregation !== "count" && (!metric.column || !numeric.has(metric.column))) {
160
+ ctx.addIssue({
161
+ code: "custom",
162
+ path: ["metrics", index, "column"],
163
+ message: "Sum and average metrics require a generated numeric column.",
164
+ });
165
+ }
166
+ }
167
+ })
168
+ .describe("Validated plan for deterministic synthetic data and analytics assets.");
169
+
170
+ /** Structured generator plan. */
171
+ export type GeneratorPlan = z.infer<typeof GeneratorPlanSchema>;
172
+
173
+ /** Input for the standalone structured data-planning tool. */
174
+ export const PlanGeneratorDataRequestSchema = z
175
+ .object({
176
+ request: GeneratorRequestSchema,
177
+ brand: BrandPackageSchema,
178
+ kpiResearch: KpiResearchResultSchema,
179
+ })
180
+ .strict()
181
+ .describe("Inputs needed to build a typed generator plan.");
182
+
183
+ /** Input for the standalone structured data-planning tool. */
184
+ export type PlanGeneratorDataRequest = z.infer<typeof PlanGeneratorDataRequestSchema>;
185
+
186
+ /** Location and trusted identity for one generated schema. */
187
+ export const GeneratedSchemaSchema = z
188
+ .object({
189
+ catalog: identifier.describe("Configured Unity Catalog."),
190
+ schema: identifier.describe("Per-user generated schema."),
191
+ fullName: nonBlankString.describe("Quoted-safe catalog.schema display name."),
192
+ principal: nonBlankString.describe("Trusted OBO Databricks user name."),
193
+ })
194
+ .strict()
195
+ .describe("Provisioned per-user Unity Catalog schema.");
196
+
197
+ /** Provisioned generated schema. */
198
+ export type GeneratedSchema = z.infer<typeof GeneratedSchemaSchema>;
199
+
200
+ /** Input for per-user schema provisioning. */
201
+ export const ProvisionGeneratorSchemaRequestSchema = z
202
+ .object({
203
+ request: GeneratorRequestSchema.pick({ company: true, purpose: true }),
204
+ })
205
+ .strict()
206
+ .describe("Request to provision the active user's generated schema.");
207
+
208
+ /** Input for per-user schema provisioning. */
209
+ export type ProvisionGeneratorSchemaRequest = z.infer<typeof ProvisionGeneratorSchemaRequestSchema>;
210
+
211
+ /** Input for generated data materialization. */
212
+ export const MaterializeGeneratorDataRequestSchema = z
213
+ .object({
214
+ location: GeneratedSchemaSchema,
215
+ plan: GeneratorPlanSchema,
216
+ })
217
+ .strict()
218
+ .describe("Request to materialize and validate generated Delta data.");
219
+
220
+ /** Input for generated data materialization. */
221
+ export type MaterializeGeneratorDataRequest = z.infer<typeof MaterializeGeneratorDataRequestSchema>;
222
+
223
+ /** Created tables and KPI validation statements. */
224
+ export const MaterializedGeneratorDataSchema = z
225
+ .object({
226
+ tables: z.array(nonBlankString).min(1).describe("Created fully qualified Delta tables."),
227
+ validationStatements: z
228
+ .record(identifier, nonBlankString)
229
+ .describe("Statement IDs keyed by validated KPI name."),
230
+ })
231
+ .strict()
232
+ .describe("Materialized and validated generated data.");
233
+
234
+ /** Created tables and KPI validation statements. */
235
+ export type MaterializedGeneratorData = z.infer<typeof MaterializedGeneratorDataSchema>;
236
+
237
+ /** Input shared by dashboard and standalone Genie creation tools. */
238
+ export const CreateGeneratorPresentationRequestSchema = z
239
+ .object({
240
+ request: GeneratorRequestSchema.pick({
241
+ company: true,
242
+ purpose: true,
243
+ }),
244
+ location: GeneratedSchemaSchema,
245
+ plan: GeneratorPlanSchema,
246
+ brand: BrandPackageSchema,
247
+ })
248
+ .strict()
249
+ .describe("Request to create a presentation asset over generated data.");
250
+
251
+ /** Input shared by dashboard and standalone Genie creation tools. */
252
+ export type CreateGeneratorPresentationRequest = z.infer<
253
+ typeof CreateGeneratorPresentationRequestSchema
254
+ >;
255
+
256
+ /** Dashboard output with its automatic companion Genie Agent. */
257
+ export const GeneratedDashboardSchema = z
258
+ .object({
259
+ dashboardId: nonBlankString.describe("Created Lakeview dashboard ID."),
260
+ path: nonBlankString.optional().describe("Workspace path, when returned."),
261
+ companionGenie: z.literal("AUTO").describe("Dashboard-published companion Genie mode."),
262
+ })
263
+ .strict();
264
+
265
+ /** Published dashboard with automatic companion Genie. */
266
+ export type GeneratedDashboard = z.infer<typeof GeneratedDashboardSchema>;
267
+
268
+ /** Standalone Genie output used only when no dashboard is requested. */
269
+ export const GeneratedGenieSpaceSchema = z
270
+ .object({
271
+ spaceId: nonBlankString.describe("Created standalone Genie space ID."),
272
+ title: nonBlankString.describe("Genie space title."),
273
+ })
274
+ .strict();
275
+
276
+ /** Created standalone Genie space. */
277
+ export type GeneratedGenieSpace = z.infer<typeof GeneratedGenieSpaceSchema>;
278
+
279
+ /** Terminal workflow output. */
280
+ export const GeneratedAssetsSchema = z
281
+ .object({
282
+ request: GeneratorRequestSchema,
283
+ schema: GeneratedSchemaSchema,
284
+ tables: z.array(nonBlankString).min(1).describe("Created fully qualified Delta tables."),
285
+ brand: BrandPackageSchema,
286
+ kpiResearch: KpiResearchResultSchema,
287
+ plan: GeneratorPlanSchema,
288
+ dashboard: GeneratedDashboardSchema.optional(),
289
+ genie: GeneratedGenieSpaceSchema.optional(),
290
+ })
291
+ .strict()
292
+ .superRefine((value, ctx) => {
293
+ if ((value.dashboard === undefined) === (value.genie === undefined)) {
294
+ ctx.addIssue({
295
+ code: "custom",
296
+ message: "Exactly one dashboard or standalone Genie space is required.",
297
+ });
298
+ }
299
+ })
300
+ .describe("Generated Databricks data and presentation assets.");
301
+
302
+ /** Terminal generator workflow output. */
303
+ export type GeneratedAssets = z.infer<typeof GeneratedAssetsSchema>;