Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33

Open
lilleman wants to merge 966 commits from worktree-todo-relative-dates-exact-counts into main
3 changed files with 21 additions and 8 deletions
Showing only changes of commit 1edc3b57dd - Show all commits
+17 -4
View File
@@ -352,6 +352,8 @@ v = t.Fake() // render many times,
r, err := f.FakeRecord("users") // one record: each field a column
s := r.JSON() // {"first":"Ada","last":"Lovelace"}
r, err = f.FakeRecordTemplate(`{"format":"{x}","x":["a","b"]}`) // compile + render inline
rt, err := f.NewRecordTemplate(`{"format":"","id":"{seq(users)}"}`) // compile a record once
r = rt.Fake() // render a row; loop this for bulk output
err = f.FakeStruct(&user) // fill a struct's fake:"…" tagged fields
ok, err := fejkdata.IsTemplate(arg) // an inline template by its shape, else a path
```
@@ -363,7 +365,8 @@ ok, err := fejkdata.IsTemplate(arg) // an inline template by its shape, el
| `WithDataFS(modules...)` | layer modules in order, each an `fs.FS`: a shipped package's `Modules()...`, or your own `embed.FS`; `WithDataFS()` loads none |
A shipped package's `Modules()` returns its own `FS` and every module it reads, such as a
locale's country's places. Your program links only the packages it imports.
locale's country's places; `misc.*` comes from `misc.Modules()`, in
`github.com/larvit/fejkdata/data/misc`. Your program links only the packages it imports.
`data.Modules()`, from `github.com/larvit/fejkdata/data`, is every shipped module, and
links all of them. Two locales, with `enus` from `github.com/larvit/fejkdata/data/en_US`,
are `WithDataFS(append(svse.Modules(), enus.Modules()...)...)`. To stand in your
@@ -389,7 +392,7 @@ A path, wherever a call takes one, may start with one `/`, as a reference does.
A `*Record` carries its columns via `Columns()` — each a `Column` of `Name`,
`DataType`, rendered `Value` and `Null` — and serializes them with `JSON()`
(one object), `CSVHeader()`/`CSVLine()`, or `SQLInsert(table)` — the shapes the
CLI's `--format` writes. `FakeRecord` and `FakeRecordTemplate` take a record; a
CLI's `--format` writes, each without a trailing newline. `FakeRecord` and `FakeRecordTemplate` take a record; a
path or template that is not one — a bare string, a choice of more than one item, or a
folder — errors.
@@ -401,6 +404,12 @@ type User struct {
Nick *string `fake:"[null, \"{/sv_SE.username}\"]"`
Home Address // filled from Address's own tags
}
type Address struct {
Street string `fake:"{/sv_SE.address as a}{a.street} {a.street-number}"`
PostalCode string `fake:"{a.postal-code}"` // the same address's code
Locality string `fake:"{a.locality}"`
}
```
`FakeStruct` fills a struct through a pointer: each exported field tagged `fake:"…"` is
@@ -447,7 +456,10 @@ var mydata embed.FS
func main() { os.Exit(cli.Main(append(data.Modules(), mydata)...)) }
```
Add `*.tsv` to the embed where your data holds a table. The CLI takes `fejkdata`'s flags
The embed's folders are the paths: `//go:embed acme` serves `acme/customer.json` as
`{/acme.customer}`. Add `*.tsv` to the embed where your data holds a table. The CLI loads
its data when it runs, so a test calling `fejkdata.New(fejkdata.WithDataFS(...))` over the
same modules catches broken data at `go test`. The CLI takes `fejkdata`'s flags
and exit codes, and names itself by the file it runs from in its help and errors. `--no-shipped-data` leaves out the modules passed to `Main`, and
`--version` prints your module's version beside the fejkdata version it is built with.
@@ -768,7 +780,8 @@ Rejected at `New`: a bound that is no calendar date, or after the other; an unqu
or double-quoted layout, naming the single-quoted one; and `time` with a layout naming a
date field, naming `date`, since `time` draws no date. `{seq()}` spans `Fake`
calls and `repeat`, resets with a new generator, and is the natural primary key for
the SQL example above.
the SQL example above; give each table its own counter, `{seq(orders)}`, where one
generator fills several.
### Computation
+2 -2
View File
@@ -139,7 +139,7 @@ A directory a machine happens to have would make `--seed 42` machine-dependent;
## The shipped data is Go packages a library imports by choice, and the CLI carries every one, from 0.1.0
2026-10-04, Lilleman auf Larv; revised 2026-10-09 to put the packages in the core's Go module. Serves goals 2.2, 6.2, 7.3, 9 and 10.1. Carried out by `todo.md` items 181, 185, 186 and 196. The CLI binary may grow to hundreds of MB.
2026-10-04, Lilleman auf Larv; revised 2026-10-09 to put the packages in the core's Go module. Serves goals 2.2, 6.2, 7.3, 9 and 10.1. Carried out by `todo.md` items 181, 186 and 196. The CLI binary may grow to hundreds of MB.
- One Go package per locale, one per country's `geo` tree, and one for `misc`, all in the core's Go module. A package registers nothing when imported.
- A bare `New()` loads no data and fails, naming the option to add. `WithoutShippedData` goes.
@@ -149,7 +149,7 @@ A directory a machine happens to have would make `--seed 42` machine-dependent;
- In the CLI, a flag of its own says a `--data-path` replaces what it clashes with, so flags still go anywhere on the line. Data authors and hand fixture authors bench it.
- The README asks for functions with no side effects of their own.
- The CLI is a library call. One exported list names every shipped package, and `fejkdata`'s own `main` passes it to that call. The list lives in a package of its own, so a library importing the core links no data it did not import. A custom CLI is the same few lines with other modules added. No API and no flag exists only for custom CLIs; `Main` tells one apart only by its build info and file name, so its help and errors carry its name and its `--version` its own module's version beside fejkdata's. The maintainer chose so on 2026-10-11.
- Before the module API ships, a panel of the README's audience personas tries pulling in data with it.
- The help's examples and its hint for an empty stdin read no data, so each renders in any custom CLI; `--list` points to the paths. "Shipped data", in `--no-shipped-data` and in `-d`'s help, names the modules passed to `Main`, a custom CLI's own included. A custom-CLI builder ruled so on 2026-10-11, in the audience bench that preceded the module API's release.
Valid while the shipped data stays under 100 MiB, which a gate test holds (`todo.md` item 192): `go get` fetches the whole Go module, and the `go` command refuses a Go module zip over 500 MiB (`MaxZipFile` in `golang.org/x/mod/zip`). Past it, `todo.md` item 193 moves the largest packages into nested Go modules that keep their import paths, each requiring the core release that drops the package, so no build sees it twice.
+2 -2
View File
@@ -92,8 +92,8 @@ func (loadError) Is(target error) bool { return target == ErrLoad }
// winning a name clash; it fails where no [WithDataFS] or [WithDataPath] names the data
// to load. Each JSON file becomes a category named after the file (address.json ->
// "address") and each subdirectory a namespace segment. It errors on a missing
// directory, invalid JSON or invalid data; a generator with no data at all renders
// templates that read none. A source whose .fejkdata.json carries an index, as each
// directory, invalid JSON or invalid data. WithDataFS() alone loads no data, and the
// generator renders templates that read none. A source whose .fejkdata.json carries an index, as each
// shipped module's does, loads each category on the first call reaching it. Data failing
// to load, in New or on that first call, gives an error matching [ErrLoad].
func New(opts ...Option) (*Generator, error) {