@cratis/scene.engine 4.25.0 → 4.26.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 (108) hide show
  1. package/dist/cjs/index.js +41 -0
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/sampleData/SampleRandom.js +77 -0
  4. package/dist/cjs/sampleData/SampleRandom.js.map +1 -0
  5. package/dist/cjs/sampleData/describeSampleDataCatalog.js +61 -0
  6. package/dist/cjs/sampleData/describeSampleDataCatalog.js.map +1 -0
  7. package/dist/cjs/sampleData/findSampleDataSet.js +18 -0
  8. package/dist/cjs/sampleData/findSampleDataSet.js.map +1 -0
  9. package/dist/cjs/sampleData/findSampleRowLiterals.js +73 -0
  10. package/dist/cjs/sampleData/findSampleRowLiterals.js.map +1 -0
  11. package/dist/cjs/sampleData/generateSample.js +188 -0
  12. package/dist/cjs/sampleData/generateSample.js.map +1 -0
  13. package/dist/cjs/sampleData/inferSampleFieldKind.js +176 -0
  14. package/dist/cjs/sampleData/inferSampleFieldKind.js.map +1 -0
  15. package/dist/cjs/sampleData/resolveSampleData.js +107 -0
  16. package/dist/cjs/sampleData/resolveSampleData.js.map +1 -0
  17. package/dist/cjs/sampleData/sampleDataRules.js +26 -0
  18. package/dist/cjs/sampleData/sampleDataRules.js.map +1 -0
  19. package/dist/cjs/sampleData/sampleLocales.js +359 -0
  20. package/dist/cjs/sampleData/sampleLocales.js.map +1 -0
  21. package/dist/cjs/sampleData/validateSampleDataPack.js +44 -0
  22. package/dist/cjs/sampleData/validateSampleDataPack.js.map +1 -0
  23. package/dist/cjs/sampleData/validateSampleDataPackages.js +71 -0
  24. package/dist/cjs/sampleData/validateSampleDataPackages.js.map +1 -0
  25. package/dist/cjs/sampleData/validateSampleDataSelection.js +52 -0
  26. package/dist/cjs/sampleData/validateSampleDataSelection.js.map +1 -0
  27. package/dist/esm/index.d.ts +1 -0
  28. package/dist/esm/index.d.ts.map +1 -1
  29. package/dist/esm/index.js +12 -0
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/sampleData/SampleDataPackSource.d.ts +6 -0
  32. package/dist/esm/sampleData/SampleDataPackSource.d.ts.map +1 -0
  33. package/dist/esm/sampleData/SampleDataPackSource.js +2 -0
  34. package/dist/esm/sampleData/SampleDataPackSource.js.map +1 -0
  35. package/dist/esm/sampleData/SampleDataResolution.d.ts +29 -0
  36. package/dist/esm/sampleData/SampleDataResolution.d.ts.map +1 -0
  37. package/dist/esm/sampleData/SampleDataResolution.js +2 -0
  38. package/dist/esm/sampleData/SampleDataResolution.js.map +1 -0
  39. package/dist/esm/sampleData/SampleRandom.d.ts +14 -0
  40. package/dist/esm/sampleData/SampleRandom.d.ts.map +1 -0
  41. package/dist/esm/sampleData/SampleRandom.js +72 -0
  42. package/dist/esm/sampleData/SampleRandom.js.map +1 -0
  43. package/dist/esm/sampleData/describeSampleDataCatalog.d.ts +24 -0
  44. package/dist/esm/sampleData/describeSampleDataCatalog.d.ts.map +1 -0
  45. package/dist/esm/sampleData/describeSampleDataCatalog.js +57 -0
  46. package/dist/esm/sampleData/describeSampleDataCatalog.js.map +1 -0
  47. package/dist/esm/sampleData/findSampleDataSet.d.ts +3 -0
  48. package/dist/esm/sampleData/findSampleDataSet.d.ts.map +1 -0
  49. package/dist/esm/sampleData/findSampleDataSet.js +16 -0
  50. package/dist/esm/sampleData/findSampleDataSet.js.map +1 -0
  51. package/dist/esm/sampleData/findSampleRowLiterals.d.ts +11 -0
  52. package/dist/esm/sampleData/findSampleRowLiterals.d.ts.map +1 -0
  53. package/dist/esm/sampleData/findSampleRowLiterals.js +69 -0
  54. package/dist/esm/sampleData/findSampleRowLiterals.js.map +1 -0
  55. package/dist/esm/sampleData/generateSample.d.ts +6 -0
  56. package/dist/esm/sampleData/generateSample.d.ts.map +1 -0
  57. package/dist/esm/sampleData/generateSample.js +183 -0
  58. package/dist/esm/sampleData/generateSample.js.map +1 -0
  59. package/dist/esm/sampleData/index.d.ts +15 -0
  60. package/dist/esm/sampleData/index.d.ts.map +1 -0
  61. package/dist/esm/sampleData/index.js +15 -0
  62. package/dist/esm/sampleData/index.js.map +1 -0
  63. package/dist/esm/sampleData/inferSampleFieldKind.d.ts +3 -0
  64. package/dist/esm/sampleData/inferSampleFieldKind.d.ts.map +1 -0
  65. package/dist/esm/sampleData/inferSampleFieldKind.js +174 -0
  66. package/dist/esm/sampleData/inferSampleFieldKind.js.map +1 -0
  67. package/dist/esm/sampleData/resolveSampleData.d.ts +3 -0
  68. package/dist/esm/sampleData/resolveSampleData.d.ts.map +1 -0
  69. package/dist/esm/sampleData/resolveSampleData.js +105 -0
  70. package/dist/esm/sampleData/resolveSampleData.js.map +1 -0
  71. package/dist/esm/sampleData/sampleDataRules.d.ts +7 -0
  72. package/dist/esm/sampleData/sampleDataRules.d.ts.map +1 -0
  73. package/dist/esm/sampleData/sampleDataRules.js +19 -0
  74. package/dist/esm/sampleData/sampleDataRules.js.map +1 -0
  75. package/dist/esm/sampleData/sampleLocales.d.ts +13 -0
  76. package/dist/esm/sampleData/sampleLocales.d.ts.map +1 -0
  77. package/dist/esm/sampleData/sampleLocales.js +355 -0
  78. package/dist/esm/sampleData/sampleLocales.js.map +1 -0
  79. package/dist/esm/sampleData/validateSampleDataPack.d.ts +3 -0
  80. package/dist/esm/sampleData/validateSampleDataPack.d.ts.map +1 -0
  81. package/dist/esm/sampleData/validateSampleDataPack.js +42 -0
  82. package/dist/esm/sampleData/validateSampleDataPack.js.map +1 -0
  83. package/dist/esm/sampleData/validateSampleDataPackages.d.ts +3 -0
  84. package/dist/esm/sampleData/validateSampleDataPackages.d.ts.map +1 -0
  85. package/dist/esm/sampleData/validateSampleDataPackages.js +69 -0
  86. package/dist/esm/sampleData/validateSampleDataPackages.js.map +1 -0
  87. package/dist/esm/sampleData/validateSampleDataSelection.d.ts +3 -0
  88. package/dist/esm/sampleData/validateSampleDataSelection.d.ts.map +1 -0
  89. package/dist/esm/sampleData/validateSampleDataSelection.js +50 -0
  90. package/dist/esm/sampleData/validateSampleDataSelection.js.map +1 -0
  91. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  92. package/index.ts +1 -0
  93. package/package.json +3 -3
  94. package/sampleData/SampleDataPackSource.ts +13 -0
  95. package/sampleData/SampleDataResolution.ts +93 -0
  96. package/sampleData/SampleRandom.ts +85 -0
  97. package/sampleData/describeSampleDataCatalog.ts +108 -0
  98. package/sampleData/findSampleDataSet.ts +18 -0
  99. package/sampleData/findSampleRowLiterals.ts +86 -0
  100. package/sampleData/generateSample.ts +156 -0
  101. package/sampleData/index.ts +17 -0
  102. package/sampleData/inferSampleFieldKind.ts +64 -0
  103. package/sampleData/resolveSampleData.ts +96 -0
  104. package/sampleData/sampleDataRules.ts +30 -0
  105. package/sampleData/sampleLocales.ts +91 -0
  106. package/sampleData/validateSampleDataPack.ts +48 -0
  107. package/sampleData/validateSampleDataPackages.ts +79 -0
  108. package/sampleData/validateSampleDataSelection.ts +55 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SampleDataPackSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SampleDataPackSource.js","sourceRoot":"","sources":["../../../sampleData/SampleDataPackSource.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import { SampleDataPack, SampleShape, UiProfile } from '@cratis/scene.model';
