@metaobjectsdev/codegen-ts-tanstack 0.24.3 → 0.24.5
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/README.md +9 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/reference-templates.d.ts +5 -0
- package/dist/reference-templates.d.ts.map +1 -0
- package/dist/reference-templates.js +12 -0
- package/dist/reference-templates.js.map +1 -0
- package/dist/tanstack-grid-hook.d.ts.map +1 -1
- package/dist/tanstack-grid-hook.js +2 -2
- package/dist/tanstack-grid-hook.js.map +1 -1
- package/dist/tanstack-grid.d.ts.map +1 -1
- package/dist/tanstack-grid.js +2 -2
- package/dist/tanstack-grid.js.map +1 -1
- package/dist/tanstack-query.d.ts.map +1 -1
- package/dist/tanstack-query.js +4 -2
- package/dist/tanstack-query.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +19 -0
- package/src/reference/grid-hook.ts +114 -0
- package/src/reference/grid.ts +93 -0
- package/src/reference/hooks.ts +93 -0
- package/src/reference-templates.ts +16 -0
- package/src/tanstack-grid-hook.ts +7 -2
- package/src/tanstack-grid.ts +7 -2
- package/src/tanstack-query.ts +9 -2
package/README.md
CHANGED
|
@@ -57,6 +57,15 @@ the entity module from wherever `entityFile()` is routed (relative when same tar
|
|
|
57
57
|
the entity-module target's `importBase` when not); the grid-hook imports its sibling
|
|
58
58
|
`<Entity>.columns` from within its own target.
|
|
59
59
|
|
|
60
|
+
### The generator is yours
|
|
61
|
+
|
|
62
|
+
Each of `tanstackQuery()`, `tanstackGrid()` and `tanstackGridHook()` has a reference template:
|
|
63
|
+
`meta eject hooks` / `grid` / `grid-hook` copies one into `codegen/generators/` for you to own. Each
|
|
64
|
+
renderer (`renderHooksFile`, `renderColumnsFile`, `renderGridHookFile`) is exported, so retargeting
|
|
65
|
+
is usually a wrapper, not a rewrite — compose it and change the one step your framework needs.
|
|
66
|
+
Inside the ejected file's existing `if (!ctx.renderContext) throw …` guard, change only the
|
|
67
|
+
`content:` line, e.g. `content: '"use client";\n' + renderHooksFile(entity, ctx.renderContext)`.
|
|
68
|
+
|
|
60
69
|
## Pairs with
|
|
61
70
|
|
|
62
71
|
- Runtime: [`@metaobjectsdev/tanstack`](../../../../client/web/packages/tanstack) — generated hooks and columns import from here.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export { tanstackQuery, type TanstackQueryOpts } from "./tanstack-query.js";
|
|
2
2
|
export { tanstackGrid, type TanstackGridOpts } from "./tanstack-grid.js";
|
|
3
3
|
export { tanstackGridHook, type TanstackGridHookOpts } from "./tanstack-grid-hook.js";
|
|
4
|
+
export { renderHooksFile } from "./templates/hooks-file.js";
|
|
5
|
+
export { renderColumnsFile } from "./templates/columns-file.js";
|
|
6
|
+
export { renderGridHookFile } from "./templates/grid-hook-file.js";
|
|
7
|
+
export { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
8
|
+
export { resolveReferenceRoot, readReferenceTemplate, REFERENCE_GENERATOR_NAMES } from "./reference-templates.js";
|
|
9
|
+
export type { ReferenceGeneratorName } from "./reference-templates.js";
|
|
4
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAItF,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAMnE,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAInF,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAGlH,YAAY,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,4 +2,17 @@
|
|
|
2
2
|
export { tanstackQuery } from "./tanstack-query.js";
|
|
3
3
|
export { tanstackGrid } from "./tanstack-grid.js";
|
|
4
4
|
export { tanstackGridHook } from "./tanstack-grid-hook.js";
|
|
5
|
+
// FR-040 §4.2(b) — public so an owned generator composes the engine rather than
|
|
6
|
+
// forking it. Signatures are stable API: (entity, ctx) => string.
|
|
7
|
+
export { renderHooksFile } from "./templates/hooks-file.js";
|
|
8
|
+
export { renderColumnsFile } from "./templates/columns-file.js";
|
|
9
|
+
export { renderGridHookFile } from "./templates/grid-hook-file.js";
|
|
10
|
+
// FR-040 §4.2(b) — the grid/grid-hook data-grid opt-in gate is a STEP in the pipeline
|
|
11
|
+
// those two owned templates compose, not an internal detail either may fork. Public so
|
|
12
|
+
// `grid.ts` and `grid-hook.ts` import one shared implementation instead of each
|
|
13
|
+
// carrying its own copy.
|
|
14
|
+
export { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
15
|
+
// FR-040 §4.1 — the copyable reference generators this package ships in
|
|
16
|
+
// `src/reference/`, and the reader `meta init`/`meta eject` use to read them.
|
|
17
|
+
export { resolveReferenceRoot, readReferenceTemplate, REFERENCE_GENERATOR_NAMES } from "./reference-templates.js";
|
|
5
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAA0B,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAyB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAA6B,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,OAAO,EAAE,aAAa,EAA0B,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAyB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAA6B,MAAM,yBAAyB,CAAC;AAEtF,gFAAgF;AAChF,kEAAkE;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,sFAAsF;AACtF,uFAAuF;AACvF,gFAAgF;AAChF,yBAAyB;AACzB,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,wEAAwE;AACxE,8EAA8E;AAC9E,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const REFERENCE_GENERATOR_NAMES: readonly ["hooks", "grid", "grid-hook"];
|
|
2
|
+
export type ReferenceGeneratorName = (typeof REFERENCE_GENERATOR_NAMES)[number];
|
|
3
|
+
export declare function resolveReferenceRoot(): string;
|
|
4
|
+
export declare function readReferenceTemplate(name: ReferenceGeneratorName): string;
|
|
5
|
+
//# sourceMappingURL=reference-templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-templates.d.ts","sourceRoot":"","sources":["../src/reference-templates.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,yBAAyB,yCAA0C,CAAC;AACjF,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAIhF,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,CAE1E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// FR-040 §4.1 — this package hosts its own copyable reference generators in
|
|
2
|
+
// `src/reference/`, read through the shared factory so the resolver is not duplicated.
|
|
3
|
+
import { makeReferenceReader } from "@metaobjectsdev/codegen-ts";
|
|
4
|
+
export const REFERENCE_GENERATOR_NAMES = ["hooks", "grid", "grid-hook"];
|
|
5
|
+
const reader = makeReferenceReader(import.meta.url, REFERENCE_GENERATOR_NAMES);
|
|
6
|
+
export function resolveReferenceRoot() {
|
|
7
|
+
return reader.resolveReferenceRoot();
|
|
8
|
+
}
|
|
9
|
+
export function readReferenceTemplate(name) {
|
|
10
|
+
return reader.readReferenceTemplate(name);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=reference-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reference-templates.js","sourceRoot":"","sources":["../src/reference-templates.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,uFAAuF;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAU,CAAC;AAGjF,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;AAE/E,MAAM,UAAU,oBAAoB;IAClC,OAAO,MAAM,CAAC,oBAAoB,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAA4B;IAChE,OAAO,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstack-grid-hook.d.ts","sourceRoot":"","sources":["../src/tanstack-grid-hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"tanstack-grid-hook.d.ts","sourceRoot":"","sources":["../src/tanstack-grid-hook.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,EAExD,MAAM,4BAA4B,CAAC;AAIpC,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EA0DxB,gBAAgB,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { perEntity, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID } from "@metaobjectsdev/codegen-ts";
|
|
1
|
+
import { perEntity, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID, withClientDirective, } from "@metaobjectsdev/codegen-ts";
|
|
2
2
|
import { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
3
3
|
import { renderGridHookFile } from "./templates/grid-hook-file.js";
|
|
4
4
|
/**
|
|
@@ -42,7 +42,7 @@ export const tanstackGridHook = function tanstackGridHook(opts) {
|
|
|
42
42
|
content: await formatTs(renderEntityMetaFile(entity, ctx.renderContext.apiPrefix)),
|
|
43
43
|
}, {
|
|
44
44
|
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.grid.ts`),
|
|
45
|
-
content: await formatTs(renderGridHookFile(entity, ctx.renderContext)),
|
|
45
|
+
content: withClientDirective(await formatTs(renderGridHookFile(entity, ctx.renderContext)), ctx.renderContext.clientDirective),
|
|
46
46
|
}];
|
|
47
47
|
});
|
|
48
48
|
const generator = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstack-grid-hook.js","sourceRoot":"","sources":["../src/tanstack-grid-hook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"tanstack-grid-hook.js","sourceRoot":"","sources":["../src/tanstack-grid-hook.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EAAE,sBAAsB,EAC9M,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAOnE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,gBAAgB,CAAC,IAA2B;IACnF,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,gFAAgF;IAChF,iFAAiF;IACjF,gFAAgF;IAChF,0BAA0B;IAC1B,EAAE;IACF,sFAAsF;IACtF,wFAAwF;IACxF,yFAAyF;IACzF,uFAAuF;IACvF,oFAAoF;IACpF,mFAAmF;IACnF,sFAAsF;IACtF,yDAAyD;IACzD,MAAM,gBAAgB,GAAG,CAAC,CAAa,EAAW,EAAE,CAClD,aAAa,CAAC,CAAC,CAAC;QAChB,2FAA2F;WACxF,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,KAAK,KAAK;WAC5C,UAAU,CAAC,CAAC,CAAC;WACb,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,MAAkB,EAAE,GAAG,EAAE,EAAE;QACvD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACxF,CAAC;QACD,0EAA0E;QAC1E,8EAA8E;QAC9E,+EAA+E;QAC/E,+EAA+E;QAC/E,2BAA2B;QAC3B,OAAO,CAAC;gBACN,IAAI,EAAE,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,EACnE,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAClC,OAAO,EAAE,MAAM,QAAQ,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;aACnF,EAAE;gBACD,IAAI,EAAE,gBAAgB,CACpB,GAAG,CAAC,aAAa,CAAC,YAAY,EAC9B,MAAM,CAAC,OAAO,EACd,GAAG,MAAM,CAAC,IAAI,UAAU,CACzB;gBACD,OAAO,EAAE,mBAAmB,CAC1B,MAAM,QAAQ,CAAC,kBAAkB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,EAC7D,GAAG,CAAC,aAAa,CAAC,eAAe,CAClC;aACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,oBAAoB;QAC1B,MAAM,EAAE,CAAC,CAAa,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC;QACtE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACtB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;YACrE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;KACF,CAAC;IACF,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAkD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstack-grid.d.ts","sourceRoot":"","sources":["../src/tanstack-grid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"tanstack-grid.d.ts","sourceRoot":"","sources":["../src/tanstack-grid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,EAExD,MAAM,4BAA4B,CAAC;AAIpC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAwCpB,gBAAgB,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC"}
|
package/dist/tanstack-grid.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { perEntity, formatTs, entityOutputPath, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID } from "@metaobjectsdev/codegen-ts";
|
|
1
|
+
import { perEntity, formatTs, entityOutputPath, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID, withClientDirective, } from "@metaobjectsdev/codegen-ts";
|
|
2
2
|
import { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
3
3
|
import { renderColumnsFile } from "./templates/columns-file.js";
|
|
4
4
|
/**
|
|
@@ -27,7 +27,7 @@ export const tanstackGrid = function tanstackGrid(opts) {
|
|
|
27
27
|
}
|
|
28
28
|
return {
|
|
29
29
|
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.columns.tsx`),
|
|
30
|
-
content: await formatTs(renderColumnsFile(entity, ctx.renderContext)),
|
|
30
|
+
content: withClientDirective(await formatTs(renderColumnsFile(entity, ctx.renderContext)), ctx.renderContext.clientDirective),
|
|
31
31
|
};
|
|
32
32
|
});
|
|
33
33
|
const generator = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstack-grid.js","sourceRoot":"","sources":["../src/tanstack-grid.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"tanstack-grid.js","sourceRoot":"","sources":["../src/tanstack-grid.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EAAE,sBAAsB,EACpK,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAOhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,YAAY,CAAC,IAAuB;IACvE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,gFAAgF;IAChF,2EAA2E;IAC3E,0EAA0E;IAC1E,iFAAiF;IACjF,kFAAkF;IAClF,0BAA0B;IAC1B,iFAAiF;IACjF,iFAAiF;IACjF,MAAM,gBAAgB,GAAG,CAAC,CAAa,EAAW,EAAE,CAClD,aAAa,CAAC,CAAC,CAAC;QAChB,2FAA2F;WACxF,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,KAAK,KAAK;WAC5C,UAAU,CAAC,CAAC,CAAC;WACb,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,KAAK,IAAI,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,MAAkB,EAAE,GAAG,EAAE,EAAE;QACvD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QACD,OAAO;YACL,IAAI,EAAE,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,cAAc,CAAC;YACpG,OAAO,EAAE,mBAAmB,CAC1B,MAAM,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,EAC5D,GAAG,CAAC,aAAa,CAAC,eAAe,CAClC;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,eAAe;QACrB,MAAM,EAAE,CAAC,CAAa,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC;QACtE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACtB,yBAAyB,CAAC,GAAG,EAAE,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;YACzE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;KACF,CAAC;IACF,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAA8C,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstack-query.d.ts","sourceRoot":"","sources":["../src/tanstack-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"tanstack-query.d.ts","sourceRoot":"","sources":["../src/tanstack-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAA6B,KAAK,gBAAgB,EAExD,MAAM,4BAA4B,CAAC;AAGpC,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EA0CrB,gBAAgB,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC"}
|
package/dist/tanstack-query.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { perEntity, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK } from "@metaobjectsdev/codegen-ts";
|
|
1
|
+
import { perEntity, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, withClientDirective, } from "@metaobjectsdev/codegen-ts";
|
|
2
2
|
import { renderHooksFile } from "./templates/hooks-file.js";
|
|
3
3
|
/**
|
|
4
4
|
* Per-entity generator that emits <Entity>.hooks.ts — a query-key factory
|
|
@@ -33,7 +33,9 @@ export const tanstackQuery = function tanstackQuery(opts) {
|
|
|
33
33
|
};
|
|
34
34
|
return [metaFile, {
|
|
35
35
|
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.hooks.ts`),
|
|
36
|
-
|
|
36
|
+
// Outside formatTs deliberately: the directive must stay the module's first
|
|
37
|
+
// token, and a formatter is entitled to move a leading string expression.
|
|
38
|
+
content: withClientDirective(await formatTs(renderHooksFile(entity, ctx.renderContext)), ctx.renderContext.clientDirective),
|
|
37
39
|
}];
|
|
38
40
|
}),
|
|
39
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tanstack-query.js","sourceRoot":"","sources":["../src/tanstack-query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,
|
|
1
|
+
{"version":3,"file":"tanstack-query.js","sourceRoot":"","sources":["../src/tanstack-query.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyC,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,0BAA0B,EACtL,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAO5D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,aAAa,CAAC,IAAwB;IAC1E,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,SAAS,GAAc;QAC3B,IAAI,EAAE,gBAAgB;QACtB,6EAA6E;QAC7E,6EAA6E;QAC7E,6EAA6E;QAC7E,0EAA0E;QAC1E,+EAA+E;QAC/E,iFAAiF;QACjF,iFAAiF;QACjF,MAAM,EAAE,CAAC,CAAa,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC;QAChI,QAAQ,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;YACxC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;gBACvB,MAAM,IAAI,KAAK,CACb,gEAAgE,CACjE,CAAC;YACJ,CAAC,CAAM,0EAA0E;YACjF,yEAAyE;YACzE,+EAA+E;YAC/E,gFAAgF;YAChF,qCAAqC;YACrC,MAAM,QAAQ,GAAG;gBACf,IAAI,EAAE,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,EACnE,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAClC,OAAO,EAAE,MAAM,QAAQ,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;aACnF,CAAC;YACF,OAAO,CAAC,QAAQ,EAAE;oBAChB,IAAI,EAAE,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,WAAW,CAAC;oBACjG,4EAA4E;oBAC5E,0EAA0E;oBAC1E,OAAO,EAAE,mBAAmB,CAC1B,MAAM,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,EAC1D,GAAG,CAAC,aAAa,CAAC,eAAe,CAClC;iBACF,CAAC,CAAC;QACL,CAAC,CAAC;KACH,CAAC;IACF,IAAI,IAAI,EAAE,MAAM,EAAE,CAAC;QACjB,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAA+C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/codegen-ts-tanstack",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.5",
|
|
4
4
|
"description": "TanStack codegen for metaobjects — TanStack Query hooks for every entity, plus TanStack Table column definitions and grid-state hooks for entities declaring a layout.dataGrid.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@metaobjectsdev/metadata": "0.24.
|
|
48
|
-
"@metaobjectsdev/codegen-ts": "0.24.
|
|
47
|
+
"@metaobjectsdev/metadata": "0.24.5",
|
|
48
|
+
"@metaobjectsdev/codegen-ts": "0.24.5",
|
|
49
49
|
"ts-poet": "^6.10.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -2,3 +2,22 @@
|
|
|
2
2
|
export { tanstackQuery, type TanstackQueryOpts } from "./tanstack-query.js";
|
|
3
3
|
export { tanstackGrid, type TanstackGridOpts } from "./tanstack-grid.js";
|
|
4
4
|
export { tanstackGridHook, type TanstackGridHookOpts } from "./tanstack-grid-hook.js";
|
|
5
|
+
|
|
6
|
+
// FR-040 §4.2(b) — public so an owned generator composes the engine rather than
|
|
7
|
+
// forking it. Signatures are stable API: (entity, ctx) => string.
|
|
8
|
+
export { renderHooksFile } from "./templates/hooks-file.js";
|
|
9
|
+
export { renderColumnsFile } from "./templates/columns-file.js";
|
|
10
|
+
export { renderGridHookFile } from "./templates/grid-hook-file.js";
|
|
11
|
+
|
|
12
|
+
// FR-040 §4.2(b) — the grid/grid-hook data-grid opt-in gate is a STEP in the pipeline
|
|
13
|
+
// those two owned templates compose, not an internal detail either may fork. Public so
|
|
14
|
+
// `grid.ts` and `grid-hook.ts` import one shared implementation instead of each
|
|
15
|
+
// carrying its own copy.
|
|
16
|
+
export { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
17
|
+
|
|
18
|
+
// FR-040 §4.1 — the copyable reference generators this package ships in
|
|
19
|
+
// `src/reference/`, and the reader `meta init`/`meta eject` use to read them.
|
|
20
|
+
export { resolveReferenceRoot, readReferenceTemplate, REFERENCE_GENERATOR_NAMES } from "./reference-templates.js";
|
|
21
|
+
// The name union travels with the names array — codegen-ts exports both, and a
|
|
22
|
+
// consumer keying anything by ejectable name needs the type as much as the values.
|
|
23
|
+
export type { ReferenceGeneratorName } from "./reference-templates.js";
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// REFERENCE TEMPLATE — copy this into your repo (e.g. codegen/generators/grid-hook.ts) and own it.
|
|
2
|
+
// Then import it LOCALLY in metaobjects.config.ts:
|
|
3
|
+
// import { tanstackGridHook } from "./codegen/generators/grid-hook.js";
|
|
4
|
+
//
|
|
5
|
+
// RUNTIME: this file executes under whatever runs `meta gen` — NODE, even in a Bun
|
|
6
|
+
// project. Do not reach for `Bun.*` globals here.
|
|
7
|
+
// targets: TanStack Query. The emitted hook calls `useEntityFetcher()` from
|
|
8
|
+
// `@metaobjectsdev/tanstack`, so the module is a CLIENT component.
|
|
9
|
+
// If your framework compiles server and client from one tree and resolves
|
|
10
|
+
// each half under different conditions, the emitted file may need a marker
|
|
11
|
+
// directive — prepend it to `renderGridHookFile`'s result below. That is a
|
|
12
|
+
// one-line change in THIS file and is the intended way to do it.
|
|
13
|
+
// use-when: you want a use<Entity><Grid>Grid() state hook — sort/filter/pagination
|
|
14
|
+
// wired to TanStack Query — for each `layout.dataGrid` an entity declares.
|
|
15
|
+
// emits: <target>/<Entity>.grid.ts, plus the DB-free <Entity>.meta.ts descriptor
|
|
16
|
+
// the hook module imports from. Emissions byte-identical to another UI
|
|
17
|
+
// generator's copy of the same descriptor collapse to one file (#266).
|
|
18
|
+
// customize: this generator is YOURS. `renderGridHookFile` (exported from
|
|
19
|
+
// @metaobjectsdev/codegen-ts-tanstack) produces the hook body — wrap it,
|
|
20
|
+
// prepend to it, or replace the call entirely with your own renderer.
|
|
21
|
+
// composes-with: grid.ts (the column definitions this hook's grid state pairs with).
|
|
22
|
+
|
|
23
|
+
import { type MetaObject } from "@metaobjectsdev/metadata";
|
|
24
|
+
import {
|
|
25
|
+
perEntity,
|
|
26
|
+
type Generator,
|
|
27
|
+
type GeneratorFactory,
|
|
28
|
+
formatTs,
|
|
29
|
+
entityOutputPath,
|
|
30
|
+
entityMetaFileName,
|
|
31
|
+
renderEntityMetaFile,
|
|
32
|
+
servesReadApi,
|
|
33
|
+
isTphSubtype,
|
|
34
|
+
CODEGEN_ATTR_EMIT_TANSTACK,
|
|
35
|
+
CODEGEN_ATTR_EMIT_GRID,
|
|
36
|
+
withClientDirective,
|
|
37
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
38
|
+
import {
|
|
39
|
+
renderGridHookFile,
|
|
40
|
+
hasDataGridLayout,
|
|
41
|
+
warnMissingDataGridLayout,
|
|
42
|
+
} from "@metaobjectsdev/codegen-ts-tanstack";
|
|
43
|
+
|
|
44
|
+
export interface TanstackGridHookOpts {
|
|
45
|
+
filter?: (entity: MetaObject) => boolean;
|
|
46
|
+
target?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Per-entity generator that emits <Entity>.grid.ts — one
|
|
51
|
+
* use<Entity><Grid>Grid() hook per layout[dataGrid] declared on the entity.
|
|
52
|
+
*
|
|
53
|
+
* Per-entity opt-out via @emitTanstack: false. Per-entity opt-IN: presence of
|
|
54
|
+
* at least one dataGrid layout on the object (mirrors tanstackGrid).
|
|
55
|
+
*/
|
|
56
|
+
export const tanstackGridHook = function tanstackGridHook(opts?: TanstackGridHookOpts): Generator {
|
|
57
|
+
const userFilter = opts?.filter ?? (() => true);
|
|
58
|
+
// Every gate EXCEPT the dataGrid-layout opt-in: the framework instance-artifact
|
|
59
|
+
// guard (skips abstract types), the metadata opt-out, and the user filter. Split
|
|
60
|
+
// out so the discoverability note can name exactly the entities the LAYOUT gate
|
|
61
|
+
// alone held back (#287).
|
|
62
|
+
//
|
|
63
|
+
// The TPH clause must MATCH tanstackGrid's exactly. A TPH subtype inherits its base's
|
|
64
|
+
// dataGrid layout via extends, so `hasDataGridLayout` is true for it — but tanstackGrid
|
|
65
|
+
// deliberately emits no per-subtype columns without an own `@emitGrid: true` (the base's
|
|
66
|
+
// polymorphic grid is the single source of truth). Without the same clause here, a TPH
|
|
67
|
+
// subtype got a `<Sub>.grid.ts` whose sibling `<Sub>.columns.tsx` is never emitted:
|
|
68
|
+
// a dangling `use<Sub>DefaultGrid()` with nothing to pair it with, and an outright
|
|
69
|
+
// TS2307 when the inherited layout carries an `@filter` preset (the hook then imports
|
|
70
|
+
// `<sub>DefaultFilter` from the missing columns module).
|
|
71
|
+
const passesOtherGates = (e: MetaObject): boolean =>
|
|
72
|
+
servesReadApi(e)
|
|
73
|
+
// ADR-0039: resolving — a concrete entity may inherit its @emit* opt-out flag via extends.
|
|
74
|
+
&& e.attr(CODEGEN_ATTR_EMIT_TANSTACK) !== false
|
|
75
|
+
&& userFilter(e)
|
|
76
|
+
&& (!isTphSubtype(e) || e.attr(CODEGEN_ATTR_EMIT_GRID) === true);
|
|
77
|
+
const emit = perEntity(async (entity: MetaObject, ctx) => {
|
|
78
|
+
if (!ctx.renderContext) {
|
|
79
|
+
throw new Error("tanstack-grid-hook: renderContext is required (provided by runGen)");
|
|
80
|
+
}
|
|
81
|
+
// Also emit the DB-free descriptor module this file imports from. Each UI
|
|
82
|
+
// generator emits it rather than relying on the consumer wiring an extra one:
|
|
83
|
+
// the entity generator is scaffold-and-own (ADR-0034), so it cannot be changed
|
|
84
|
+
// from the package. Emissions are byte-identical between generators, which the
|
|
85
|
+
// runner collapses (#266).
|
|
86
|
+
return [{
|
|
87
|
+
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package,
|
|
88
|
+
entityMetaFileName(entity.name)),
|
|
89
|
+
content: await formatTs(renderEntityMetaFile(entity, ctx.renderContext.apiPrefix)),
|
|
90
|
+
}, {
|
|
91
|
+
path: entityOutputPath(
|
|
92
|
+
ctx.renderContext.outputLayout,
|
|
93
|
+
entity.package,
|
|
94
|
+
`${entity.name}.grid.ts`,
|
|
95
|
+
),
|
|
96
|
+
content: withClientDirective(
|
|
97
|
+
await formatTs(renderGridHookFile(entity, ctx.renderContext)),
|
|
98
|
+
ctx.renderContext.clientDirective,
|
|
99
|
+
),
|
|
100
|
+
}];
|
|
101
|
+
});
|
|
102
|
+
const generator: Generator = {
|
|
103
|
+
name: "tanstack-grid-hook",
|
|
104
|
+
filter: (e: MetaObject) => passesOtherGates(e) && hasDataGridLayout(e),
|
|
105
|
+
generate: async (ctx) => {
|
|
106
|
+
warnMissingDataGridLayout(ctx, passesOtherGates, "<Entity>.grid.ts");
|
|
107
|
+
return emit(ctx);
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
if (opts?.target) {
|
|
111
|
+
generator.target = opts.target;
|
|
112
|
+
}
|
|
113
|
+
return generator;
|
|
114
|
+
} as GeneratorFactory<TanstackGridHookOpts | void>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// REFERENCE TEMPLATE — copy this into your repo (e.g. codegen/generators/grid.ts) and own it.
|
|
2
|
+
// Then import it LOCALLY in metaobjects.config.ts:
|
|
3
|
+
// import { tanstackGrid } from "./codegen/generators/grid.js";
|
|
4
|
+
//
|
|
5
|
+
// RUNTIME: this file executes under whatever runs `meta gen` — NODE, even in a Bun
|
|
6
|
+
// project. Do not reach for `Bun.*` globals here.
|
|
7
|
+
// targets: TanStack Table. The emitted module's `ColumnDef` comes from
|
|
8
|
+
// `@tanstack/react-table`, so it is a CLIENT component.
|
|
9
|
+
// If your framework compiles server and client from one tree and resolves
|
|
10
|
+
// each half under different conditions, the emitted file may need a marker
|
|
11
|
+
// directive — prepend it to `renderColumnsFile`'s result below. That is a
|
|
12
|
+
// one-line change in THIS file and is the intended way to do it.
|
|
13
|
+
// use-when: you want generated grid column definitions for any entity declaring a
|
|
14
|
+
// `layout.dataGrid` child.
|
|
15
|
+
// emits: <target>/<Entity>.columns.tsx — one column set per declared dataGrid
|
|
16
|
+
// layout; a TPH discriminator base's grid folds in its subtypes' fields.
|
|
17
|
+
// customize: this generator is YOURS. `renderColumnsFile` (exported from
|
|
18
|
+
// @metaobjectsdev/codegen-ts-tanstack) produces the column definitions —
|
|
19
|
+
// wrap it, prepend to it, or replace the call entirely with your own
|
|
20
|
+
// renderer.
|
|
21
|
+
// composes-with: entity.ts (imports the Row type the columns are typed against),
|
|
22
|
+
// hooks.ts (the query hook a grid usually pairs with).
|
|
23
|
+
|
|
24
|
+
import { type MetaObject } from "@metaobjectsdev/metadata";
|
|
25
|
+
import {
|
|
26
|
+
perEntity,
|
|
27
|
+
type Generator,
|
|
28
|
+
type GeneratorFactory,
|
|
29
|
+
formatTs,
|
|
30
|
+
entityOutputPath,
|
|
31
|
+
servesReadApi,
|
|
32
|
+
isTphSubtype,
|
|
33
|
+
CODEGEN_ATTR_EMIT_TANSTACK,
|
|
34
|
+
CODEGEN_ATTR_EMIT_GRID,
|
|
35
|
+
withClientDirective,
|
|
36
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
37
|
+
import {
|
|
38
|
+
renderColumnsFile,
|
|
39
|
+
hasDataGridLayout,
|
|
40
|
+
warnMissingDataGridLayout,
|
|
41
|
+
} from "@metaobjectsdev/codegen-ts-tanstack";
|
|
42
|
+
|
|
43
|
+
export interface TanstackGridOpts {
|
|
44
|
+
filter?: (entity: MetaObject) => boolean;
|
|
45
|
+
target?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Per-entity opt-out via `@emitTanstack: false`. Per-entity opt-IN: presence of
|
|
50
|
+
* at least one `dataGrid` layout on the object. If both pass and the user-supplied
|
|
51
|
+
* filter passes, the generator emits.
|
|
52
|
+
*/
|
|
53
|
+
export const tanstackGrid = function tanstackGrid(opts?: TanstackGridOpts): Generator {
|
|
54
|
+
const userFilter = opts?.filter ?? (() => true);
|
|
55
|
+
// Every gate EXCEPT the dataGrid-layout opt-in: the framework instance-artifact
|
|
56
|
+
// guard (skips abstract types), the metadata opt-out, and the user filter.
|
|
57
|
+
// FR-017 Tier 3: a TPH discriminator base emits ONE polymorphic grid. Its
|
|
58
|
+
// subtypes inherit the base's dataGrid layout via extends, but per-subtype grids
|
|
59
|
+
// are opt-IN only (own `@emitGrid: true`) — otherwise the polymorphic grid is the
|
|
60
|
+
// single source of truth.
|
|
61
|
+
// Split out so the discoverability note can name exactly the entities the LAYOUT
|
|
62
|
+
// gate alone held back (#287) — an opted-out or abstract type is not a surprise.
|
|
63
|
+
const passesOtherGates = (e: MetaObject): boolean =>
|
|
64
|
+
servesReadApi(e)
|
|
65
|
+
// ADR-0039: resolving — a concrete entity may inherit its @emit* opt-out flag via extends.
|
|
66
|
+
&& e.attr(CODEGEN_ATTR_EMIT_TANSTACK) !== false
|
|
67
|
+
&& userFilter(e)
|
|
68
|
+
&& (!isTphSubtype(e) || e.attr(CODEGEN_ATTR_EMIT_GRID) === true);
|
|
69
|
+
const emit = perEntity(async (entity: MetaObject, ctx) => {
|
|
70
|
+
if (!ctx.renderContext) {
|
|
71
|
+
throw new Error("tanstack-grid: renderContext is required (provided by runGen)");
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.columns.tsx`),
|
|
75
|
+
content: withClientDirective(
|
|
76
|
+
await formatTs(renderColumnsFile(entity, ctx.renderContext)),
|
|
77
|
+
ctx.renderContext.clientDirective,
|
|
78
|
+
),
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
const generator: Generator = {
|
|
82
|
+
name: "tanstack-grid",
|
|
83
|
+
filter: (e: MetaObject) => passesOtherGates(e) && hasDataGridLayout(e),
|
|
84
|
+
generate: async (ctx) => {
|
|
85
|
+
warnMissingDataGridLayout(ctx, passesOtherGates, "<Entity>.columns.tsx");
|
|
86
|
+
return emit(ctx);
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
if (opts?.target) {
|
|
90
|
+
generator.target = opts.target;
|
|
91
|
+
}
|
|
92
|
+
return generator;
|
|
93
|
+
} as GeneratorFactory<TanstackGridOpts | void>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// REFERENCE TEMPLATE — copy this into your repo (e.g. codegen/generators/hooks.ts) and own it.
|
|
2
|
+
// Then import it LOCALLY in metaobjects.config.ts:
|
|
3
|
+
// import { tanstackQuery } from "./codegen/generators/hooks.js";
|
|
4
|
+
//
|
|
5
|
+
// RUNTIME: this file executes under whatever runs `meta gen` — NODE, even in a Bun
|
|
6
|
+
// project. Do not reach for `Bun.*` globals here.
|
|
7
|
+
// targets: TanStack Query. The emitted hooks call `useEntityFetcher()` from
|
|
8
|
+
// `@metaobjectsdev/tanstack`, so the module is a CLIENT component.
|
|
9
|
+
// If your framework compiles server and client from one tree and resolves
|
|
10
|
+
// each half under different conditions, the emitted file may need a marker
|
|
11
|
+
// directive — prepend it to `renderHooksFile`'s result below. That is a
|
|
12
|
+
// one-line change in THIS file and is the intended way to do it.
|
|
13
|
+
// use-when: you want a query-key factory plus 2 query hooks and 3 mutation hooks,
|
|
14
|
+
// backed by TanStack Query, per entity.
|
|
15
|
+
// emits: <target>/<Entity>.hooks.ts, plus the DB-free <Entity>.meta.ts descriptor
|
|
16
|
+
// the hooks module imports from. Emissions byte-identical to another UI
|
|
17
|
+
// generator's copy of the same descriptor collapse to one file (#266).
|
|
18
|
+
// customize: this generator is YOURS. `renderHooksFile` (exported from
|
|
19
|
+
// @metaobjectsdev/codegen-ts-tanstack) produces the hooks body — wrap it,
|
|
20
|
+
// prepend to it, or replace the call entirely with your own renderer.
|
|
21
|
+
// composes-with: entity.ts (imports the table/schemas these hooks fetch/validate against).
|
|
22
|
+
|
|
23
|
+
import { type MetaObject } from "@metaobjectsdev/metadata";
|
|
24
|
+
import {
|
|
25
|
+
perEntity,
|
|
26
|
+
type Generator,
|
|
27
|
+
type GeneratorFactory,
|
|
28
|
+
formatTs,
|
|
29
|
+
entityOutputPath,
|
|
30
|
+
entityMetaFileName,
|
|
31
|
+
renderEntityMetaFile,
|
|
32
|
+
servesReadApi,
|
|
33
|
+
isTphSubtype,
|
|
34
|
+
CODEGEN_ATTR_EMIT_TANSTACK,
|
|
35
|
+
withClientDirective,
|
|
36
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
37
|
+
import { renderHooksFile } from "@metaobjectsdev/codegen-ts-tanstack";
|
|
38
|
+
|
|
39
|
+
export interface TanstackQueryOpts {
|
|
40
|
+
filter?: (entity: MetaObject) => boolean;
|
|
41
|
+
target?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Per-entity generator that emits <Entity>.hooks.ts — a query-key factory
|
|
46
|
+
* plus 2 query hooks and 3 mutation hooks backed by useEntityFetcher().
|
|
47
|
+
*
|
|
48
|
+
* Per-entity opt-out via `@emitTanstack: false` is honored. If the user
|
|
49
|
+
* supplies their own filter, both must pass (AND).
|
|
50
|
+
*/
|
|
51
|
+
export const tanstackQuery = function tanstackQuery(opts?: TanstackQueryOpts): Generator {
|
|
52
|
+
const userFilter = opts?.filter ?? (() => true);
|
|
53
|
+
const generator: Generator = {
|
|
54
|
+
name: "tanstack-query",
|
|
55
|
+
// AND-composes the framework instance-artifact guard (skips abstract types —
|
|
56
|
+
// they contribute shape via inheritance only and have no instance to query),
|
|
57
|
+
// the metadata opt-out, and the optional user filter. Projections still pass
|
|
58
|
+
// here and get read-only hooks via renderHooksFile's isProjection branch.
|
|
59
|
+
// FR-017 Tier 3: TPH subtypes get no standalone hooks file — their per-subtype
|
|
60
|
+
// hooks live in the discriminator base's hooks file (polymorphic + per-subtype).
|
|
61
|
+
// ADR-0039: resolving — a concrete entity may inherit @emitTanstack via extends.
|
|
62
|
+
filter: (e: MetaObject) => servesReadApi(e) && e.attr(CODEGEN_ATTR_EMIT_TANSTACK) !== false && !isTphSubtype(e) && userFilter(e),
|
|
63
|
+
generate: perEntity(async (entity, ctx) => {
|
|
64
|
+
if (!ctx.renderContext) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
"tanstack-query: renderContext is required (provided by runGen)",
|
|
67
|
+
);
|
|
68
|
+
} // Also emit the DB-free descriptor module this file imports from. Each UI
|
|
69
|
+
// generator emits it rather than relying on the consumer wiring an extra
|
|
70
|
+
// generator: the entity generator is scaffold-and-own (ADR-0034), so it cannot
|
|
71
|
+
// be changed from the package. Emissions are byte-identical between generators,
|
|
72
|
+
// which the runner collapses (#266).
|
|
73
|
+
const metaFile = {
|
|
74
|
+
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package,
|
|
75
|
+
entityMetaFileName(entity.name)),
|
|
76
|
+
content: await formatTs(renderEntityMetaFile(entity, ctx.renderContext.apiPrefix)),
|
|
77
|
+
};
|
|
78
|
+
return [metaFile, {
|
|
79
|
+
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.hooks.ts`),
|
|
80
|
+
// Outside formatTs deliberately: the directive must stay the module's first
|
|
81
|
+
// token, and a formatter is entitled to move a leading string expression.
|
|
82
|
+
content: withClientDirective(
|
|
83
|
+
await formatTs(renderHooksFile(entity, ctx.renderContext)),
|
|
84
|
+
ctx.renderContext.clientDirective,
|
|
85
|
+
),
|
|
86
|
+
}];
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
if (opts?.target) {
|
|
90
|
+
generator.target = opts.target;
|
|
91
|
+
}
|
|
92
|
+
return generator;
|
|
93
|
+
} as GeneratorFactory<TanstackQueryOpts | void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// FR-040 §4.1 — this package hosts its own copyable reference generators in
|
|
2
|
+
// `src/reference/`, read through the shared factory so the resolver is not duplicated.
|
|
3
|
+
import { makeReferenceReader } from "@metaobjectsdev/codegen-ts";
|
|
4
|
+
|
|
5
|
+
export const REFERENCE_GENERATOR_NAMES = ["hooks", "grid", "grid-hook"] as const;
|
|
6
|
+
export type ReferenceGeneratorName = (typeof REFERENCE_GENERATOR_NAMES)[number];
|
|
7
|
+
|
|
8
|
+
const reader = makeReferenceReader(import.meta.url, REFERENCE_GENERATOR_NAMES);
|
|
9
|
+
|
|
10
|
+
export function resolveReferenceRoot(): string {
|
|
11
|
+
return reader.resolveReferenceRoot();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function readReferenceTemplate(name: ReferenceGeneratorName): string {
|
|
15
|
+
return reader.readReferenceTemplate(name);
|
|
16
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
2
|
-
import { perEntity, type Generator, type GeneratorFactory, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID
|
|
2
|
+
import { perEntity, type Generator, type GeneratorFactory, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID,
|
|
3
|
+
withClientDirective,
|
|
4
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
3
5
|
import { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
4
6
|
import { renderGridHookFile } from "./templates/grid-hook-file.js";
|
|
5
7
|
|
|
@@ -55,7 +57,10 @@ export const tanstackGridHook = function tanstackGridHook(opts?: TanstackGridHoo
|
|
|
55
57
|
entity.package,
|
|
56
58
|
`${entity.name}.grid.ts`,
|
|
57
59
|
),
|
|
58
|
-
content:
|
|
60
|
+
content: withClientDirective(
|
|
61
|
+
await formatTs(renderGridHookFile(entity, ctx.renderContext)),
|
|
62
|
+
ctx.renderContext.clientDirective,
|
|
63
|
+
),
|
|
59
64
|
}];
|
|
60
65
|
});
|
|
61
66
|
const generator: Generator = {
|
package/src/tanstack-grid.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
2
|
-
import { perEntity, type Generator, type GeneratorFactory, formatTs, entityOutputPath, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID
|
|
2
|
+
import { perEntity, type Generator, type GeneratorFactory, formatTs, entityOutputPath, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK, CODEGEN_ATTR_EMIT_GRID,
|
|
3
|
+
withClientDirective,
|
|
4
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
3
5
|
import { hasDataGridLayout, warnMissingDataGridLayout } from "./data-grid-gate.js";
|
|
4
6
|
import { renderColumnsFile } from "./templates/columns-file.js";
|
|
5
7
|
|
|
@@ -35,7 +37,10 @@ export const tanstackGrid = function tanstackGrid(opts?: TanstackGridOpts): Gene
|
|
|
35
37
|
}
|
|
36
38
|
return {
|
|
37
39
|
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.columns.tsx`),
|
|
38
|
-
content:
|
|
40
|
+
content: withClientDirective(
|
|
41
|
+
await formatTs(renderColumnsFile(entity, ctx.renderContext)),
|
|
42
|
+
ctx.renderContext.clientDirective,
|
|
43
|
+
),
|
|
39
44
|
};
|
|
40
45
|
});
|
|
41
46
|
const generator: Generator = {
|
package/src/tanstack-query.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
2
|
-
import { perEntity, type Generator, type GeneratorFactory, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK
|
|
2
|
+
import { perEntity, type Generator, type GeneratorFactory, formatTs, entityOutputPath, entityMetaFileName, renderEntityMetaFile, servesReadApi, isTphSubtype, CODEGEN_ATTR_EMIT_TANSTACK,
|
|
3
|
+
withClientDirective,
|
|
4
|
+
} from "@metaobjectsdev/codegen-ts";
|
|
3
5
|
import { renderHooksFile } from "./templates/hooks-file.js";
|
|
4
6
|
|
|
5
7
|
export interface TanstackQueryOpts {
|
|
@@ -43,7 +45,12 @@ export const tanstackQuery = function tanstackQuery(opts?: TanstackQueryOpts): G
|
|
|
43
45
|
};
|
|
44
46
|
return [metaFile, {
|
|
45
47
|
path: entityOutputPath(ctx.renderContext.outputLayout, entity.package, `${entity.name}.hooks.ts`),
|
|
46
|
-
|
|
48
|
+
// Outside formatTs deliberately: the directive must stay the module's first
|
|
49
|
+
// token, and a formatter is entitled to move a leading string expression.
|
|
50
|
+
content: withClientDirective(
|
|
51
|
+
await formatTs(renderHooksFile(entity, ctx.renderContext)),
|
|
52
|
+
ctx.renderContext.clientDirective,
|
|
53
|
+
),
|
|
47
54
|
}];
|
|
48
55
|
}),
|
|
49
56
|
};
|