@contentstorage/core 0.3.32 → 0.3.34

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/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AppConfig, LanguageCode, ContentStructure } from './types.js';
2
- import { setContentLanguage, getText, getImage, getVariation } from './lib/contentManagement.js';
2
+ import { setContentLanguage, getText, getImage, getVariation, initContentStorage } from './lib/contentManagement.js';
3
+ import { fetchContent } from './lib/functions/fetchContent.js';
3
4
  export { AppConfig, LanguageCode, ContentStructure };
4
- export { setContentLanguage, getText, getImage, getVariation };
5
+ export { initContentStorage, fetchContent, setContentLanguage, getText, getImage, getVariation, };
package/dist/index.js CHANGED
@@ -1,2 +1,50 @@
1
- import { setContentLanguage, getText, getImage, getVariation, } from './lib/contentManagement.js';
2
- export { setContentLanguage, getText, getImage, getVariation };
1
+ import { setContentLanguage, getText, getImage, getVariation, initContentStorage, } from './lib/contentManagement.js';
2
+ import { fetchContent } from './lib/functions/fetchContent.js';
3
+ export { initContentStorage, fetchContent, setContentLanguage, getText, getImage, getVariation, };
4
+ async function isLiveEditorMode() {
5
+ try {
6
+ const inIframe = window.self !== window.top;
7
+ const urlParams = new URLSearchParams(window.location.search);
8
+ const iframeMarkerFromParent = urlParams.get('contentstorage_live_editor');
9
+ return !!(inIframe && iframeMarkerFromParent);
10
+ }
11
+ catch (e) {
12
+ // This catch block is for rare edge cases or highly sandboxed environments
13
+ // where accessing window.top might throw an error.
14
+ // If an error occurs, it's safer to assume it might be in an iframe.
15
+ console.warn('Error accessing window.top, assuming iframe context:', e);
16
+ return false;
17
+ }
18
+ }
19
+ isLiveEditorMode().then(async (isLiveMode) => {
20
+ if (!isLiveMode) {
21
+ return;
22
+ }
23
+ const cdnScriptUrl = `https://your-cdn-domain.com/contentstorage-live-editor.js?contentstorage-live-editor=true`;
24
+ return new Promise((resolve, reject) => {
25
+ console.log(`Attempting to load script from: ${cdnScriptUrl}`);
26
+ // 1. Create a new <script> element
27
+ const scriptElement = document.createElement('script');
28
+ scriptElement.type = 'text/javascript';
29
+ // 2. Set the src attribute to your script's URL
30
+ // The browser will fetch and execute it.
31
+ scriptElement.src = cdnScriptUrl;
32
+ // 3. Handle successful loading
33
+ scriptElement.onload = () => {
34
+ console.log(`Script loaded successfully from: ${cdnScriptUrl}`);
35
+ // The script has been fetched and executed by the browser.
36
+ // If it's an IIFE, it has already run.
37
+ resolve(true); // Resolve the promise indicating success
38
+ };
39
+ // 4. Handle errors during loading (e.g., network error, 404)
40
+ scriptElement.onerror = (error) => {
41
+ console.error(`Failed to load script from: ${cdnScriptUrl}`, error);
42
+ reject(new Error(`Failed to load script: ${cdnScriptUrl}`)); // Reject the promise
43
+ };
44
+ // 5. Append the script element to the document's head (or body)
45
+ // This triggers the browser to start loading the script.
46
+ document.head.appendChild(scriptElement);
47
+ // Or: document.body.appendChild(scriptElement);
48
+ });
49
+ // fetch script to handle iframe communication
50
+ });
@@ -1,25 +1,27 @@
1
- import { ContentStructure, ImageObject } from '../types.js';
1
+ import { AppConfig, ContentStructure, GetImageReturn, GetTextReturn, GetVariationReturn } from '../types.js';
2
+ export declare let activeContent: object | null;
3
+ export declare let appConfig: AppConfig | null;
2
4
  /**
3
5
  * Loads and sets the content for a specific language.
4
6
  * It will internally ensure the application configuration (for contentDir) is loaded.
5
7
  * @param contentJson
6
8
  */
