@tutorialkit-rb/types 0.1.4

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.
@@ -0,0 +1,229 @@
1
+ import { z } from 'zod';
2
+ import { i18nSchema } from './i18n.js';
3
+ import { metaTagsSchema } from './metatags.js';
4
+ export const commandSchema = z.union([
5
+ // a single string, the command to run
6
+ z.string(),
7
+ // a tuple of two strings, the command followed by a title
8
+ z.tuple([z.string(), z.string()]),
9
+ z.strictObject({
10
+ command: z.string().describe('Command to execute in WebContainer.'),
11
+ title: z.string().describe('Title to show for this step in the Prepare Environment section.'),
12
+ }),
13
+ ]);
14
+ export const commandsSchema = z.object({
15
+ mainCommand: commandSchema.optional().describe('The last command to be executed. Typically a dev server.'),
16
+ prepareCommands: commandSchema
17
+ .array()
18
+ .optional()
19
+ .describe('List of commands to be executed to prepare the environment in WebContainer. Each command executed and its status will be shown in the Prepare Environment section.'),
20
+ });
21
+ export const previewSchema = z.union([
22
+ // `false` if you want to disable the preview entirely
23
+ z.boolean(),
24
+ z
25
+ .union([
26
+ // a single number, the port for the preview
27
+ z.number(),
28
+ // a string, the port and pathname
29
+ z.string(),
30
+ // a tuple, the port followed by a title and optional pathname
31
+ z.tuple([z.number(), z.string()]),
32
+ z.tuple([z.number(), z.string(), z.string()]),
33
+ z.strictObject({
34
+ port: z.number().describe('Port number of the preview.'),
35
+ title: z.string().describe('Title of the preview.'),
36
+ pathname: z.string().optional().describe('Pathname of the preview URL.'),
37
+ }),
38
+ ])
39
+ .array(),
40
+ ]);
41
+ export const fileSystemSchema = z.object({
42
+ watch: z
43
+ .union([z.boolean(), z.array(z.string())])
44
+ .describe('When set to true, file changes in WebContainer are updated in the editor as well. When set to an array, file changes or new files in the matching paths are updated in the editor.')
45
+ .optional(),
46
+ });
47
+ const panelTypeSchema = z
48
+ .union([z.literal('output'), z.literal('terminal')])
49
+ .describe(`The type of the terminal which can either be 'output' or 'terminal'.`);
50
+ const allowRedirectsSchema = z
51
+ .boolean()
52
+ .optional()
53
+ .describe("Set to `true` if you want to enable output redirects in the terminal. It's disabled by default.");
54
+ const allowCommandsSchema = z
55
+ .array(z.string())
56
+ .optional()
57
+ .describe('List of command that are allowed in the terminal, if not provided, all commands are allowed.');
58
+ export const terminalSchema = z.union([
59
+ // `false` if you want to disable the terminal entirely
60
+ z.boolean(),
61
+ z.strictObject({
62
+ open: z.boolean().optional().describe('Defines if terminal should be open by default'),
63
+ panels: z.union([
64
+ // either literally just `output`
65
+ z.literal('output'),
66
+ // or literally `terminal`
67
+ z.literal('terminal'),
68
+ /**
69
+ * Or an array of `output` and/or `terminal` literals and/or tuples where the first value is either `output` or
70
+ * `terminal`, and the second being the title and/or panel config objects.
71
+ */
72
+ z
73
+ .array(z.union([
74
+ // the type of the panel
75
+ panelTypeSchema,
76
+ // or a tuple with the type and the title of the panel
77
+ z.tuple([
78
+ // the type of the panel
79
+ panelTypeSchema,
80
+ // the title of the panel which is shown in the tab
81
+ z.string(),
82
+ ]),
83
+ // or an object defining the panel
84
+ z.strictObject({
85
+ // the type of the panel
86
+ type: panelTypeSchema,
87
+ // an id linking the terminal of multiple lessons together
88
+ id: z
89
+ .string()
90
+ .optional()
91
+ .describe('An id linking the terminal of multiple lessons together so that its state is preserved between lessons.'),
92
+ // the title of the panel which is shown in the tab
93
+ title: z.string().optional().describe('The title of the panel which is shown in the tab.'),
94
+ // `true` if you want to enable output redirects in the terminal, disabled by default
95
+ allowRedirects: allowRedirectsSchema,
96
+ // list of command that are allowed in the terminal, if not provided, all commands are allowed
97
+ allowCommands: allowCommandsSchema,
98
+ }),
99
+ ]))
100
+ .refine((arg) => {
101
+ let output = 0;
102
+ for (const value of arg) {
103
+ if (value === 'output' ||
104
+ (Array.isArray(value) && value[0] === 'output') ||
105
+ (typeof value === 'object' && value.type === 'output')) {
106
+ output++;
107
+ }
108
+ if (output > 1) {
109
+ return false;
110
+ }
111
+ }
112
+ return true;
113
+ }, {
114
+ message: 'Only a single output panel can be defined.',
115
+ }),
116
+ ]),
117
+ activePanel: z.number().gte(0).optional().describe('Defines which panel should be visible by default.'),
118
+ // `true` if you want to enable output redirects in the terminal, disabled by default
119
+ allowRedirects: allowRedirectsSchema,
120
+ // list of command that are allowed in the terminal, if not provided, all commands are allowed
121
+ allowCommands: allowCommandsSchema,
122
+ }),
123
+ ]);
124
+ export const editorSchema = z.union([
125
+ // can either be completely removed by setting it to `false`
126
+ z.boolean().optional(),
127
+ z.strictObject({
128
+ fileTree: z
129
+ .union([
130
+ // or you can only remove the file tree
131
+ z.boolean(),
132
+ // or configure file tree with options
133
+ z.strictObject({
134
+ allowEdits: z
135
+ .union([
136
+ // allow editing all files or disable completely
137
+ z.boolean(),
138
+ // limit file editing to files and folders that match a single glob pattern
139
+ z.string(),
140
+ // limit file editing to files and folders that match one of multiple glob patterns
141
+ z.array(z.string()),
142
+ ])
143
+ .describe('Allow file tree’s items to be edited by right clicking them. Supports file and folder creation.'),
144
+ }),
145
+ ])
146
+ .optional(),
147
+ }),
148
+ ]);
149
+ const customSchema = z.record(z.string(), z.any());
150
+ export const webcontainerSchema = commandsSchema.extend({
151
+ meta: metaTagsSchema.optional().describe('Configures `<meta>` tags for Open Graph protocole and Twitter.'),
152
+ custom: customSchema.optional().describe('Assign custom fields to a chapter/part/lesson in the Astro collection'),
153
+ previews: previewSchema
154
+ .optional()
155
+ .describe('Configure which ports should be used for the previews allowing you to align the behavior with your demo application’s dev server setup. If not specified, the lowest port will be used.'),
156
+ autoReload: z
157
+ .boolean()
158
+ .optional()
159
+ .describe('Navigating to a lesson that specifies autoReload will always reload the preview. This is typically only needed if your server does not support HMR.'),
160
+ filesystem: fileSystemSchema
161
+ .optional()
162
+ .describe('Configure how changes happening on the filesystem should impact the Tutorial. For instance, when new files are being changed, whether those change should be reflected in the editor.'),
163
+ template: z
164
+ .string()
165
+ .optional()
166
+ .describe('Specifies which folder from the `src/templates/` directory should be used as the basis for the code. See the "Code templates" guide for a detailed explainer.'),
167
+ terminal: terminalSchema
168
+ .optional()
169
+ .describe('Configures one or more terminals. TutorialKit provides two types of terminals: read-only, called output, and interactive, called terminal.'),
170
+ focus: z
171
+ .string()
172
+ .optional()
173
+ .describe('Defines which file should be opened in the code editor by default when lesson loads.'),
174
+ editor: editorSchema
175
+ .optional()
176
+ .describe('Configure whether or not the editor should be rendered. File tree can be configured by proving an object with fileTree option.'),
177
+ i18n: i18nSchema
178
+ .optional()
179
+ .describe('Lets you define alternative texts used in the UI. This is useful for localization.'),
180
+ editPageLink: z
181
+ .union([
182
+ // pattern for creating the URL
183
+ z.string(),
184
+ // `false` for disabling the edit link
185
+ z.boolean(),
186
+ ])
187
+ .optional()
188
+ .describe('Display a link in lesson for editing the page content. The value is a URL pattern where `${path}` is replaced with the lesson’s location relative to `src/content/tutorial`.'),
189
+ openInStackBlitz: z
190
+ .union([
191
+ // `false` for disabling the link
192
+ z.boolean(),
193
+ z.strictObject({
194
+ projectTitle: z.string().optional(),
195
+ projectDescription: z.string().optional(),
196
+ projectTemplate: z
197
+ .union([
198
+ z.literal('html'),
199
+ z.literal('node'),
200
+ z.literal('angular-cli'),
201
+ z.literal('create-react-app'),
202
+ z.literal('javascript'),
203
+ z.literal('polymer'),
204
+ z.literal('typescript'),
205
+ z.literal('vue'),
206
+ ])
207
+ .optional(),
208
+ }),
209
+ ])
210
+ .optional()
211
+ .describe('Display a link for opening current lesson in StackBlitz.'),
212
+ downloadAsZip: z
213
+ .union([
214
+ // `false` for disabling the button
215
+ z.boolean(),
216
+ z.strictObject({
217
+ filename: z.string(),
218
+ }),
219
+ ])
220
+ .optional()
221
+ .describe('Display a button for downloading the current lesson as `.zip` file.'),
222
+ });
223
+ export const baseSchema = webcontainerSchema.extend({
224
+ title: z.string().describe('The title of the part, chapter, or lesson.'),
225
+ slug: z
226
+ .string()
227
+ .optional()
228
+ .describe('Customize the URL segment of this part, chapter or lesson. The full URL path is `/:partSlug/:chapterSlug/:lessonSlug`.'),
229
+ });