directus-template-cli 0.7.4 → 0.7.6

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/bin/dev.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env -S node --loader ts-node/esm --disable-warning=ExperimentalWarning
2
2
 
3
- // eslint-disable-next-line n/shebang
4
3
  import {execute} from '@oclif/core'
5
4
 
6
5
  await execute({development: true, dir: import.meta.url})
package/bin/run.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ /* eslint-disable n/no-unpublished-bin */
2
3
 
3
4
  import {execute} from '@oclif/core'
4
5
 
@@ -7,9 +7,11 @@ export default class ApplyCommand extends BaseCommand {
7
7
  dashboards: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
8
  directusToken: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
9
  directusUrl: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ disableTelemetry: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  extensions: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
12
  files: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
13
  flows: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ noExit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
15
  partial: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
16
  permissions: import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
17
  programmatic: import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -20,7 +22,6 @@ export default class ApplyCommand extends BaseCommand {
20
22
  userEmail: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
21
23
  userPassword: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
22
24
  users: import("@oclif/core/interfaces").BooleanFlag<boolean>;
23
- disableTelemetry: import("@oclif/core/interfaces").BooleanFlag<boolean>;
24
25
  };
25
26
  /**
26
27
  * MAIN
@@ -1,20 +1,19 @@
1
+ import { intro, log, select, text } from '@clack/prompts';
1
2
  import { Flags, ux } from '@oclif/core';
2
- import { text, select, log, intro } from '@clack/prompts';
3
+ import chalk from 'chalk';
3
4
  import * as path from 'pathe';
4
- import { animatedBunny } from '../lib/utils/animated-bunny.js';
5
5
  import * as customFlags from '../flags/common.js';
6
- import { DIRECTUS_PINK, DIRECTUS_PURPLE, SEPARATOR } from '../lib/constants.js';
6
+ import { BSL_LICENSE_CTA, BSL_LICENSE_HEADLINE, BSL_LICENSE_TEXT, DIRECTUS_PINK, DIRECTUS_PURPLE, SEPARATOR } from '../lib/constants.js';
7
7
  import { validateInteractiveFlags, validateProgrammaticFlags } from '../lib/load/apply-flags.js';
8
8
  import apply from '../lib/load/index.js';
9
- import { getDirectusToken, getDirectusUrl, initializeDirectusApi, getDirectusEmailAndPassword } from '../lib/utils/auth.js';
9
+ import { animatedBunny } from '../lib/utils/animated-bunny.js';
10
+ import { getDirectusEmailAndPassword, getDirectusToken, getDirectusUrl, initializeDirectusApi } from '../lib/utils/auth.js';
10
11
  import catchError from '../lib/utils/catch-error.js';
11
12
  import { getCommunityTemplates, getGithubTemplate, getInteractiveLocalTemplate, getLocalTemplate } from '../lib/utils/get-template.js';
12
13
  import { logger } from '../lib/utils/logger.js';
13
14
  import openUrl from '../lib/utils/open-url.js';
14
- import chalk from 'chalk';
15
+ import { shutdown, track } from '../services/posthog.js';
15
16
  import { BaseCommand } from './base.js';
16
- import { track, shutdown } from '../services/posthog.js';
17
- import { BSL_LICENSE_HEADLINE, BSL_LICENSE_TEXT, BSL_LICENSE_CTA } from '../lib/constants.js';
18
17
  export default class ApplyCommand extends BaseCommand {
19
18
  static description = 'Apply a template to a blank Directus instance.';
20
19
  static examples = [
@@ -35,6 +34,7 @@ export default class ApplyCommand extends BaseCommand {
35
34
  }),
36
35
  directusToken: customFlags.directusToken,
37
36
  directusUrl: customFlags.directusUrl,
37
+ disableTelemetry: customFlags.disableTelemetry,
38
38
  extensions: Flags.boolean({
39
39
  allowNo: true,
40
40
  default: undefined,
@@ -50,6 +50,10 @@ export default class ApplyCommand extends BaseCommand {
50
50
  default: undefined,
51
51
  description: 'Load Flows (operations, flows)',
52
52
  }),
53
+ noExit: Flags.boolean({
54
+ default: false,
55
+ hidden: true,
56
+ }),
53
57
  partial: Flags.boolean({
54
58
  dependsOn: ['programmatic'],
55
59
  description: 'Enable partial template application (all components enabled by default)',
@@ -88,7 +92,6 @@ export default class ApplyCommand extends BaseCommand {
88
92
  default: undefined,
89
93
  description: 'Load users',
90
94
  }),
91
- disableTelemetry: customFlags.disableTelemetry,
92
95
  };
93
96
  /**
94
97
  * MAIN
@@ -112,32 +115,25 @@ export default class ApplyCommand extends BaseCommand {
112
115
  await animatedBunny('Let\'s apply a template!');
113
116
  intro(`${chalk.bgHex(DIRECTUS_PURPLE).white.bold('Directus Template CLI')} - Apply Template`);
114
117
  const templateType = await select({
118
+ message: 'What type of template would you like to apply?',
115
119
  options: [
116
120
  { label: 'Community templates', value: 'community' },
117
121
  { label: 'From a local directory', value: 'local' },
118
122
  { label: 'From a public GitHub repository', value: 'github' },
119
123
  { label: 'Get premium templates', value: 'directus-plus' },
120
124
  ],
121
- message: 'What type of template would you like to apply?',
122
125
  });
123
126
  let template;
124
127
  switch (templateType) {
125
128
  case 'community': {
126
129
  const templates = await getCommunityTemplates();
127
130
  const selectedTemplate = await select({
128
- options: templates.map(t => ({ label: t.templateName, value: t })),
129
131
  message: 'Select a template.',
132
+ options: templates.map(t => ({ label: t.templateName, value: t })),
130
133
  });
131
134
  template = selectedTemplate;
132
135
  break;
133
136
  }
134
- case 'local': {
135
- const localTemplateDir = await text({
136
- message: 'What is the local template directory?',
137
- });
138
- template = await this.selectLocalTemplate(localTemplateDir);
139
- break;
140
- }
141
137
  case 'github': {
142
138
  const ghTemplateUrl = await text({
143
139
  message: 'What is the public GitHub repository URL?',
@@ -145,10 +141,19 @@ export default class ApplyCommand extends BaseCommand {
145
141
  template = await getGithubTemplate(ghTemplateUrl);
146
142
  break;
147
143
  }
144
+ case 'local': {
145
+ const localTemplateDir = await text({
146
+ message: 'What is the local template directory?',
147
+ });
148
+ template = await this.selectLocalTemplate(localTemplateDir);
149
+ break;
150
+ }
148
151
  case 'directus-plus': {
149
152
  openUrl('https://directus.io/plus?utm_source=directus-template-cli&utm_content=apply-command');
150
153
  log.info('Redirecting to Directus website.');
151
- ux.exit(0);
154
+ if (!validatedFlags.noExit)
155
+ process.exit(0);
156
+ return;
152
157
  }
153
158
  }
154
159
  log.info(`You selected ${ux.colorize(DIRECTUS_PINK, template.templateName)}`);
@@ -157,11 +162,11 @@ export default class ApplyCommand extends BaseCommand {
157
162
  validatedFlags.directusUrl = directusUrl;
158
163
  // Prompt for login method
159
164
  const loginMethod = await select({
165
+ message: 'How do you want to log in?',
160
166
  options: [
161
167
  { label: 'Directus Access Token', value: 'token' },
162
168
  { label: 'Email and Password', value: 'email' },
163
169
  ],
164
- message: 'How do you want to log in?',
165
170
  });
166
171
  if (loginMethod === 'token') {
167
172
  const directusToken = await getDirectusToken(directusUrl);
@@ -179,7 +184,7 @@ export default class ApplyCommand extends BaseCommand {
179
184
  if (!validatedFlags.disableTelemetry) {
180
185
  await track({
181
186
  command: 'apply',
182
- lifecycle: 'start',
187
+ config: this.config,
183
188
  distinctId: this.userConfig.distinctId,
184
189
  flags: {
185
190
  programmatic: false,
@@ -188,8 +193,8 @@ export default class ApplyCommand extends BaseCommand {
188
193
  // Include other relevant flags from validatedFlags if needed
189
194
  ...validatedFlags,
190
195
  },
196
+ lifecycle: 'start',
191
197
  runId: this.runId,
192
- config: this.config,
193
198
  });
194
199
  }
195
200
  await apply(template.directoryPath, validatedFlags);
@@ -198,15 +203,15 @@ export default class ApplyCommand extends BaseCommand {
198
203
  if (!validatedFlags.disableTelemetry) {
199
204
  await track({
200
205
  command: 'apply',
201
- lifecycle: 'complete',
206
+ config: this.config,
202
207
  distinctId: this.userConfig.distinctId,
203
208
  flags: {
204
209
  templateName: template.templateName,
205
210
  templateType,
206
211
  ...validatedFlags,
207
212
  },
213
+ lifecycle: 'complete',
208
214
  runId: this.runId,
209
- config: this.config,
210
215
  });
211
216
  await shutdown();
212
217
  }
@@ -215,7 +220,9 @@ export default class ApplyCommand extends BaseCommand {
215
220
  log.info(BSL_LICENSE_TEXT);
216
221
  log.info(BSL_LICENSE_CTA);
217
222
  ux.stdout('Template applied successfully.');
218
- ux.exit(0);
223
+ if (!validatedFlags.noExit)
224
+ process.exit(0);
225
+ return;
219
226
  }
220
227
  }
221
228
  /**
@@ -233,14 +240,14 @@ export default class ApplyCommand extends BaseCommand {
233
240
  template = templates.find(t => t.templateName === validatedFlags.templateLocation) || templates[0];
234
241
  break;
235
242
  }
236
- case 'local': {
237
- template = await getLocalTemplate(validatedFlags.templateLocation);
238
- break;
239
- }
240
243
  case 'github': {
241
244
  template = await getGithubTemplate(validatedFlags.templateLocation);
242
245
  break;
243
246
  }
247
+ case 'local': {
248
+ template = await getLocalTemplate(validatedFlags.templateLocation);
249
+ break;
250
+ }
244
251
  default: {
245
252
  catchError('Invalid template type. Please check your template type.', {
246
253
  fatal: true,
@@ -255,7 +262,7 @@ export default class ApplyCommand extends BaseCommand {
255
262
  if (!validatedFlags.disableTelemetry) {
256
263
  await track({
257
264
  command: 'apply',
258
- lifecycle: 'start',
265
+ config: this.config,
259
266
  distinctId: this.userConfig.distinctId,
260
267
  flags: {
261
268
  programmatic: true,
@@ -263,8 +270,8 @@ export default class ApplyCommand extends BaseCommand {
263
270
  // Include other relevant flags from validatedFlags
264
271
  ...validatedFlags,
265
272
  },
273
+ lifecycle: 'start',
266
274
  runId: this.runId,
267
- config: this.config,
268
275
  });
269
276
  }
270
277
  await apply(template.directoryPath, validatedFlags);
@@ -273,25 +280,26 @@ export default class ApplyCommand extends BaseCommand {
273
280
  if (!validatedFlags.disableTelemetry) {
274
281
  await track({
275
282
  command: 'apply',
276
- lifecycle: 'complete',
283
+ config: this.config,
277
284
  distinctId: this.userConfig.distinctId,
278
285
  flags: {
279
286
  templateName: template.templateName,
280
287
  // Include other relevant flags from validatedFlags
281
288
  ...validatedFlags,
282
289
  },
290
+ lifecycle: 'complete',
283
291
  runId: this.runId,
284
- config: this.config,
285
292
  });
286
293
  await shutdown();
287
294
  }
288
295
  ux.stdout(SEPARATOR);
289
296
  ux.stdout('Template applied successfully.');
297
+ if (!validatedFlags.noExit)
298
+ process.exit(0);
290
299
  // Hide BSL license info if running programatically for now
291
300
  // log.warn(BSL_LICENSE_HEADLINE)
292
301
  // log.info(BSL_LICENSE_TEXT)
293
302
  // log.info(BSL_LICENSE_CTA)
294
- ux.exit(0);
295
303
  }
296
304
  /**
297
305
  * INTERACTIVE
@@ -306,11 +314,11 @@ export default class ApplyCommand extends BaseCommand {
306
314
  return templates[0];
307
315
  }
308
316
  const selectedTemplate = await select({
317
+ message: 'Multiple templates found. Please select one:',
309
318
  options: templates.map(t => ({
310
319
  label: `${t.templateName} (${path.basename(t.directoryPath)})`,
311
320
  value: t,
312
321
  })),
313
- message: 'Multiple templates found. Please select one:',
314
322
  });
315
323
  return selectedTemplate;
316
324
  }
@@ -1,16 +1,16 @@
1
1
  import { Command, type Config } from '@oclif/core';
2
2
  interface UserConfig {
3
- distinctId?: string | null;
3
+ distinctId?: null | string;
4
4
  }
5
5
  export declare abstract class BaseCommand extends Command {
6
6
  runId: string;
7
7
  userConfig: UserConfig;
8
8
  constructor(argv: string[], config: Config);
9
9
  init(): Promise<void>;
10
- private loadUserConfig;
11
10
  /**
12
11
  * Save the current user configuration to disk
13
12
  */
14
13
  protected saveUserConfig(): void;
14
+ private loadUserConfig;
15
15
  }
