howone 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "howone",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "private": false,
5
5
  "description": "HowOne command line tools for creating app templates.",
6
6
  "type": "module",
@@ -12,21 +12,78 @@ This skill is the normal source of truth for HowOne SDK usage in generated apps.
12
12
  ## Workflow
13
13
 
14
14
  1. Establish the app root. All `.howone/*` metadata and `src/lib/sdk.ts` work belongs inside that app root.
15
- 2. Read `references/usage-patterns.md` once before writing SDK-related code. It contains the SDK mental model, essential public API, generation recipes, and common traps.
16
- 3. Read the existing app SDK entry, usually `src/lib/sdk.ts`, before editing. Preserve its imports and local style.
17
- 4. For Entity bindings, read `.howone/database/manifest.json`.
18
- 5. For AI action bindings, read `.howone/ai/manifest.json`.
19
- 6. Generate source code from the manifests, not from memory or tool-call summaries.
20
- 7. Keep sync tools and app-code edits separate. `sync_schema_artifacts` and `sync_ai_artifacts` write metadata only; the coding agent edits `src/lib/sdk.ts`.
15
+ 2. Read `node_modules/@howone/sdk/dist/index.d.ts` and `node_modules/@howone/sdk/dist/react.d.ts` to get the complete, always-up-to-date type signatures and public exports.
16
+ 3. Read `references/usage-patterns.md` for generation recipes, usage examples, and known traps that aren't in the type declarations.
17
+ 4. Read the existing app SDK entry, usually `src/lib/sdk.ts`, before editing. Preserve its imports and local style.
18
+ 5. For Entity bindings, read `.howone/database/manifest.json`.
19
+ 6. For AI action bindings, read `.howone/ai/manifest.json`.
20
+ 7. Generate source code from the manifests, not from memory or tool-call summaries.
21
+ 8. Keep sync tools and app-code edits separate. `sync_schema_artifacts` and `sync_ai_artifacts` write metadata only; the coding agent edits `src/lib/sdk.ts`.
22
+
23
+ ## Quick SDK Contract
24
+
25
+ See `/sdk/dist/index.d.ts` and `/sdk/dist/react.d.ts` for the full type signatures. The minimal app wiring looks like:
26
+
27
+ ```ts
28
+ import {
29
+ createClient,
30
+ defineAiAction,
31
+ defineAiActions,
32
+ defineEntities,
33
+ type EntityRecord,
34
+ withAiActions,
35
+ withEntities,
36
+ } from '@howone/sdk'
37
+ import { HowOneProvider, useHowoneContext } from '@howone/sdk/react'
38
+ import { z } from 'zod'
39
+
40
+ const client = createClient({
41
+ projectId: import.meta.env.VITE_HOWONE_PROJECT_ID,
42
+ env: import.meta.env.VITE_HOWONE_ENV,
43
+ })
44
+
45
+ export const entities = defineEntities({
46
+ Todo: client.entity<Todo, TodoCreate, TodoUpdate>('Todo'),
47
+ })
48
+
49
+ export const ai = defineAiActions({
50
+ summarizeTodo: defineAiAction('summarizeTodo', {
51
+ inputSchema: z.object({ title: z.string() }),
52
+ }),
53
+ })
54
+
55
+ const howone = withAiActions(withEntities(client, entities), ai)
56
+ export default howone
57
+ ```
58
+
59
+ Entity calls are plain async SDK calls:
60
+
61
+ ```ts
62
+ await howone.entities.Todo.list()
63
+ await howone.entities.Todo.create({ title: 'Ship it', completed: false })
64
+ await howone.entities.Todo.update(id, { completed: true })
65
+ await howone.entities.Todo.delete(id)
66
+ ```
67
+
68
+ AI action calls are bound by action name:
69
+
70
+ ```ts
71
+ const result = await howone.ai.summarizeTodo.run({ title })
72
+ const session = howone.ai.summarizeTodo.stream({ title })
73
+ for await (const event of howone.ai.summarizeTodo.events({ title })) {
74
+ // handle event
75
+ }
76
+ ```
77
+
78
+ React integration provides provider/auth/loading UI only: `HowOneProvider`, `useHowoneContext`, `FloatingButton`, `Loading`, and `LoadingSpinner`. It does not provide entity/query/AI data hooks. Use `useEffect`/`useState` or a data-fetching library around plain async SDK calls.
21
79
 
