@ic-reactor/codegen 0.2.0 → 0.3.1

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.
@@ -1,42 +0,0 @@
1
- import { describe, it, expect } from "vitest"
2
- import {
3
- generateInfiniteQueryHook,
4
- InfiniteQueryHookOptions,
5
- } from "./infiniteQuery"
6
- import type { MethodInfo } from "../types"
7
-
8
- describe("Infinite Query Hook Generation", () => {
9
- const listItems: MethodInfo = {
10
- name: "list_items",
11
- type: "query",
12
- hasArgs: true,
13
- }
14
-
15
- it("generates infinite query hook correctly", () => {
16
- const options: InfiniteQueryHookOptions = {
17
- canisterName: "my_canister",
18
- method: listItems,
19
- type: "infiniteQuery",
20
- }
21
- const result = generateInfiniteQueryHook(options)
22
- expect(result).toMatchSnapshot()
23
- expect(result).toContain("createInfiniteQuery(myCanisterReactor, {")
24
- expect(result).toContain(
25
- "export const useListItemsInfiniteQuery = listItemsInfiniteQuery.useInfiniteQuery"
26
- )
27
- // Should contain default pagination logic placeholders
28
- expect(result).toContain("initialPageParam: 0 as PageCursor")
29
- })
30
-
31
- it("handles suspense infinite query type", () => {
32
- const options: InfiniteQueryHookOptions = {
33
- canisterName: "my_canister",
34
- method: listItems,
35
- type: "suspenseInfiniteQuery",
36
- }
37
- const result = generateInfiniteQueryHook(options)
38
- expect(result).toContain(
39
- "export const useListItemsSuspenseInfiniteQuery = listItemsSuspenseInfiniteQuery.useInfiniteQuery"
40
- )
41
- })
42
- })
@@ -1,74 +0,0 @@
1
- /**
2
- * Infinite Query hook template generator
3
- *
4
- * Generates createInfiniteQuery-based hooks for paginated canister methods.
5
- */
6
-
7
- import type { MethodInfo, HookType } from "../types.js"
8
- import {
9
- getReactorName,
10
- getServiceTypeName,
11
- getHookExportName,
12
- getReactHookName,
13
- } from "../naming.js"
14
-
15
- export interface InfiniteQueryHookOptions {
16
- canisterName: string
17
- method: MethodInfo
18
- type?: HookType
19
- }
20
-
21
- /**
22
- * Generate an infinite query hook file content
23
- */
24
- export function generateInfiniteQueryHook(
25
- options: InfiniteQueryHookOptions
26
- ): string {
27
- const { canisterName, method, type = "infiniteQuery" } = options
28
-
29
- const reactorName = getReactorName(canisterName)
30
- const serviceName = getServiceTypeName(canisterName)
31
- const hookExportName = getHookExportName(method.name, type)
32
- const reactHookName = getReactHookName(method.name, type)
33
-
34
- return `/**
35
- * Infinite Query: ${method.name}
36
- *
37
- * Auto-generated by @ic-reactor/codegen
38
- *
39
- * ⚠️ CUSTOMIZATION REQUIRED: Configure getArgs and getNextPageParam below.
40
- *
41
- * @example
42
- * const { data, fetchNextPage, hasNextPage } = ${hookExportName}.useInfiniteQuery()
43
- * const allItems = data?.pages.flatMap(page => page.items) ?? []
44
- */
45
-
46
- import { createInfiniteQuery } from "@ic-reactor/react"
47
- import { ${reactorName}, type ${serviceName} } from "../reactor"
48
-
49
- /** Define your pagination cursor type */
50
- type PageCursor = number
51
-
52
- export const ${hookExportName} = createInfiniteQuery(${reactorName}, {
53
- functionName: "${method.name}",
54
-
55
- initialPageParam: 0 as PageCursor,
56
-
57
- /** Convert page param to method arguments — customize for your API */
58
- getArgs: (pageParam: PageCursor) => {
59
- return [{ offset: pageParam, limit: 10 }] as Parameters<${serviceName}["${method.name}"]>
60
- },
61
-
62
- /** Extract next page param — return undefined when no more pages */
63
- getNextPageParam: (lastPage, allPages, lastPageParam) => {
64
- // Example: offset-based
65
- // if (lastPage.items.length < 10) return undefined
66
- // return lastPageParam + 10
67
- return undefined
68
- },
69
- })
70
-
71
- /** React hook for paginated ${method.name} */
72
- export const ${reactHookName} = ${hookExportName}.useInfiniteQuery
73
- `
74
- }
@@ -1,43 +0,0 @@
1
- import { describe, it, expect } from "vitest"
2
- import { generateMutationHook, MutationHookOptions } from "./mutation"
3
- import type { MethodInfo } from "../types"
4
-
5
- describe("Mutation Hook Generation", () => {
6
- const methodWithArgs: MethodInfo = {
7
- name: "create_item",
8
- type: "mutation",
9
- hasArgs: true,
10
- }
11
-
12
- const methodNoArgs: MethodInfo = {
13
- name: "init_system",
14
- type: "mutation",
15
- hasArgs: false,
16
- }
17
-
18
- it("generates hook correctly for mutation with args", () => {
19
- const options: MutationHookOptions = {
20
- canisterName: "my_canister",
21
- method: methodWithArgs,
22
- }
23
- const result = generateMutationHook(options)
24
- expect(result).toMatchSnapshot()
25
- expect(result).toContain("createMutation(myCanisterReactor, {")
26
- expect(result).toContain(
27
- "export const useCreateItemMutation = createItemMutation.useMutation"
28
- )
29
- })
30
-
31
- it("generates hook correctly for mutation without args", () => {
32
- const options: MutationHookOptions = {
33
- canisterName: "my_canister",
34
- method: methodNoArgs,
35
- }
36
- const result = generateMutationHook(options)
37
- expect(result).toMatchSnapshot()
38
- expect(result).toContain("createMutation(myCanisterReactor, {")
39
- expect(result).toContain(
40
- "export const executeInitSystem = initSystemMutation.execute"
41
- )
42
- })
43
- })
@@ -1,51 +0,0 @@
1
- /**
2
- * Mutation hook template generator
3
- *
4
- * Generates createMutation-based hooks for canister update methods.
5
- */
6
-
7
- import type { MethodInfo } from "../types.js"
8
- import { toPascalCase, getHookExportName, getReactorName } from "../naming.js"
9
-
10
- export interface MutationHookOptions {
11
- canisterName: string
12
- method: MethodInfo
13
- }
14
-
15
- /**
16
- * Generate a mutation hook file content
17
- */
18
- export function generateMutationHook(options: MutationHookOptions): string {
19
- const { canisterName, method } = options
20
-
21
- const pascalMethod = toPascalCase(method.name)
22
- const reactorName = getReactorName(canisterName)
23
- const hookExportName = getHookExportName(method.name, "mutation")
24
-
25
- return `/**
26
- * Mutation: ${method.name}
27
- *
28
- * Auto-generated by @ic-reactor/codegen
29
- *
30
- * @example
31
- * const { mutate, isPending } = ${hookExportName}.useMutation()
32
- * mutate(${method.hasArgs ? "[arg1, arg2]" : "[]"})
33
- *
34
- * // Direct execution (outside React)
35
- * const result = await ${hookExportName}.execute(${method.hasArgs ? "[arg1, arg2]" : "[]"})
36
- */
37
-
38
- import { createMutation } from "@ic-reactor/react"
39
- import { ${reactorName} } from "../reactor"
40
-
41
- export const ${hookExportName} = createMutation(${reactorName}, {
42
- functionName: "${method.name}",
43
- })
44
-
45
- /** React hook for ${method.name} */
46
- export const use${pascalMethod}Mutation = ${hookExportName}.useMutation
47
-
48
- /** Execute ${method.name} directly (outside React) */
49
- export const execute${pascalMethod} = ${hookExportName}.execute
50
- `
51
- }
@@ -1,44 +0,0 @@
1
- import { describe, it, expect } from "vitest"
2
- import { generateQueryHook, QueryHookOptions } from "./query"
3
- import type { MethodInfo } from "../types"
4
-
5
- describe("Query Hook Generation", () => {
6
- const methodWithArgs: MethodInfo = {
7
- name: "get_user",
8
- type: "query",
9
- hasArgs: true,
10
- }
11
-
12
- const methodNoArgs: MethodInfo = {
13
- name: "list_items",
14
- type: "query",
15
- hasArgs: false,
16
- }
17
-
18
- it("generates hook for query with arguments (factory)", () => {
19
- const options: QueryHookOptions = {
20
- canisterName: "my_canister",
21
- method: methodWithArgs,
22
- }
23
- expect(generateQueryHook(options)).toMatchSnapshot()
24
- })
25
-
26
- it("generates hook for query without arguments (static)", () => {
27
- const options: QueryHookOptions = {
28
- canisterName: "my_canister",
29
- method: methodNoArgs,
30
- }
31
- expect(generateQueryHook(options)).toMatchSnapshot()
32
- })
33
-
34
- it("generates suspense hooks correctly", () => {
35
- const options: QueryHookOptions = {
36
- canisterName: "my_canister",
37
- method: methodWithArgs,
38
- type: "suspenseQuery",
39
- }
40
- const result = generateQueryHook(options)
41
- expect(result).toMatchSnapshot()
42
- expect(result).toContain("createSuspenseQueryFactory")
43
- })
44
- })
@@ -1,71 +0,0 @@
1
- /**
2
- * Query hook template generator
3
- *
4
- * Generates createQuery/createQueryFactory-based hooks for canister query methods.
5
- */
6
-
7
- import type { MethodInfo, HookType } from "../types.js"
8
- import { getHookExportName, getReactorName } from "../naming.js"
9
-
10
- export interface QueryHookOptions {
11
- canisterName: string
12
- method: MethodInfo
13
- type?: HookType
14
- }
15
-
16
- /**
17
- * Generate a query hook file content
18
- */
19
- export function generateQueryHook(options: QueryHookOptions): string {
20
- const { canisterName, method, type = "query" } = options
21
-
22
- const reactorName = getReactorName(canisterName)
23
- const hookExportName = getHookExportName(method.name, type)
24
-
25
- const isSuspense = type === "suspenseQuery"
26
- const creatorFn = isSuspense ? "createSuspenseQuery" : "createQuery"
27
- const factoryFn = isSuspense
28
- ? "createSuspenseQueryFactory"
29
- : "createQueryFactory"
30
- const hookName = isSuspense ? "useSuspenseQuery" : "useQuery"
31
-
32
- if (method.hasArgs) {
33
- return `/**
34
- * Query Factory: ${method.name}
35
- *
36
- * Auto-generated by @ic-reactor/codegen
37
- *
38
- * @example
39
- * const { data } = ${hookExportName}([arg1, arg2]).${hookName}()
40
- * const data = await ${hookExportName}([arg1, arg2]).fetch()
41
- * ${hookExportName}([arg1, arg2]).invalidate()
42
- */
43
-
44
- import { ${factoryFn} } from "@ic-reactor/react"
45
- import { ${reactorName} } from "../reactor"
46
-
47
- export const ${hookExportName} = ${factoryFn}(${reactorName}, {
48
- functionName: "${method.name}",
49
- })
50
- `
51
- }
52
-
53
- return `/**
54
- * Query: ${method.name}
55
- *
56
- * Auto-generated by @ic-reactor/codegen
57
- *
58
- * @example
59
- * const { data } = ${hookExportName}.${hookName}()
60
- * const data = await ${hookExportName}.fetch()
61
- * ${hookExportName}.invalidate()
62
- */
63
-
64
- import { ${creatorFn} } from "@ic-reactor/react"
65
- import { ${reactorName} } from "../reactor"
66
-
67
- export const ${hookExportName} = ${creatorFn}(${reactorName}, {
68
- functionName: "${method.name}",
69
- })
70
- `
71
- }
package/src/types.ts DELETED
@@ -1,78 +0,0 @@
1
- /**
2
- * Shared types for IC Reactor code generation
3
- */
4
-
5
- /**
6
- * Information about a canister method extracted from a .did file
7
- */
8
- export interface MethodInfo {
9
- /** Method name as defined in the Candid interface */
10
- name: string
11
- /** Whether this method is a query or update (mutation) */
12
- type: "query" | "mutation"
13
- /** Whether the method accepts arguments */
14
- hasArgs: boolean
15
- /** Human-readable description of the arguments */
16
- argsDescription?: string
17
- /** Human-readable description of the return type */
18
- returnDescription?: string
19
- }
20
-
21
- /**
22
- * Configuration for a single canister
23
- */
24
- export interface CanisterConfig {
25
- /** Name of the canister (used for variable naming) */
26
- name?: string
27
- /** Path to the .did file */
28
- didFile: string
29
- /** Output directory (default: ./src/canisters/<name>) */
30
- outDir?: string
31
- /** Use DisplayReactor for automatic type transformations (default: true) */
32
- useDisplayReactor?: boolean
33
- /**
34
- * Path to import ClientManager from (relative to generated file).
35
- * The file at this path should export: { clientManager: ClientManager }
36
- * Default: "../../lib/client"
37
- */
38
- clientManagerPath?: string
39
- /** Custom canister ID (optional, uses environment by default) */
40
- canisterId?: string
41
- }
42
-
43
- /**
44
- * Hook generation type
45
- */
46
- export type HookType =
47
- | "query"
48
- | "suspenseQuery"
49
- | "infiniteQuery"
50
- | "suspenseInfiniteQuery"
51
- | "mutation"
52
-
53
- /**
54
- * Options for generating a hook file
55
- */
56
- export interface GeneratorOptions {
57
- canisterName: string
58
- methodName: string
59
- methodType: "query" | "mutation"
60
- hasArgs: boolean
61
- outDir: string
62
- }
63
-
64
- /**
65
- * Options for reactor file generation
66
- */
67
- export interface ReactorGeneratorOptions {
68
- canisterName: string
69
- canisterConfig: CanisterConfig
70
- /** Global default clientManagerPath */
71
- globalClientManagerPath?: string
72
- /** Whether declarations have been generated */
73
- hasDeclarations?: boolean
74
- /** Whether to generate advanced per-method hooks (default: false) */
75
- advanced?: boolean
76
- /** DID content (required when advanced=true) */
77
- didContent?: string
78
- }