reactivated 0.25.0 → 1.0.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/{babel.config.d.ts → dist/babel.config.d.ts} +0 -0
- package/{babel.config.js → dist/babel.config.js} +0 -0
- package/dist/babel.config.js.map +1 -0
- package/dist/build.client.d.ts +2 -0
- package/{build.client.js → dist/build.client.js} +14 -13
- package/dist/build.client.js.map +1 -0
- package/dist/build.renderer.d.ts +2 -0
- package/{build.renderer.js → dist/build.renderer.js} +21 -14
- package/dist/build.renderer.js.map +1 -0
- package/{client.d.ts → dist/client.d.ts} +0 -0
- package/dist/client.js +19 -0
- package/dist/client.js.map +1 -0
- package/{components → dist/components}/Form.d.ts +1 -0
- package/{components → dist/components}/Form.js +4 -5
- package/dist/components/Form.js.map +1 -0
- package/{components → dist/components}/Widget.d.ts +0 -0
- package/{components → dist/components}/Widget.js +5 -7
- package/dist/components/Widget.js.map +1 -0
- package/{context.d.ts → dist/context.d.ts} +0 -0
- package/dist/context.js +20 -0
- package/dist/context.js.map +1 -0
- package/{eslintrc.d.ts → dist/eslintrc.d.ts} +0 -0
- package/{eslintrc.js → dist/eslintrc.js} +0 -0
- package/dist/eslintrc.js.map +1 -0
- package/{forms → dist/forms}/index.d.ts +0 -0
- package/dist/forms/index.js +377 -0
- package/dist/forms/index.js.map +1 -0
- package/{forms → dist/forms}/widgets.d.ts +1 -0
- package/{forms → dist/forms}/widgets.js +11 -11
- package/dist/forms/widgets.js.map +1 -0
- package/{generated.d.ts → dist/generated.d.ts} +0 -0
- package/{generated.js → dist/generated.js} +0 -0
- package/dist/generated.js.map +1 -0
- package/dist/generator/constants.d.ts +2 -0
- package/{generator → dist/generator}/constants.js +11 -11
- package/dist/generator/constants.js.map +1 -0
- package/dist/generator.d.ts +2 -0
- package/dist/generator.js +155 -0
- package/dist/generator.js.map +1 -0
- package/{index.d.ts → dist/index.d.ts} +0 -0
- package/{index.js → dist/index.js} +0 -0
- package/dist/index.js.map +1 -0
- package/{models.d.ts → dist/models.d.ts} +0 -0
- package/{models.js → dist/models.js} +0 -0
- package/dist/models.js.map +1 -0
- package/{renderer.d.ts → dist/renderer.d.ts} +0 -0
- package/dist/renderer.js +117 -0
- package/dist/renderer.js.map +1 -0
- package/{types.d.ts → dist/types.d.ts} +0 -0
- package/{types.js → dist/types.js} +0 -0
- package/dist/types.js.map +1 -0
- package/package.json +23 -19
- package/scripts/setup_environment.sh +39 -0
- package/{README.md → src/README.md} +0 -0
- package/src/babel.config.tsx +14 -0
- package/src/build.client.tsx +59 -0
- package/src/build.renderer.tsx +69 -0
- package/src/client.tsx +15 -0
- package/src/components/Form.tsx +73 -0
- package/src/components/Widget.tsx +202 -0
- package/src/context.tsx +28 -0
- package/src/eslintrc.tsx +117 -0
- package/src/forms/index.tsx +769 -0
- package/src/forms/widgets.tsx +85 -0
- package/src/generated.tsx +267 -0
- package/src/generator/constants.tsx +40 -0
- package/src/generator.tsx +181 -0
- package/src/index.tsx +4 -0
- package/src/models.tsx +12 -0
- package/src/renderer.tsx +165 -0
- package/src/types.tsx +6 -0
- package/tsconfig.json +10 -20
- package/babel.config.js.map +0 -1
- package/build.client.d.ts +0 -1
- package/build.client.js.map +0 -1
- package/build.renderer.d.ts +0 -1
- package/build.renderer.js.map +0 -1
- package/client.js +0 -30
- package/client.js.map +0 -1
- package/components/Form.js.map +0 -1
- package/components/Widget.js.map +0 -1
- package/context.js +0 -31
- package/context.js.map +0 -1
- package/eslintrc.js.map +0 -1
- package/forms/index.js +0 -401
- package/forms/index.js.map +0 -1
- package/forms/widgets.js.map +0 -1
- package/generated.js.map +0 -1
- package/generator/constants.d.ts +0 -1
- package/generator/constants.js.map +0 -1
- package/generator.d.ts +0 -1
- package/generator.js +0 -109
- package/generator.js.map +0 -1
- package/index.js.map +0 -1
- package/models.js.map +0 -1
- package/renderer.js +0 -108
- package/renderer.js.map +0 -1
- package/types.js.map +0 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {Types} from "../generated";
|
|
3
|
+
|
|
4
|
+
export type CoreWidget = Types["Widget"];
|
|
5
|
+
|
|
6
|
+
type Optgroup = Types["Optgroup"];
|
|
7
|
+
|
|
8
|
+
export const CheckboxInput = (props: {
|
|
9
|
+
name: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
value: true | false;
|
|
12
|
+
onChange: (value: boolean) => void;
|
|
13
|
+
}) => {
|
|
14
|
+
return (
|
|
15
|
+
<input
|
|
16
|
+
type="checkbox"
|
|
17
|
+
name={props.name}
|
|
18
|
+
className={props.className}
|
|
19
|
+
checked={props.value}
|
|
20
|
+
onChange={(event) => props.onChange(event.target.checked)}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const TextInput = (props: {
|
|
26
|
+
name: string;
|
|
27
|
+
className?: string;
|
|
28
|
+
value: string | null;
|
|
29
|
+
onChange: (value: string) => void;
|
|
30
|
+
}) => {
|
|
31
|
+
return (
|
|
32
|
+
<input
|
|
33
|
+
type="text"
|
|
34
|
+
name={props.name}
|
|
35
|
+
className={props.className}
|
|
36
|
+
value={props.value ?? ""}
|
|
37
|
+
onChange={(event) => props.onChange(event.target.value)}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Select = (props: {
|
|
43
|
+
name: string;
|
|
44
|
+
className?: string;
|
|
45
|
+
value: string | number | null;
|
|
46
|
+
optgroups: Optgroup[];
|
|
47
|
+
onChange: (value: string) => void;
|
|
48
|
+
}) => {
|
|
49
|
+
const {name, optgroups, value} = props;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<select
|
|
53
|
+
key={name}
|
|
54
|
+
name={name}
|
|
55
|
+
className={props.className}
|
|
56
|
+
value={value ?? ""}
|
|
57
|
+
onChange={(event) => props.onChange(event.target.value)}
|
|
58
|
+
>
|
|
59
|
+
{optgroups.map((optgroup) => {
|
|
60
|
+
const optgroupValue = (optgroup[1][0].value ?? "").toString();
|
|
61
|
+
return (
|
|
62
|
+
<option key={optgroupValue} value={optgroupValue}>
|
|
63
|
+
{optgroup[1][0].label}
|
|
64
|
+
</option>
|
|
65
|
+
);
|
|
66
|
+
})}
|
|
67
|
+
</select>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const Textarea = (props: {
|
|
72
|
+
name: string;
|
|
73
|
+
className?: string;
|
|
74
|
+
value: string | null;
|
|
75
|
+
onChange: (value: string) => void;
|
|
76
|
+
}) => {
|
|
77
|
+
return (
|
|
78
|
+
<textarea
|
|
79
|
+
name={props.name}
|
|
80
|
+
className={props.className}
|
|
81
|
+
value={props.value ?? ""}
|
|
82
|
+
onChange={(event) => props.onChange(event.target.value)}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by json-schema-to-typescript.
|
|
4
|
+
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
|
5
|
+
* and run json-schema-to-typescript to regenerate this file.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface Types {
|
|
9
|
+
Widget:
|
|
10
|
+
| DjangoFormsWidgetsHiddenInput
|
|
11
|
+
| DjangoFormsWidgetsTextInput
|
|
12
|
+
| DjangoFormsWidgetsNumberInput
|
|
13
|
+
| DjangoFormsWidgetsURLInput
|
|
14
|
+
| DjangoFormsWidgetsTimeInput
|
|
15
|
+
| DjangoFormsWidgetsDateInput
|
|
16
|
+
| DjangoFormsWidgetsCheckboxInput
|
|
17
|
+
| DjangoFormsWidgetsPasswordInput
|
|
18
|
+
| DjangoFormsWidgetsEmailInput
|
|
19
|
+
| DjangoFormsWidgetsTextarea
|
|
20
|
+
| DjangoFormsWidgetsSelect
|
|
21
|
+
| DjangoFormsWidgetsSelectMultiple
|
|
22
|
+
| DjangoFormsWidgetsClearableFileInput
|
|
23
|
+
| DjangoFormsWidgetsSelectDateWidget
|
|
24
|
+
| DjangoFormsWidgetsSplitDateTimeWidget;
|
|
25
|
+
Optgroup: [null, [ReactivatedTypesOptgroupMember], number];
|
|
26
|
+
URLSchema: {
|
|
27
|
+
[k: string]: ReactivatedTypesURL;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface DjangoFormsWidgetsHiddenInput {
|
|
31
|
+
template_name: "django/forms/widgets/hidden.html";
|
|
32
|
+
name: string;
|
|
33
|
+
is_hidden: boolean;
|
|
34
|
+
required: boolean;
|
|
35
|
+
value: string | null;
|
|
36
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
37
|
+
type: "hidden";
|
|
38
|
+
tag: "django.forms.widgets.HiddenInput";
|
|
39
|
+
}
|
|
40
|
+
export interface ReactivatedSerializationWidgetsBaseWidgetAttrs {
|
|
41
|
+
id: string;
|
|
42
|
+
disabled?: boolean;
|
|
43
|
+
required?: boolean;
|
|
44
|
+
placeholder?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface DjangoFormsWidgetsTextInput {
|
|
47
|
+
template_name: "django/forms/widgets/text.html";
|
|
48
|
+
name: string;
|
|
49
|
+
is_hidden: boolean;
|
|
50
|
+
required: boolean;
|
|
51
|
+
value: string | null;
|
|
52
|
+
attrs: ReactivatedSerializationWidgetsMaxLengthAttrs;
|
|
53
|
+
type: "text";
|
|
54
|
+
tag: "django.forms.widgets.TextInput";
|
|
55
|
+
}
|
|
56
|
+
export interface ReactivatedSerializationWidgetsMaxLengthAttrs {
|
|
57
|
+
id: string;
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
required?: boolean;
|
|
60
|
+
placeholder?: string;
|
|
61
|
+
maxlength?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface DjangoFormsWidgetsNumberInput {
|
|
64
|
+
template_name: "django/forms/widgets/number.html";
|
|
65
|
+
name: string;
|
|
66
|
+
is_hidden: boolean;
|
|
67
|
+
required: boolean;
|
|
68
|
+
value: string | null;
|
|
69
|
+
attrs: ReactivatedSerializationWidgetsStepAttrs;
|
|
70
|
+
type: "number";
|
|
71
|
+
tag: "django.forms.widgets.NumberInput";
|
|
72
|
+
}
|
|
73
|
+
export interface ReactivatedSerializationWidgetsStepAttrs {
|
|
74
|
+
id: string;
|
|
75
|
+
disabled?: boolean;
|
|
76
|
+
required?: boolean;
|
|
77
|
+
placeholder?: string;
|
|
78
|
+
step?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface DjangoFormsWidgetsURLInput {
|
|
81
|
+
template_name: "django/forms/widgets/url.html";
|
|
82
|
+
name: string;
|
|
83
|
+
is_hidden: boolean;
|
|
84
|
+
required: boolean;
|
|
85
|
+
value: string | null;
|
|
86
|
+
attrs: ReactivatedSerializationWidgetsMaxLengthAttrs;
|
|
87
|
+
type: "url";
|
|
88
|
+
tag: "django.forms.widgets.URLInput";
|
|
89
|
+
}
|
|
90
|
+
export interface DjangoFormsWidgetsTimeInput {
|
|
91
|
+
template_name: "django/forms/widgets/time.html";
|
|
92
|
+
name: string;
|
|
93
|
+
is_hidden: boolean;
|
|
94
|
+
required: boolean;
|
|
95
|
+
value: string | null;
|
|
96
|
+
attrs: ReactivatedSerializationWidgetsTimeAttrs;
|
|
97
|
+
type: "text";
|
|
98
|
+
tag: "django.forms.widgets.TimeInput";
|
|
99
|
+
}
|
|
100
|
+
export interface ReactivatedSerializationWidgetsTimeAttrs {
|
|
101
|
+
id: string;
|
|
102
|
+
disabled?: boolean;
|
|
103
|
+
required?: boolean;
|
|
104
|
+
placeholder?: string;
|
|
105
|
+
format?: string;
|
|
106
|
+
}
|
|
107
|
+
export interface DjangoFormsWidgetsDateInput {
|
|
108
|
+
template_name: "django/forms/widgets/date.html";
|
|
109
|
+
name: string;
|
|
110
|
+
is_hidden: boolean;
|
|
111
|
+
required: boolean;
|
|
112
|
+
value: string | null;
|
|
113
|
+
attrs: ReactivatedSerializationWidgetsDateAttrs;
|
|
114
|
+
type: "text";
|
|
115
|
+
tag: "django.forms.widgets.DateInput";
|
|
116
|
+
}
|
|
117
|
+
export interface ReactivatedSerializationWidgetsDateAttrs {
|
|
118
|
+
id: string;
|
|
119
|
+
disabled?: boolean;
|
|
120
|
+
required?: boolean;
|
|
121
|
+
placeholder?: string;
|
|
122
|
+
format?: string;
|
|
123
|
+
}
|
|
124
|
+
export interface DjangoFormsWidgetsCheckboxInput {
|
|
125
|
+
template_name: "django/forms/widgets/checkbox.html";
|
|
126
|
+
name: string;
|
|
127
|
+
is_hidden: boolean;
|
|
128
|
+
required: boolean;
|
|
129
|
+
value: boolean;
|
|
130
|
+
attrs: ReactivatedSerializationWidgetsCheckAttrs;
|
|
131
|
+
type: "checkbox";
|
|
132
|
+
tag: "django.forms.widgets.CheckboxInput";
|
|
133
|
+
}
|
|
134
|
+
export interface ReactivatedSerializationWidgetsCheckAttrs {
|
|
135
|
+
id: string;
|
|
136
|
+
disabled?: boolean;
|
|
137
|
+
required?: boolean;
|
|
138
|
+
placeholder?: string;
|
|
139
|
+
checked?: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface DjangoFormsWidgetsPasswordInput {
|
|
142
|
+
template_name: "django/forms/widgets/password.html";
|
|
143
|
+
name: string;
|
|
144
|
+
is_hidden: boolean;
|
|
145
|
+
required: boolean;
|
|
146
|
+
value: string | null;
|
|
147
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
148
|
+
type: "password";
|
|
149
|
+
tag: "django.forms.widgets.PasswordInput";
|
|
150
|
+
}
|
|
151
|
+
export interface DjangoFormsWidgetsEmailInput {
|
|
152
|
+
template_name: "django/forms/widgets/email.html";
|
|
153
|
+
name: string;
|
|
154
|
+
is_hidden: boolean;
|
|
155
|
+
required: boolean;
|
|
156
|
+
value: string | null;
|
|
157
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
158
|
+
type: "email";
|
|
159
|
+
tag: "django.forms.widgets.EmailInput";
|
|
160
|
+
}
|
|
161
|
+
export interface DjangoFormsWidgetsTextarea {
|
|
162
|
+
template_name: "django/forms/widgets/textarea.html";
|
|
163
|
+
name: string;
|
|
164
|
+
is_hidden: boolean;
|
|
165
|
+
required: boolean;
|
|
166
|
+
value: string | null;
|
|
167
|
+
attrs: ReactivatedSerializationWidgetsTextareaAttrs;
|
|
168
|
+
tag: "django.forms.widgets.Textarea";
|
|
169
|
+
}
|
|
170
|
+
export interface ReactivatedSerializationWidgetsTextareaAttrs {
|
|
171
|
+
id: string;
|
|
172
|
+
disabled?: boolean;
|
|
173
|
+
required?: boolean;
|
|
174
|
+
placeholder?: string;
|
|
175
|
+
cols: string;
|
|
176
|
+
rows: string;
|
|
177
|
+
}
|
|
178
|
+
export interface DjangoFormsWidgetsSelect {
|
|
179
|
+
template_name: "django/forms/widgets/select.html";
|
|
180
|
+
name: string;
|
|
181
|
+
is_hidden: boolean;
|
|
182
|
+
required: boolean;
|
|
183
|
+
value: string | null;
|
|
184
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
185
|
+
optgroups: [null, [ReactivatedSerializationWidgetsOptgroupMember], number][];
|
|
186
|
+
tag: "django.forms.widgets.Select";
|
|
187
|
+
}
|
|
188
|
+
export interface ReactivatedSerializationWidgetsOptgroupMember {
|
|
189
|
+
name: string;
|
|
190
|
+
value: string | number | boolean | null;
|
|
191
|
+
label: string;
|
|
192
|
+
selected: boolean;
|
|
193
|
+
}
|
|
194
|
+
export interface DjangoFormsWidgetsSelectMultiple {
|
|
195
|
+
template_name: "django/forms/widgets/select.html";
|
|
196
|
+
name: string;
|
|
197
|
+
is_hidden: boolean;
|
|
198
|
+
required: boolean;
|
|
199
|
+
value: string[];
|
|
200
|
+
attrs: ReactivatedSerializationWidgetsSelectMultipleAttrs;
|
|
201
|
+
optgroups: [null, [ReactivatedSerializationWidgetsOptgroupMember], number][];
|
|
202
|
+
tag: "django.forms.widgets.SelectMultiple";
|
|
203
|
+
}
|
|
204
|
+
export interface ReactivatedSerializationWidgetsSelectMultipleAttrs {
|
|
205
|
+
id: string;
|
|
206
|
+
disabled?: boolean;
|
|
207
|
+
required?: boolean;
|
|
208
|
+
placeholder?: string;
|
|
209
|
+
multiple: boolean;
|
|
210
|
+
}
|
|
211
|
+
export interface DjangoFormsWidgetsClearableFileInput {
|
|
212
|
+
template_name: "django/forms/widgets/clearable_file_input.html";
|
|
213
|
+
name: string;
|
|
214
|
+
is_hidden: boolean;
|
|
215
|
+
required: boolean;
|
|
216
|
+
value: string | null;
|
|
217
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
218
|
+
type: "file";
|
|
219
|
+
checkbox_name: string;
|
|
220
|
+
checkbox_id: string;
|
|
221
|
+
is_initial: boolean;
|
|
222
|
+
input_text: string;
|
|
223
|
+
initial_text: string;
|
|
224
|
+
clear_checkbox_label: string;
|
|
225
|
+
tag: "django.forms.widgets.ClearableFileInput";
|
|
226
|
+
}
|
|
227
|
+
export interface DjangoFormsWidgetsSelectDateWidget {
|
|
228
|
+
template_name: "django/forms/widgets/select_date.html";
|
|
229
|
+
name: string;
|
|
230
|
+
is_hidden: boolean;
|
|
231
|
+
required: boolean;
|
|
232
|
+
value: unknown;
|
|
233
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
234
|
+
_reactivated_value_do_not_use?: {
|
|
235
|
+
year: string | null;
|
|
236
|
+
month: string | null;
|
|
237
|
+
day: string | null;
|
|
238
|
+
};
|
|
239
|
+
subwidgets: [DjangoFormsWidgetsSelect, DjangoFormsWidgetsSelect, DjangoFormsWidgetsSelect];
|
|
240
|
+
tag: "django.forms.widgets.SelectDateWidget";
|
|
241
|
+
}
|
|
242
|
+
export interface DjangoFormsWidgetsSplitDateTimeWidget {
|
|
243
|
+
template_name: "django/forms/widgets/splitdatetime.html";
|
|
244
|
+
name: string;
|
|
245
|
+
is_hidden: boolean;
|
|
246
|
+
required: boolean;
|
|
247
|
+
value: unknown;
|
|
248
|
+
attrs: ReactivatedSerializationWidgetsBaseWidgetAttrs;
|
|
249
|
+
_reactivated_value_do_not_use?: {
|
|
250
|
+
"0": string | null;
|
|
251
|
+
"1": string | null;
|
|
252
|
+
};
|
|
253
|
+
subwidgets: [DjangoFormsWidgetsDateInput, DjangoFormsWidgetsTimeInput];
|
|
254
|
+
tag: "django.forms.widgets.SplitDateTimeWidget";
|
|
255
|
+
}
|
|
256
|
+
export interface ReactivatedTypesOptgroupMember {
|
|
257
|
+
name: string;
|
|
258
|
+
value: string | number | boolean | null;
|
|
259
|
+
label: string;
|
|
260
|
+
selected: boolean;
|
|
261
|
+
}
|
|
262
|
+
export interface ReactivatedTypesURL {
|
|
263
|
+
route: string;
|
|
264
|
+
args: {
|
|
265
|
+
[k: string]: string;
|
|
266
|
+
};
|
|
267
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
|
|
5
|
+
// Must be above the compile import as get-stdin used by
|
|
6
|
+
// json-schema-to-typescript messes up the descriptor even if unused.
|
|
7
|
+
const stdinBuffer = fs.readFileSync(0);
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
Project,
|
|
11
|
+
SourceFile,
|
|
12
|
+
StructureKind,
|
|
13
|
+
SyntaxKind,
|
|
14
|
+
VariableDeclarationKind,
|
|
15
|
+
WriterFunction,
|
|
16
|
+
Writers,
|
|
17
|
+
} from "ts-morph";
|
|
18
|
+
|
|
19
|
+
const schema = JSON.parse(stdinBuffer.toString("utf8"));
|
|
20
|
+
|
|
21
|
+
const project = new Project();
|
|
22
|
+
|
|
23
|
+
const interfaces = project.createSourceFile("");
|
|
24
|
+
|
|
25
|
+
const {urls, templates, types, values} = schema;
|
|
26
|
+
|
|
27
|
+
for (const name of Object.keys(values)) {
|
|
28
|
+
interfaces.addVariableStatement({
|
|
29
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
30
|
+
isExported: true,
|
|
31
|
+
declarations: [
|
|
32
|
+
{
|
|
33
|
+
name,
|
|
34
|
+
initializer: Writers.assertion(JSON.stringify(values[name]), "const"),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
process.stdout.write(interfaces.getText());
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import * as generated from "./generated";
|
|
5
|
+
|
|
6
|
+
// Must be above the compile import as get-stdin used by
|
|
7
|
+
// json-schema-to-typescript messes up the descriptor even if unused.
|
|
8
|
+
const stdinBuffer = fs.readFileSync(0);
|
|
9
|
+
|
|
10
|
+
import {compile} from "json-schema-to-typescript";
|
|
11
|
+
import {
|
|
12
|
+
Project,
|
|
13
|
+
SourceFile,
|
|
14
|
+
StructureKind,
|
|
15
|
+
SyntaxKind,
|
|
16
|
+
VariableDeclarationKind,
|
|
17
|
+
WriterFunction,
|
|
18
|
+
Writers,
|
|
19
|
+
} from "ts-morph";
|
|
20
|
+
|
|
21
|
+
const schema = JSON.parse(stdinBuffer.toString("utf8"));
|
|
22
|
+
const {urls: possibleEmptyUrls, templates, interfaces, types, values} = schema;
|
|
23
|
+
|
|
24
|
+
const urls: generated.Types["URLSchema"] = {
|
|
25
|
+
...possibleEmptyUrls,
|
|
26
|
+
__reactivated_do_not_use: {
|
|
27
|
+
route: "__reactivated_do_not_use",
|
|
28
|
+
args: {},
|
|
29
|
+
},
|
|
30
|
+
__reactivated_do_not_use_args: {
|
|
31
|
+
route: "__reactivated_do_not_use_args",
|
|
32
|
+
args: {
|
|
33
|
+
_: "string",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const project = new Project();
|
|
39
|
+
|
|
40
|
+
const sourceFile = project.createSourceFile("");
|
|
41
|
+
|
|
42
|
+
if (Object.keys(urls).length !== 0) {
|
|
43
|
+
sourceFile.addVariableStatement({
|
|
44
|
+
declarationKind: VariableDeclarationKind.Const,
|
|
45
|
+
declarations: [
|
|
46
|
+
{
|
|
47
|
+
name: "urls",
|
|
48
|
+
initializer: JSON.stringify(urls),
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const urlMap = sourceFile.addInterface({
|
|
54
|
+
name: "URLMap",
|
|
55
|
+
});
|
|
56
|
+
urlMap.setIsExported(true);
|
|
57
|
+
|
|
58
|
+
const withArguments = [""];
|
|
59
|
+
const withoutArguments = [""];
|
|
60
|
+
|
|
61
|
+
for (const name of Object.keys(urls)) {
|
|
62
|
+
const properties = urls[name as keyof typeof urls].args;
|
|
63
|
+
const normalizedName = name.replace(/[^\w]/g, "_");
|
|
64
|
+
|
|
65
|
+
const urlInterface = sourceFile.addInterface({
|
|
66
|
+
name: normalizedName,
|
|
67
|
+
properties: [{name: "name", type: `'${name}'`}],
|
|
68
|
+
});
|
|
69
|
+
const argsInterface = sourceFile.addInterface({
|
|
70
|
+
name: `${normalizedName}_args`,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
for (const propertyName of Object.keys(properties)) {
|
|
74
|
+
argsInterface.addProperty({
|
|
75
|
+
name: propertyName,
|
|
76
|
+
type: properties[propertyName as keyof typeof properties],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
urlInterface.addProperty({
|
|
80
|
+
name: "args",
|
|
81
|
+
type: `${normalizedName}_args`,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
urlMap.addProperty({
|
|
85
|
+
name: normalizedName,
|
|
86
|
+
type: normalizedName,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (Object.keys(properties).length === 0) {
|
|
90
|
+
withoutArguments.push(normalizedName);
|
|
91
|
+
} else {
|
|
92
|
+
withArguments.push(normalizedName);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
sourceFile.addTypeAlias({name: "WithArguments", type: withArguments.join("|")});
|
|
96
|
+
sourceFile.addTypeAlias({
|
|
97
|
+
name: "WithoutArguments",
|
|
98
|
+
type: withoutArguments.join("|"),
|
|
99
|
+
});
|
|
100
|
+
sourceFile.addStatements(`
|
|
101
|
+
|
|
102
|
+
type All = WithArguments|WithoutArguments;
|
|
103
|
+
export function reverse<T extends WithoutArguments['name']>(name: T): string;
|
|
104
|
+
export function reverse<T extends WithArguments['name']>(name: T, args: Extract<WithArguments, {name: T}>['args']): string;
|
|
105
|
+
export function reverse<T extends All['name']>(name: T, args?: Extract<WithArguments, {name: T}>['args']): string {
|
|
106
|
+
let route = urls[name].route;
|
|
107
|
+
|
|
108
|
+
if (args != null) {
|
|
109
|
+
for (const token of Object.keys(args)) {
|
|
110
|
+
route = route.replace(new RegExp('<(.+?:)' + token + '>'), (args as any)[token]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return route;
|
|
114
|
+
}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
sourceFile.addStatements(`
|
|
118
|
+
import React from "react"
|
|
119
|
+
import createContext from "reactivated/dist/context";
|
|
120
|
+
import * as forms from "reactivated/dist/forms";
|
|
121
|
+
import * as generated from "reactivated/dist/generated";
|
|
122
|
+
|
|
123
|
+
// Note: this needs strict function types to behave correctly with excess properties etc.
|
|
124
|
+
export type Checker<P, U extends (React.FunctionComponent<P> | React.ComponentClass<P>)> = {};
|
|
125
|
+
|
|
126
|
+
export const {Context, Provider, getServerData} = createContext<_Types["Context"]>();
|
|
127
|
+
|
|
128
|
+
export const getTemplate = ({template_name}: {template_name: string}) => {
|
|
129
|
+
// This require needs to be *inside* the function to avoid circular dependencies with esbuild.
|
|
130
|
+
const { default: templates, filenames } = require('../../client/templates/**/*');
|
|
131
|
+
const templatePath = "../../client/templates/" + template_name + ".tsx";
|
|
132
|
+
const possibleTemplate: {default: React.ComponentType<any>} | null = templates.find((t: any, index: number) => filenames[index] === templatePath);
|
|
133
|
+
|
|
134
|
+
if (possibleTemplate == null) {
|
|
135
|
+
throw new Error("Template " + template_name + ".tsx not found");
|
|
136
|
+
}
|
|
137
|
+
return possibleTemplate.default;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const CSRFToken = forms.createCSRFToken(Context);
|
|
141
|
+
|
|
142
|
+
export const {createRenderer, Iterator} = forms.bindWidgetType<_Types["globals"]["Widget"]>();
|
|
143
|
+
export type FieldHandler = forms.FieldHandler<_Types["globals"]["Widget"]>;
|
|
144
|
+
|
|
145
|
+
export const {Form, FormSet, Widget, useForm, useFormSet, ManagementForm} = forms;
|
|
146
|
+
`);
|
|
147
|
+
|
|
148
|
+
// tslint:disable-next-line
|
|
149
|
+
compile(types, "_Types").then((ts) => {
|
|
150
|
+
process.stdout.write("/* eslint-disable */\n");
|
|
151
|
+
process.stdout.write(ts);
|
|
152
|
+
|
|
153
|
+
for (const name of Object.keys(templates)) {
|
|
154
|
+
const propsName = templates[name];
|
|
155
|
+
sourceFile.addStatements(`
|
|
156
|
+
|
|
157
|
+
import ${name}Implementation from "@client/templates/${name}"
|
|
158
|
+
export type ${name}Check = Checker<_Types["${propsName}"], typeof ${name}Implementation>;
|
|
159
|
+
|
|
160
|
+
export namespace templates {
|
|
161
|
+
export type ${name} = _Types["${propsName}"];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
for (const name of Object.keys(interfaces)) {
|
|
169
|
+
const propsName = interfaces[name];
|
|
170
|
+
sourceFile.addStatements(`
|
|
171
|
+
|
|
172
|
+
export namespace interfaces {
|
|
173
|
+
export type ${name} = _Types["${propsName}"];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
process.stdout.write(sourceFile.getText());
|
|
181
|
+
});
|
package/src/index.tsx
ADDED
package/src/models.tsx
ADDED