22
80
  ## Source Order
23
81
 
24
82
  Use this order when deciding what to read:
25
83
 
26
- 1. Current app files: `src/lib/sdk.ts`, relevant UI files, and generated manifests.
27
- 2. This skill: `SKILL.md` plus `references/usage-patterns.md`.
28
- 3. TypeScript/compiler errors from verification.
29
- 4. SDK source or declaration files, only as a narrow fallback for a missing or disputed API.
84
+ 1. `packages/sdk/dist/index.d.ts` and `packages/sdk/dist/react.d.ts` complete public API.
85
+ 2. `references/usage-patterns.md` — generation recipes, examples, traps.
86
+ 3. Current app files: `src/lib/sdk.ts`, relevant UI files, and generated manifests.
30
87
 
31
88
  ## Rules
32
89
 
@@ -42,4 +99,5 @@ Use this order when deciding what to read:
42
99
 
43
100
  ## References
44
101
 
45
- Read `references/usage-patterns.md` before writing SDK-related code. It is the working reference for `@howone/sdk` and `@howone/sdk/react`: mental model, imports, method names, app SDK entry shape, entity examples, AI action examples, React usage, validation caveats, and when source fallback is justified.
102
+ Read `packages/sdk/dist/index.d.ts` and `packages/sdk/dist/react.d.ts` for the full SDK type surface.
103
+ Read `references/usage-patterns.md` for generation recipes, usage examples, and known traps.
@@ -1,18 +1,6 @@
1
1
  # HowOne SDK Usage Patterns
2
2
 
3
- Working reference for `@howone/sdk` and `@howone/sdk/react`. It covers the SDK surface that generated HowOne apps normally need: client setup, entity bindings, AI action bindings, React provider usage, and the known traps that cause repeated source inspection.
4
-
5
- ## Reading Strategy
6
-
7
- Use this file as the working SDK manual for normal app generation. It intentionally includes the public imports, client shape, entity methods, AI action bindings, React exports, app SDK entry shape, and known validation caveats.
8
-
9
- Do not inspect `node_modules/@howone/sdk` for the same information unless:
10
-
11
- - This file does not cover the exact API needed.
12
- - TypeScript or runtime verification contradicts this file.
13
- - You are intentionally updating the SDK package itself, not an app that consumes it.
14
-
15
- When source fallback is necessary, keep it narrow: inspect the exact exported symbol or declaration that is missing, then return to app code. Do not glob or read the whole SDK package to relearn the basic usage below.
3
+ This file covers what the type declarations don't: generation recipes, usage examples, and known traps. For the complete public API (all types, method signatures, exports), read `node_modules/@howone/sdk/dist/index.d.ts` and `node_modules/@howone/sdk/dist/react.d.ts` first.
16
4
 
17
5
  ## SDK Mental Model
18
6
 
@@ -23,191 +11,6 @@ When source fallback is necessary, keep it narrow: inspect the exact exported sy
23
11
  - `@howone/sdk/react` provides auth/theme/loading UI primitives only. It does not provide entity, query, or AI data hooks.
24
12
  - `.howone/database/manifest.json` and `.howone/ai/manifest.json` are the generated contracts. App source should be generated from those manifests, not from memory.
25
13
 