2
+ export type SampleDataResolutionSource = 'binding' | 'activePack' | 'blueprintDefault' | 'generated' | 'disabled' | 'none';
3
+ export interface SampleDataRequest {
4
+ target?: string;
5
+ shape?: SampleShape;
6
+ }
7
+ export interface SampleDataContext {
8
+ packs: SampleDataPack[];
9
+ profile?: Pick<UiProfile, 'sampleData'>;
10
+ sessionActivePack?: string;
11
+ blueprintDefaultPack?: string;
12
+ locale?: string;
13
+ seed?: number;
14
+ rowCount?: number;
15
+ isDesignOrPreview?: boolean;
16
+ }
17
+ export interface SampleDataDiagnostic {
18
+ code: string;
19
+ message: string;
20
+ }
21
+ export interface SampleDataResolution {
22
+ source: SampleDataResolutionSource;
23
+ pack?: string;
24
+ locale: string;
25
+ shape?: string;
26
+ rows: Record<string, unknown>[];
27
+ diagnostics: SampleDataDiagnostic[];
28
+ }
29
+ //# sourceMappingURL=SampleDataResolution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SampleDataResolution.d.ts","sourceRoot":"","sources":["../../../sampleData/SampleDataResolution.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAG7E,MAAM,MAAM,0BAA0B,GAEhC,SAAS,GAET,YAAY,GAEZ,kBAAkB,GAElB,WAAW,GAEX,UAAU,GAEV,MAAM,CAAC;AAGb,MAAM,WAAW,iBAAiB;IAE9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,KAAK,CAAC,EAAE,WAAW,CAAC;CACvB;AAGD,MAAM,WAAW,iBAAiB;IAE9B,KAAK,EAAE,cAAc,EAAE,CAAC;IAOxB,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAQxC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAMlB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAGD,MAAM,WAAW,oBAAoB;IAEjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,oBAAoB;IAEjC,MAAM,EAAE,0BAA0B,CAAC;IAGnC,IAAI,CAAC,EAAE,MAAM,CAAC;IAGd,MAAM,EAAE,MAAM,CAAC;IAGf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAEhC,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACvC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=SampleDataResolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SampleDataResolution.js","sourceRoot":"","sources":["../../../sampleData/SampleDataResolution.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ export declare function hash32(value: number): number;
2
+ export declare function fnv1a32(text: string): number;
3
+ export declare function rowSeed(seed: number, shapeName: string, rowIndex: number): number;
4
+ export declare class SampleRandom {
5
+ private s0;
6
+ private s1;
7
+ private s2;
8
+ private s3;
9
+ constructor(seed: number);
10
+ next(): number;
11
+ nextInt(bound: number): number;
12
+ pick<T>(items: readonly T[]): T;
13
+ }
14
+ //# sourceMappingURL=SampleRandom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SampleRandom.d.ts","sourceRoot":"","sources":["../../../sampleData/SampleRandom.ts"],"names":[],"mappings":"AAiBA,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK5C;AAGD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C;AAGD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEjF;AAGD,qBAAa,YAAY;IACrB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,EAAE,CAAS;IAEnB,YAAY,IAAI,EAAE,MAAM,EAWvB;IAGD,IAAI,IAAI,MAAM,CAUb;IAGD,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7B;IAGD,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAE9B;CACJ"}
@@ -0,0 +1,72 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * The pseudo-random generator behind generated sample data. The C# engine implements the identical
5
+ * algorithm, and both are asserted against golden rows in `sample-data-resolution-fixtures.json`.
6
+ *
7
+ * Algorithm (all arithmetic on unsigned 32-bit integers, wrapping):
8
+ *
9
+ * - `hash32(x)`: `x = (x ^ (x >>> 16)) * 0x85EBCA6B; x = (x ^ (x >>> 13)) * 0xC2B2AE35; return x ^ (x >>> 16)`.
10
+ * - `splitmix32(state)`: `state += 0x9E3779B9`, then `hash32(state)`.
11
+ * - `fnv1a32(text)`: FNV-1a over the UTF-8 bytes of the text (offset basis `0x811C9DC5`, prime `0x01000193`).
12
+ * - The generator is xoshiro128** seeded with four consecutive `splitmix32` outputs of the seed.
13
+ * - `nextInt(bound)` is `next() % bound`.
14
+ * - Row `i` of a shape named `S` generated with seed `n` uses its own generator seeded with
15
+ * `hash32((n ^ fnv1a32(S)) + (i + 1) * 0x9E3779B9)`, so a row never depends on how many rows are asked for.
16
+ */ function hash32(value) {
17
+ let x = value >>> 0;
18
+ x = Math.imul(x ^ x >>> 16, 0x85EBCA6B) >>> 0;
19
+ x = Math.imul(x ^ x >>> 13, 0xC2B2AE35) >>> 0;
20
+ return (x ^ x >>> 16) >>> 0;
21
+ }
22
+ /** FNV-1a (32-bit) over the UTF-8 bytes of a string. */ function fnv1a32(text) {
23
+ let hash = 0x811C9DC5;
24
+ for (const byte of new TextEncoder().encode(text)){
25
+ hash = Math.imul(hash ^ byte, 0x01000193) >>> 0;
26
+ }
27
+ return hash;
28
+ }
29
+ /** The seed of the generator for one row of one shape. */ function rowSeed(seed, shapeName, rowIndex) {
30
+ return hash32(((seed ^ fnv1a32(shapeName)) >>> 0) + Math.imul(rowIndex + 1, 0x9E3779B9) >>> 0);
31
+ }
32
+ /** xoshiro128** with splitmix32 seeding. */ class SampleRandom {
33
+ s0;
34
+ s1;
35
+ s2;
36
+ s3;
37
+ constructor(seed){
38
+ let state = seed >>> 0;
39
+ const step = ()=>{
40
+ state = state + 0x9E3779B9 >>> 0;
41
+ return hash32(state);
42
+ };
43
+ this.s0 = step();
44
+ this.s1 = step();
45
+ this.s2 = step();
46
+ this.s3 = step();
47
+ if ((this.s0 | this.s1 | this.s2 | this.s3) === 0) this.s0 = 1;
48
+ }
49
+ /** The next unsigned 32-bit value. */ next() {
50
+ const result = Math.imul(rotateLeft(Math.imul(this.s1, 5) >>> 0, 7), 9) >>> 0;
51
+ const t = this.s1 << 9 >>> 0;
52
+ this.s2 = (this.s2 ^ this.s0) >>> 0;
53
+ this.s3 = (this.s3 ^ this.s1) >>> 0;
54
+ this.s1 = (this.s1 ^ this.s2) >>> 0;
55
+ this.s0 = (this.s0 ^ this.s3) >>> 0;
56
+ this.s2 = (this.s2 ^ t) >>> 0;
57
+ this.s3 = rotateLeft(this.s3, 11);
58
+ return result;
59
+ }
60
+ /** A value in `[0, bound)`; zero when the bound is zero. */ nextInt(bound) {
61
+ return bound <= 0 ? 0 : this.next() % bound;
62
+ }
63
+ /** One element of a non-empty list. */ pick(items) {
64
+ return items[this.nextInt(items.length)];
65
+ }
66
+ }
67
+ function rotateLeft(value, bits) {
68
+ return (value << bits | value >>> 32 - bits) >>> 0;
69
+ }
70
+
71
+ export { SampleRandom, fnv1a32, hash32, rowSeed };
72
+ //# sourceMappingURL=SampleRandom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SampleRandom.js","sources":["../../../sampleData/SampleRandom.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\n/**\n * The pseudo-random generator behind generated sample data. The C# engine implements the identical\n * algorithm, and both are asserted against golden rows in `sample-data-resolution-fixtures.json`.\n *\n * Algorithm (all arithmetic on unsigned 32-bit integers, wrapping):\n *\n * - `hash32(x)`: `x = (x ^ (x >>> 16)) * 0x85EBCA6B; x = (x ^ (x >>> 13)) * 0xC2B2AE35; return x ^ (x >>> 16)`.\n * - `splitmix32(state)`: `state += 0x9E3779B9`, then `hash32(state)`.\n * - `fnv1a32(text)`: FNV-1a over the UTF-8 bytes of the text (offset basis `0x811C9DC5`, prime `0x01000193`).\n * - The generator is xoshiro128** seeded with four consecutive `splitmix32` outputs of the seed.\n * - `nextInt(bound)` is `next() % bound`.\n * - Row `i` of a shape named `S` generated with seed `n` uses its own generator seeded with\n * `hash32((n ^ fnv1a32(S)) + (i + 1) * 0x9E3779B9)`, so a row never depends on how many rows are asked for.\n */\nexport function hash32(value: number): number {\n let x = value >>> 0;\n x = Math.imul(x ^ (x >>> 16), 0x85EBCA6B) >>> 0;\n x = Math.imul(x ^ (x >>> 13), 0xC2B2AE35) >>> 0;\n return (x ^ (x >>> 16)) >>> 0;\n}\n\n/** FNV-1a (32-bit) over the UTF-8 bytes of a string. */\nexport function fnv1a32(text: string): number {\n let hash = 0x811C9DC5;\n for (const byte of new TextEncoder().encode(text)) {\n hash = Math.imul(hash ^ byte, 0x01000193) >>> 0;\n }\n return hash;\n}\n\n/** The seed of the generator for one row of one shape. */\nexport function rowSeed(seed: number, shapeName: string, rowIndex: number): number {\n return hash32((((seed ^ fnv1a32(shapeName)) >>> 0) + Math.imul(rowIndex + 1, 0x9E3779B9)) >>> 0);\n}\n\n/** xoshiro128** with splitmix32 seeding. */\nexport class SampleRandom {\n private s0: number;\n private s1: number;\n private s2: number;\n private s3: number;\n\n constructor(seed: number) {\n let state = seed >>> 0;\n const step = () => {\n state = (state + 0x9E3779B9) >>> 0;\n return hash32(state);\n };\n this.s0 = step();\n this.s1 = step();\n this.s2 = step();\n this.s3 = step();\n if ((this.s0 | this.s1 | this.s2 | this.s3) === 0) this.s0 = 1;\n }\n\n /** The next unsigned 32-bit value. */\n next(): number {\n const result = Math.imul(rotateLeft(Math.imul(this.s1, 5) >>> 0, 7), 9) >>> 0;\n const t = (this.s1 << 9) >>> 0;\n this.s2 = (this.s2 ^ this.s0) >>> 0;\n this.s3 = (this.s3 ^ this.s1) >>> 0;\n this.s1 = (this.s1 ^ this.s2) >>> 0;\n this.s0 = (this.s0 ^ this.s3) >>> 0;\n this.s2 = (this.s2 ^ t) >>> 0;\n this.s3 = rotateLeft(this.s3, 11);\n return result;\n }\n\n /** A value in `[0, bound)`; zero when the bound is zero. */\n nextInt(bound: number): number {\n return bound <= 0 ? 0 : this.next() % bound;\n }\n\n /** One element of a non-empty list. */\n pick<T>(items: readonly T[]): T {\n return items[this.nextInt(items.length)];\n }\n}\n\nfunction rotateLeft(value: number, bits: number): number {\n return ((value << bits) | (value >>> (32 - bits))) >>> 0;\n}\n"],"names":["hash32","value","x","Math","imul","fnv1a32","text","hash","byte","TextEncoder","encode","rowSeed","seed","shapeName","rowIndex","SampleRandom","s0","s1","s2","s3","state","step","next","result","rotateLeft","t","nextInt","bound","pick","items","length","bits"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { SampleDataPackReference } from '@cratis/scene.model';
2
+ import { SampleDataPackSource } from './SampleDataPackSource';
3
+ export declare const sampleDataLabelSeparator = " \u00B7 ";
4
+ export interface SampleDataCatalogEntry {
5
+ id: string;
6
+ isGenerated: boolean;
7
+ name: string;
8
+ label: string;
9
+ locale?: string;
10
+ selected: boolean;
11
+ }
12
+ export interface SampleDataCatalogGroup {
13
+ blueprint: string;
14
+ packs: SampleDataCatalogEntry[];
15
+ }
16
+ export interface SampleDataCatalog {
17
+ generated: SampleDataCatalogEntry;
18
+ own: SampleDataCatalogEntry[];
19
+ blueprints: SampleDataCatalogGroup[];
20
+ problems: string[];
21
+ }
22
+ export declare const generatedSampleDataName = "Generic (typed by field kind)";
23
+ export declare function describeSampleDataCatalog(sources: readonly SampleDataPackSource[], ownPacks?: readonly Pick<SampleDataPackReference, 'id' | 'title' | 'locale'>[], activePack?: string): SampleDataCatalog;
24
+ //# sourceMappingURL=describeSampleDataCatalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describeSampleDataCatalog.d.ts","sourceRoot":"","sources":["../../../sampleData/describeSampleDataCatalog.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAgB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAGnD,MAAM,WAAW,sBAAsB;IAEnC,EAAE,EAAE,MAAM,CAAC;IAGX,WAAW,EAAE,OAAO,CAAC;IAGrB,IAAI,EAAE,MAAM,CAAC;IAGb,KAAK,EAAE,MAAM,CAAC;IAGd,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,QAAQ,EAAE,OAAO,CAAC;CACrB;AAGD,MAAM,WAAW,sBAAsB;IAEnC,SAAS,EAAE,MAAM,CAAC;IAElB,KAAK,EAAE,sBAAsB,EAAE,CAAC;CACnC;AAGD,MAAM,WAAW,iBAAiB;IAE9B,SAAS,EAAE,sBAAsB,CAAC;IAGlC,GAAG,EAAE,sBAAsB,EAAE,CAAC;IAG9B,UAAU,EAAE,sBAAsB,EAAE,CAAC;IAGrC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAGD,eAAO,MAAM,uBAAuB,kCAAkC,CAAC;AAYvE,wBAAgB,yBAAyB,CACrC,OAAO,EAAE,SAAS,oBAAoB,EAAE,EACxC,QAAQ,GAAE,SAAS,IAAI,CAAC,uBAAuB,EAAE,IAAI,GAAG,OAAO,GAAG,QAAQ,CAAC,EAAO,EAClF,UAAU,CAAC,EAAE,MAAM,GACpB,iBAAiB,CAgCnB"}
@@ -0,0 +1,57 @@
1
+ import { validateSampleDataPackages } from './validateSampleDataPackages.js';
2
+
3
+ // Copyright (c) Cratis. All rights reserved.
4
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5
+ /** The separator between blueprint and pack in a label (`CRM · Nordic SMB`). */ const sampleDataLabelSeparator = ' \u00b7 ';
6
+ /** The name of the generated entry. */ const generatedSampleDataName = 'Generic (typed by field kind)';
7
+ /**
8
+ * Describes the sample data selector's content: the generated entry first, then the author's own packs, then
9
+ * each blueprint's packs grouped by the blueprint's display name (falling back to its package name). A pack
10
+ * whose title already starts with `<Blueprint> · ` shows the rest as its name, so `CRM · Nordic SMB` under
11
+ * `CRM` is `Nordic SMB`. Same own-first, then Blueprints menu pattern as the template picker (spec §11).
12
+ *
13
+ * @param sources The packages and the packs they ship (only their `sampleData` references are listed).
14
+ * @param ownPacks The author's own packs (id, title, locale).
15
+ * @param activePack The selection's active pack id, if any.
16
+ */ function describeSampleDataCatalog(sources, ownPacks = [], activePack) {
17
+ const entry = (id, name, label, locale)=>({
18
+ id,
19
+ isGenerated: false,
20
+ name,
21
+ label,
22
+ locale,
23
+ selected: id === activePack
24
+ });
25
+ const blueprints = [];
26
+ for (const source of sources){
27
+ const references = source.manifest.sampleData ?? [];
28
+ if (references.length === 0) continue;
29
+ const group = groupName(source.manifest);
30
+ const prefix = `${group}${sampleDataLabelSeparator}`;
31
+ blueprints.push({
32
+ blueprint: group,
33
+ packs: references.map((reference)=>{
34
+ const name = reference.title.startsWith(prefix) ? reference.title.slice(prefix.length) : reference.title;
35
+ return entry(reference.id, name, `${group}${sampleDataLabelSeparator}${name}`, reference.locale);
36
+ })
37
+ });
38
+ }
39
+ return {
40
+ generated: {
41
+ id: '',
42
+ isGenerated: true,
43
+ name: generatedSampleDataName,
44
+ label: generatedSampleDataName,
45
+ selected: activePack === undefined || activePack === null || activePack === ''
46
+ },
47
+ own: ownPacks.map((pack)=>entry(pack.id, pack.title, pack.title, pack.locale)),
48
+ blueprints,
49
+ problems: validateSampleDataPackages(sources)
50
+ };
51
+ }
52
+ function groupName(manifest) {
53
+ return manifest.displayName !== undefined && manifest.displayName.trim() !== '' ? manifest.displayName : manifest.name;
54
+ }
55
+
56
+ export { describeSampleDataCatalog, generatedSampleDataName, sampleDataLabelSeparator };
57
+ //# sourceMappingURL=describeSampleDataCatalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describeSampleDataCatalog.js","sources":["../../../sampleData/describeSampleDataCatalog.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SampleDataPackReference, ScenePackage } from '@cratis/scene.model';\nimport { SampleDataPackSource } from './SampleDataPackSource';\nimport { validateSampleDataPackages } from './validateSampleDataPackages';\n\n/** The separator between blueprint and pack in a label (`CRM · Nordic SMB`). */\nexport const sampleDataLabelSeparator = ' \\u00b7 ';\n\n/** One entry of the sample data selector. */\nexport interface SampleDataCatalogEntry {\n /** The pack identity a selection stores as `activePack`; empty for the generated entry. */\n id: string;\n\n /** Whether this is the generated entry, the choice that stores no active pack. */\n isGenerated: boolean;\n\n /** The pack's name within its group (`Nordic SMB`). */\n name: string;\n\n /** The full label (`CRM · Nordic SMB`, or just the name for generated and own packs). */\n label: string;\n\n /** The locale tag, absent for the generated entry. */\n locale?: string;\n\n /** Whether it is the active pack (the generated entry is selected when no pack is active). */\n selected: boolean;\n}\n\n/** A blueprint's packs, one group of the Blueprints submenu. */\nexport interface SampleDataCatalogGroup {\n /** The blueprint's display name (`CRM`). */\n blueprint: string;\n\n packs: SampleDataCatalogEntry[];\n}\n\n/** The selector's content: generated, the author's own sets, then blueprint groups. */\nexport interface SampleDataCatalog {\n /** `Generic (typed by field kind)`. */\n generated: SampleDataCatalogEntry;\n\n /** The author's own data sets, in the order given. */\n own: SampleDataCatalogEntry[];\n\n /** Blueprints that ship at least one pack, in package order; blueprints with none are not listed. */\n blueprints: SampleDataCatalogGroup[];\n\n /** Problems found validating what the packages ship. */\n problems: string[];\n}\n\n/** The name of the generated entry. */\nexport const generatedSampleDataName = 'Generic (typed by field kind)';\n\n/**\n * Describes the sample data selector's content: the generated entry first, then the author's own packs, then\n * each blueprint's packs grouped by the blueprint's display name (falling back to its package name). A pack\n * whose title already starts with `<Blueprint> · ` shows the rest as its name, so `CRM · Nordic SMB` under\n * `CRM` is `Nordic SMB`. Same own-first, then Blueprints menu pattern as the template picker (spec §11).\n *\n * @param sources The packages and the packs they ship (only their `sampleData` references are listed).\n * @param ownPacks The author's own packs (id, title, locale).\n * @param activePack The selection's active pack id, if any.\n */\nexport function describeSampleDataCatalog(\n sources: readonly SampleDataPackSource[],\n ownPacks: readonly Pick<SampleDataPackReference, 'id' | 'title' | 'locale'>[] = [],\n activePack?: string,\n): SampleDataCatalog {\n const entry = (id: string, name: string, label: string, locale: string): SampleDataCatalogEntry => ({\n id, isGenerated: false, name, label, locale, selected: id === activePack,\n });\n\n const blueprints: SampleDataCatalogGroup[] = [];\n for (const source of sources) {\n const references = source.manifest.sampleData ?? [];\n if (references.length === 0) continue;\n const group = groupName(source.manifest);\n const prefix = `${group}${sampleDataLabelSeparator}`;\n blueprints.push({\n blueprint: group,\n packs: references.map(reference => {\n const name = reference.title.startsWith(prefix) ? reference.title.slice(prefix.length) : reference.title;\n return entry(reference.id, name, `${group}${sampleDataLabelSeparator}${name}`, reference.locale);\n }),\n });\n }\n\n return {\n generated: {\n id: '',\n isGenerated: true,\n name: generatedSampleDataName,\n label: generatedSampleDataName,\n selected: activePack === undefined || activePack === null || activePack === '',\n },\n own: ownPacks.map(pack => entry(pack.id, pack.title, pack.title, pack.locale)),\n blueprints,\n problems: validateSampleDataPackages(sources),\n };\n}\n\nfunction groupName(manifest: ScenePackage): string {\n return manifest.displayName !== undefined && manifest.displayName.trim() !== '' ? manifest.displayName : manifest.name;\n}\n"],"names":["sampleDataLabelSeparator","generatedSampleDataName","describeSampleDataCatalog","sources","ownPacks","activePack","entry","id","name","label","locale","isGenerated","selected","blueprints","source","references","manifest","sampleData","length","group","groupName","prefix","push","blueprint","packs","map","reference","title","startsWith","slice","generated","undefined","own","pack","problems","validateSampleDataPackages","displayName","trim"],"mappings":";;AAAA;AACA;AAMA,iFACO,MAAMA,wBAAAA,GAA2B;AA8CxC,wCACO,MAAMC,uBAAAA,GAA0B;AAEvC;;;;;;;;;IAUO,SAASC,yBAAAA,CACZC,OAAwC,EACxCC,QAAAA,GAAgF,EAAE,EAClFC,UAAmB,EAAA;AAEnB,IAAA,MAAMC,QAAQ,CAACC,EAAAA,EAAYC,IAAAA,EAAcC,KAAAA,EAAeC,UAA4C;AAChGH,YAAAA,EAAAA;YAAII,WAAAA,EAAa,KAAA;AAAOH,YAAAA,IAAAA;AAAMC,YAAAA,KAAAA;AAAOC,YAAAA,MAAAA;AAAQE,YAAAA,QAAAA,EAAUL,EAAAA,KAAOF;SAClE,CAAA;AAEA,IAAA,MAAMQ,aAAuC,EAAE;IAC/C,KAAK,MAAMC,UAAUX,OAAAA,CAAS;AAC1B,QAAA,MAAMY,aAAaD,MAAAA,CAAOE,QAAQ,CAACC,UAAU,IAAI,EAAE;QACnD,IAAIF,UAAAA,CAAWG,MAAM,KAAK,CAAA,EAAG;QAC7B,MAAMC,KAAAA,GAAQC,SAAAA,CAAUN,MAAAA,CAAOE,QAAQ,CAAA;QACvC,MAAMK,MAAAA,GAAS,CAAA,EAAGF,KAAAA,CAAAA,EAAQnB,wBAAAA,CAAAA,CAA0B;AACpDa,QAAAA,UAAAA,CAAWS,IAAI,CAAC;YACZC,SAAAA,EAAWJ,KAAAA;YACXK,KAAAA,EAAOT,UAAAA,CAAWU,GAAG,CAACC,CAAAA,SAAAA,GAAAA;AAClB,gBAAA,MAAMlB,OAAOkB,SAAAA,CAAUC,KAAK,CAACC,UAAU,CAACP,MAAAA,CAAAA,GAAUK,SAAAA,CAAUC,KAAK,CAACE,KAAK,CAACR,MAAAA,CAAOH,MAAM,CAAA,GAAIQ,UAAUC,KAAK;gBACxG,OAAOrB,KAAAA,CAAMoB,SAAAA,CAAUnB,EAAE,EAAEC,IAAAA,EAAM,CAAA,EAAGW,KAAAA,CAAAA,EAAQnB,wBAAAA,CAAAA,EAA2BQ,IAAAA,CAAAA,CAAM,EAAEkB,SAAAA,CAAUhB,MAAM,CAAA;AACnG,YAAA,CAAA;AACJ,SAAA,CAAA;AACJ,IAAA;IAEA,OAAO;QACHoB,SAAAA,EAAW;YACPvB,EAAAA,EAAI,EAAA;YACJI,WAAAA,EAAa,IAAA;YACbH,IAAAA,EAAMP,uBAAAA;YACNQ,KAAAA,EAAOR,uBAAAA;AACPW,YAAAA,QAAAA,EAAUP,UAAAA,KAAe0B,SAAAA,IAAa1B,UAAAA,KAAe,IAAA,IAAQA,UAAAA,KAAe;AAChF,SAAA;AACA2B,QAAAA,GAAAA,EAAK5B,SAASqB,GAAG,CAACQ,CAAAA,IAAAA,GAAQ3B,MAAM2B,IAAAA,CAAK1B,EAAE,EAAE0B,IAAAA,CAAKN,KAAK,EAAEM,IAAAA,CAAKN,KAAK,EAAEM,KAAKvB,MAAM,CAAA,CAAA;AAC5EG,QAAAA,UAAAA;AACAqB,QAAAA,QAAAA,EAAUC,0BAAAA,CAA2BhC,OAAAA;AACzC,KAAA;AACJ;AAEA,SAASiB,UAAUJ,QAAsB,EAAA;AACrC,IAAA,OAAOA,QAAAA,CAASoB,WAAW,KAAKL,SAAAA,IAAaf,SAASoB,WAAW,CAACC,IAAI,EAAA,KAAO,EAAA,GAAKrB,QAAAA,CAASoB,WAAW,GAAGpB,SAASR,IAAI;AAC1H;;"}
@@ -0,0 +1,3 @@
1
+ import { SampleDataMapping, SampleDataPack, SampleDataSet } from '@cratis/scene.model';
2
+ export declare function findSampleDataSet(pack: SampleDataPack, target: string, mappings?: readonly SampleDataMapping[]): SampleDataSet | undefined;
3
+ //# sourceMappingURL=findSampleDataSet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findSampleDataSet.d.ts","sourceRoot":"","sources":["../../../sampleData/findSampleDataSet.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,iBAAiB,EAAO,GAAG,aAAa,GAAG,SAAS,CAQ9I"}
@@ -0,0 +1,16 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * Finds the set of a pack that supplies rows for a read model or shape. An explicit mapping whose read model is
5
+ * the target wins; otherwise a set whose shape has the target's name (compared exactly, case-sensitively).
6
+ */ function findSampleDataSet(pack, target, mappings = []) {
7
+ for (const mapping of mappings){
8
+ if (mapping.readModel !== target) continue;
9
+ const mapped = (pack.sets ?? []).find((set)=>set.shape === mapping.shape);
10
+ if (mapped !== undefined) return mapped;
11
+ }
12
+ return (pack.sets ?? []).find((set)=>set.shape === target);
13
+ }
14
+
15
+ export { findSampleDataSet };
16
+ //# sourceMappingURL=findSampleDataSet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findSampleDataSet.js","sources":["../../../sampleData/findSampleDataSet.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SampleDataMapping, SampleDataPack, SampleDataSet } from '@cratis/scene.model';\n\n/**\n * Finds the set of a pack that supplies rows for a read model or shape. An explicit mapping whose read model is\n * the target wins; otherwise a set whose shape has the target's name (compared exactly, case-sensitively).\n */\nexport function findSampleDataSet(pack: SampleDataPack, target: string, mappings: readonly SampleDataMapping[] = []): SampleDataSet | undefined {\n for (const mapping of mappings) {\n if (mapping.readModel !== target) continue;\n const mapped = (pack.sets ?? []).find(set => set.shape === mapping.shape);\n if (mapped !== undefined) return mapped;\n }\n\n return (pack.sets ?? []).find(set => set.shape === target);\n}\n"],"names":["findSampleDataSet","pack","target","mappings","mapping","readModel","mapped","sets","find","set","shape","undefined"],"mappings":"AAAA;AACA;AAIA;;;IAIO,SAASA,iBAAAA,CAAkBC,IAAoB,EAAEC,MAAc,EAAEC,WAAyC,EAAE,EAAA;IAC/G,KAAK,MAAMC,WAAWD,QAAAA,CAAU;QAC5B,IAAIC,OAAAA,CAAQC,SAAS,KAAKH,MAAAA,EAAQ;AAClC,QAAA,MAAMI,SAAS,CAACL,IAAAA,CAAKM,IAAI,IAAI,EAAC,EAAGC,IAAI,CAACC,CAAAA,GAAAA,GAAOA,IAAIC,KAAK,KAAKN,QAAQM,KAAK,CAAA;QACxE,IAAIJ,MAAAA,KAAWK,WAAW,OAAOL,MAAAA;AACrC,IAAA;AAEA,IAAA,OAAO,CAACL,IAAAA,CAAKM,IAAI,IAAI,EAAC,EAAGC,IAAI,CAACC,CAAAA,GAAAA,GAAOA,GAAAA,CAAIC,KAAK,KAAKR,MAAAA,CAAAA;AACvD;;"}
@@ -0,0 +1,11 @@
1
+ import { ComponentDescriptor } from '@cratis/scene.model';
2
+ export declare function findSampleRowLiterals(value: unknown, path?: string): string[];
3
+ export declare function findDescriptorSampleRowLiterals(descriptors: readonly ComponentDescriptor[]): string[];
4
+ interface ScannedElement {
5
+ componentName?: string;
6
+ properties?: Record<string, unknown>;
7
+ slots?: Record<string, ScannedElement[]>;
8
+ }
9
+ export declare function findTemplateSampleRowLiterals(content: Record<string, ScannedElement[]> | undefined): string[];
10
+ export {};
11
+ //# sourceMappingURL=findSampleRowLiterals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findSampleRowLiterals.d.ts","sourceRoot":"","sources":["../../../sampleData/findSampleRowLiterals.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAa1D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAK,GAAG,MAAM,EAAE,CAYzE;AAQD,wBAAgB,+BAA+B,CAAC,WAAW,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,EAAE,CAYrG;AAOD,UAAU,cAAc;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;CAC5C;AASD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,GAAG,SAAS,GAAG,MAAM,EAAE,CAiB7G"}
@@ -0,0 +1,69 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+ /**
4
+ * Finds sample-row literals inside a value: an array holding plain objects of two or more keys, which is what
5
+ * a hand-written list of demo rows looks like. Returns the path of each, e.g. `rows` or `items[2].children`.
6
+ * A single-key object is a choice or a token, not a row, and is not reported.
7
+ *
8
+ * Spec §11 SD1: components keep declaring shapes only, so a component descriptor's defaults and a template's
9
+ * properties must not carry row literals; demo rows belong to sample-data packs.
10
+ *
11
+ * @param value The value to inspect.
12
+ * @param path The path prefix of the value, empty for the root.
13
+ */ function findSampleRowLiterals(value, path = '') {
14
+ const found = [];
15
+ if (Array.isArray(value)) {
16
+ if (value.some(isRow)) found.push(path === '' ? '(root)' : path);
17
+ value.forEach((item, index)=>found.push(...findSampleRowLiterals(item, `${path}[${index}]`)));
18
+ } else if (typeof value === 'object' && value !== null) {
19
+ for (const [key, child] of Object.entries(value)){
20
+ found.push(...findSampleRowLiterals(child, path === '' ? key : `${path}.${key}`));
21
+ }
22
+ }
23
+ return found;
24
+ }
25
+ /**
26
+ * Finds the sample-row literals in the defaults of component descriptors, as `<component>: <property path>`
27
+ * entries (the property path is followed by the location inside the default).
28
+ *
29
+ * @param descriptors The descriptors to inspect.
30
+ */ function findDescriptorSampleRowLiterals(descriptors) {
31
+ const found = [];
32
+ for (const descriptor of descriptors){
33
+ for (const property of descriptor.properties ?? []){
34
+ for (const location of findSampleRowLiterals(property.default)){
35
+ const suffix = location === '(root)' ? '' : location.startsWith('[') ? location : `.${location}`;
36
+ found.push(`${descriptor.component}: ${property.path}${suffix}`);
37
+ }
38
+ }
39
+ }
40
+ return found;
41
+ }
42
+ function isRow(item) {
43
+ return typeof item === 'object' && item !== null && !Array.isArray(item) && Object.keys(item).length >= 2;
44
+ }
45
+ /**
46
+ * Finds the sample-row literals in the element properties of a template's content, as
47
+ * `<componentName>.<property>` entries (with the location inside the value when it is nested). Only property
48
+ * values are scanned: the element tree itself is made of objects and is not data.
49
+ *
50
+ * @param content A template's content, keyed by slot name.
51
+ */ function findTemplateSampleRowLiterals(content) {
52
+ const found = [];
53
+ const visit = (elements)=>{
54
+ for (const element of elements ?? []){
55
+ for (const [name, value] of Object.entries(element.properties ?? {})){
56
+ for (const location of findSampleRowLiterals(value)){
57
+ const suffix = location === '(root)' ? '' : location.startsWith('[') ? location : `.${location}`;
58
+ found.push(`${element.componentName ?? '(unnamed)'}.${name}${suffix}`);
59
+ }
60
+ }
61
+ Object.values(element.slots ?? {}).forEach(visit);
62
+ }
63
+ };
64
+ Object.values(content ?? {}).forEach(visit);
65
+ return found;
66
+ }
67
+
68
+ export { findDescriptorSampleRowLiterals, findSampleRowLiterals, findTemplateSampleRowLiterals };
69
+ //# sourceMappingURL=findSampleRowLiterals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"findSampleRowLiterals.js","sources":["../../../sampleData/findSampleRowLiterals.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { ComponentDescriptor } from '@cratis/scene.model';\n\n/**\n * Finds sample-row literals inside a value: an array holding plain objects of two or more keys, which is what\n * a hand-written list of demo rows looks like. Returns the path of each, e.g. `rows` or `items[2].children`.\n * A single-key object is a choice or a token, not a row, and is not reported.\n *\n * Spec §11 SD1: components keep declaring shapes only, so a component descriptor's defaults and a template's\n * properties must not carry row literals; demo rows belong to sample-data packs.\n *\n * @param value The value to inspect.\n * @param path The path prefix of the value, empty for the root.\n */\nexport function findSampleRowLiterals(value: unknown, path = ''): string[] {\n const found: string[] = [];\n if (Array.isArray(value)) {\n if (value.some(isRow)) found.push(path === '' ? '(root)' : path);\n value.forEach((item, index) => found.push(...findSampleRowLiterals(item, `${path}[${index}]`)));\n } else if (typeof value === 'object' && value !== null) {\n for (const [key, child] of Object.entries(value)) {\n found.push(...findSampleRowLiterals(child, path === '' ? key : `${path}.${key}`));\n }\n }\n\n return found;\n}\n\n/**\n * Finds the sample-row literals in the defaults of component descriptors, as `<component>: <property path>`\n * entries (the property path is followed by the location inside the default).\n *\n * @param descriptors The descriptors to inspect.\n */\nexport function findDescriptorSampleRowLiterals(descriptors: readonly ComponentDescriptor[]): string[] {\n const found: string[] = [];\n for (const descriptor of descriptors) {\n for (const property of descriptor.properties ?? []) {\n for (const location of findSampleRowLiterals(property.default)) {\n const suffix = location === '(root)' ? '' : (location.startsWith('[') ? location : `.${location}`);\n found.push(`${descriptor.component}: ${property.path}${suffix}`);\n }\n }\n }\n\n return found;\n}\n\nfunction isRow(item: unknown): boolean {\n return typeof item === 'object' && item !== null && !Array.isArray(item) && Object.keys(item).length >= 2;\n}\n\n/** The part of a scene element the scan reads: its properties and the child elements in its slots. */\ninterface ScannedElement {\n componentName?: string;\n properties?: Record<string, unknown>;\n slots?: Record<string, ScannedElement[]>;\n}\n\n/**\n * Finds the sample-row literals in the element properties of a template's content, as\n * `<componentName>.<property>` entries (with the location inside the value when it is nested). Only property\n * values are scanned: the element tree itself is made of objects and is not data.\n *\n * @param content A template's content, keyed by slot name.\n */\nexport function findTemplateSampleRowLiterals(content: Record<string, ScannedElement[]> | undefined): string[] {\n const found: string[] = [];\n const visit = (elements: ScannedElement[] | undefined) => {\n for (const element of elements ?? []) {\n for (const [name, value] of Object.entries(element.properties ?? {})) {\n for (const location of findSampleRowLiterals(value)) {\n const suffix = location === '(root)' ? '' : (location.startsWith('[') ? location : `.${location}`);\n found.push(`${element.componentName ?? '(unnamed)'}.${name}${suffix}`);\n }\n }\n\n Object.values(element.slots ?? {}).forEach(visit);\n }\n };\n\n Object.values(content ?? {}).forEach(visit);\n return found;\n}\n"],"names":["findSampleRowLiterals","value","path","found","Array","isArray","some","isRow","push","forEach","item","index","key","child","Object","entries","findDescriptorSampleRowLiterals","descriptors","descriptor","property","properties","location","default","suffix","startsWith","component","keys","length","findTemplateSampleRowLiterals","content","visit","elements","element","name","componentName","values","slots"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { SampleShape } from '@cratis/scene.model';
2
+ export declare const defaultSampleSeed = 1;
3
+ export declare const defaultSampleRowCount = 5;
4
+ export declare const maximumSampleRowCount = 1000;
5
+ export declare function generateSample(shape: SampleShape, seed?: number, rowCount?: number, locale?: string): Record<string, unknown>[];
6
+ //# sourceMappingURL=generateSample.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateSample.d.ts","sourceRoot":"","sources":["../../../sampleData/generateSample.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,WAAW,EAAoB,MAAM,qBAAqB,CAAC;AAMrF,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAGnC,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAGvC,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAuB1C,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAkB/H"}
@@ -0,0 +1,183 @@
1
+ import { SampleFieldKind } from '@cratis/scene.model';
2
+ import { inferSampleFieldKind } from './inferSampleFieldKind.js';
3
+ import { sampleLocaleFor } from './sampleLocales.js';
4
+ import { SampleRandom, rowSeed } from './SampleRandom.js';
5
+
6
+ // Copyright (c) Cratis. All rights reserved.
7
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
8
+ /** The seed used when none is given, so previews are stable without any configuration. */ const defaultSampleSeed = 1;
9
+ /** How many rows are generated when no count is given. */ const defaultSampleRowCount = 5;
10
+ /** The most rows one call generates. */ const maximumSampleRowCount = 1000;
11
+ /** Days since 1970-01-01 of 2024-01-01, the anchor generated dates count forward from. */ const anchorDay = 19723;
12
+ /** Generated dates fall within this many days after the anchor. */ const dateSpanDays = 731;
13
+ /**
14
+ * Generates `rowCount` rows of a shape, deterministically for a seed: the same shape, seed, row count and
15
+ * locale yield the same rows (byte-identical once serialized) in the C# and TypeScript engines.
16
+ *
17
+ * Each row has its own generator (see {@link rowSeed}), so row `i` is the same however many rows are asked
18
+ * for. Within a row the fields are generated in declaration order. A nullable field first draws whether it is
19
+ * null (one in five is) and then always draws its value, so the sequence never depends on nullability
20
+ * outcomes. Values follow the field's kind and locale; enum fields only ever produce one of their values,
21
+ * dates stay within 2024-2025 and amounts have two decimals.
22
+ *
23
+ * @param shape The shape to generate rows for.
24
+ * @param seed The seed; defaults to {@link defaultSampleSeed}.
25
+ * @param rowCount The number of rows; defaults to {@link defaultSampleRowCount}, clamped to `[0, 1000]`.
26
+ * @param locale The BCP 47 locale tag selecting names, cities and formats; unknown tags use the default pool.
27
+ */ function generateSample(shape, seed, rowCount, locale) {
28
+ const count = Math.min(Math.max(Math.trunc(rowCount ?? defaultSampleRowCount), 0), maximumSampleRowCount);
29
+ const effectiveSeed = (seed ?? defaultSampleSeed) >>> 0;
30
+ const pool = sampleLocaleFor(locale);
31
+ const rows = [];
32
+ for(let index = 0; index < count; index++){
33
+ const random = new SampleRandom(rowSeed(effectiveSeed, shape.name, index));
34
+ const row = {};
35
+ for (const field of shape.fields){
36
+ const isNull = field.nullable === true && random.nextInt(5) === 0;
37
+ const value = generateValue(field, inferSampleFieldKind(field), random, pool);
38
+ row[field.name] = isNull ? null : value;
39
+ }
40
+ rows.push(row);
41
+ }
42
+ return rows;
43
+ }
44
+ function generateValue(field, kind, random, pool) {
45
+ switch(kind){
46
+ case SampleFieldKind.Id:
47
+ return generateId(random);
48
+ case SampleFieldKind.Name:
49
+ return `${random.pick(pool.firstNames)} ${random.pick(pool.lastNames)}`;
50
+ case SampleFieldKind.Company:
51
+ return random.pick(pool.companies);
52
+ case SampleFieldKind.Email:
53
+ {
54
+ const first = random.pick(pool.firstNames);
55
+ const last = random.pick(pool.lastNames);
56
+ return `${slug(first)}.${slug(last)}@${random.pick(pool.domains)}`;
57
+ }
58
+ case SampleFieldKind.Phone:
59
+ return [
60
+ ...pool.phoneTemplate
61
+ ].map((character)=>character === '#' ? String(random.nextInt(10)) : character).join('');
62
+ case SampleFieldKind.City:
63
+ return random.pick(pool.cities);
64
+ case SampleFieldKind.Text:
65
+ {
66
+ const words = Array.from({
67
+ length: 3 + random.nextInt(4)
68
+ }, ()=>random.pick(pool.words));
69
+ return capitalize(words.join(' '));
70
+ }
71
+ case SampleFieldKind.WholeNumber:
72
+ {
73
+ const [low, high] = range(field.min, field.max, 0, 1000, Math.trunc);
74
+ return low + random.nextInt(high - low + 1);
75
+ }
76
+ case SampleFieldKind.Amount:
77
+ {
78
+ const [low, high] = range(field.min, field.max, 10, 5000, (value)=>Math.floor(value * 100 + 0.5));
79
+ return (low + random.nextInt(high - low + 1)) / 100;
80
+ }
81
+ case SampleFieldKind.Boolean:
82
+ return random.nextInt(2) === 1;
83
+ case SampleFieldKind.Date:
84
+ return formatDay(anchorDay + random.nextInt(dateSpanDays));
85
+ case SampleFieldKind.DateTime:
86
+ {
87
+ const day = anchorDay + random.nextInt(dateSpanDays);
88
+ const seconds = random.nextInt(86400);
89
+ return `${formatDay(day)}T${pad(Math.floor(seconds / 3600))}:${pad(Math.floor(seconds / 60) % 60)}:${pad(seconds % 60)}Z`;
90
+ }
91
+ case SampleFieldKind.Enum:
92
+ return field.enumValues !== undefined && field.enumValues !== null && field.enumValues.length > 0 ? random.pick(field.enumValues) : null;
93
+ default:
94
+ return null;
95
+ }
96
+ }
97
+ function range(min, max, defaultMin, defaultMax, convert) {
98
+ const low = convert(min ?? defaultMin);
99
+ const high = convert(max ?? defaultMax);
100
+ return high < low ? [
101
+ high,
102
+ low
103
+ ] : [
104
+ low,
105
+ high
106
+ ];
107
+ }
108
+ function generateId(random) {
109
+ const a = random.next();
110
+ const b = (random.next() & 0xFFFF0FFF | 0x00004000) >>> 0;
111
+ const c = (random.next() & 0x3FFFFFFF | 0x80000000) >>> 0;
112
+ const d = random.next();
113
+ return `${hex(a, 8)}-${hex(b >>> 16, 4)}-${hex(b & 0xFFFF, 4)}-${hex(c >>> 16, 4)}-${hex(c & 0xFFFF, 4)}${hex(d, 8)}`;
114
+ }
115
+ const transliterations = new Map([
116
+ [
117
+ 'æ',
118
+ 'ae'
119
+ ],
120
+ [
121
+ 'ø',
122
+ 'o'
123
+ ],
124
+ [
125
+ 'å',
126
+ 'a'
127
+ ],
128
+ [
129
+ 'ä',
130
+ 'a'
131
+ ],
132
+ [
133
+ 'ö',
134
+ 'o'
135
+ ],
136
+ [
137
+ 'ü',
138
+ 'u'
139
+ ],
140
+ [
141
+ 'ß',
142
+ 'ss'
143
+ ],
144
+ [
145
+ 'é',
146
+ 'e'
147
+ ]
148
+ ]);
149
+ function slug(text) {
150
+ let result = '';
151
+ for (const character of text.toLowerCase()){
152
+ const mapped = transliterations.get(character) ?? character;
153
+ for (const part of mapped){
154
+ if (part >= 'a' && part <= 'z' || part >= '0' && part <= '9') result += part;
155
+ }
156
+ }
157
+ return result;
158
+ }
159
+ function capitalize(text) {
160
+ const first = text.charAt(0);
161
+ return first >= 'a' && first <= 'z' ? first.toUpperCase() + text.slice(1) : text;
162
+ }
163
+ function hex(value, digits) {
164
+ return (value >>> 0).toString(16).padStart(digits, '0');
165
+ }
166
+ function pad(value) {
167
+ return value < 10 ? `0${value}` : String(value);
168
+ }
169
+ /** Formats days since 1970-01-01 as `yyyy-MM-dd` (Howard Hinnant's civil-from-days). */ function formatDay(days) {
170
+ const shifted = days + 719468;
171
+ const era = Math.floor(shifted / 146097);
172
+ const dayOfEra = shifted - era * 146097;
173
+ const yearOfEra = Math.floor((dayOfEra - Math.floor(dayOfEra / 1460) + Math.floor(dayOfEra / 36524) - Math.floor(dayOfEra / 146096)) / 365);
174
+ const dayOfYear = dayOfEra - (365 * yearOfEra + Math.floor(yearOfEra / 4) - Math.floor(yearOfEra / 100));
175
+ const monthPrime = Math.floor((5 * dayOfYear + 2) / 153);
176
+ const day = dayOfYear - Math.floor((153 * monthPrime + 2) / 5) + 1;
177
+ const month = monthPrime < 10 ? monthPrime + 3 : monthPrime - 9;
178
+ const year = yearOfEra + era * 400 + (month <= 2 ? 1 : 0);
179
+ return `${String(year).padStart(4, '0')}-${pad(month)}-${pad(day)}`;
180
+ }
181
+
182
+ export { defaultSampleRowCount, defaultSampleSeed, generateSample, maximumSampleRowCount };
183
+ //# sourceMappingURL=generateSample.js.map