16
16
  export {};
@@ -14,15 +14,27 @@ export class BaseCommand extends Command {
14
14
  async init() {
15
15
  await super.init();
16
16
  const { flags } = await this.parse({
17
- flags: this.ctor.flags,
18
17
  args: this.ctor.args,
18
+ flags: this.ctor.flags,
19
19
  strict: false,
20
20
  });
21
21
  setExecutionContext({
22
- distinctId: this.userConfig.distinctId ?? undefined,
23
22
  disableTelemetry: flags?.disableTelemetry ?? false,
23
+ distinctId: this.userConfig.distinctId ?? undefined,
24
24
  });
25
25
  }
26
+ /**
27
+ * Save the current user configuration to disk
28
+ */
29
+ saveUserConfig() {
30
+ try {
31
+ const configPath = path.join(this.config.configDir, 'config.json');
32
+ fs.writeFileSync(configPath, JSON.stringify(this.userConfig, null, 2));
33
+ }
34
+ catch (error) {
35
+ this.warn(`Failed to save user config: ${error}`);
36
+ }
37
+ }
26
38
  loadUserConfig() {
27
39
  try {
28
40
  const configPath = path.join(this.config.configDir, 'config.json');
@@ -43,16 +55,4 @@ export class BaseCommand extends Command {
43
55
  this.warn(`Failed to load user config: ${error}`);
44
56
  }
45
57
  }
46
- /**
47
- * Save the current user configuration to disk
48
- */
49
- saveUserConfig() {
50
- try {
51
- const configPath = path.join(this.config.configDir, 'config.json');
52
- fs.writeFileSync(configPath, JSON.stringify(this.userConfig, null, 2));
53
- }
54
- catch (error) {
55
- this.warn(`Failed to save user config: ${error}`);
56
- }
57
- }
58
58
  }
@@ -2,12 +2,12 @@ import { BaseCommand } from './base.js';
2
2
  export interface ExtractFlags {
3
3
  directusToken: string;
4
4
  directusUrl: string;
5
+ disableTelemetry?: boolean;
5
6
  programmatic: boolean;
6
7
  templateLocation: string;
7
8
  templateName: string;
8
9
  userEmail: string;
9
10
  userPassword: string;
10
- disableTelemetry?: boolean;
11
11
  }
12
12
  export default class ExtractCommand extends BaseCommand {
13
13
  static description: string;
@@ -15,12 +15,12 @@ export default class ExtractCommand extends BaseCommand {
15
15
  static flags: {
16
16
  directusToken: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
17
17
  directusUrl: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
18
+ disableTelemetry: import("@oclif/core/interfaces").BooleanFlag<boolean>;
18
19
  programmatic: import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
20
  templateLocation: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
20
21
  templateName: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
21
22
  userEmail: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
22
23
  userPassword: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
23
- disableTelemetry: import("@oclif/core/interfaces").BooleanFlag<boolean>;
24
24
  };
25
25
  /**
26
26
  * Main run method for the ExtractCommand
@@ -1,18 +1,18 @@
1
- import { text, select, intro, log } from '@clack/prompts';
1
+ import { intro, log, select, text } from '@clack/prompts';
2
2
  import { ux } from '@oclif/core';
3
3
  import slugify from '@sindresorhus/slugify';
4
4
  import chalk from 'chalk';
5
5
  import fs from 'node:fs';
6
6
  import path from 'pathe';
7
7
  import * as customFlags from '../flags/common.js';
8
- import { DIRECTUS_PINK, DIRECTUS_PURPLE, SEPARATOR, BSL_LICENSE_TEXT, BSL_LICENSE_CTA, BSL_LICENSE_HEADLINE } from '../lib/constants.js';
9
- import { animatedBunny } from '../lib/utils/animated-bunny.js';
10
- import { BaseCommand } from './base.js';
11
- import { track, shutdown } from '../services/posthog.js';
8
+ import { BSL_LICENSE_CTA, BSL_LICENSE_HEADLINE, BSL_LICENSE_TEXT, DIRECTUS_PINK, DIRECTUS_PURPLE, SEPARATOR } from '../lib/constants.js';
12
9
  import extract from '../lib/extract/index.js';
13
- import { getDirectusToken, getDirectusUrl, initializeDirectusApi, validateAuthFlags, getDirectusEmailAndPassword } from '../lib/utils/auth.js';
10
+ import { animatedBunny } from '../lib/utils/animated-bunny.js';
11
+ import { getDirectusEmailAndPassword, getDirectusToken, getDirectusUrl, initializeDirectusApi, validateAuthFlags } from '../lib/utils/auth.js';
14
12
  import catchError from '../lib/utils/catch-error.js';
15
13
  import { generatePackageJsonContent, generateReadmeContent, } from '../lib/utils/template-defaults.js';
14
+ import { shutdown, track } from '../services/posthog.js';
15
+ import { BaseCommand } from './base.js';
16
16
  export default class ExtractCommand extends BaseCommand {
17
17
  static description = 'Extract a template from a Directus instance.';
18
18
  static examples = [
@@ -22,12 +22,12 @@ export default class ExtractCommand extends BaseCommand {
22
22
  static flags = {
23
23
  directusToken: customFlags.directusToken,
24
24
  directusUrl: customFlags.directusUrl,
25
+ disableTelemetry: customFlags.disableTelemetry,
25
26
  programmatic: customFlags.programmatic,
26
27
  templateLocation: customFlags.templateLocation,
27
28
  templateName: customFlags.templateName,
28
29
  userEmail: customFlags.userEmail,
29
30
  userPassword: customFlags.userPassword,
30
- disableTelemetry: customFlags.disableTelemetry,
31
31
  };
32
32
  /**
33
33
  * Main run method for the ExtractCommand
@@ -50,16 +50,16 @@ export default class ExtractCommand extends BaseCommand {
50
50
  if (!flags.disableTelemetry) {
51
51
  await track({
52
52
  command: 'extract',
53
- lifecycle: 'start',
53
+ config: this.config,
54
54
  distinctId: this.userConfig.distinctId,
55
55
  flags: {
56
- templateName,
57
- templateLocation: directory,
58
56
  directusUrl: flags.directusUrl,
59
57
  programmatic: flags.programmatic,
58
+ templateLocation: directory,
59
+ templateName,
60
60
  },
61
+ lifecycle: 'start',
61
62
  runId: this.runId,
62
- config: this.config,
63
63
  });
64
64
  }
65
65
  try {
@@ -88,16 +88,16 @@ export default class ExtractCommand extends BaseCommand {
88
88
  if (!flags.disableTelemetry) {
89
89
  await track({
90
90
  command: 'extract',
91
- lifecycle: 'complete',
91
+ config: this.config,
92
92
  distinctId: this.userConfig.distinctId,
93
93
  flags: {
94
- templateName,
95
- templateLocation: directory,
96
94
  directusUrl: flags.directusUrl,
97
95
  programmatic: flags.programmatic,
96
+ templateLocation: directory,
97
+ templateName,
98
98
  },
99
+ lifecycle: 'complete',
99
100
  runId: this.runId,
100
- config: this.config,
101
101
  });
102
102
  await shutdown();
103
103
  }
@@ -121,9 +121,9 @@ export default class ExtractCommand extends BaseCommand {
121
121
  placeholder: 'My Template',
122
122
  });
123
123
  const directory = await text({
124
- placeholder: `templates/${slugify(templateName)}`,
125
124
  defaultValue: `templates/${slugify(templateName)}`,
126
125
  message: "What directory would you like to extract the template to? If it doesn't exist, it will be created.",
126
+ placeholder: `templates/${slugify(templateName)}`,
127
127
  });
128
128
  ux.stdout(`You selected ${ux.colorize(DIRECTUS_PINK, directory)}`);
129
129
  ux.stdout(SEPARATOR);
@@ -132,11 +132,11 @@ export default class ExtractCommand extends BaseCommand {
132
132
  flags.directusUrl = directusUrl;
133
133
  // Prompt for login method
134
134
  const loginMethod = await select({
135
+ message: 'How do you want to log in?',
135
136
  options: [
136
137
  { label: 'Directus Access Token', value: 'token' },
137
138
  { label: 'Email and Password', value: 'email' },
138
139
  ],
139
- message: 'How do you want to log in?',
140
140
  });
141
141
  if (loginMethod === 'token') {
142
142
  const directusToken = await getDirectusToken(directusUrl);
@@ -1,11 +1,11 @@
1
1
  import { BaseCommand } from './base.js';
2
2
  export interface InitFlags {
3
+ disableTelemetry?: boolean;
3
4
  frontend?: string;
4
5
  gitInit?: boolean;
5
6
  installDeps?: boolean;
6
7
  overwriteDir?: boolean;
7
8
  template?: string;
8
- disableTelemetry?: boolean;
9
9
  }
10
10
  export interface InitArgs {
11
11
  directory: string;
@@ -19,12 +19,12 @@ export default class InitCommand extends BaseCommand {
19
19
  static description: string;
20
20
  static examples: string[];
21
21
  static flags: {
22
+ disableTelemetry: import("@oclif/core/interfaces").BooleanFlag<boolean>;
22
23
  frontend: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
23
24
  gitInit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
24
25
  installDeps: import("@oclif/core/interfaces").BooleanFlag<boolean>;
25
26
  overwriteDir: import("@oclif/core/interfaces").BooleanFlag<boolean>;
26
27
  template: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
27
- disableTelemetry: import("@oclif/core/interfaces").BooleanFlag<boolean>;
28
28
  };
29
29
  private targetDir;
30
30
  /**