26
- ## Import Reference
27
-
28
- ```ts
29
- // @howone/sdk — all public exports
30
- import {
31
- createClient,
32
- defineAiAction,
33
- defineAiActions,
34
- defineEntities,
35
- withAiActions,
36
- withEntities,
37
- type CreateClientOptions,
38
- type EntityRecord,
39
- type EntityClient,
40
- type EntityBindings,
41
- type QueryOptions,
42
- type QueryResult,
43
- type PageInfo,
44
- type DeleteResult,
45
- type AiClient,
46
- type AiActionDefinition,
47
- type AiActionClient,
48
- type AiActionConfig,
49
- type AiResult, // = ExecutionResult
50
- type AiSession, // { result: Promise<AiResult>, cancel(): void, signal: AbortSignal }
51
- type AiEvent, // SSE event payload
52
- type AiOptions,
53
- type UserProfile,
54
- AiSchemaValidationError,
55
- } from '@howone/sdk'
56
-
57
- // @howone/sdk/react — React components and hooks
58
- import {
59
- HowOneProvider,
60
- useHowoneContext,
61
- FloatingButton,
62
- Loading,
63
- LoadingSpinner,
64
- type HowOneProviderProps,
65
- type HowOneAuthMode,
66
- type HowOneThemeMode,
67
- type HowOneBrandMode,
68
- } from '@howone/sdk/react'
69
-
70
- import { z } from 'zod'
71
- ```
72
-
73
- ---
74
-
75
- ## createClient
76
-
77
- ```ts
78
- const client = createClient({
79
- projectId: import.meta.env.VITE_HOWONE_PROJECT_ID, // required in Vite apps
80
- env: import.meta.env.VITE_HOWONE_ENV, // 'local' | 'dev' | 'prod'
81
- // Optional advanced options (rarely needed):
82
- // apiUrl, aiUrl, caseStyle ('camel'|'snake'), auth: { mode, getToken }
83
- })
84
-
85
- // client shape:
86
- client.entity<TRecord, TCreate, TUpdate>(entityName: string): EntityClient<...>
87
- client.entities: Record<string, EntityClient>
88
- client.ai: AiClient // low-level; prefer withAiActions bindings
89
- client.me(): Promise<UserProfile | null>
90
- client.requireMe(): Promise<UserProfile>
91
- client.auth.setToken(t: string | null): void
92
- client.auth.getToken(): string | null
93
- client.auth.isAuthenticated(): boolean
94
- client.auth.login(redirect?: string): void
95
- client.auth.logout(): void
96
- client.upload.file(file, options?): Promise<{ url, thumbnailUrl?, id?, size?, mimeType? }>
97
- client.upload.image(file): Promise<{ url }>
98
- client.upload.batch({ files, concurrent?, onProgress?, onFileComplete? }): Promise<BatchUploadResponse>
99
- ```
100
-
101
- ---
102
-
103
- ## EntityClient
104
-
105
- ```ts
106
- type EntityClient<TRecord, TCreate, TUpdate> = {
107
- name: string
108
- // Basic CRUD
109
- list(options?: { page?, limit?, sort?, order?, ...filters }): Promise<TRecord[]>
110
- get(id: string): Promise<TRecord | null>
111
- getOrThrow(id: string): Promise<TRecord>
112
- create(data: TCreate): Promise<TRecord>
113
- update(id: string, data: TUpdate): Promise<TRecord>
114
- delete(id: string): Promise<{ deleted: boolean; id: string; message? }>
115
- // Advanced query with filters/pagination
116
- query(options?: QueryOptions<TRecord>): Promise<QueryResult<TRecord>>
117
- query.mine(options?: QueryOptions<TRecord>): Promise<QueryResult<TRecord>>
118
- bulkCreate(records: TCreate[], options?: { sample?: boolean }): Promise<TRecord[]>
119
- aggregate(pipeline: unknown[]): Promise<unknown[]>
120
- }
121
-
122
- // QueryOptions
123
- type QueryOptions<TRecord> = {
124
- where?: { [K in keyof TRecord]?: TRecord[K] | FieldOperator }
125
- // FieldOperator: { eq, ne, gt, gte, lt, lte, contains, like, startsWith, endsWith, in, notIn }
126
- search?: string
127
- page?: { number?: number; size?: number }
128
- orderBy?: Partial<Record<keyof TRecord | string, 'asc' | 'desc'>>
129
- }
130
-
131
- // QueryResult
132
- type QueryResult<T> = {
133
- items: T[]
134
- page: { number, size, total, totalPages, hasNext, hasPrev }
135
- }
136
-
137
- // EntityRecord base
138
- type EntityRecord = {
139
- id: string
140
- createdDate?: string
141
- updatedDate?: string
142
- createdById?: string
143
- isSample?: boolean
144
- [key: string]: unknown
145
- }
146
- ```
147
-
148
- ---
149
-
150
- ## AI Action
151
-
152
- ```ts
153
- // Define a typed action
154
- defineAiAction(id: string, config?: {
155
- inputSchema?: z.ZodType<TInput>
156
- outputSchema?: z.ZodType<TOutput>
157
- mode?: 'run' | 'stream' | 'events'
158
- }): AiActionDefinition<TInput, TOutput>
159
-
160
- // Group actions
161
- defineAiActions({ [name]: AiActionDefinition, ... }): actions
162
-
163
- // Bind to client
164
- withAiActions(client, actions): client & { ai: { [name]: AiActionClient } }
165
-
166
- // AiActionClient methods
167
- howone.ai.<actionName>.run(inputs?, options?): Promise<TOutput>
168
- howone.ai.<actionName>.stream(inputs?, options?): AiSession
169
- howone.ai.<actionName>.events(inputs?, options?): AsyncIterable<AiEvent>
170
-
171
- // AiSession
172
- type AiSession = {
173
- result: Promise<AiResult>
174
- cancel(): void
175
- signal: AbortSignal
176
- }
177
-
178
- // Reserved names — do NOT use as action names: run, stream, events
179
- ```
180
-
181
- ---
182
-
183
- ## React: HowOneProvider & hooks
184
-
185
- `@howone/sdk/react` exports exactly: `HowOneProvider`, `useHowoneContext`, `FloatingButton`, `Loading`, `LoadingSpinner`.
186
-
187
- **There are no `useEntity`, `useQuery`, `useAi`, or other data-fetching hooks.** Entity and AI calls are plain async functions — call them directly in components with `useEffect`/`useState` or any data-fetching library (SWR, React Query, etc.).
188
-
189
- ```tsx
190
- // Wrap app root — handles auth, theme, toasts, floating button
191
- <HowOneProvider
192
- projectId={...} // optional if client is already configured
193
- auth="optional" // 'required' | 'optional' | 'none'
194
- brand="visible" // 'visible' | 'hidden'
195
- theme="inherit" // 'dark' | 'light' | 'system' | 'inherit'
196
- showBrandButton={true}
197
- >
198
- <App />
199
- </HowOneProvider>
200
-
201
- // Auth context hook — the only hook in the package
202
- const { user, token, isAuthenticated, logout } = useHowoneContext()
203
- // user shape: { id, email, name, avatar } | null
204
-
205
- // Loading components
206
- <Loading size="md" tone="brand" label="..." description="..." fullScreen />
207
- <LoadingSpinner size="sm" tone="neutral" />
208
- // size: 'sm' | 'md' | 'lg' tone: 'brand' | 'neutral' | 'inverse'
209
- ```
210
-
211
14
  ## App SDK Entry
