@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 +2 -2
- package/src/cli.ts +4 -0
- package/src/readme.ts +52 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sungen/driver-data-factory",
|
|
3
|
-
"version": "3.2.10-beta.
|
|
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.
|
|
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
|
+
}
|