7
9
  export declare function setContentLanguage(contentJson: object): void;
10
+ export declare function initContentStorage(config: AppConfig): void;
8
11
  /**
9
12
  * Retrieves the text string from the loaded JSON content for the given path.
10
13
  * Autocompletion for pathString is enabled via module augmentation of CustomContentStructure.
11
14
  * `setContentLanguage()` must be called successfully before using this.
12
15
  *
13
- * @param pathString A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
16
+ * @param contentKey A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
14
17
  * @param variables Variables help to render dynamic content inside text strings
15
- * @param fallbackValue Optional string to return if the path is not found or the value is not a string.
16
18
  * If not provided, and path is not found/value not string, undefined is returned.
17
19
  * @returns The text string from the JSON, or the fallbackValue, or undefined.
18
20
  */
19
- export declare function getText<Path extends keyof ContentStructure>(pathString: Path, variables?: ContentStructure[Path] extends {
21
+ export declare function getText<Path extends keyof ContentStructure>(contentKey: Path, variables?: ContentStructure[Path] extends {
20
22
  variables: infer Vars;
21
- } ? keyof Vars : Record<string, any>): string | undefined;
22
- export declare function getImage(pathString: keyof ContentStructure, fallbackValue?: ImageObject): ImageObject | undefined;
23
- export declare function getVariation<Path extends keyof ContentStructure>(pathString: Path, variationKey?: ContentStructure[Path] extends {
23
+ } ? keyof Vars : Record<string, any>): GetTextReturn;
24
+ export declare function getImage(contentKey: keyof ContentStructure): GetImageReturn | undefined;
25
+ export declare function getVariation<Path extends keyof ContentStructure>(contentKey: Path, variationKey?: ContentStructure[Path] extends {
24
26
  data: infer D;
25
- } ? keyof D : string, variables?: Record<string, any>): string | undefined;
27
+ } ? keyof D : string, variables?: Record<string, any>): GetVariationReturn;
@@ -1,5 +1,6 @@
1
1
  import { populateTextWithVariables } from '../helpers/populateTextWithVariables.js';
2
- let activeContent = null;
2
+ export let activeContent = null;
3
+ export let appConfig = null;
3
4
  /**
4
5
  * Loads and sets the content for a specific language.
5
6
  * It will internally ensure the application configuration (for contentDir) is loaded.
@@ -18,94 +19,131 @@ export function setContentLanguage(contentJson) {
18
19
  console.error(`[Contentstorage] Failed to load content. Error: ${error.message}`);
19
20
  }
20
21
  }
22
+ export function initContentStorage(config) {
23
+ if (!config ||
24
+ typeof config !== 'object' ||
25
+ !config.contentKey ||
26
+ !Array.isArray(config.languageCodes)) {
27
+ if (!config.contentKey) {
28
+ throw new Error('[Contentstorage] No contentKey provided in initContentStorage function.');
29
+ }
30
+ if (!Array.isArray(config.languageCodes)) {
31
+ throw new Error('[Contentstorage] No languageCodes provided in initContentStorage function.');
32
+ }
33
+ throw new Error('[Contentstorage] Invalid config.');
34
+ }
35
+ appConfig = config;
36
+ }
21
37
  /**
22
38
  * Retrieves the text string from the loaded JSON content for the given path.
23
39
  * Autocompletion for pathString is enabled via module augmentation of CustomContentStructure.
24
40
  * `setContentLanguage()` must be called successfully before using this.
25
41
  *
26
- * @param pathString A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
42
+ * @param contentKey A dot-notation path string (e.g., 'HomePage.Login'). Autocompletion is provided.
27
43
  * @param variables Variables help to render dynamic content inside text strings
28
- * @param fallbackValue Optional string to return if the path is not found or the value is not a string.
29
44
  * If not provided, and path is not found/value not string, undefined is returned.
30
45
  * @returns The text string from the JSON, or the fallbackValue, or undefined.
31
46
  */