212
15
 
213
16
  Preferred Vite app entry shape:
@@ -401,37 +204,6 @@ await howone.entities.Story.create({
401
204
  })
402
205
  ```
403
206
 
404
- ## Do Not Generate
405
-
406
- Avoid these patterns unless the SDK has explicitly added them:
407
-
408
- ```ts
409
- // No data hooks in @howone/sdk/react
410
- const todos = useEntity('Todo')
411
- const query = useQuery(...)
412
- const result = useAi(...)
413
-
414
- // Wrong AI binding shape
415
- await howone.ai.run.generateStory(input)
416
-
417
- // Too-loose create payload
418
- type StoryCreate = Omit<StoryRecord, 'id' | 'createdDate' | 'updatedDate'>
419
-
420
- // Generated files do not belong under .howone
421
- // .howone stores synced manifests only.
422
- ```
423
-
424
- ## When To Read SDK Source
425
-
426
- Read SDK source or declaration files only for details not covered above, for example:
427
-
428
- - A newly added public method not listed here.
429
- - A TypeScript error proving a signature drifted.
430
- - A runtime error that points to a specific SDK helper.
431
- - Work that intentionally modifies `packages/sdk` itself.
432
-
433
- For app generation, do not inspect SDK source to rediscover `createClient`, entity CRUD, AI action binding shape, React exports, or Vite env setup.
434
-
435
207
  ## Generated Code Checklist
436
208
 
437
209
  - `src/lib/sdk.ts` imports only APIs it uses.