Module: ArSync::TypeScript

Defined in:
lib/ar_sync/type_script.rb

Class Method Summary collapse

Class Method Details



19
20
21
22
# File 'lib/ar_sync/type_script.rb', line 19

def self.api_related_classes(api_class)
  classes = ArSerializer::TypeScript.related_serializer_types([api_class]).map(&:type)
  classes - [api_class]
end

.generate_api_script ⇒ Object



66
67
68
69
70
71
72
73
74
75
# File 'lib/ar_sync/type_script.rb', line 66

def self.generate_api_script
  <<~CODE
    import { TypeRequest } from './types'
    import DataTypeFromRequest from './DataTypeFromRequest'
    import ArSyncApi from 'ar_sync/core/ArSyncApi'
    export function fetch<R extends TypeRequest>(request: R) {
      return ArSyncApi.fetch(request) as Promise<DataTypeFromRequest<R>>
    }
  CODE
end

.generate_hooks_script ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/ar_sync/type_script.rb', line 86

def self.generate_hooks_script
  <<~CODE
    import { useState, useEffect, useMemo } from 'react'
    import { TypeRequest } from './types'
    import DataTypeFromRequest from './DataTypeFromRequest'
    import { initializeHooks, useArSyncModel as useArSyncModelBase, useArSyncFetch as useArSyncFetchBase } from 'ar_sync/core/hooks'
    initializeHooks({ useState, useEffect, useMemo })
    export function useArSyncModel<R extends TypeRequest>(request: R | null) {
      return useArSyncModelBase<DataTypeFromRequest<R>>(request)
    }
    export function useArSyncFetch<R extends TypeRequest>(request: R | null) {
      return useArSyncFetchBase<DataTypeFromRequest<R>>(request)
    }
  CODE
end

.generate_model_script ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ar_sync/type_script.rb', line 54

def self.generate_model_script
  <<~CODE
    import { TypeRequest } from './types'
    import DataTypeFromRequest from './DataTypeFromRequest'
    import { default as ArSyncModelBase } from 'ar_sync/core/ArSyncModel'
    declare class ArSyncModel<R extends TypeRequest> extends ArSyncModelBase<DataTypeFromRequest<R>> {
      constructor(r: R, option?: { immutable: boolean })
    }
    export default ArSyncModelBase as typeof ArSyncModel
  CODE
end

.generate_type_definition(api_class) ⇒ Object



12
13
14
15
16
17
# File 'lib/ar_sync/type_script.rb', line 12

def self.generate_type_definition(api_class)
  [
    ArSerializer::TypeScript.generate_type_definition(api_related_classes(api_class)),
    request_type_definition(api_class)
  ].join "\n"
end

.generate_type_util_script ⇒ Object



77
78
79
80
81
82
83
84
# File 'lib/ar_sync/type_script.rb', line 77

def self.generate_type_util_script
  <<~CODE
    import { TypeRequest, ApiNameRequests } from './types'
    import { DataTypeFromRequest as DataTypeFromRequestPair } from 'ar_sync/core/DataType'
    type DataTypeFromRequest<R extends TypeRequest> = DataTypeFromRequestPair<ApiNameRequests[R['api']], R>
    export default DataTypeFromRequest
  CODE
end

.generate_typed_files(api_class, dir:, comment: nil) ⇒ Object



2
3
4
5
6
7
8
9
10
# File 'lib/ar_sync/type_script.rb', line 2

def self.generate_typed_files(api_class, dir:, comment: nil)
  {
    'types.ts' => generate_type_definition(api_class),
    'ArSyncModel.ts' => generate_model_script,
    'ArSyncApi.ts' => generate_api_script,
    'hooks.ts' => generate_hooks_script,
    'DataTypeFromRequest.ts' => generate_type_util_script
  }.each { |file, code| File.write File.join(dir, file), "#{comment}#{code}" }
end

.request_type_definition(api_class) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/ar_sync/type_script.rb', line 24

def self.request_type_definition(api_class)
  type = ArSerializer::GraphQL::TypeClass.from api_class
  definitions = []
  request_types = {}
  type.fields.each do |field|
    association_type = field.type.association_type
    next unless association_type
    prefix = 'Class' if field.name.match?(/\A[A-Z]/) # for class reload query
    request_type_name = "Type#{prefix}#{field.name.camelize}Request"
    request_types[field.name] = request_type_name
    multiple = field.type.is_a? ArSerializer::GraphQL::ListTypeClass
    definitions << <<~CODE
      export interface #{request_type_name} {
        api: '#{field.name}'
        params?: #{field.args_ts_type}
        query: Type#{association_type.name}Query
        _meta?: { data: Type#{field.type.association_type.name}#{'[]' if multiple} }
      }
    CODE
  end
  [
    'export type TypeRequest = ',
    request_types.values.map { |value| "  | #{value}" },
    'export type ApiNameRequests =  {',
    request_types.map { |key, value| "  #{key}: #{value}" },
    '}',
    definitions
  ].join("\n")
end