32
- export function getText(pathString, variables) {
47
+ export function getText(contentKey, variables) {
48
+ const defaultVal = {
49
+ contentKey,
50
+ text: '',
51
+ };
33
52
  if (!activeContent) {
34
- const msg = `[Contentstorage] getText: Content not loaded (Key: "${String(pathString)}"). Ensure setContentLanguage() was called and completed successfully.`;
53
+ const msg = `[Contentstorage] getText: Content not loaded (Key: "${String(contentKey)}"). Ensure setContentLanguage() was called and completed successfully.`;
35
54
  console.warn(msg);
36
- return '';
55
+ return defaultVal;
37
56
  }
38
- const keys = pathString.split('.');
57
+ const keys = contentKey.split('.');
39
58
  let current = activeContent;
40
59
  for (const key of keys) {
41
60
  if (current && typeof current === 'object' && key in current) {
42
61
  current = current[key];
43
62
  }
44
63
  else {
45
- const msg = `[Contentstorage] getText: Path "${String(pathString)}" not found in loaded content.`;
64
+ const msg = `[Contentstorage] getText: Path "${String(contentKey)}" not found in loaded content.`;
46
65
  console.warn(msg);
47
- return '';
66
+ return defaultVal;
48
67
  }
49
68
  }
50
69
  if (typeof current === 'string') {
51
70
  if (!variables || Object.keys(variables).length === 0) {
52
- return current;
71
+ return {
72
+ contentKey,
73
+ text: current,
74
+ };
53
75
  }
54
- return populateTextWithVariables(current, variables, pathString);
76
+ return {
77
+ contentKey,
78
+ text: populateTextWithVariables(current, variables, contentKey),
79
+ };
55
80
  }
56
81
  else {
57
- const msg = `[Contentstorage] getText: Value at path "${String(pathString)}" is not a string (actual type: ${typeof current}).`;
82
+ const msg = `[Contentstorage] getText: Value at path "${String(contentKey)}" is not a string (actual type: ${typeof current}).`;
58
83
  console.warn(msg);
59
- return '';
84
+ return defaultVal;
60
85
  }
61
86
  }
62
- export function getImage(pathString, fallbackValue) {
87
+ export function getImage(contentKey) {
88
+ const defaultVal = {
89
+ contentKey,
90
+ data: { url: '', altText: '', contentstorage_type: 'image' },
91
+ };
63
92
  if (!activeContent) {
64
- const msg = `[Contentstorage] getImage: Content not loaded (Key: "${pathString}"). Ensure setContentLanguage() was called and completed successfully.`;
93
+ const msg = `[Contentstorage] getImage: Content not loaded (Key: "${contentKey}"). Ensure setContentLanguage() was called and completed successfully.`;
65
94
  console.warn(msg);
66
- return fallbackValue;
95
+ return {
96
+ contentKey,
97
+ data: { url: '', altText: '', contentstorage_type: 'image' },
98
+ };
67
99
  }
68
- const keys = pathString.split('.');
100
+ const keys = contentKey.split('.');
69
101
  let current = activeContent;
70
102
  for (const key of keys) {
71
103
  if (current && typeof current === 'object' && key in current) {
72
104
  current = current[key];
73
105
  }
74
106
  else {
75
- const msg = `[Contentstorage] getImage: Path "${pathString}" not found in loaded content.`;
107
+ const msg = `[Contentstorage] getImage: Path "${contentKey}" not found in loaded content.`;
76
108
  console.warn(msg);
77
- return fallbackValue;
109
+ return defaultVal;
78
110
  }
79
111
  }
80
112
  if (current &&
81
113
  typeof current === 'object' &&
82
114
  current.contentstorage_type === 'image' &&
83
- typeof current.url === 'string' &&
84
- typeof current.altText === 'string') {
85
- return current;
115
+ typeof current.url === 'string') {
116
+ return {
117
+ contentKey,
118
+ data: current,
119
+ };
86
120
  }
87
121
  else {
88
- const msg = `[Contentstorage] getImage: Value at path "${pathString}" is not a valid image object (actual value: ${JSON.stringify(current)}).`;
122
+ const msg = `[Contentstorage] getImage: Value at path "${contentKey}" is not a valid image object (actual value: ${JSON.stringify(current)}).`;
89
123
  console.warn(msg);
90
- return fallbackValue;
124
+ return defaultVal;
91
125
  }
92
126
  }
93
- export function getVariation(pathString, variationKey, variables) {
127
+ export function getVariation(contentKey, variationKey, variables) {
128
+ const defaultVal = {
129
+ contentKey,
130
+ text: '',
131
+ };
94
132
  if (!activeContent) {
95
- const msg = `[Contentstorage] getVariation: Content not loaded (Key: "${pathString}", Variation: "${variationKey?.toString()}"). Ensure setContentLanguage() was called and completed successfully.`;
133
+ const msg = `[Contentstorage] getVariation: Content not loaded (Key: "${contentKey}", Variation: "${variationKey?.toString()}"). Ensure setContentLanguage() was called and completed successfully.`;
96
134
  console.warn(msg);
97
- return '';
135
+ return defaultVal;
98
136
  }
99
- const keys = pathString.split('.');
137
+ const keys = contentKey.split('.');
100
138
  let current = activeContent;
101
139
  for (const key of keys) {
102
140
  if (current && typeof current === 'object' && key in current) {
103
141
  current = current[key];
104
142
  }
105
143
  else {
106
- const msg = `[Contentstorage] getVariation: Path "${pathString}" for variation object not found in loaded content.`;
144
+ const msg = `[Contentstorage] getVariation: Path "${contentKey}" for variation object not found in loaded content.`;
107
145
  console.warn(msg);
108
- return '';
146
+ return defaultVal;
109
147
  }
110
148
  }
111
149
  if (current &&
@@ -120,12 +158,18 @@ export function getVariation(pathString, variationKey, variables) {
120
158
  if (typeof variationObject.data[variationKey] === 'string') {
121
159
  const current = variationObject.data[variationKey];
122
160
  if (!variables || Object.keys(variables).length === 0) {
123
- return current;
161
+ return {
162
+ contentKey,
163
+ text: current,
164
+ };
124
165
  }
125
- return populateTextWithVariables(current, variables, pathString);
166
+ return {
167
+ contentKey,
168
+ text: populateTextWithVariables(current, variables, contentKey),
169
+ };
126
170
  }
127
171
  else {
128
- const msg = `[Contentstorage] getVariation: Variation value for key "${variationKey}" at path "${pathString}" is not a string (actual type: ${typeof variationObject.data[variationKey]}).`;
172
+ const msg = `[Contentstorage] getVariation: Variation value for key "${variationKey}" at path "${contentKey}" is not a string (actual type: ${typeof variationObject.data[variationKey]}).`;
129
173
  console.warn(msg);
130
174
  }
131
175
  }
@@ -133,20 +177,23 @@ export function getVariation(pathString, variationKey, variables) {
133
177
  if ('default' in variationObject.data && typeof variationKey === 'string') {
134
178
  if (typeof variationObject.data.default === 'string') {
135
179
  if (variationKey && variationKey !== 'default') {
136
- console.warn(`[Contentstorage] getVariation: Variation key "${variationKey}" not found at path "${pathString}". Returning 'default' variation.`);
180
+ console.warn(`[Contentstorage] getVariation: Variation key "${variationKey}" not found at path "${contentKey}". Returning 'default' variation.`);
137
181
  }
138
- return variationObject.data.default;
182
+ return {
183
+ contentKey,
184
+ text: variationObject.data.default,
185
+ };
139
186
  }
140
187
  else {
141
- console.warn(`[Contentstorage] getVariation: 'default' variation value at path "${pathString}" is not a string (actual type: ${typeof variationObject.data.default}).`);
188
+ console.warn(`[Contentstorage] getVariation: 'default' variation value at path "${contentKey}" is not a string (actual type: ${typeof variationObject.data.default}).`);
142
189
  }
143
190
  }
144
191
  // If neither specific key nor 'default' is found or valid
145
- console.warn(`[Contentstorage] getVariation: Neither variation key "${variationKey?.toString()}" nor 'default' variation found or valid at path "${pathString}".`);
146
- return '';
192
+ console.warn(`[Contentstorage] getVariation: Neither variation key "${variationKey?.toString()}" nor 'default' variation found or valid at path "${contentKey}".`);
193
+ return defaultVal;
147
194
  }
148
195
  else {
149
- console.warn(`[Contentstorage] getVariation: Value at path "${pathString}" is not a valid variation object (actual value: ${JSON.stringify(current)}).`);
150
- return '';
196
+ console.warn(`[Contentstorage] getVariation: Value at path "${contentKey}" is not a valid variation object (actual value: ${JSON.stringify(current)}).`);
197
+ return defaultVal;
151
198
  }
152
199
  }
@@ -0,0 +1,2 @@
1
+ import { LanguageCode } from '../../types.js';
2
+ export declare function fetchContent(language?: LanguageCode): Promise<void>;
@@ -0,0 +1,43 @@
1
+ import axios from 'axios';
2
+ import { CONTENTSTORAGE_CONFIG } from '../../contentstorage-config.js';
3
+ import { appConfig, setContentLanguage } from '../contentManagement.js';
4
+ export async function fetchContent(language) {
5
+ const languageToFetch = language || appConfig?.languageCodes?.[0];
6
+ console.log(`Starting content fetch for language ${language}...`);
7
+ if (!languageToFetch) {
8
+ throw Error(`No language found`);
9
+ }
10
+ if (!appConfig) {
11
+ throw Error(`No app config found`);
12
+ }
13
+ const fileUrl = `${CONTENTSTORAGE_CONFIG.BASE_URL}/${appConfig.contentKey}/content/${languageToFetch}.json`;
14
+ try {
15
+ // Fetch data for the current language
16
+ const response = await axios.get(fileUrl);
17
+ const jsonData = response.data;
18
+ // Basic check for data existence, although axios usually throws for non-2xx responses
19
+ if (jsonData === undefined || jsonData === null) {
20
+ throw new Error(`No data received from ${fileUrl} for language ${languageToFetch}.`);
21
+ }
22
+ // Validate that jsonData is a single, non-null JSON object (not an array)
23
+ // This check mirrors the original code's expectation for the content of a JSON file.
24
+ if (typeof jsonData !== 'object') {
25
+ throw new Error(`Expected a single JSON object from ${fileUrl} for language ${languageToFetch}, but received type ${typeof jsonData}. Cannot proceed.`);
26
+ }
27
+ console.log(`Received JSON for ${languageToFetch}`);
28
+ setContentLanguage(jsonData);
29
+ }
30
+ catch (error) {
31
+ // Catch errors related to fetching or saving a single language file
32
+ console.error(`\nError processing language ${languageToFetch} from ${fileUrl}:`);
33
+ if (axios.isAxiosError(error)) {
34
+ console.error(` Status: ${error.response?.status}`);
35
+ console.error(`Response Data: ${error.response?.data ? JSON.stringify(error.response.data) : 'N/A'}`);
36
+ console.error(` Message: ${error.message}`); // Axios error message
37
+ }
38
+ else {
39
+ // For non-Axios errors (e.g., manually thrown errors, fs errors)
40
+ console.error(` Error: ${error.message}`);
41
+ }
42
+ }
43
+ }
package/dist/types.d.ts CHANGED
@@ -22,6 +22,18 @@ export type LanguageCode = 'SQ' | 'BE' | 'BS' | 'BG' | 'HR' | 'CS' | 'DA' | 'NL'
22
22
  */
23
23
  export interface ContentStructure {
24
24
  }
25
+ export type GetTextReturn = {
26
+ contentKey: string;
27
+ text: string;
28
+ };
29
+ export type GetImageReturn = {
30
+ contentKey: string;
31
+ data: ImageObject;
32
+ };
33
+ export type GetVariationReturn = {
34
+ contentKey: string;
35
+ text: string;
36
+ };
25
37
  export interface ImageObject {
26
38
  contentstorage_type: 'image';
27
39
  url: string;
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.32",
5
+ "version": "0.3.34",
6
6
  "type": "module",
7
7
  "description": "Fetch content from contentstorage and generate TypeScript types",
8
8
  "module": "dist/index.js",