create-questpie 2.0.4 → 2.1.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.
- package/dist/index.mjs +362 -119
- package/package.json +2 -3
- package/templates/elysia/AGENTS.md +56 -0
- package/templates/elysia/CLAUDE.md +39 -0
- package/templates/elysia/Dockerfile +24 -0
- package/templates/elysia/README.md +148 -0
- package/templates/elysia/docker/init-extensions.sql +11 -0
- package/templates/elysia/docker-compose.yml +21 -0
- package/templates/elysia/env.example +16 -0
- package/templates/elysia/gitignore +6 -0
- package/templates/elysia/package.json +47 -0
- package/templates/elysia/questpie.config.ts +12 -0
- package/templates/elysia/src/index.ts +21 -0
- package/templates/elysia/src/lib/auth-client.ts +32 -0
- package/templates/elysia/src/lib/client.ts +13 -0
- package/templates/elysia/src/lib/env.ts +24 -0
- package/templates/elysia/src/lib/query-client.ts +18 -0
- package/templates/elysia/src/lib/query.ts +18 -0
- package/templates/elysia/src/questpie/server/.generated/context.gen.ts +200 -0
- package/templates/elysia/src/questpie/server/.generated/entities.gen.ts +84 -0
- package/templates/elysia/src/questpie/server/.generated/factories.ts +65 -0
- package/templates/elysia/src/questpie/server/.generated/index.ts +131 -0
- package/templates/elysia/src/questpie/server/.generated/names.gen.ts +25 -0
- package/templates/elysia/src/questpie/server/app.ts +10 -0
- package/templates/elysia/src/questpie/server/collections/index.ts +1 -0
- package/templates/elysia/src/questpie/server/collections/posts.collection.ts +10 -0
- package/templates/elysia/src/questpie/server/config/auth.ts +8 -0
- package/templates/elysia/src/questpie/server/config/openapi.ts +10 -0
- package/templates/elysia/src/questpie/server/globals/index.ts +1 -0
- package/templates/elysia/src/questpie/server/globals/site-settings.global.ts +10 -0
- package/templates/elysia/src/questpie/server/modules.ts +8 -0
- package/templates/elysia/src/questpie/server/questpie.config.ts +21 -0
- package/templates/elysia/tsconfig.json +28 -0
- package/templates/hono/AGENTS.md +56 -0
- package/templates/hono/CLAUDE.md +39 -0
- package/templates/hono/Dockerfile +24 -0
- package/templates/hono/README.md +148 -0
- package/templates/hono/docker/init-extensions.sql +11 -0
- package/templates/hono/docker-compose.yml +21 -0
- package/templates/hono/env.example +16 -0
- package/templates/hono/gitignore +6 -0
- package/templates/hono/package.json +47 -0
- package/templates/hono/questpie.config.ts +12 -0
- package/templates/hono/src/index.ts +30 -0
- package/templates/hono/src/lib/auth-client.ts +32 -0
- package/templates/hono/src/lib/client.ts +13 -0
- package/templates/hono/src/lib/env.ts +24 -0
- package/templates/hono/src/lib/query-client.ts +18 -0
- package/templates/hono/src/lib/query.ts +18 -0
- package/templates/hono/src/questpie/server/.generated/context.gen.ts +200 -0
- package/templates/hono/src/questpie/server/.generated/entities.gen.ts +84 -0
- package/templates/hono/src/questpie/server/.generated/factories.ts +65 -0
- package/templates/hono/src/questpie/server/.generated/index.ts +131 -0
- package/templates/hono/src/questpie/server/.generated/names.gen.ts +25 -0
- package/templates/hono/src/questpie/server/app.ts +10 -0
- package/templates/hono/src/questpie/server/collections/index.ts +1 -0
- package/templates/hono/src/questpie/server/collections/posts.collection.ts +10 -0
- package/templates/hono/src/questpie/server/config/auth.ts +8 -0
- package/templates/hono/src/questpie/server/config/openapi.ts +10 -0
- package/templates/hono/src/questpie/server/globals/index.ts +1 -0
- package/templates/hono/src/questpie/server/globals/site-settings.global.ts +10 -0
- package/templates/hono/src/questpie/server/modules.ts +8 -0
- package/templates/hono/src/questpie/server/questpie.config.ts +21 -0
- package/templates/hono/tsconfig.json +28 -0
- package/templates/next/AGENTS.md +55 -0
- package/templates/next/CLAUDE.md +39 -0
- package/templates/next/Dockerfile +25 -0
- package/templates/next/README.md +148 -0
- package/templates/next/components.json +22 -0
- package/templates/next/docker/init-extensions.sql +11 -0
- package/templates/next/docker-compose.yml +21 -0
- package/templates/next/env.example +16 -0
- package/templates/next/gitignore +10 -0
- package/templates/next/next-env.d.ts +5 -0
- package/templates/next/next.config.ts +20 -0
- package/templates/next/package.json +54 -0
- package/templates/next/postcss.config.mjs +8 -0
- package/templates/next/public/.gitkeep +0 -0
- package/templates/next/questpie.config.ts +12 -0
- package/templates/next/src/app/admin/[[...all]]/page.tsx +34 -0
- package/templates/next/src/app/admin/admin.css +4 -0
- package/templates/next/src/app/admin/layout.tsx +63 -0
- package/templates/next/src/app/api/[...all]/route.ts +24 -0
- package/templates/next/src/app/layout.tsx +24 -0
- package/templates/next/src/app/not-found.tsx +18 -0
- package/templates/next/src/app/page.tsx +74 -0
- package/templates/next/src/app/providers.tsx +11 -0
- package/templates/next/src/lib/auth-client.ts +12 -0
- package/templates/next/src/lib/client.ts +13 -0
- package/templates/next/src/lib/env.ts +24 -0
- package/templates/next/src/lib/query-client.ts +18 -0
- package/templates/next/src/lib/query.ts +18 -0
- package/templates/next/src/questpie/admin/.generated/client.ts +13 -0
- package/templates/next/src/questpie/admin/admin.ts +9 -0
- package/templates/next/src/questpie/admin/modules.ts +3 -0
- package/templates/next/src/questpie/server/.generated/context.gen.ts +204 -0
- package/templates/next/src/questpie/server/.generated/entities.gen.ts +100 -0
- package/templates/next/src/questpie/server/.generated/factories.ts +204 -0
- package/templates/next/src/questpie/server/.generated/index.ts +139 -0
- package/templates/next/src/questpie/server/.generated/names.gen.ts +31 -0
- package/templates/next/src/questpie/server/app.ts +10 -0
- package/templates/next/src/questpie/server/collections/index.ts +1 -0
- package/templates/next/src/questpie/server/collections/posts.collection.ts +58 -0
- package/templates/next/src/questpie/server/config/admin.ts +80 -0
- package/templates/next/src/questpie/server/config/auth.ts +8 -0
- package/templates/next/src/questpie/server/config/openapi.ts +10 -0
- package/templates/next/src/questpie/server/globals/index.ts +1 -0
- package/templates/next/src/questpie/server/globals/site-settings.global.ts +19 -0
- package/templates/next/src/questpie/server/modules.ts +9 -0
- package/templates/next/src/questpie/server/questpie.config.ts +21 -0
- package/templates/next/src/styles.css +125 -0
- package/templates/next/tsconfig.json +37 -0
- package/templates/tanstack-start/AGENTS.md +35 -607
- package/templates/tanstack-start/CLAUDE.md +26 -134
- package/templates/tanstack-start/README.md +13 -1
- package/templates/tanstack-start/docker/init-extensions.sql +11 -0
- package/templates/tanstack-start/docker-compose.yml +1 -0
- package/templates/tanstack-start/src/lib/auth-client.ts +1 -1
- package/templates/tanstack-start/src/lib/client.ts +1 -1
- package/templates/tanstack-start/src/lib/query.ts +18 -0
- package/templates/tanstack-start/src/questpie/server/collections/index.ts +1 -1
- package/templates/tanstack-start/src/questpie/server/globals/index.ts +1 -1
- package/templates/tanstack-start/src/questpie/server/questpie.config.ts +1 -1
- package/templates/tanstack-start/src/routes/__root.tsx +31 -1
- package/templates/tanstack-start/src/routes/api/$.ts +1 -1
- package/templates/tanstack-start/src/routes/index.tsx +97 -0
- package/skills/questpie/AGENTS.md +0 -2871
- package/skills/questpie/SKILL.md +0 -293
- package/skills/questpie/coverage.json +0 -213
- package/skills/questpie/references/auth.md +0 -236
- package/skills/questpie/references/business-logic.md +0 -620
- package/skills/questpie/references/codegen-plugin-api.md +0 -382
- package/skills/questpie/references/crud-api.md +0 -580
- package/skills/questpie/references/data-modeling.md +0 -509
- package/skills/questpie/references/extend.md +0 -584
- package/skills/questpie/references/field-types.md +0 -398
- package/skills/questpie/references/infrastructure-adapters.md +0 -720
- package/skills/questpie/references/mcp.md +0 -147
- package/skills/questpie/references/multi-tenancy.md +0 -363
- package/skills/questpie/references/production.md +0 -640
- package/skills/questpie/references/query-operators.md +0 -125
- package/skills/questpie/references/quickstart.md +0 -562
- package/skills/questpie/references/rules.md +0 -454
- package/skills/questpie/references/sandbox.md +0 -110
- package/skills/questpie/references/tanstack-query.md +0 -543
- package/skills/questpie/references/type-inference.md +0 -167
- package/skills/questpie/references/workflows.md +0 -155
- package/skills/questpie-admin/AGENTS.md +0 -1515
- package/skills/questpie-admin/SKILL.md +0 -443
- package/skills/questpie-admin/references/blocks.md +0 -331
- package/skills/questpie-admin/references/custom-ui.md +0 -305
- package/skills/questpie-admin/references/views.md +0 -449
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/* oxlint-disable */
|
|
2
|
+
// AUTO-GENERATED by questpie codegen — DO NOT EDIT
|
|
3
|
+
// Typed factory functions with plugin extensions. Regenerate with: questpie generate
|
|
4
|
+
|
|
5
|
+
// ── Core Imports ───────────────────────────────────────────
|
|
6
|
+
import { CollectionBuilder, GlobalBuilder, wrapBuilderWithExtensions, builtinFields, type EmptyCollectionState, type EmptyGlobalState, type BuiltinFields, type CollectionBuilderState, type GlobalBuilderState, type FieldState, Field } from "questpie/builders";
|
|
7
|
+
|
|
8
|
+
// ── Runtime Field Imports ──────────────────────────────────
|
|
9
|
+
import { adminFields } from "@questpie/admin/fields";
|
|
10
|
+
|
|
11
|
+
const _fieldExt: Record<string, { stateKey: string; resolve: (value: unknown) => unknown }> = {
|
|
12
|
+
admin: { stateKey: "admin", resolve: (v: unknown) => v },
|
|
13
|
+
form: {
|
|
14
|
+
stateKey: "form",
|
|
15
|
+
resolve(configOrFn: unknown) {
|
|
16
|
+
if (typeof configOrFn === 'function') return configOrFn({ f: createFieldNameProxy() });
|
|
17
|
+
return configOrFn;
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Merged field factories — builtins + module-contributed (e.g. richText, blocks) + user fields
|
|
23
|
+
const _rawFieldDefs = { ...builtinFields, ...adminFields } as const;
|
|
24
|
+
|
|
25
|
+
// Wrap field factories so returned Field instances have extension methods
|
|
26
|
+
type _FieldFactory = (...args: never[]) => unknown;
|
|
27
|
+
function _wrapFieldFactory<TFactory extends _FieldFactory>(fn: TFactory): TFactory {
|
|
28
|
+
return ((...args: Parameters<TFactory>) => wrapBuilderWithExtensions(fn(...args), _fieldExt, Field)) as unknown as TFactory;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const _allFieldDefs = Object.fromEntries(
|
|
32
|
+
Object.entries(_rawFieldDefs).map(([k, v]) => [k, _wrapFieldFactory(v)])
|
|
33
|
+
) as unknown as typeof _rawFieldDefs;
|
|
34
|
+
|
|
35
|
+
// ── Entity key registry (names only — acyclic by construction) ─────
|
|
36
|
+
declare global {
|
|
37
|
+
namespace Questpie {
|
|
38
|
+
interface CollectionKeys { posts: unknown }
|
|
39
|
+
interface GlobalKeys { siteSettings: unknown }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── Plugin Imports ─────────────────────────────────────────
|
|
44
|
+
import { type AdminCollectionConfig, type AdminConfigContext, type ListViewConfig, type ListViewConfigContext, type FilterViewsByKind, type FormViewConfig, type FormViewConfigContext, type PreviewConfig, type ServerActionsConfig, type ActionsConfigContext, type AdminGlobalConfig, type AdminConfigInput, createViewCallbackProxy, createComponentCallbackProxy, createActionCallbackProxy, createActionFieldBuilderProxy } from "@questpie/admin/factories";
|
|
45
|
+
import { type AppConfigInput, type AuthConfig } from "questpie/types";
|
|
46
|
+
import { type OpenApiModuleConfig } from "@questpie/openapi";
|
|
47
|
+
import { createFieldNameProxy } from "questpie/builders";
|
|
48
|
+
|
|
49
|
+
// ════════════════════════════════════════════════════════════
|
|
50
|
+
// Type extraction — driven by CategoryDeclaration
|
|
51
|
+
// ════════════════════════════════════════════════════════════
|
|
52
|
+
|
|
53
|
+
type _ViewsNames = (keyof Questpie.ViewsRegistry & string) | (string & {});
|
|
54
|
+
type _ViewsRecord = Questpie.ViewsRegistry;
|
|
55
|
+
type _ComponentsNames = (keyof Questpie.ComponentsRegistry & string) | (string & {});
|
|
56
|
+
type _ComponentsNames_Strict = keyof Questpie.ComponentsRegistry & string;
|
|
57
|
+
type _ComponentsRecord = Questpie.ComponentsRegistry;
|
|
58
|
+
|
|
59
|
+
// Field types — populated by module codegen via Questpie.FieldTypesMap
|
|
60
|
+
type _AllFieldTypes = Questpie.FieldTypesMap;
|
|
61
|
+
|
|
62
|
+
// ════════════════════════════════════════════════════════════
|
|
63
|
+
// Type augmentations — generated from plugin registries
|
|
64
|
+
// ════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
declare module "questpie/builders" {
|
|
67
|
+
interface CollectionBuilder<TState extends CollectionBuilderState> {
|
|
68
|
+
admin(configFn: AdminCollectionConfig | ((ctx: AdminConfigContext<_ComponentsRecord>) => AdminCollectionConfig)): CollectionBuilder<TState>;
|
|
69
|
+
list(configFn: (ctx: ListViewConfigContext<TState extends { fieldDefinitions: infer F extends Record<string, unknown> } ? F : Record<string, unknown>, FilterViewsByKind<_ViewsRecord, "list">, _ComponentsRecord>) => ListViewConfig): CollectionBuilder<TState>;
|
|
70
|
+
form(configFn: (ctx: FormViewConfigContext<TState extends { fieldDefinitions: infer F extends Record<string, unknown> } ? F : Record<string, unknown>, FilterViewsByKind<_ViewsRecord, "form">>) => FormViewConfig): CollectionBuilder<TState>;
|
|
71
|
+
preview(config: PreviewConfig): CollectionBuilder<TState>;
|
|
72
|
+
actions(configFn: (ctx: ActionsConfigContext<Record<string, unknown>, _ComponentsRecord>) => ServerActionsConfig): CollectionBuilder<TState>;
|
|
73
|
+
}
|
|
74
|
+
interface GlobalBuilder<TState extends GlobalBuilderState> {
|
|
75
|
+
admin(configFn: AdminGlobalConfig | ((ctx: AdminConfigContext<_ComponentsRecord>) => AdminGlobalConfig)): GlobalBuilder<TState>;
|
|
76
|
+
form(configFn: (ctx: FormViewConfigContext<TState extends { fieldDefinitions: infer F extends Record<string, unknown> } ? F : Record<string, unknown>, FilterViewsByKind<_ViewsRecord, "form">>) => FormViewConfig): GlobalBuilder<TState>;
|
|
77
|
+
}
|
|
78
|
+
interface Field<TState extends FieldState = FieldState> {
|
|
79
|
+
admin(config: unknown): Field<TState>;
|
|
80
|
+
form(configFn: (ctx: { f: Record<string, string> }) => { fields: import('@questpie/admin/factories').FieldLayoutItem[] }): Field<TState>;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
declare global {
|
|
85
|
+
namespace Questpie {
|
|
86
|
+
interface FieldTypesMap extends BuiltinFields {}
|
|
87
|
+
interface FieldTypeRegistry extends Record<keyof _AllFieldTypes, {}> {}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
declare module "@questpie/admin/factories" {
|
|
92
|
+
interface ComponentTypeRegistry extends Record<_ComponentsNames_Strict, {}> {}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ════════════════════════════════════════════════════════════
|
|
96
|
+
// Extension registries
|
|
97
|
+
// ════════════════════════════════════════════════════════════
|
|
98
|
+
|
|
99
|
+
const _collExt: Record<string, { stateKey: string; resolve: (value: unknown) => unknown }> = {
|
|
100
|
+
admin: {
|
|
101
|
+
stateKey: "admin",
|
|
102
|
+
resolve(configOrFn: unknown) {
|
|
103
|
+
if (typeof configOrFn === 'function') return configOrFn({ c: createComponentCallbackProxy() });
|
|
104
|
+
return configOrFn;
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
list: {
|
|
108
|
+
stateKey: "adminList",
|
|
109
|
+
resolve(configOrFn: unknown) {
|
|
110
|
+
const resolved = typeof configOrFn === 'function' ? configOrFn({ v: createViewCallbackProxy(), f: createFieldNameProxy(), a: createActionCallbackProxy(), c: createComponentCallbackProxy() }) : configOrFn;
|
|
111
|
+
return { ...{"view":"collection-table","showSearch":true,"showFilters":true,"showToolbar":true}, ...(resolved && typeof resolved === 'object' ? resolved : {}) };
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
form: {
|
|
115
|
+
stateKey: "adminForm",
|
|
116
|
+
resolve(configOrFn: unknown) {
|
|
117
|
+
const resolved = typeof configOrFn === 'function' ? configOrFn({ v: createViewCallbackProxy(), f: createFieldNameProxy() }) : configOrFn;
|
|
118
|
+
return { ...{"view":"collection-form","showMeta":true}, ...(resolved && typeof resolved === 'object' ? resolved : {}) };
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
preview: { stateKey: "adminPreview", resolve: (v: unknown) => v },
|
|
122
|
+
actions: {
|
|
123
|
+
stateKey: "adminActions",
|
|
124
|
+
resolve(configOrFn: unknown) {
|
|
125
|
+
if (typeof configOrFn === 'function') return configOrFn({ a: createActionCallbackProxy(), c: createComponentCallbackProxy(), f: createActionFieldBuilderProxy() });
|
|
126
|
+
return configOrFn;
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const _globExt: Record<string, { stateKey: string; resolve: (value: unknown) => unknown }> = {
|
|
132
|
+
admin: {
|
|
133
|
+
stateKey: "admin",
|
|
134
|
+
resolve(configOrFn: unknown) {
|
|
135
|
+
if (typeof configOrFn === 'function') return configOrFn({ c: createComponentCallbackProxy() });
|
|
136
|
+
return configOrFn;
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
form: {
|
|
140
|
+
stateKey: "adminForm",
|
|
141
|
+
resolve(configOrFn: unknown) {
|
|
142
|
+
const resolved = typeof configOrFn === 'function' ? configOrFn({ v: createViewCallbackProxy(), f: createFieldNameProxy() }) : configOrFn;
|
|
143
|
+
return { ...{"view":"global-form","showMeta":true}, ...(resolved && typeof resolved === 'object' ? resolved : {}) };
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// ════════════════════════════════════════════════════════════
|
|
149
|
+
// Factory functions
|
|
150
|
+
// ════════════════════════════════════════════════════════════
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Create a typed collection builder with plugin extensions.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* import { collection } from "#questpie/factories";
|
|
158
|
+
*
|
|
159
|
+
* export default collection("posts")
|
|
160
|
+
* .fields(({ f }) => ({ title: f.text(255).required() }))
|
|
161
|
+
* .admin(({ c }) => ({ icon: c.icon("ph:article") }))
|
|
162
|
+
* .list(({ v, f }) => v.collectionTable({ columns: [f.title] }))
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export function collection<TName extends string>(name: TName): CollectionBuilder<EmptyCollectionState<TName, undefined, _AllFieldTypes>> {
|
|
166
|
+
return wrapBuilderWithExtensions(CollectionBuilder.create<TName, _AllFieldTypes>(name, _allFieldDefs), _collExt, CollectionBuilder) as unknown as CollectionBuilder<EmptyCollectionState<TName, undefined, _AllFieldTypes>>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Create a typed global builder with plugin extensions.
|
|
171
|
+
*/
|
|
172
|
+
export function global<TName extends string>(name: TName): GlobalBuilder<EmptyGlobalState<TName, undefined, _AllFieldTypes>> {
|
|
173
|
+
return wrapBuilderWithExtensions(GlobalBuilder.create<TName, _AllFieldTypes>(name, _allFieldDefs), _globExt, GlobalBuilder) as unknown as GlobalBuilder<EmptyGlobalState<TName, undefined, _AllFieldTypes>>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ════════════════════════════════════════════════════════════
|
|
177
|
+
// Builder factory functions (plugin-contributed)
|
|
178
|
+
// ════════════════════════════════════════════════════════════
|
|
179
|
+
|
|
180
|
+
import { BlockBuilder } from "@questpie/admin/factories";
|
|
181
|
+
/**
|
|
182
|
+
* Create a typed block builder with wrapped field defs.
|
|
183
|
+
*/
|
|
184
|
+
export function block<TName extends string>(name: TName): import('@questpie/admin/factories').BlockBuilder<{ name: TName }> {
|
|
185
|
+
return BlockBuilder.create(name, _allFieldDefs) as unknown as import('@questpie/admin/factories').BlockBuilder<{ name: TName }>;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ════════════════════════════════════════════════════════════
|
|
189
|
+
// Singleton factory functions
|
|
190
|
+
// ════════════════════════════════════════════════════════════
|
|
191
|
+
|
|
192
|
+
/** Typed factory for appConfig config. */
|
|
193
|
+
export function appConfig<T extends AppConfigInput>(config: T): T { return config; }
|
|
194
|
+
|
|
195
|
+
/** Typed factory for authConfig config. */
|
|
196
|
+
export function authConfig<T extends AuthConfig>(config: T): T { return config; }
|
|
197
|
+
|
|
198
|
+
/** Typed factory for adminConfig config. Accepts plain config or callback. */
|
|
199
|
+
export function adminConfig<T extends AdminConfigInput>(config: T): T;
|
|
200
|
+
export function adminConfig<T extends (...args: never[]) => AdminConfigInput>(cb: T): T;
|
|
201
|
+
export function adminConfig<T>(v: T): T { return v; }
|
|
202
|
+
|
|
203
|
+
/** Typed factory for openapi config. */
|
|
204
|
+
export function openapi<T extends OpenApiModuleConfig>(config: T): T { return config; }
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/* oxlint-disable */
|
|
2
|
+
// AUTO-GENERATED by questpie codegen — DO NOT EDIT
|
|
3
|
+
// Regenerate with: questpie generate
|
|
4
|
+
|
|
5
|
+
import { createApp, createContextFactory } from "questpie/app";
|
|
6
|
+
import "./names.gen";
|
|
7
|
+
import type { AccessContext, AppDefinition, CollectionSelect, GlobalSelect, HookContext, Where } from "questpie/types";
|
|
8
|
+
import type { AppCollections, AppGlobals, AppRoutes } from "./entities.gen";
|
|
9
|
+
import type { _AppQuestpie, AppSession, AppSessionUser } from "./context.gen";
|
|
10
|
+
|
|
11
|
+
// ── Runtime ────────────────────────────────────────────────
|
|
12
|
+
import _runtime from "../questpie.config";
|
|
13
|
+
|
|
14
|
+
// ── Modules ────────────────────────────────────────────────
|
|
15
|
+
import _modules from "../modules";
|
|
16
|
+
|
|
17
|
+
// ── Collections ────────────────────────────────────────────
|
|
18
|
+
import { posts as _coll_posts } from "../collections/posts.collection";
|
|
19
|
+
|
|
20
|
+
// ── Globals ────────────────────────────────────────────────
|
|
21
|
+
import { siteSettings as _glob_siteSettings } from "../globals/site-settings.global";
|
|
22
|
+
|
|
23
|
+
// ── Core Singles ───────────────────────────────────────────
|
|
24
|
+
import _authConfig from "../config/auth";
|
|
25
|
+
|
|
26
|
+
// ── Plugin Singles ─────────────────────────────────────────
|
|
27
|
+
import _adminConfig from "../config/admin";
|
|
28
|
+
import _openapi from "../config/openapi";
|
|
29
|
+
|
|
30
|
+
export type * from "./entities.gen";
|
|
31
|
+
export type * from "./context.gen";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Select/document type for a collection key — prefer over `Record<string, any>` for docs.
|
|
35
|
+
*/
|
|
36
|
+
export type CollectionDoc<K extends keyof AppCollections> = CollectionSelect<AppCollections[K]>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Select/document type for a global key.
|
|
40
|
+
*/
|
|
41
|
+
export type GlobalDoc<K extends keyof AppGlobals> = GlobalSelect<AppGlobals[K]>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Typed `where` filter for a collection key — prefer over `Record<string, unknown>`
|
|
45
|
+
* when building a `where` clause dynamically before a `find`/`findOne` call.
|
|
46
|
+
*/
|
|
47
|
+
export type CollectionWhere<K extends keyof AppCollections> = Where<AppCollections[K], AppConfig>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Access-rule ctx for shared helpers. `K` narrows `data` to that collection's row.
|
|
51
|
+
*
|
|
52
|
+
* CYCLE RULE: import these only from files NOT imported by a collection
|
|
53
|
+
* (routes, services, jobs, scripts). Helpers imported by collections take
|
|
54
|
+
* the package-level `AccessContext` from "questpie" instead — see the
|
|
55
|
+
* type-inference reference.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* export async function isOwner(ctx: AccessRuleContext<"posts">) {
|
|
60
|
+
* return ctx.data?.authorId === ctx.session?.user.id; // ctx.collections typed
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export type AccessRuleContext<K extends keyof AppCollections | unknown = unknown> =
|
|
65
|
+
AccessContext<K extends keyof AppCollections ? CollectionDoc<K> : unknown>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Hook ctx for shared helpers. `K` narrows `data` to that collection's row.
|
|
69
|
+
* Same cycle rule as `AccessRuleContext`.
|
|
70
|
+
*/
|
|
71
|
+
export type HookRuleContext<K extends keyof AppCollections | unknown = unknown> =
|
|
72
|
+
HookContext<K extends keyof AppCollections ? CollectionDoc<K> : unknown>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Flat config type for client APIs.
|
|
76
|
+
* Use with `createClient<AppConfig>()` and `createAdminAuthClient<AppConfig>()`.
|
|
77
|
+
* For handler context, use `AppContext` (auto-typed via module augmentation).
|
|
78
|
+
*/
|
|
79
|
+
export type AppConfig = {
|
|
80
|
+
collections: AppCollections;
|
|
81
|
+
globals: AppGlobals;
|
|
82
|
+
routes: AppRoutes;
|
|
83
|
+
storage: (typeof _runtime)["storage"];
|
|
84
|
+
auth: typeof _authConfig;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// ════════════════════════════════════════════════════════════
|
|
88
|
+
// RUNTIME — create the app instance
|
|
89
|
+
// ════════════════════════════════════════════════════════════
|
|
90
|
+
|
|
91
|
+
var _appPromise: Promise<unknown> | undefined;
|
|
92
|
+
|
|
93
|
+
_appPromise = createApp(
|
|
94
|
+
({
|
|
95
|
+
modules: _modules,
|
|
96
|
+
collections: {
|
|
97
|
+
posts: _coll_posts,
|
|
98
|
+
},
|
|
99
|
+
globals: {
|
|
100
|
+
siteSettings: _glob_siteSettings,
|
|
101
|
+
},
|
|
102
|
+
config: {
|
|
103
|
+
auth: _authConfig,
|
|
104
|
+
admin: _adminConfig,
|
|
105
|
+
openapi: _openapi,
|
|
106
|
+
},
|
|
107
|
+
}) satisfies AppDefinition,
|
|
108
|
+
_runtime,
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
export const app = (await _appPromise) as unknown as _AppQuestpie;
|
|
112
|
+
|
|
113
|
+
/** Fully typed QUESTPIE app instance. */
|
|
114
|
+
export type App = typeof app;
|
|
115
|
+
|
|
116
|
+
// ── createContext — typed context for scripts ──────────────
|
|
117
|
+
/**
|
|
118
|
+
* Create a typed AppContext for use in scripts, tests, or standalone code.
|
|
119
|
+
* Resolves all services and provides flat access to infrastructure.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* import { createContext } from "#questpie";
|
|
124
|
+
*
|
|
125
|
+
* const ctx = await createContext();
|
|
126
|
+
* const posts = await ctx.collections.posts.find({});
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export async function createContext(
|
|
130
|
+
options?: Parameters<ReturnType<typeof createContextFactory>>[0],
|
|
131
|
+
) {
|
|
132
|
+
while (!_appPromise) {
|
|
133
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return createContextFactory((await _appPromise) as _AppQuestpie)(options);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Factories: import { collection, global, ... } from '#questpie/factories';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* oxlint-disable */
|
|
2
|
+
// AUTO-GENERATED by questpie codegen — DO NOT EDIT
|
|
3
|
+
// Regenerate with: questpie generate
|
|
4
|
+
|
|
5
|
+
// ── Modules ────────────────────────────────────────────────
|
|
6
|
+
import _modules from "../modules";
|
|
7
|
+
|
|
8
|
+
// ── Module entity-name key sets (distributive `keyof`) ─────
|
|
9
|
+
type _ModuleCollectionsKeyNames = (typeof _modules)[number] extends infer M ? M extends { collections: infer C } ? keyof C & string : never : never;
|
|
10
|
+
type _ModuleGlobalsKeyNames = (typeof _modules)[number] extends infer M ? M extends { globals: infer C } ? keyof C & string : never : never;
|
|
11
|
+
type _ModuleJobsKeyNames = (typeof _modules)[number] extends infer M ? M extends { jobs: infer C } ? keyof C & string : never : never;
|
|
12
|
+
type _ModuleRoutesKeyNames = (typeof _modules)[number] extends infer M ? M extends { routes: infer C } ? keyof C & string : never : never;
|
|
13
|
+
type _ModuleServicesKeyNames = (typeof _modules)[number] extends infer M ? M extends { services: infer C } ? keyof C & string : never : never;
|
|
14
|
+
type _ModuleFieldTypesKeyNames = (typeof _modules)[number] extends infer M ? M extends { fieldTypes: infer C } ? keyof C & string : never : never;
|
|
15
|
+
type _ModuleViewsKeyNames = (typeof _modules)[number] extends infer M ? M extends { views: infer C } ? keyof C & string : never : never;
|
|
16
|
+
type _ModuleComponentsKeyNames = (typeof _modules)[number] extends infer M ? M extends { components: infer C } ? keyof C & string : never : never;
|
|
17
|
+
type _ModuleBlocksKeyNames = (typeof _modules)[number] extends infer M ? M extends { blocks: infer C } ? keyof C & string : never : never;
|
|
18
|
+
|
|
19
|
+
declare global {
|
|
20
|
+
namespace Questpie {
|
|
21
|
+
interface CollectionKeys extends Record<_ModuleCollectionsKeyNames, unknown> {}
|
|
22
|
+
interface GlobalKeys extends Record<_ModuleGlobalsKeyNames, unknown> {}
|
|
23
|
+
interface JobKeys extends Record<_ModuleJobsKeyNames, unknown> {}
|
|
24
|
+
interface RouteKeys extends Record<_ModuleRoutesKeyNames, unknown> {}
|
|
25
|
+
interface ServiceKeys extends Record<_ModuleServicesKeyNames, unknown> {}
|
|
26
|
+
interface FieldTypeKeys extends Record<_ModuleFieldTypesKeyNames, unknown> {}
|
|
27
|
+
interface ViewKeys extends Record<_ModuleViewsKeyNames, unknown> {}
|
|
28
|
+
interface ComponentKeys extends Record<_ModuleComponentsKeyNames, unknown> {}
|
|
29
|
+
interface BlockKeys extends Record<_ModuleBlocksKeyNames, unknown> {}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App Instance
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the app from the generated entrypoint.
|
|
5
|
+
* Run `questpie generate` to regenerate .generated/index.ts.
|
|
6
|
+
*
|
|
7
|
+
* If .generated/ does not exist yet, run: bun questpie generate
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export { type App, type AppConfig, app } from "./.generated/index";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { posts } from "./posts.collection";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { collection } from "#questpie/factories";
|
|
2
|
+
|
|
3
|
+
export const posts = collection("posts")
|
|
4
|
+
.fields(({ f }) => ({
|
|
5
|
+
title: f.text(255).label("Title").required(),
|
|
6
|
+
slug: f
|
|
7
|
+
.text(255)
|
|
8
|
+
.label("Slug")
|
|
9
|
+
.required()
|
|
10
|
+
.inputOptional()
|
|
11
|
+
.admin({
|
|
12
|
+
compute: {
|
|
13
|
+
handler: ({
|
|
14
|
+
data,
|
|
15
|
+
prev,
|
|
16
|
+
}: {
|
|
17
|
+
data: Record<string, unknown>;
|
|
18
|
+
prev: { data: Record<string, unknown> };
|
|
19
|
+
}) => {
|
|
20
|
+
const title = data.title;
|
|
21
|
+
const currentSlug = data.slug;
|
|
22
|
+
const prevTitle = prev.data.title;
|
|
23
|
+
|
|
24
|
+
if (currentSlug && prevTitle === title) return undefined;
|
|
25
|
+
|
|
26
|
+
if (title && typeof title === "string") {
|
|
27
|
+
return title
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
30
|
+
.replace(/^-|-$/g, "");
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
},
|
|
34
|
+
deps: ({ data }: { data: Record<string, unknown> }) => [
|
|
35
|
+
data.title,
|
|
36
|
+
data.slug,
|
|
37
|
+
],
|
|
38
|
+
debounce: 300,
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
content: f.richText().label("Content"),
|
|
42
|
+
published: f.boolean().label("Published").default(false).required(),
|
|
43
|
+
}))
|
|
44
|
+
.title(({ f }) => f.title)
|
|
45
|
+
.admin(({ c }) => ({
|
|
46
|
+
label: "Posts",
|
|
47
|
+
icon: c.icon("ph:article"),
|
|
48
|
+
}))
|
|
49
|
+
.list(({ v }) => v.collectionTable({}))
|
|
50
|
+
.form(({ v, f }) =>
|
|
51
|
+
v.collectionForm({
|
|
52
|
+
sidebar: {
|
|
53
|
+
position: "right",
|
|
54
|
+
fields: [f.slug, f.published],
|
|
55
|
+
},
|
|
56
|
+
fields: [f.title, f.content],
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { adminConfig } from "#questpie/factories";
|
|
2
|
+
|
|
3
|
+
export default adminConfig({
|
|
4
|
+
branding: {
|
|
5
|
+
name: "{{projectName}}",
|
|
6
|
+
},
|
|
7
|
+
sidebar: {
|
|
8
|
+
sections: [
|
|
9
|
+
{
|
|
10
|
+
id: "main",
|
|
11
|
+
title: "Content",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
items: [
|
|
15
|
+
{
|
|
16
|
+
sectionId: "main",
|
|
17
|
+
type: "link",
|
|
18
|
+
label: "Dashboard",
|
|
19
|
+
href: "/admin",
|
|
20
|
+
icon: { type: "icon", props: { name: "ph:house" } },
|
|
21
|
+
},
|
|
22
|
+
{ sectionId: "main", type: "collection", collection: "posts" },
|
|
23
|
+
{ sectionId: "main", type: "global", global: "siteSettings" },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
dashboard: {
|
|
27
|
+
title: "Dashboard",
|
|
28
|
+
description: "Overview of your content",
|
|
29
|
+
columns: 4,
|
|
30
|
+
actions: [
|
|
31
|
+
{
|
|
32
|
+
id: "new-post",
|
|
33
|
+
label: "New Post",
|
|
34
|
+
href: "/admin/collections/posts/create",
|
|
35
|
+
icon: { type: "icon", props: { name: "ph:article" } },
|
|
36
|
+
variant: "primary",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "site-settings",
|
|
40
|
+
label: "Site Settings",
|
|
41
|
+
href: "/admin/globals/siteSettings",
|
|
42
|
+
icon: { type: "icon", props: { name: "ph:gear" } },
|
|
43
|
+
variant: "outline",
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
sections: [
|
|
47
|
+
{ id: "content", label: "Content", layout: "grid", columns: 2 },
|
|
48
|
+
{ id: "recent", label: "Recent", layout: "grid", columns: 4 },
|
|
49
|
+
],
|
|
50
|
+
items: [
|
|
51
|
+
{
|
|
52
|
+
sectionId: "content",
|
|
53
|
+
id: "total-posts",
|
|
54
|
+
type: "stats",
|
|
55
|
+
collection: "posts",
|
|
56
|
+
label: "Total Posts",
|
|
57
|
+
span: 1,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
sectionId: "content",
|
|
61
|
+
id: "published-posts",
|
|
62
|
+
type: "stats",
|
|
63
|
+
collection: "posts",
|
|
64
|
+
label: "Published",
|
|
65
|
+
filter: { published: true },
|
|
66
|
+
variant: "primary",
|
|
67
|
+
span: 1,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
sectionId: "recent",
|
|
71
|
+
id: "recent-posts",
|
|
72
|
+
type: "recentItems",
|
|
73
|
+
collection: "posts",
|
|
74
|
+
label: "Recent Posts",
|
|
75
|
+
limit: 5,
|
|
76
|
+
span: 2,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { siteSettings } from "./site-settings.global";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { global } from "#questpie/factories";
|
|
2
|
+
|
|
3
|
+
export const siteSettings = global("siteSettings")
|
|
4
|
+
.fields(({ f }) => ({
|
|
5
|
+
siteName: f.text().label("Site Name").required().default("{{projectName}}"),
|
|
6
|
+
description: f
|
|
7
|
+
.textarea()
|
|
8
|
+
.label("Site Description")
|
|
9
|
+
.default("A QUESTPIE powered site"),
|
|
10
|
+
}))
|
|
11
|
+
.admin(({ c }) => ({
|
|
12
|
+
label: "Site Settings",
|
|
13
|
+
icon: c.icon("ph:gear"),
|
|
14
|
+
}))
|
|
15
|
+
.form(({ v, f }) =>
|
|
16
|
+
v.globalForm({
|
|
17
|
+
fields: [f.siteName, f.description],
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modules — static module dependencies for this project.
|
|
3
|
+
*/
|
|
4
|
+
import { adminModule } from "@questpie/admin/modules/admin";
|
|
5
|
+
import { openApiModule } from "@questpie/openapi";
|
|
6
|
+
|
|
7
|
+
const modules = [adminModule, openApiModule] as const;
|
|
8
|
+
|
|
9
|
+
export default modules;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QUESTPIE Runtime Configuration
|
|
3
|
+
*
|
|
4
|
+
* Runtime-only configuration: database, adapters, secrets.
|
|
5
|
+
* Entity definitions (collections, globals, etc.) are codegen-generated.
|
|
6
|
+
* Admin sidebar, dashboard, and branding live in config/admin.ts.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { runtimeConfig } from "questpie/app";
|
|
10
|
+
import { ConsoleAdapter } from "questpie/adapters/console";
|
|
11
|
+
|
|
12
|
+
import { env } from "@/lib/env";
|
|
13
|
+
|
|
14
|
+
export default runtimeConfig({
|
|
15
|
+
app: { url: env.APP_URL },
|
|
16
|
+
db: { url: env.DATABASE_URL },
|
|
17
|
+
storage: { basePath: "/api" },
|
|
18
|
+
email: {
|
|
19
|
+
adapter: new ConsoleAdapter({ logHtml: false }),
|
|
20
|
+
},
|
|
21
|
+
});
|