@contentstorage/core 0.3.9 → 0.3.11

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,6 @@
1
+ import { AppConfig } from '../types.js';
2
+ /**
3
+ * Helper function to define your application configuration.
4
+ * Provides autocompletion and type-checking for contentstorage.config.js files.
5
+ */
6
+ export declare function defineConfig(config: AppConfig): AppConfig;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Helper function to define your application configuration.
3
+ * Provides autocompletion and type-checking for contentstorage.config.js files.
4
+ */
5
+ export function defineConfig(config) {
6
+ // You can add basic runtime validation here if desired,
7
+ // e.g., check if contentUrl is a valid URL format,
8
+ // or if languageCodes is not empty.
9
+ if (!config.languageCodes || config.languageCodes.length === 0) {
10
+ console.warn('Warning: languageCodes array is empty or missing in the configuration.');
11
+ }
12
+ if (!config.contentDir) {
13
+ // This would typically be a hard error, but defineConfig is more for type safety at edit time.
14
+ // Runtime validation (see point 3) is better for hard errors.
15
+ console.warn('Warning: contentDir is missing in the configuration.');
16
+ }
17
+ // ... other checks
18
+ return config;
19
+ }
@@ -2,8 +2,8 @@ import path from 'path';
2
2
  import fs from 'fs';
3
3
  const DEFAULT_CONFIG = {
4
4
  languageCodes: [],
5
- contentDir: path.join('src', 'assets', 'content'),
6
- typesOutputFile: path.join('src', 'generated', 'content-types.ts'),
5
+ contentDir: path.join('src', 'content', 'json'),
6
+ typesOutputFile: path.join('src', 'content', 'content-types.ts'),
7
7
  };
