@nexushub/client 0.4.3 → 0.4.5

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.
@@ -1,84 +1,216 @@
1
1
  // src/content/local-cache-server.ts
2
2
  import fs from "fs";
3
3
  import path from "path";
4
+
5
+ // src/config.ts
6
+ var DEFAULT_API_URL = "https://endpoints.gnexus.co.tz";
7
+ var DEFAULT_ANALYTICS_URL = "https://sentry.gnexus.co.tz";
8
+ var LOCAL_NEST_URL = "https://endpoints.gnexus.co.tz";
9
+ var LOCAL_RUST_URL = "https://sentry.gnexus.co.tz";
10
+ var getEnvConfig = () => {
11
+ const NEXT_PUBLIC_ID = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_ID : void 0;
12
+ const NEXT_PUBLIC_KEY = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_KEY : void 0;
13
+ const NEXT_PUBLIC_URL = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_API_URL : void 0;
14
+ const NODE_ID = typeof process !== "undefined" ? process.env.NEXUS_PROJECT_ID : void 0;
15
+ const NODE_KEY = typeof process !== "undefined" ? process.env.NEXUS_API_KEY : void 0;
16
+ const NODE_URL = typeof process !== "undefined" ? process.env.NEXUS_API_URL : void 0;
17
+ const NODE_ENV = typeof process !== "undefined" ? process.env.NODE_ENV : "production";
18
+ const isDev = NODE_ENV === "development" || typeof window !== "undefined" && window.location.hostname === "localhost";
19
+ const projectId = NEXT_PUBLIC_ID ?? NODE_ID;
20
+ const apiKey = NEXT_PUBLIC_KEY ?? NODE_KEY;
21
+ const apiUrl = NEXT_PUBLIC_URL ?? NODE_URL ?? (isDev ? LOCAL_NEST_URL : DEFAULT_API_URL);
22
+ const analyticsUrl = apiUrl.includes("localhost") ? LOCAL_RUST_URL : DEFAULT_ANALYTICS_URL;
23
+ return {
24
+ projectId,
25
+ apiKey,
26
+ apiUrl,
27
+ analyticsUrl
28
+ };
29
+ };
30
+
31
+ // src/content/binary-compiler.ts
32
+ import * as crypto from "crypto";
33
+ var BinaryCompiler = class {
34
+ /**
35
+ * Generates a secure, deterministic cryptographic key from the project's API key.
36
+ */
37
+ static deriveKeys(apiKey) {
38
+ const hash = crypto.createHash("sha256").update(apiKey).digest();
39
+ const encryptionKey = hash;
40
+ const hmacKey = crypto.createHmac("sha256", apiKey).update("nexus-integrity-key").digest();
41
+ return { encryptionKey, hmacKey };
42
+ }
43
+ /**
44
+ * Compiles JSON content data into a secure, signed, and encrypted .nx binary buffer.
45
+ */
46
+ static compile(data, apiKey, projectId, metadataOverrides = {}) {
47
+ const { encryptionKey, hmacKey } = this.deriveKeys(apiKey);
48
+ const metadata = {
49
+ version: "2.0.0",
50
+ compiledAt: (/* @__PURE__ */ new Date()).toISOString(),
51
+ projectId,
52
+ ...metadataOverrides
53
+ };
54
+ const metadataStr = JSON.stringify(metadata);
55
+ const metadataBuffer = Buffer.from(metadataStr, "utf-8");
56
+ const iv = crypto.randomBytes(16);
57
+ const cipher = crypto.createCipheriv(this.ALGORITHM, encryptionKey, iv);
58
+ const plainTextPayload = JSON.stringify(data);
59
+ let encryptedPayload = cipher.update(plainTextPayload, "utf8");
60
+ encryptedPayload = Buffer.concat([encryptedPayload, cipher.final()]);
61
+ const payloadBuffer = Buffer.concat([iv, encryptedPayload]);
62
+ const headerBuffer = Buffer.from(this.MAGIC_HEADER, "ascii");
63
+ const metaLengthBuffer = Buffer.alloc(4);
64
+ metaLengthBuffer.writeUInt32BE(metadataBuffer.length, 0);
65
+ const payloadLengthBuffer = Buffer.alloc(4);
66
+ payloadLengthBuffer.writeUInt32BE(payloadBuffer.length, 0);
67
+ const prefixBlock = Buffer.concat([
68
+ headerBuffer,
69
+ metaLengthBuffer,
70
+ metadataBuffer,
71
+ payloadLengthBuffer,
72
+ payloadBuffer
73
+ ]);
74
+ const hmac = crypto.createHmac("sha256", hmacKey);
75
+ hmac.update(prefixBlock);
76
+ const signature = hmac.digest();
77
+ return Buffer.concat([prefixBlock, signature]);
78
+ }
79
+ /**
80
+ * Verifies, decrypts, and decompiles a .nx binary buffer back into clean, type-safe JSON.
81
+ * Throws structured errors on integrity verification failures or file corruption.
82
+ */
83
+ static decompile(buffer, apiKey) {
84
+ if (buffer.length < 44) {
85
+ throw new Error(
86
+ "Corrupted File: Binary payload is too short to be a valid Nexus node."
87
+ );
88
+ }
89
+ const { encryptionKey, hmacKey } = this.deriveKeys(apiKey);
90
+ const prefixBlockLength = buffer.length - 32;
91
+ const prefixBlock = buffer.subarray(0, prefixBlockLength);
92
+ const expectedSignature = buffer.subarray(prefixBlockLength);
93
+ const hmac = crypto.createHmac("sha256", hmacKey);
94
+ hmac.update(prefixBlock);
95
+ const actualSignature = hmac.digest();
96
+ if (!crypto.timingSafeEqual(expectedSignature, actualSignature)) {
97
+ throw new Error(
98
+ "DATA_INTEGRITY_VIOLATION: Cryptographic signature mismatch. This local node has been modified externally or tampered with."
99
+ );
100
+ }
101
+ const magicHeader = prefixBlock.subarray(0, 4).toString("ascii");
102
+ if (magicHeader !== this.MAGIC_HEADER) {
103
+ throw new Error(
104
+ "Invalid Format: File lacks the correct Nexus binary magic header."
105
+ );
106
+ }
107
+ const metaLength = prefixBlock.readUInt32BE(4);
108
+ const metaStart = 8;
109
+ const metaEnd = metaStart + metaLength;
110
+ const metadataStr = prefixBlock.subarray(metaStart, metaEnd).toString("utf-8");
111
+ const metadata = JSON.parse(metadataStr);
112
+ const payloadLength = prefixBlock.readUInt32BE(metaEnd);
113
+ const payloadStart = metaEnd + 4;
114
+ const payloadEnd = payloadStart + payloadLength;
115
+ const payloadBuffer = prefixBlock.subarray(payloadStart, payloadEnd);
116
+ const iv = payloadBuffer.subarray(0, 16);
117
+ const cipherText = payloadBuffer.subarray(16);
118
+ const decipher = crypto.createDecipheriv(this.ALGORITHM, encryptionKey, iv);
119
+ let decrypted = decipher.update(cipherText);
120
+ decrypted = Buffer.concat([decrypted, decipher.final()]);
121
+ const data = JSON.parse(decrypted.toString("utf8"));
122
+ return { data, metadata };
123
+ }
124
+ };
125
+ BinaryCompiler.MAGIC_HEADER = "NEXS";
126
+ // 4-byte ASCII magic identifier
127
+ BinaryCompiler.ALGORITHM = "aes-256-cbc";
128
+
129
+ // src/content/local-cache-server.ts
4
130
  var LocalCache = class {
5
131
  constructor(customPath) {
132
+ this.apiKey = "";
6
133
  this.baseDir = customPath || ".nexus/local";
134
+ const config = getEnvConfig();
135
+ this.apiKey = config.apiKey || "";
7
136
  }
8
137
  isLoaded() {
9
138
  return fs.existsSync(path.resolve(process.cwd(), this.baseDir));
10
139
  }
11
140
  /**
12
- * Retrieve a specific page directly from its file.
141
+ * Helper to decrypt and decompile `.nx` files on-the-fly.
13
142
  */
14
- async getPage(slug) {
15
- try {
16
- const filePath = path.resolve(
17
- process.cwd(),
18
- this.baseDir,
19
- "pages",
20
- `${slug}.json`
21
- );
22
- if (fs.existsSync(filePath)) {
23
- const fileContent = fs.readFileSync(filePath, "utf-8");
24
- const pageData = JSON.parse(fileContent);
25
- return pageData.data !== void 0 ? pageData.data : pageData;
143
+ decompileFile(filePath) {
144
+ if (!this.apiKey) {
145
+ if (process.env.NODE_ENV === "development") {
146
+ console.warn(
147
+ "\u26A0\uFE0F NexusHub: Missing NEXUS_API_KEY. Local decryption bypassed."
148
+ );
26
149
  }
150
+ return null;
151
+ }
152
+ try {
153
+ const encryptedBuffer = fs.readFileSync(filePath);
154
+ const decompiled = BinaryCompiler.decompile(encryptedBuffer, this.apiKey);
155
+ return decompiled.data;
27
156
  } catch (error) {
28
157
  if (process.env.NODE_ENV === "development") {
29
- console.warn(
30
- `\u26A0\uFE0F NexusHub: Failed to load local page '${slug}':`,
31
- error
158
+ console.error(
159
+ `
160
+ \u{1F6A8} NexusHub Security Alert: Data Integrity Violation in file:
161
+ ${filePath}
162
+ Error: ${error.message}
163
+ This file has been disabled until regenerated via npx nexus pull.
164
+ `
32
165
  );
33
166
  }
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * Retrieve a specific page directly from its .nx file.
172
+ */
173
+ async getPage(slug) {
174
+ const filePath = path.resolve(
175
+ process.cwd(),
176
+ this.baseDir,
177
+ "pages",
178
+ `${slug}.nx`
179
+ );
180
+ if (fs.existsSync(filePath)) {
181
+ const pageData = this.decompileFile(filePath);
182
+ if (!pageData) return null;
183
+ return pageData.data !== void 0 ? pageData.data : pageData;
34
184
  }
35
185
  return null;
36
186
  }
37
187
  /**
38
- * Retrieve an entire collection from its specific collection file.
188
+ * Retrieve an entire collection from its specific .nx file.
39
189
  */
40
190
  async getCollection(collectionId) {
41
- try {
42
- const filePath = path.resolve(
43
- process.cwd(),
44
- this.baseDir,
45
- "collections",
46
- `${collectionId}.json`
47
- );
48
- if (fs.existsSync(filePath)) {
49
- const fileContent = fs.readFileSync(filePath, "utf-8");
50
- return JSON.parse(fileContent);
51
- }
52
- } catch (error) {
53
- if (process.env.NODE_ENV === "development") {
54
- console.warn(
55
- `\u26A0\uFE0F NexusHub: Failed to load local collection '${collectionId}':`,
56
- error
57
- );
58
- }
191
+ const filePath = path.resolve(
192
+ process.cwd(),
193
+ this.baseDir,
194
+ "collections",
195
+ `${collectionId}.nx`
196
+ );
197
+ if (fs.existsSync(filePath)) {
198
+ return this.decompileFile(filePath);
59
199
  }
60
200
  return null;
61
201
  }
62
202
  /**
63
- * Retrieve global settings from its file.
203
+ * Retrieve global settings from its .nx file.
64
204
  */
65
205
  async getGlobals() {
66
- try {
67
- const filePath = path.resolve(
68
- process.cwd(),
69
- this.baseDir,
70
- "globals.json"
71
- );
72
- if (fs.existsSync(filePath)) {
73
- const fileContent = fs.readFileSync(filePath, "utf-8");
74
- return JSON.parse(fileContent);
75
- }
76
- } catch {
206
+ const filePath = path.resolve(process.cwd(), this.baseDir, "globals.nx");
207
+ if (fs.existsSync(filePath)) {
208
+ return this.decompileFile(filePath);
77
209
  }
78
210
  return null;
79
211
  }
80
212
  /**
81
- * Returns a merged JSON of the entire workspace structure (for dev analytics/inspectors)
213
+ * Returns a merged JSON of the entire workspace structure.
82
214
  */
83
215
  async getAllData() {
84
216
  const pages = {};
@@ -88,8 +220,8 @@ var LocalCache = class {
88
220
  const pagesDir = path.resolve(process.cwd(), this.baseDir, "pages");
89
221
  if (fs.existsSync(pagesDir)) {
90
222
  for (const file of fs.readdirSync(pagesDir)) {
91
- if (file.endsWith(".json")) {
92
- const slug = path.basename(file, ".json");
223
+ if (file.endsWith(".nx")) {
224
+ const slug = path.basename(file, ".nx");
93
225
  pages[slug] = await this.getPage(slug);
94
226
  }
95
227
  }
@@ -97,8 +229,8 @@ var LocalCache = class {
97
229
  const colsDir = path.resolve(process.cwd(), this.baseDir, "collections");
98
230
  if (fs.existsSync(colsDir)) {
99
231
  for (const file of fs.readdirSync(colsDir)) {
100
- if (file.endsWith(".json")) {
101
- const id = path.basename(file, ".json");
232
+ if (file.endsWith(".nx")) {
233
+ const id = path.basename(file, ".nx");
102
234
  collections[id] = await this.getCollection(id) || [];
103
235
  }
104
236
  }
package/dist/index.cjs CHANGED
@@ -30,6 +30,164 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
+ // src/config.ts
34
+ var DEFAULT_API_URL, DEFAULT_ANALYTICS_URL, LOCAL_NEST_URL, LOCAL_RUST_URL, getEnvConfig, mergeConfigs, getFullConfig, validateConfig;
35
+ var init_config = __esm({
36
+ "src/config.ts"() {
37
+ "use strict";
38
+ DEFAULT_API_URL = "https://endpoints.gnexus.co.tz";
39
+ DEFAULT_ANALYTICS_URL = "https://sentry.gnexus.co.tz";
40
+ LOCAL_NEST_URL = "https://endpoints.gnexus.co.tz";
41
+ LOCAL_RUST_URL = "https://sentry.gnexus.co.tz";
42
+ getEnvConfig = () => {
43
+ const NEXT_PUBLIC_ID = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_ID : void 0;
44
+ const NEXT_PUBLIC_KEY = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_KEY : void 0;
45
+ const NEXT_PUBLIC_URL = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_API_URL : void 0;
46
+ const NODE_ID = typeof process !== "undefined" ? process.env.NEXUS_PROJECT_ID : void 0;
47
+ const NODE_KEY = typeof process !== "undefined" ? process.env.NEXUS_API_KEY : void 0;
48
+ const NODE_URL = typeof process !== "undefined" ? process.env.NEXUS_API_URL : void 0;
49
+ const NODE_ENV = typeof process !== "undefined" ? process.env.NODE_ENV : "production";
50
+ const isDev = NODE_ENV === "development" || typeof window !== "undefined" && window.location.hostname === "localhost";
51
+ const projectId = NEXT_PUBLIC_ID ?? NODE_ID;
52
+ const apiKey = NEXT_PUBLIC_KEY ?? NODE_KEY;
53
+ const apiUrl = NEXT_PUBLIC_URL ?? NODE_URL ?? (isDev ? LOCAL_NEST_URL : DEFAULT_API_URL);
54
+ const analyticsUrl = apiUrl.includes("localhost") ? LOCAL_RUST_URL : DEFAULT_ANALYTICS_URL;
55
+ return {
56
+ projectId,
57
+ apiKey,
58
+ apiUrl,
59
+ analyticsUrl
60
+ };
61
+ };
62
+ mergeConfigs = (base, override) => {
63
+ const mergedApiUrl = override.apiUrl || base.apiUrl || DEFAULT_API_URL;
64
+ const mergedAnalyticsUrl = override.analyticsUrl || base.analyticsUrl || (mergedApiUrl.includes("localhost") ? LOCAL_RUST_URL : DEFAULT_ANALYTICS_URL);
65
+ return {
66
+ ...base,
67
+ ...override,
68
+ apiUrl: mergedApiUrl,
69
+ analyticsUrl: mergedAnalyticsUrl,
70
+ projectId: override.projectId || base.projectId,
71
+ apiKey: override.apiKey || base.apiKey
72
+ };
73
+ };
74
+ getFullConfig = (partialConfig) => {
75
+ const envConfig = getEnvConfig();
76
+ return mergeConfigs(envConfig, partialConfig || {});
77
+ };
78
+ validateConfig = (config) => {
79
+ const errors = [];
80
+ if (!config.projectId) errors.push("Missing projectId");
81
+ if (!config.apiUrl) errors.push("Missing apiUrl");
82
+ return errors;
83
+ };
84
+ }
85
+ });
86
+
87
+ // src/content/binary-compiler.ts
88
+ var crypto2, BinaryCompiler;
89
+ var init_binary_compiler = __esm({
90
+ "src/content/binary-compiler.ts"() {
91
+ "use strict";
92
+ crypto2 = __toESM(require("crypto"), 1);
93
+ BinaryCompiler = class {
94
+ /**
95
+ * Generates a secure, deterministic cryptographic key from the project's API key.
96
+ */
97
+ static deriveKeys(apiKey) {
98
+ const hash = crypto2.createHash("sha256").update(apiKey).digest();
99
+ const encryptionKey = hash;
100
+ const hmacKey = crypto2.createHmac("sha256", apiKey).update("nexus-integrity-key").digest();
101
+ return { encryptionKey, hmacKey };
102
+ }
103
+ /**
104
+ * Compiles JSON content data into a secure, signed, and encrypted .nx binary buffer.
105
+ */
106
+ static compile(data, apiKey, projectId, metadataOverrides = {}) {
107
+ const { encryptionKey, hmacKey } = this.deriveKeys(apiKey);
108
+ const metadata = {
109
+ version: "2.0.0",
110
+ compiledAt: (/* @__PURE__ */ new Date()).toISOString(),
111
+ projectId,
112
+ ...metadataOverrides
113
+ };
114
+ const metadataStr = JSON.stringify(metadata);
115
+ const metadataBuffer = Buffer.from(metadataStr, "utf-8");
116
+ const iv = crypto2.randomBytes(16);
117
+ const cipher = crypto2.createCipheriv(this.ALGORITHM, encryptionKey, iv);
118
+ const plainTextPayload = JSON.stringify(data);
119
+ let encryptedPayload = cipher.update(plainTextPayload, "utf8");
120
+ encryptedPayload = Buffer.concat([encryptedPayload, cipher.final()]);
121
+ const payloadBuffer = Buffer.concat([iv, encryptedPayload]);
122
+ const headerBuffer = Buffer.from(this.MAGIC_HEADER, "ascii");
123
+ const metaLengthBuffer = Buffer.alloc(4);
124
+ metaLengthBuffer.writeUInt32BE(metadataBuffer.length, 0);
125
+ const payloadLengthBuffer = Buffer.alloc(4);
126
+ payloadLengthBuffer.writeUInt32BE(payloadBuffer.length, 0);
127
+ const prefixBlock = Buffer.concat([
128
+ headerBuffer,
129
+ metaLengthBuffer,
130
+ metadataBuffer,
131
+ payloadLengthBuffer,
132
+ payloadBuffer
133
+ ]);
134
+ const hmac = crypto2.createHmac("sha256", hmacKey);
135
+ hmac.update(prefixBlock);
136
+ const signature = hmac.digest();
137
+ return Buffer.concat([prefixBlock, signature]);
138
+ }
139
+ /**
140
+ * Verifies, decrypts, and decompiles a .nx binary buffer back into clean, type-safe JSON.
141
+ * Throws structured errors on integrity verification failures or file corruption.
142
+ */
143
+ static decompile(buffer, apiKey) {
144
+ if (buffer.length < 44) {
145
+ throw new Error(
146
+ "Corrupted File: Binary payload is too short to be a valid Nexus node."
147
+ );
148
+ }
149
+ const { encryptionKey, hmacKey } = this.deriveKeys(apiKey);
150
+ const prefixBlockLength = buffer.length - 32;
151
+ const prefixBlock = buffer.subarray(0, prefixBlockLength);
152
+ const expectedSignature = buffer.subarray(prefixBlockLength);
153
+ const hmac = crypto2.createHmac("sha256", hmacKey);
154
+ hmac.update(prefixBlock);
155
+ const actualSignature = hmac.digest();
156
+ if (!crypto2.timingSafeEqual(expectedSignature, actualSignature)) {
157
+ throw new Error(
158
+ "DATA_INTEGRITY_VIOLATION: Cryptographic signature mismatch. This local node has been modified externally or tampered with."
159
+ );
160
+ }
161
+ const magicHeader = prefixBlock.subarray(0, 4).toString("ascii");
162
+ if (magicHeader !== this.MAGIC_HEADER) {
163
+ throw new Error(
164
+ "Invalid Format: File lacks the correct Nexus binary magic header."
165
+ );
166
+ }
167
+ const metaLength = prefixBlock.readUInt32BE(4);
168
+ const metaStart = 8;
169
+ const metaEnd = metaStart + metaLength;
170
+ const metadataStr = prefixBlock.subarray(metaStart, metaEnd).toString("utf-8");
171
+ const metadata = JSON.parse(metadataStr);
172
+ const payloadLength = prefixBlock.readUInt32BE(metaEnd);
173
+ const payloadStart = metaEnd + 4;
174
+ const payloadEnd = payloadStart + payloadLength;
175
+ const payloadBuffer = prefixBlock.subarray(payloadStart, payloadEnd);
176
+ const iv = payloadBuffer.subarray(0, 16);
177
+ const cipherText = payloadBuffer.subarray(16);
178
+ const decipher = crypto2.createDecipheriv(this.ALGORITHM, encryptionKey, iv);
179
+ let decrypted = decipher.update(cipherText);
180
+ decrypted = Buffer.concat([decrypted, decipher.final()]);
181
+ const data = JSON.parse(decrypted.toString("utf8"));
182
+ return { data, metadata };
183
+ }
184
+ };
185
+ BinaryCompiler.MAGIC_HEADER = "NEXS";
186
+ // 4-byte ASCII magic identifier
187
+ BinaryCompiler.ALGORITHM = "aes-256-cbc";
188
+ }
189
+ });
190
+
33
191
  // src/content/local-cache-server.ts
34
192
  var local_cache_server_exports = {};
35
193
  __export(local_cache_server_exports, {
@@ -41,84 +199,92 @@ var init_local_cache_server = __esm({
41
199
  "use strict";
42
200
  import_fs = __toESM(require("fs"), 1);
43
201
  import_path = __toESM(require("path"), 1);
202
+ init_config();
203
+ init_binary_compiler();
44
204
  LocalCache = class {
45
205
  constructor(customPath) {
206
+ this.apiKey = "";
46
207
  this.baseDir = customPath || ".nexus/local";
208
+ const config = getEnvConfig();
209
+ this.apiKey = config.apiKey || "";
47
210
  }
48
211
  isLoaded() {
49
212
  return import_fs.default.existsSync(import_path.default.resolve(process.cwd(), this.baseDir));
50
213
  }
51
214
  /**
52
- * Retrieve a specific page directly from its file.
215
+ * Helper to decrypt and decompile `.nx` files on-the-fly.
53
216
  */
54
- async getPage(slug) {
55
- try {
56
- const filePath = import_path.default.resolve(
57
- process.cwd(),
58
- this.baseDir,
59
- "pages",
60
- `${slug}.json`
61
- );
62
- if (import_fs.default.existsSync(filePath)) {
63
- const fileContent = import_fs.default.readFileSync(filePath, "utf-8");
64
- const pageData = JSON.parse(fileContent);
65
- return pageData.data !== void 0 ? pageData.data : pageData;
217
+ decompileFile(filePath) {
218
+ if (!this.apiKey) {
219
+ if (process.env.NODE_ENV === "development") {
220
+ console.warn(
221
+ "\u26A0\uFE0F NexusHub: Missing NEXUS_API_KEY. Local decryption bypassed."
222
+ );
66
223
  }
224
+ return null;
225
+ }
226
+ try {
227
+ const encryptedBuffer = import_fs.default.readFileSync(filePath);
228
+ const decompiled = BinaryCompiler.decompile(encryptedBuffer, this.apiKey);
229
+ return decompiled.data;
67
230
  } catch (error) {
68
231
  if (process.env.NODE_ENV === "development") {
69
- console.warn(
70
- `\u26A0\uFE0F NexusHub: Failed to load local page '${slug}':`,
71
- error
232
+ console.error(
233
+ `
234
+ \u{1F6A8} NexusHub Security Alert: Data Integrity Violation in file:
235
+ ${filePath}
236
+ Error: ${error.message}
237
+ This file has been disabled until regenerated via npx nexus pull.
238
+ `
72
239
  );
73
240
  }
241
+ return null;
242
+ }
243
+ }
244
+ /**
245
+ * Retrieve a specific page directly from its .nx file.
246
+ */
247
+ async getPage(slug) {
248
+ const filePath = import_path.default.resolve(
249
+ process.cwd(),
250
+ this.baseDir,
251
+ "pages",
252
+ `${slug}.nx`
253
+ );
254
+ if (import_fs.default.existsSync(filePath)) {
255
+ const pageData = this.decompileFile(filePath);
256
+ if (!pageData) return null;
257
+ return pageData.data !== void 0 ? pageData.data : pageData;
74
258
  }
75
259
  return null;
76
260
  }
77
261
  /**
78
- * Retrieve an entire collection from its specific collection file.
262
+ * Retrieve an entire collection from its specific .nx file.
79
263
  */
80
264
  async getCollection(collectionId) {
81
- try {
82
- const filePath = import_path.default.resolve(
83
- process.cwd(),
84
- this.baseDir,
85
- "collections",
86
- `${collectionId}.json`
87
- );
88
- if (import_fs.default.existsSync(filePath)) {
89
- const fileContent = import_fs.default.readFileSync(filePath, "utf-8");
90
- return JSON.parse(fileContent);
91
- }
92
- } catch (error) {
93
- if (process.env.NODE_ENV === "development") {
94
- console.warn(
95
- `\u26A0\uFE0F NexusHub: Failed to load local collection '${collectionId}':`,
96
- error
97
- );
98
- }
265
+ const filePath = import_path.default.resolve(
266
+ process.cwd(),
267
+ this.baseDir,
268
+ "collections",
269
+ `${collectionId}.nx`
270
+ );
271
+ if (import_fs.default.existsSync(filePath)) {
272
+ return this.decompileFile(filePath);
99
273
  }
100
274
  return null;
101
275
  }
102
276
  /**
103
- * Retrieve global settings from its file.
277
+ * Retrieve global settings from its .nx file.
104
278
  */
105
279
  async getGlobals() {
106
- try {
107
- const filePath = import_path.default.resolve(
108
- process.cwd(),
109
- this.baseDir,
110
- "globals.json"
111
- );
112
- if (import_fs.default.existsSync(filePath)) {
113
- const fileContent = import_fs.default.readFileSync(filePath, "utf-8");
114
- return JSON.parse(fileContent);
115
- }
116
- } catch {
280
+ const filePath = import_path.default.resolve(process.cwd(), this.baseDir, "globals.nx");
281
+ if (import_fs.default.existsSync(filePath)) {
282
+ return this.decompileFile(filePath);
117
283
  }
118
284
  return null;
119
285
  }
120
286
  /**
121
- * Returns a merged JSON of the entire workspace structure (for dev analytics/inspectors)
287
+ * Returns a merged JSON of the entire workspace structure.
122
288
  */
123
289
  async getAllData() {
124
290
  const pages = {};
@@ -128,8 +294,8 @@ var init_local_cache_server = __esm({
128
294
  const pagesDir = import_path.default.resolve(process.cwd(), this.baseDir, "pages");
129
295
  if (import_fs.default.existsSync(pagesDir)) {
130
296
  for (const file of import_fs.default.readdirSync(pagesDir)) {
131
- if (file.endsWith(".json")) {
132
- const slug = import_path.default.basename(file, ".json");
297
+ if (file.endsWith(".nx")) {
298
+ const slug = import_path.default.basename(file, ".nx");
133
299
  pages[slug] = await this.getPage(slug);
134
300
  }
135
301
  }
@@ -137,8 +303,8 @@ var init_local_cache_server = __esm({
137
303
  const colsDir = import_path.default.resolve(process.cwd(), this.baseDir, "collections");
138
304
  if (import_fs.default.existsSync(colsDir)) {
139
305
  for (const file of import_fs.default.readdirSync(colsDir)) {
140
- if (file.endsWith(".json")) {
141
- const id = import_path.default.basename(file, ".json");
306
+ if (file.endsWith(".nx")) {
307
+ const id = import_path.default.basename(file, ".nx");
142
308
  collections[id] = await this.getCollection(id) || [];
143
309
  }
144
310
  }
@@ -243,53 +409,8 @@ __export(index_exports, {
243
409
  });
244
410
  module.exports = __toCommonJS(index_exports);
245
411
 
246
- // src/config.ts
247
- var DEFAULT_API_URL = "https://endpoints.gnexus.co.tz";
248
- var DEFAULT_ANALYTICS_URL = "https://sentry.gnexus.co.tz";
249
- var LOCAL_NEST_URL = "https://endpoints.gnexus.co.tz";
250
- var LOCAL_RUST_URL = "https://sentry.gnexus.co.tz";
251
- var getEnvConfig = () => {
252
- const NEXT_PUBLIC_ID = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_ID : void 0;
253
- const NEXT_PUBLIC_KEY = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_KEY : void 0;
254
- const NEXT_PUBLIC_URL = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_NEXUS_API_URL : void 0;
255
- const NODE_ID = typeof process !== "undefined" ? process.env.NEXUS_PROJECT_ID : void 0;
256
- const NODE_KEY = typeof process !== "undefined" ? process.env.NEXUS_API_KEY : void 0;
257
- const NODE_URL = typeof process !== "undefined" ? process.env.NEXUS_API_URL : void 0;
258
- const NODE_ENV = typeof process !== "undefined" ? process.env.NODE_ENV : "production";
259
- const isDev = NODE_ENV === "development" || typeof window !== "undefined" && window.location.hostname === "localhost";
260
- const projectId = NEXT_PUBLIC_ID ?? NODE_ID;
261
- const apiKey = NEXT_PUBLIC_KEY ?? NODE_KEY;
262
- const apiUrl = NEXT_PUBLIC_URL ?? NODE_URL ?? (isDev ? LOCAL_NEST_URL : DEFAULT_API_URL);
263
- const analyticsUrl = apiUrl.includes("localhost") ? LOCAL_RUST_URL : DEFAULT_ANALYTICS_URL;
264
- return {
265
- projectId,
266
- apiKey,
267
- apiUrl,
268
- analyticsUrl
269
- };
270
- };
271
- var mergeConfigs = (base, override) => {
272
- const mergedApiUrl = override.apiUrl || base.apiUrl || DEFAULT_API_URL;
273
- const mergedAnalyticsUrl = override.analyticsUrl || base.analyticsUrl || (mergedApiUrl.includes("localhost") ? LOCAL_RUST_URL : DEFAULT_ANALYTICS_URL);
274
- return {
275
- ...base,
276
- ...override,
277
- apiUrl: mergedApiUrl,
278
- analyticsUrl: mergedAnalyticsUrl,
279
- projectId: override.projectId || base.projectId,
280
- apiKey: override.apiKey || base.apiKey
281
- };
282
- };
283
- var getFullConfig = (partialConfig) => {
284
- const envConfig = getEnvConfig();
285
- return mergeConfigs(envConfig, partialConfig || {});
286
- };
287
- var validateConfig = (config) => {
288
- const errors = [];
289
- if (!config.projectId) errors.push("Missing projectId");
290
- if (!config.apiUrl) errors.push("Missing apiUrl");
291
- return errors;
292
- };
412
+ // src/client.ts
413
+ init_config();
293
414
 
294
415
  // src/content/cache-implementations.ts
295
416
  var CacheTags = {
@@ -2503,6 +2624,7 @@ var nexus = new NexusClient();
2503
2624
  var createNexusClient = (config) => new NexusClient(config);
2504
2625
 
2505
2626
  // src/index.ts
2627
+ init_config();
2506
2628
  var VERSION = "0.0.1";
2507
2629
  // Annotate the CommonJS export names for ESM import in node:
2508
2630
  0 && (module.exports = {