@sungen/driver-data-factory 3.2.10-beta.12 → 3.2.10-beta.14

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sungen/driver-data-factory",
3
- "version": "3.2.10-beta.12",
3
+ "version": "3.2.10-beta.14",
4
4
  "description": "Sungen Data Factory capability — standardized test-data generation from a field-type + security knowledge catalog (valid/boundary/invalid + traceability), the .overwrite merge layer, and (opt-in) @dataFactory runtime seeding. Design-time knowledge is runtime-free. Plugs into @sun-asterisk/sungen via the capability SPI.",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -14,7 +14,7 @@
14
14
  "author": "eqe team (engineer & quality) — Sun Asterisk",
15
15
  "license": "MIT",
16
16
  "dependencies": {
17
- "@sun-asterisk/sungen": "3.2.10-beta.12",
17
+ "@sun-asterisk/sungen": "3.2.10-beta.14",
18
18
  "yaml": "^2.4.0"
19
19
  },
20
20
  "files": [
package/src/cli.ts CHANGED
@@ -14,6 +14,7 @@ import { loadEffectiveCatalog } from './catalog-loader';
14
14
  import { expandFieldMap, renderTestData, type FieldMap } from './generator';
15
15
  import { lintFieldMap, summarize } from './lint';
16
16
  import { generateFixture } from './fixture';
17
+ import { ensureDataFactoryReadme } from './readme';
17
18
 
18
19
  const FIELDMAP_DIR = (cwd: string) => join(cwd, 'qa', 'data-factory');
19
20
  const fieldMapPath = (cwd: string, name: string) => join(FIELDMAP_DIR(cwd), `${name}.fields.yaml`);
@@ -96,6 +97,7 @@ export function registerDataFactoryCommand(program: any): void {
96
97
  .option('--force', 'Overwrite existing test-data without asking (implies --yes)')
97
98
  .action(async (opts: { screen?: string; all?: boolean; yes?: boolean; force?: boolean }) => {
98
99
  const cwd = process.cwd();
100
+ ensureDataFactoryReadme(cwd);
99
101
  if (opts.screen) { await genOne(cwd, opts.screen, opts); return; }
100
102
  if (!opts.all) {
101
103
  console.error('Specify --screen <name> for one unit, or --all for every unit (with confirmation).');
@@ -123,6 +125,7 @@ export function registerDataFactoryCommand(program: any): void {
123
125
  .option('--screen <name>', 'Lint one unit (default: all field-maps)')
124
126
  .action((opts: { screen?: string }) => {
125
127
  const cwd = process.cwd();
128
+ ensureDataFactoryReadme(cwd);
126
129
  const names = opts.screen ? [opts.screen] : listFieldMaps(cwd);
127
130
  if (names.length === 0) { console.error('No field-maps under qa/data-factory/*.fields.yaml.'); process.exitCode = 1; return; }
128
131
  const { catalog } = loadEffectiveCatalog(cwd);
@@ -152,6 +155,7 @@ export function registerDataFactoryCommand(program: any): void {
152
155
  .option('--force', 'Overwrite existing fixture file(s) without asking')
153
156
  .action(async (opts: { screen: string; rows?: string; invalid?: boolean; force?: boolean }) => {
154
157
  const cwd = process.cwd();
158
+ ensureDataFactoryReadme(cwd);
155
159
  const map = loadFieldMap(cwd, opts.screen);
156
160
  if (!map) { console.error(`✗ ${opts.screen}: no field-map at qa/data-factory/${opts.screen}.fields.yaml`); process.exitCode = 1; return; }
157
161
  const { catalog } = loadEffectiveCatalog(cwd);
package/src/readme.ts ADDED
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Drops a `qa/data-factory/README.md` into the user's project so the folder explains itself.
3
+ * Write-if-absent (never clobbers a user-edited README), like a config file.
4
+ */
5
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
6
+ import { join } from 'path';
7
+
8
+ const README = `# \`qa/data-factory/\` — Data Factory (your project's test-data knowledge)
9
+
10
+ This folder is your project's **test-data standard**: machine-readable data rules that
11
+ \`sungen data gen\` / \`/sungen:create-data-test\` (and \`/sungen:create-test\` step 5.3) expand into
12
+ standardized test-data — **valid / boundary / invalid** values, each carrying a \`CHK-*\` trace id back
13
+ to the spec. It is a reusable asset that **survives \`sungen update\`** (only the driver's shipped
14
+ catalog is refreshed; nothing here is touched).
15
+
16
+ It is **not** a copy of your spec — it is the structured, reusable data-rules layer the deterministic
17
+ generator needs, complementary to \`requirements/spec.md\` (which is prose spec per screen/flow).
18
+
19
+ ## What lives here
20
+
21
+ | File | What it is |
22
+ |---|---|
23
+ | \`<name>.fields.yaml\` | **Field-map** for a screen/flow — one entry per input field: its catalog \`type\`, the project's real \`constraints\`, an \`errorMap\` (catalog placeholder code → your real message code), and optionally \`unique: true\`, nested \`fields:\`, \`dependsOn:\`. Authored from \`requirements/spec.md\`; expanded deterministically. A unit with **no input fields** (navigation/list) has no field-map — that's correct. |
24
+ | \`common.overwrite.yaml\` | **Project-wide overrides** to the shipped catalog — your real length limits, real error codes, banned values, extra invalid cases. Deep-merged over the common (later-wins, keyed by \`type\` + data-point \`id\`). Genuinely new project knowledge the shipped catalog can't have. |
25
+ | \`project/<entity>.yaml\` | **Blind-spot answers** — business enums, cross-entity rules, data models the catalog can't know. You fill these when Data Factory hits a field \`type\` it doesn't have (instead of it guessing). |
26
+ | \`recipes.yaml\` | Seed recipes for the \`@dataFactory:<recipe>\` annotation — named field sets bound into \`{{recipe.*}}\` at runtime. |
27
+
28
+ ## Good to know
29
+
30
+ - **\`sungen data gen\` merges** into \`test-data/<name>.yaml\` — it replaces only the field keys it owns
31
+ and preserves everything else (create-test data, flow-namespaced keys, \`@cases\`, overrides).
32
+ - **\`unique: true\`** makes a field's valid value fresh per run (\`{{$timestamp}}\`) so a register
33
+ email/username never collides — no cross-run cache.
34
+ - \`sungen data lint\` checks coverage; \`sungen data fixture\` builds a CSV import fixture under
35
+ \`qa/fixtures/\`.
36
+ - Edit the field-map / \`.overwrite\` and re-run — never hand-edit the generated \`test-data\` values.
37
+
38
+ Full guide: https://sungen.sun-asterisk.vn/docs/guides/data-factory
39
+ `;
40
+
41
+ /** Ensure `qa/data-factory/README.md` exists (write-if-absent). */
42
+ export function ensureDataFactoryReadme(cwd: string): void {
43
+ const dir = join(cwd, 'qa', 'data-factory');
44
+ const path = join(dir, 'README.md');
45
+ if (existsSync(path)) return;
46
+ try {
47
+ mkdirSync(dir, { recursive: true });
48
+ writeFileSync(path, README, 'utf8');
49
+ } catch {
50
+ /* best-effort — a missing README must never fail a data command */
51
+ }
52
+ }