8
8
  export async function loadConfig() {
9
9
  const configPath = path.resolve(process.cwd(), 'contentstorage.config.js'); // Look in user's current working dir
@@ -7,52 +7,56 @@ import chalk from 'chalk'; // Optional: for colored output
7
7
  import { loadConfig } from '../lib/configLoader.js';
8
8
  export async function generateTypes() {
9
9
  console.log(chalk.blue('Starting type generation...'));
10
- const config = await loadConfig();
11
- console.log(chalk.gray(`Reading JSON files from: ${config.contentDir}`));
10
+ const config = await loadConfig(); // Ensure loadConfig provides languageCodes
11
+ console.log(chalk.gray(`Content will be read from directory: ${config.contentDir}`));
12
12
  console.log(chalk.gray(`Saving TypeScript types to: ${config.typesOutputFile}`));
13
13
  try {
14
- // Read the content directory
15
- let files;
14
+ // Validate languageCodes from config
15
+ if (!config.languageCodes ||
16
+ !Array.isArray(config.languageCodes) ||
17
+ config.languageCodes.length === 0) {
18
+ throw new Error('config.languageCodes is missing, not an array, or empty. Cannot determine which JSON file to use for type generation.');
19
+ }
20
+ const firstLanguageCode = config.languageCodes[0];
21
+ const targetFilename = `${firstLanguageCode}.json`;
22
+ const jsonFilePath = path.join(config.contentDir, targetFilename);
23
+ console.log(chalk.gray(`Attempting to generate types using the JSON file for the first configured language code ('${firstLanguageCode}').`));
24
+ console.log(chalk.gray(`Target file: ${jsonFilePath}`));
25
+ // Read the specific JSON file
26
+ let jsonContent;
16
27
  try {
17
- files = await fs.readdir(config.contentDir);
28
+ jsonContent = await fs.readFile(jsonFilePath, 'utf-8');
18
29
  }
19
30
  catch (err) {
20
31
  if (err.code === 'ENOENT') {
21
- throw new Error(`Content directory not found: ${config.contentDir}. Run 'pull-content' first?`);
32
+ throw new Error(`Target JSON file not found: ${jsonFilePath}. Ensure content for language code '${firstLanguageCode}' has been pulled and exists at this location.`);
22
33
  }
23
- throw err; // Re-throw other errors
24
- }
25
- // Filter for JSON files and sort them (optional, but good for consistency)
26
- const jsonFiles = files
27
- .filter((file) => file.toLowerCase().endsWith('.json'))
28
- .sort();
29
- if (jsonFiles.length === 0) {
30
- throw new Error(`No JSON files found in ${config.contentDir}.`);
34
+ // Re-throw other fs.readFile errors (e.g., permission issues)
35
+ throw new Error(`Failed to read file ${jsonFilePath}: ${err.message}`);
31
36
  }
32
- const firstJsonFile = jsonFiles[0];
33
- const jsonFilePath = path.join(config.contentDir, firstJsonFile);
34
- console.log(chalk.gray(`Using first JSON file for type generation: ${firstJsonFile}`));
35
- // Read the first JSON file
36
- const jsonContent = await fs.readFile(jsonFilePath, 'utf-8');
37
37
  // Parse the JSON content
38
38
  let jsonObject;
39
39
  try {
40
40
  jsonObject = JSON.parse(jsonContent);
41
41
  }
42
42
  catch (parseError) {
43
- throw new Error(`Failed to parse JSON file ${firstJsonFile}: ${parseError.message}`);
43
+ throw new Error(`Failed to parse JSON from file ${targetFilename}: ${parseError.message}`);
44
44
  }
45
45
  // Generate TypeScript interfaces using json-to-ts
46
- // jsonToTS returns an array of strings, each being a line of the interface/type
47
- // We need to give the root type a name.
48
- const rootTypeName = 'RootContentItem'; // Or derive from filename, or make configurable
46
+ // The root type name for the generated interface. You might want to make this configurable.
47
+ const rootTypeName = 'RootContentItem';
49
48
  const typeDeclarations = jsonToTS.default(jsonObject, {
50
49
  rootName: rootTypeName,
51
50
  });
51
+ // If your previous code `jsonToTS.default(...)` was correct for your setup,
52
+ // please revert the line above to:
53
+ // const typeDeclarations: string[] = jsonToTS.default(jsonObject, {
54
+ // rootName: rootTypeName,
55
+ // });
52
56
  if (!typeDeclarations || typeDeclarations.length === 0) {
53
- throw new Error(`Could not generate types from ${firstJsonFile}. Is the file empty or malformed?`);
57
+ throw new Error(`Could not generate types from ${targetFilename}. The file might be empty, malformed, or not produce any types.`);
54
58
  }
55
- const outputContent = typeDeclarations.join('\n\n'); // Add extra newline between interfaces
59
+ const outputContent = typeDeclarations.join('\n\n'); // Add extra newline between interfaces for readability
56
60
  // Ensure the output directory exists
57
61
  const outputDir = path.dirname(config.typesOutputFile);
58
62
  await fs.mkdir(outputDir, { recursive: true });
@@ -61,8 +65,12 @@ export async function generateTypes() {
61
65
  console.log(chalk.green(`TypeScript types generated successfully at ${config.typesOutputFile}`));
62
66
  }
63
67
  catch (error) {
64
- console.error(chalk.red('Error generating TypeScript types:'));
68
+ console.error(chalk.red.bold('\nError generating TypeScript types:'));
65
69
  console.error(chalk.red(error.message));
70
+ // It's good practice to log the stack for unexpected errors if not already done by a higher-level handler
71
+ // if (error.stack) {
72
+ // console.error(chalk.gray(error.stack));
73
+ // }
66
74
  process.exit(1); // Exit with error code
67
75
  }
68
76
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@contentstorage/core",
3
3
  "author": "Kaido Hussar <kaidohus@gmail.com>",
4
4
  "homepage": "https://contentstorage.app",
5
- "version": "0.3.9",
5
+ "version": "0.3.11",
6
6
  "type": "module",
7
7
  "description": "Fetch content from contentstorage and generate TypeScript types",
8
8
  "module": "dist/index.js",