tetrons 2.3.33 → 2.3.35
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.cjs +47 -8
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +46 -8
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.js +61 -0
- package/package.json +1 -1
- package/dist/app/api/export/route.js +0 -4
- package/dist/app/api/register/route.js +0 -32
- package/dist/app/api/save/route.js +0 -15
- package/dist/app/api/validate/route.js +0 -58
- package/dist/app/layout.d.ts +0 -6
- package/dist/app/layout.jsx +0 -30
- package/dist/app/page.jsx +0 -51
- package/dist/components/UI/Button.d.ts +0 -0
- package/dist/components/UI/Button.jsx +0 -1
- package/dist/components/UI/Dropdown.d.ts +0 -0
- package/dist/components/UI/Dropdown.jsx +0 -1
- package/dist/components/tetrons/EditorContent.jsx +0 -209
- package/dist/components/tetrons/ResizableVideo.d.ts +0 -12
- package/dist/components/tetrons/ResizableVideo.js +0 -61
- package/dist/components/tetrons/ResizableVideoComponent.d.ts +0 -4
- package/dist/components/tetrons/ResizableVideoComponent.jsx +0 -32
- package/dist/components/tetrons/helpers.d.ts +0 -0
- package/dist/components/tetrons/helpers.js +0 -1
- package/dist/components/tetrons/toolbar/ActionGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/ActionGroup.jsx +0 -167
- package/dist/components/tetrons/toolbar/ClipboardGroup.d.ts +0 -5
- package/dist/components/tetrons/toolbar/ClipboardGroup.jsx +0 -36
- package/dist/components/tetrons/toolbar/FileGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/FileGroup.jsx +0 -40
- package/dist/components/tetrons/toolbar/FontStyleGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/FontStyleGroup.jsx +0 -104
- package/dist/components/tetrons/toolbar/InsertGroup.d.ts +0 -5
- package/dist/components/tetrons/toolbar/InsertGroup.jsx +0 -163
- package/dist/components/tetrons/toolbar/ListAlignGroup.d.ts +0 -5
- package/dist/components/tetrons/toolbar/ListAlignGroup.jsx +0 -16
- package/dist/components/tetrons/toolbar/MiscGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/MiscGroup.jsx +0 -31
- package/dist/components/tetrons/toolbar/TableContextMenu.d.ts +0 -7
- package/dist/components/tetrons/toolbar/TableContextMenu.jsx +0 -52
- package/dist/components/tetrons/toolbar/TetronsToolbar.d.ts +0 -6
- package/dist/components/tetrons/toolbar/TetronsToolbar.jsx +0 -46
- package/dist/components/tetrons/toolbar/ToolbarButton.d.ts +0 -12
- package/dist/components/tetrons/toolbar/ToolbarButton.jsx +0 -8
- package/dist/components/tetrons/toolbar/extensions/Comment.d.ts +0 -17
- package/dist/components/tetrons/toolbar/extensions/Comment.js +0 -45
- package/dist/components/tetrons/toolbar/extensions/Embed.d.ts +0 -2
- package/dist/components/tetrons/toolbar/extensions/Embed.js +0 -90
- package/dist/components/tetrons/toolbar/extensions/FontFamily.d.ts +0 -9
- package/dist/components/tetrons/toolbar/extensions/FontFamily.js +0 -28
- package/dist/components/tetrons/toolbar/extensions/FontSize.d.ts +0 -9
- package/dist/components/tetrons/toolbar/extensions/FontSize.js +0 -28
- package/dist/components/tetrons/toolbar/extensions/ResizableTable.d.ts +0 -1
- package/dist/components/tetrons/toolbar/extensions/ResizableTable.js +0 -11
- package/dist/components/tetrons/toolbar/marks/Subscript.d.ts +0 -2
- package/dist/components/tetrons/toolbar/marks/Subscript.js +0 -35
- package/dist/components/tetrons/toolbar/marks/Superscript.d.ts +0 -2
- package/dist/components/tetrons/toolbar/marks/Superscript.js +0 -35
- package/dist/lib/db.d.ts +0 -1
- package/dist/lib/db.js +0 -15
- package/dist/lib/export.d.ts +0 -0
- package/dist/lib/export.js +0 -1
- package/dist/lib/tiptap-extensions.d.ts +0 -0
- package/dist/lib/tiptap-extensions.js +0 -1
- package/dist/models/ApiKey.d.ts +0 -2
- package/dist/models/ApiKey.js +0 -14
- package/dist/src/app/page.d.ts +0 -2
- package/dist/src/app/page.jsx +0 -51
- package/dist/src/components/tetrons/toolbar/AIGroup.d.ts +0 -5
- package/dist/src/components/tetrons/toolbar/AIGroup.jsx +0 -140
- package/dist/utils/apiKeyUtils.d.ts +0 -11
- package/dist/utils/apiKeyUtils.js +0 -33
- package/dist/utils/loadEmojiPicker.d.ts +0 -1
- package/dist/utils/loadEmojiPicker.js +0 -12
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
EditorContent: () => EditorContent,
|
|
34
34
|
default: () => index_default,
|
|
35
|
+
getTetronsRemainingDays: () => getTetronsRemainingDays,
|
|
35
36
|
getTetronsVersion: () => getTetronsVersion,
|
|
36
37
|
initializeTetrons: () => initializeTetrons,
|
|
37
38
|
isApiKeyValid: () => isApiKeyValid
|
|
@@ -988,11 +989,11 @@ var ResolvedPos = class _ResolvedPos {
|
|
|
988
989
|
/**
|
|
989
990
|
@internal
|
|
990
991
|
*/
|
|
991
|
-
constructor(pos,
|
|
992
|
+
constructor(pos, path2, parentOffset) {
|
|
992
993
|
this.pos = pos;
|
|
993
|
-
this.path =
|
|
994
|
+
this.path = path2;
|
|
994
995
|
this.parentOffset = parentOffset;
|
|
995
|
-
this.depth =
|
|
996
|
+
this.depth = path2.length / 3 - 1;
|
|
996
997
|
}
|
|
997
998
|
/**
|
|
998
999
|
@internal
|
|
@@ -1223,12 +1224,12 @@ var ResolvedPos = class _ResolvedPos {
|
|
|
1223
1224
|
static resolve(doc3, pos) {
|
|
1224
1225
|
if (!(pos >= 0 && pos <= doc3.content.size))
|
|
1225
1226
|
throw new RangeError("Position " + pos + " out of range");
|
|
1226
|
-
let
|
|
1227
|
+
let path2 = [];
|
|
1227
1228
|
let start = 0, parentOffset = pos;
|
|
1228
1229
|
for (let node = doc3; ; ) {
|
|
1229
1230
|
let { index, offset } = node.content.findIndex(parentOffset);
|
|
1230
1231
|
let rem = parentOffset - offset;
|
|
1231
|
-
|
|
1232
|
+
path2.push(node, index, start + offset);
|
|
1232
1233
|
if (!rem)
|
|
1233
1234
|
break;
|
|
1234
1235
|
node = node.child(index);
|
|
@@ -1237,7 +1238,7 @@ var ResolvedPos = class _ResolvedPos {
|
|
|
1237
1238
|
parentOffset = rem - 1;
|
|
1238
1239
|
start += offset + 1;
|
|
1239
1240
|
}
|
|
1240
|
-
return new _ResolvedPos(pos,
|
|
1241
|
+
return new _ResolvedPos(pos, path2, parentOffset);
|
|
1241
1242
|
}
|
|
1242
1243
|
/**
|
|
1243
1244
|
@internal
|
|
@@ -16656,7 +16657,7 @@ function AiGroup({ editor }) {
|
|
|
16656
16657
|
const formData = new FormData();
|
|
16657
16658
|
formData.append("file", blob, "voice.webm");
|
|
16658
16659
|
try {
|
|
16659
|
-
const res = await fetch("/api/transcribe", {
|
|
16660
|
+
const res = await fetch("https://staging.tetrons.com/api/transcribe", {
|
|
16660
16661
|
method: "POST",
|
|
16661
16662
|
body: formData
|
|
16662
16663
|
});
|
|
@@ -16682,7 +16683,7 @@ function AiGroup({ editor }) {
|
|
|
16682
16683
|
setIsLoadingAI(true);
|
|
16683
16684
|
setAiError("");
|
|
16684
16685
|
try {
|
|
16685
|
-
const res = await fetch("/api/ai-action", {
|
|
16686
|
+
const res = await fetch("https://staging.tetrons.com/api/ai-action", {
|
|
16686
16687
|
method: "POST",
|
|
16687
16688
|
headers: { "Content-Type": "application/json" },
|
|
16688
16689
|
body: JSON.stringify({ content: prompt2 })
|
|
@@ -16978,8 +16979,27 @@ function EditorContent({ apiKey }) {
|
|
|
16978
16979
|
}
|
|
16979
16980
|
|
|
16980
16981
|
// src/index.ts
|
|
16982
|
+
var import_fs = __toESM(require("fs"));
|
|
16983
|
+
var import_path = __toESM(require("path"));
|
|
16981
16984
|
var API_VALID = false;
|
|
16982
16985
|
var API_VERSION = "";
|
|
16986
|
+
var USAGE_FILE_PATH = import_path.default.join(process.cwd(), ".tetrons-usage.json");
|
|
16987
|
+
function getOrCreateInstallDate() {
|
|
16988
|
+
if (import_fs.default.existsSync(USAGE_FILE_PATH)) {
|
|
16989
|
+
const data = JSON.parse(import_fs.default.readFileSync(USAGE_FILE_PATH, "utf-8"));
|
|
16990
|
+
return new Date(data.installedAt);
|
|
16991
|
+
}
|
|
16992
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
16993
|
+
import_fs.default.writeFileSync(USAGE_FILE_PATH, JSON.stringify({ installedAt: now }));
|
|
16994
|
+
return new Date(now);
|
|
16995
|
+
}
|
|
16996
|
+
function getRemainingDays(installedAt, validityDays) {
|
|
16997
|
+
const now = /* @__PURE__ */ new Date();
|
|
16998
|
+
const diff = Math.floor(
|
|
16999
|
+
(now.getTime() - installedAt.getTime()) / (1e3 * 60 * 60 * 24)
|
|
17000
|
+
);
|
|
17001
|
+
return validityDays - diff;
|
|
17002
|
+
}
|
|
16983
17003
|
async function initializeTetrons(apiKey) {
|
|
16984
17004
|
const res = await fetch("https://staging.tetrons.com/api/validate", {
|
|
16985
17005
|
method: "POST",
|
|
@@ -16995,6 +17015,18 @@ async function initializeTetrons(apiKey) {
|
|
|
16995
17015
|
const data = await res.json();
|
|
16996
17016
|
API_VALID = data.valid;
|
|
16997
17017
|
API_VERSION = data.version;
|
|
17018
|
+
if (!API_VALID) {
|
|
17019
|
+
throw new Error("API Key is not valid.");
|
|
17020
|
+
}
|
|
17021
|
+
const validityDays = API_VERSION === "free" ? 14 : 30;
|
|
17022
|
+
const installedAt = getOrCreateInstallDate();
|
|
17023
|
+
const remainingDays = getRemainingDays(installedAt, validityDays);
|
|
17024
|
+
if (remainingDays <= 0) {
|
|
17025
|
+
throw new Error(`Your ${API_VERSION} license has expired.`);
|
|
17026
|
+
}
|
|
17027
|
+
console.log(
|
|
17028
|
+
`[TETRONS] Initialized: ${API_VERSION} | Remaining days: ${remainingDays}`
|
|
17029
|
+
);
|
|
16998
17030
|
}
|
|
16999
17031
|
function getTetronsVersion() {
|
|
17000
17032
|
return API_VERSION;
|
|
@@ -17002,10 +17034,17 @@ function getTetronsVersion() {
|
|
|
17002
17034
|
function isApiKeyValid() {
|
|
17003
17035
|
return API_VALID;
|
|
17004
17036
|
}
|
|
17037
|
+
function getTetronsRemainingDays() {
|
|
17038
|
+
if (!API_VALID || !API_VERSION) return null;
|
|
17039
|
+
const validityDays = API_VERSION === "free" ? 14 : 30;
|
|
17040
|
+
const installedAt = getOrCreateInstallDate();
|
|
17041
|
+
return getRemainingDays(installedAt, validityDays);
|
|
17042
|
+
}
|
|
17005
17043
|
var index_default = EditorContent;
|
|
17006
17044
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17007
17045
|
0 && (module.exports = {
|
|
17008
17046
|
EditorContent,
|
|
17047
|
+
getTetronsRemainingDays,
|
|
17009
17048
|
getTetronsVersion,
|
|
17010
17049
|
initializeTetrons,
|
|
17011
17050
|
isApiKeyValid
|
package/dist/index.d.mts
CHANGED
|
@@ -8,5 +8,6 @@ declare function EditorContent({ apiKey }: EditorContentProps): React.JSX.Elemen
|
|
|
8
8
|
declare function initializeTetrons(apiKey: string): Promise<void>;
|
|
9
9
|
declare function getTetronsVersion(): "" | "free" | "pro" | "premium" | "platinum";
|
|
10
10
|
declare function isApiKeyValid(): boolean;
|
|
11
|
+
declare function getTetronsRemainingDays(): number | null;
|
|
11
12
|
|
|
12
|
-
export { EditorContent, EditorContent as default, getTetronsVersion, initializeTetrons, isApiKeyValid };
|
|
13
|
+
export { EditorContent, EditorContent as default, getTetronsRemainingDays, getTetronsVersion, initializeTetrons, isApiKeyValid };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,5 +8,6 @@ declare function EditorContent({ apiKey }: EditorContentProps): React.JSX.Elemen
|
|
|
8
8
|
declare function initializeTetrons(apiKey: string): Promise<void>;
|
|
9
9
|
declare function getTetronsVersion(): "" | "free" | "pro" | "premium" | "platinum";
|
|
10
10
|
declare function isApiKeyValid(): boolean;
|
|
11
|
+
declare function getTetronsRemainingDays(): number | null;
|
|
11
12
|
|
|
12
|
-
export { EditorContent, EditorContent as default, getTetronsVersion, initializeTetrons, isApiKeyValid };
|
|
13
|
+
export { EditorContent, EditorContent as default, getTetronsRemainingDays, getTetronsVersion, initializeTetrons, isApiKeyValid };
|
package/dist/index.mjs
CHANGED
|
@@ -951,11 +951,11 @@ var ResolvedPos = class _ResolvedPos {
|
|
|
951
951
|
/**
|
|
952
952
|
@internal
|
|
953
953
|
*/
|
|
954
|
-
constructor(pos,
|
|
954
|
+
constructor(pos, path2, parentOffset) {
|
|
955
955
|
this.pos = pos;
|
|
956
|
-
this.path =
|
|
956
|
+
this.path = path2;
|
|
957
957
|
this.parentOffset = parentOffset;
|
|
958
|
-
this.depth =
|
|
958
|
+
this.depth = path2.length / 3 - 1;
|
|
959
959
|
}
|
|
960
960
|
/**
|
|
961
961
|
@internal
|
|
@@ -1186,12 +1186,12 @@ var ResolvedPos = class _ResolvedPos {
|
|
|
1186
1186
|
static resolve(doc3, pos) {
|
|
1187
1187
|
if (!(pos >= 0 && pos <= doc3.content.size))
|
|
1188
1188
|
throw new RangeError("Position " + pos + " out of range");
|
|
1189
|
-
let
|
|
1189
|
+
let path2 = [];
|
|
1190
1190
|
let start = 0, parentOffset = pos;
|
|
1191
1191
|
for (let node = doc3; ; ) {
|
|
1192
1192
|
let { index, offset } = node.content.findIndex(parentOffset);
|
|
1193
1193
|
let rem = parentOffset - offset;
|
|
1194
|
-
|
|
1194
|
+
path2.push(node, index, start + offset);
|
|
1195
1195
|
if (!rem)
|
|
1196
1196
|
break;
|
|
1197
1197
|
node = node.child(index);
|
|
@@ -1200,7 +1200,7 @@ var ResolvedPos = class _ResolvedPos {
|
|
|
1200
1200
|
parentOffset = rem - 1;
|
|
1201
1201
|
start += offset + 1;
|
|
1202
1202
|
}
|
|
1203
|
-
return new _ResolvedPos(pos,
|
|
1203
|
+
return new _ResolvedPos(pos, path2, parentOffset);
|
|
1204
1204
|
}
|
|
1205
1205
|
/**
|
|
1206
1206
|
@internal
|
|
@@ -16664,7 +16664,7 @@ function AiGroup({ editor }) {
|
|
|
16664
16664
|
const formData = new FormData();
|
|
16665
16665
|
formData.append("file", blob, "voice.webm");
|
|
16666
16666
|
try {
|
|
16667
|
-
const res = await fetch("/api/transcribe", {
|
|
16667
|
+
const res = await fetch("https://staging.tetrons.com/api/transcribe", {
|
|
16668
16668
|
method: "POST",
|
|
16669
16669
|
body: formData
|
|
16670
16670
|
});
|
|
@@ -16690,7 +16690,7 @@ function AiGroup({ editor }) {
|
|
|
16690
16690
|
setIsLoadingAI(true);
|
|
16691
16691
|
setAiError("");
|
|
16692
16692
|
try {
|
|
16693
|
-
const res = await fetch("/api/ai-action", {
|
|
16693
|
+
const res = await fetch("https://staging.tetrons.com/api/ai-action", {
|
|
16694
16694
|
method: "POST",
|
|
16695
16695
|
headers: { "Content-Type": "application/json" },
|
|
16696
16696
|
body: JSON.stringify({ content: prompt2 })
|
|
@@ -16985,8 +16985,27 @@ function EditorContent({ apiKey }) {
|
|
|
16985
16985
|
}
|
|
16986
16986
|
|
|
16987
16987
|
// src/index.ts
|
|
16988
|
+
import fs from "fs";
|
|
16989
|
+
import path from "path";
|
|
16988
16990
|
var API_VALID = false;
|
|
16989
16991
|
var API_VERSION = "";
|
|
16992
|
+
var USAGE_FILE_PATH = path.join(process.cwd(), ".tetrons-usage.json");
|
|
16993
|
+
function getOrCreateInstallDate() {
|
|
16994
|
+
if (fs.existsSync(USAGE_FILE_PATH)) {
|
|
16995
|
+
const data = JSON.parse(fs.readFileSync(USAGE_FILE_PATH, "utf-8"));
|
|
16996
|
+
return new Date(data.installedAt);
|
|
16997
|
+
}
|
|
16998
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
16999
|
+
fs.writeFileSync(USAGE_FILE_PATH, JSON.stringify({ installedAt: now }));
|
|
17000
|
+
return new Date(now);
|
|
17001
|
+
}
|
|
17002
|
+
function getRemainingDays(installedAt, validityDays) {
|
|
17003
|
+
const now = /* @__PURE__ */ new Date();
|
|
17004
|
+
const diff = Math.floor(
|
|
17005
|
+
(now.getTime() - installedAt.getTime()) / (1e3 * 60 * 60 * 24)
|
|
17006
|
+
);
|
|
17007
|
+
return validityDays - diff;
|
|
17008
|
+
}
|
|
16990
17009
|
async function initializeTetrons(apiKey) {
|
|
16991
17010
|
const res = await fetch("https://staging.tetrons.com/api/validate", {
|
|
16992
17011
|
method: "POST",
|
|
@@ -17002,6 +17021,18 @@ async function initializeTetrons(apiKey) {
|
|
|
17002
17021
|
const data = await res.json();
|
|
17003
17022
|
API_VALID = data.valid;
|
|
17004
17023
|
API_VERSION = data.version;
|
|
17024
|
+
if (!API_VALID) {
|
|
17025
|
+
throw new Error("API Key is not valid.");
|
|
17026
|
+
}
|
|
17027
|
+
const validityDays = API_VERSION === "free" ? 14 : 30;
|
|
17028
|
+
const installedAt = getOrCreateInstallDate();
|
|
17029
|
+
const remainingDays = getRemainingDays(installedAt, validityDays);
|
|
17030
|
+
if (remainingDays <= 0) {
|
|
17031
|
+
throw new Error(`Your ${API_VERSION} license has expired.`);
|
|
17032
|
+
}
|
|
17033
|
+
console.log(
|
|
17034
|
+
`[TETRONS] Initialized: ${API_VERSION} | Remaining days: ${remainingDays}`
|
|
17035
|
+
);
|
|
17005
17036
|
}
|
|
17006
17037
|
function getTetronsVersion() {
|
|
17007
17038
|
return API_VERSION;
|
|
@@ -17009,10 +17040,17 @@ function getTetronsVersion() {
|
|
|
17009
17040
|
function isApiKeyValid() {
|
|
17010
17041
|
return API_VALID;
|
|
17011
17042
|
}
|
|
17043
|
+
function getTetronsRemainingDays() {
|
|
17044
|
+
if (!API_VALID || !API_VERSION) return null;
|
|
17045
|
+
const validityDays = API_VERSION === "free" ? 14 : 30;
|
|
17046
|
+
const installedAt = getOrCreateInstallDate();
|
|
17047
|
+
return getRemainingDays(installedAt, validityDays);
|
|
17048
|
+
}
|
|
17012
17049
|
var index_default = EditorContent;
|
|
17013
17050
|
export {
|
|
17014
17051
|
EditorContent,
|
|
17015
17052
|
index_default as default,
|
|
17053
|
+
getTetronsRemainingDays,
|
|
17016
17054
|
getTetronsVersion,
|
|
17017
17055
|
initializeTetrons,
|
|
17018
17056
|
isApiKeyValid
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import EditorContent from "./components/tetrons/EditorContent";
|
|
2
|
+
export declare function initializeTetrons(apiKey: string): Promise<void>;
|
|
3
|
+
export declare function getTetronsVersion(): "" | "free" | "pro" | "premium" | "platinum";
|
|
4
|
+
export declare function isApiKeyValid(): boolean;
|
|
5
|
+
export declare function getTetronsRemainingDays(): number | null;
|
|
6
|
+
export { EditorContent };
|
|
7
|
+
export default EditorContent;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import EditorContent from "./components/tetrons/EditorContent";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
let API_VALID = false;
|
|
5
|
+
let API_VERSION = "";
|
|
6
|
+
const USAGE_FILE_PATH = path.join(process.cwd(), ".tetrons-usage.json");
|
|
7
|
+
function getOrCreateInstallDate() {
|
|
8
|
+
if (fs.existsSync(USAGE_FILE_PATH)) {
|
|
9
|
+
const data = JSON.parse(fs.readFileSync(USAGE_FILE_PATH, "utf-8"));
|
|
10
|
+
return new Date(data.installedAt);
|
|
11
|
+
}
|
|
12
|
+
const now = new Date().toISOString();
|
|
13
|
+
fs.writeFileSync(USAGE_FILE_PATH, JSON.stringify({ installedAt: now }));
|
|
14
|
+
return new Date(now);
|
|
15
|
+
}
|
|
16
|
+
function getRemainingDays(installedAt, validityDays) {
|
|
17
|
+
const now = new Date();
|
|
18
|
+
const diff = Math.floor((now.getTime() - installedAt.getTime()) / (1000 * 60 * 60 * 24));
|
|
19
|
+
return validityDays - diff;
|
|
20
|
+
}
|
|
21
|
+
export async function initializeTetrons(apiKey) {
|
|
22
|
+
const res = await fetch("https://staging.tetrons.com/api/validate", {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: {
|
|
25
|
+
"Content-Type": "application/json",
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({ apiKey }),
|
|
28
|
+
});
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
const error = await res.json();
|
|
31
|
+
throw new Error(`API Key validation failed: ${error.error}`);
|
|
32
|
+
}
|
|
33
|
+
const data = await res.json();
|
|
34
|
+
API_VALID = data.valid;
|
|
35
|
+
API_VERSION = data.version;
|
|
36
|
+
if (!API_VALID) {
|
|
37
|
+
throw new Error("API Key is not valid.");
|
|
38
|
+
}
|
|
39
|
+
const validityDays = API_VERSION === "free" ? 14 : 30;
|
|
40
|
+
const installedAt = getOrCreateInstallDate();
|
|
41
|
+
const remainingDays = getRemainingDays(installedAt, validityDays);
|
|
42
|
+
if (remainingDays <= 0) {
|
|
43
|
+
throw new Error(`Your ${API_VERSION} license has expired.`);
|
|
44
|
+
}
|
|
45
|
+
console.log(`[TETRONS] Initialized: ${API_VERSION} | Remaining days: ${remainingDays}`);
|
|
46
|
+
}
|
|
47
|
+
export function getTetronsVersion() {
|
|
48
|
+
return API_VERSION;
|
|
49
|
+
}
|
|
50
|
+
export function isApiKeyValid() {
|
|
51
|
+
return API_VALID;
|
|
52
|
+
}
|
|
53
|
+
export function getTetronsRemainingDays() {
|
|
54
|
+
if (!API_VALID || !API_VERSION)
|
|
55
|
+
return null;
|
|
56
|
+
const validityDays = API_VERSION === "free" ? 14 : 30;
|
|
57
|
+
const installedAt = getOrCreateInstallDate();
|
|
58
|
+
return getRemainingDays(installedAt, validityDays);
|
|
59
|
+
}
|
|
60
|
+
export { EditorContent };
|
|
61
|
+
export default EditorContent;
|
package/package.json
CHANGED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { connectDB } from "../../../lib/db";
|
|
3
|
-
import { ApiKey } from "../../../models/ApiKey";
|
|
4
|
-
import { generateUserApiKey, getFreeApiKey } from "../../../utils/apiKeyUtils";
|
|
5
|
-
export async function POST(req) {
|
|
6
|
-
const body = await req.json();
|
|
7
|
-
const { email, organization, version } = body;
|
|
8
|
-
if (!email || !organization || !version) {
|
|
9
|
-
return NextResponse.json({ error: "Missing fields" }, { status: 400 });
|
|
10
|
-
}
|
|
11
|
-
await connectDB();
|
|
12
|
-
const lowerEmail = email.trim().toLowerCase();
|
|
13
|
-
const lowerOrg = organization.trim().toLowerCase();
|
|
14
|
-
await ApiKey.deleteMany({ email: lowerEmail, version });
|
|
15
|
-
let apiKey;
|
|
16
|
-
let expiresAt = null;
|
|
17
|
-
if (version === "free") {
|
|
18
|
-
apiKey = getFreeApiKey();
|
|
19
|
-
expiresAt = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
apiKey = generateUserApiKey(lowerEmail, lowerOrg, version);
|
|
23
|
-
}
|
|
24
|
-
await ApiKey.create({
|
|
25
|
-
email: lowerEmail,
|
|
26
|
-
organization: lowerOrg,
|
|
27
|
-
version,
|
|
28
|
-
apiKey,
|
|
29
|
-
expiresAt,
|
|
30
|
-
});
|
|
31
|
-
return NextResponse.json({ apiKey, expiresAt });
|
|
32
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fs from "fs/promises";
|
|
4
|
-
export async function POST(request) {
|
|
5
|
-
try {
|
|
6
|
-
const json = await request.json();
|
|
7
|
-
const publicDir = path.join(process.cwd(), "public");
|
|
8
|
-
const filePath = path.join(publicDir, "editor-content.json");
|
|
9
|
-
await fs.writeFile(filePath, JSON.stringify(json, null, 2), "utf-8");
|
|
10
|
-
return NextResponse.json({ message: "File saved successfully" });
|
|
11
|
-
}
|
|
12
|
-
catch (_a) {
|
|
13
|
-
return NextResponse.json({ error: "Failed to save file" }, { status: 500 });
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { connectDB } from "../../../lib/db";
|
|
3
|
-
import { ApiKey } from "../../../models/ApiKey";
|
|
4
|
-
const corsHeaders = {
|
|
5
|
-
"Access-Control-Allow-Origin": "*",
|
|
6
|
-
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
7
|
-
"Access-Control-Allow-Headers": "Content-Type",
|
|
8
|
-
};
|
|
9
|
-
export async function OPTIONS() {
|
|
10
|
-
return new Response(null, {
|
|
11
|
-
status: 204,
|
|
12
|
-
headers: corsHeaders,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
export async function POST(req) {
|
|
16
|
-
try {
|
|
17
|
-
const body = (await req.json());
|
|
18
|
-
const apiKey = body.apiKey;
|
|
19
|
-
if (!apiKey) {
|
|
20
|
-
return NextResponse.json({ error: "API key required" }, {
|
|
21
|
-
status: 400,
|
|
22
|
-
headers: corsHeaders,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
await connectDB();
|
|
26
|
-
const keyEntry = await ApiKey.findOne({ apiKey });
|
|
27
|
-
if (!keyEntry) {
|
|
28
|
-
return NextResponse.json({ error: "Invalid API key" }, {
|
|
29
|
-
status: 401,
|
|
30
|
-
headers: corsHeaders,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
if (keyEntry.version === "free" &&
|
|
34
|
-
keyEntry.expiresAt &&
|
|
35
|
-
new Date() > new Date(keyEntry.expiresAt)) {
|
|
36
|
-
return NextResponse.json({ error: "Free trial expired" }, {
|
|
37
|
-
status: 403,
|
|
38
|
-
headers: corsHeaders,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
return NextResponse.json({
|
|
42
|
-
valid: true,
|
|
43
|
-
version: keyEntry.version,
|
|
44
|
-
email: keyEntry.email,
|
|
45
|
-
organization: keyEntry.organization,
|
|
46
|
-
}, {
|
|
47
|
-
status: 200,
|
|
48
|
-
headers: corsHeaders,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
console.error("Validation Error:", err);
|
|
53
|
-
return NextResponse.json({ error: "Server error" }, {
|
|
54
|
-
status: 500,
|
|
55
|
-
headers: corsHeaders,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
package/dist/app/layout.d.ts
DELETED
package/dist/app/layout.jsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
2
|
-
import "./globals.css";
|
|
3
|
-
const geistSans = Geist({
|
|
4
|
-
variable: "--font-geist-sans",
|
|
5
|
-
subsets: ["latin"],
|
|
6
|
-
});
|
|
7
|
-
const geistMono = Geist_Mono({
|
|
8
|
-
variable: "--font-geist-mono",
|
|
9
|
-
subsets: ["latin"],
|
|
10
|
-
});
|
|
11
|
-
export const metadata = {
|
|
12
|
-
title: "Tetrons",
|
|
13
|
-
description: "A modern Word-style rich text editor built with Next.js",
|
|
14
|
-
icons: {
|
|
15
|
-
icon: [
|
|
16
|
-
{ url: "/favicon.ico", type: "image/x-icon" },
|
|
17
|
-
{ url: "/favicon-32x32.png", type: "image/png", sizes: "32x32" },
|
|
18
|
-
{ url: "/favicon-16x16.png", type: "image/png", sizes: "16x16" },
|
|
19
|
-
],
|
|
20
|
-
apple: "/apple-touch-icon.png",
|
|
21
|
-
},
|
|
22
|
-
manifest: "/site.webmanifest",
|
|
23
|
-
};
|
|
24
|
-
export default function RootLayout({ children, }) {
|
|
25
|
-
return (<html lang="en">
|
|
26
|
-
<body suppressHydrationWarning className={`${geistSans.variable} ${geistMono.variable} font-sans antialiased bg-gray-50 text-gray-900`}>
|
|
27
|
-
<main className="max-w-screen-xl mx-auto p-4">{children}</main>
|
|
28
|
-
</body>
|
|
29
|
-
</html>);
|
|
30
|
-
}
|
package/dist/app/page.jsx
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
import EditorContent from "../components/tetrons/EditorContent";
|
|
4
|
-
import "../styles/tetrons.css";
|
|
5
|
-
export default function Home() {
|
|
6
|
-
const [apiKey, setApiKey] = useState(null);
|
|
7
|
-
const [loading, setLoading] = useState(true);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
const fetchOrGenerateApiKey = async () => {
|
|
10
|
-
let key = localStorage.getItem("tetrons-key");
|
|
11
|
-
if (!key) {
|
|
12
|
-
try {
|
|
13
|
-
const res = await fetch("/api/register", {
|
|
14
|
-
method: "POST",
|
|
15
|
-
headers: { "Content-Type": "application/json" },
|
|
16
|
-
body: JSON.stringify({
|
|
17
|
-
email: "developer@finapsys.co.in",
|
|
18
|
-
organization: "FCSPL",
|
|
19
|
-
version: "free",
|
|
20
|
-
}),
|
|
21
|
-
});
|
|
22
|
-
const data = await res.json();
|
|
23
|
-
if (!res.ok || !data.apiKey) {
|
|
24
|
-
throw new Error(data.error || "Failed to register for API key");
|
|
25
|
-
}
|
|
26
|
-
key = data.apiKey;
|
|
27
|
-
if (key) {
|
|
28
|
-
localStorage.setItem("tetrons-key", key);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
console.error("❌ Failed to fetch or register API key:", err);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
setApiKey(key);
|
|
36
|
-
setLoading(false);
|
|
37
|
-
};
|
|
38
|
-
fetchOrGenerateApiKey();
|
|
39
|
-
}, []);
|
|
40
|
-
if (loading) {
|
|
41
|
-
return <div className="text-center p-4">⏳ Loading Editor...</div>;
|
|
42
|
-
}
|
|
43
|
-
if (!apiKey) {
|
|
44
|
-
return <div className="text-red-600 text-center">❌ API key not found</div>;
|
|
45
|
-
}
|
|
46
|
-
return (<main className="flex flex-col h-screen overflow-hidden">
|
|
47
|
-
<div className="flex-1 overflow-auto flex flex-col">
|
|
48
|
-
<EditorContent apiKey={apiKey}/>
|
|
49
|
-
</div>
|
|
50
|
-
</main>);
|
|
51
|
-
}
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|