quik-cli 1.0.0
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/README.md +0 -0
- package/bin/quik.dev.ts +8 -0
- package/bin/quik.js +9 -0
- package/dist/commands/VersionCommand.d.ts +12 -0
- package/dist/commands/VersionCommand.d.ts.map +1 -0
- package/dist/commands/VersionCommand.js +13 -0
- package/dist/commands/VersionCommand.js.map +1 -0
- package/dist/commands/init/InitCommand.d.ts +21 -0
- package/dist/commands/init/InitCommand.d.ts.map +1 -0
- package/dist/commands/init/InitCommand.js +22 -0
- package/dist/commands/init/InitCommand.js.map +1 -0
- package/dist/commands/init/impl/astro.scaffold.d.ts +9 -0
- package/dist/commands/init/impl/astro.scaffold.d.ts.map +1 -0
- package/dist/commands/init/impl/astro.scaffold.js +23 -0
- package/dist/commands/init/impl/astro.scaffold.js.map +1 -0
- package/dist/commands/init/impl/init.impl.d.ts +3 -0
- package/dist/commands/init/impl/init.impl.d.ts.map +1 -0
- package/dist/commands/init/impl/init.impl.js +201 -0
- package/dist/commands/init/impl/init.impl.js.map +1 -0
- package/dist/commands/init/impl/nextjs.scaffold.d.ts +9 -0
- package/dist/commands/init/impl/nextjs.scaffold.d.ts.map +1 -0
- package/dist/commands/init/impl/nextjs.scaffold.js +29 -0
- package/dist/commands/init/impl/nextjs.scaffold.js.map +1 -0
- package/dist/commands/init/templates/astro/.env.template +23 -0
- package/dist/commands/init/templates/astro/api-proxy.template +8 -0
- package/dist/commands/init/templates/astro/env.template +23 -0
- package/dist/commands/init/templates/astro/page.template +14 -0
- package/dist/commands/init/templates/nextjs/api-proxy.template +25 -0
- package/dist/commands/init/templates/nextjs/config.template +15 -0
- package/dist/commands/init/templates/nextjs/env.template +23 -0
- package/dist/commands/init/templates/nextjs/layout.template +67 -0
- package/dist/commands/init/templates/nextjs/page.template +12 -0
- package/dist/commands/run/RunCommand.d.ts +13 -0
- package/dist/commands/run/RunCommand.d.ts.map +1 -0
- package/dist/commands/run/RunCommand.js +15 -0
- package/dist/commands/run/RunCommand.js.map +1 -0
- package/dist/commands/run/impl/run.impl.d.ts +3 -0
- package/dist/commands/run/impl/run.impl.d.ts.map +1 -0
- package/dist/commands/run/impl/run.impl.js +73 -0
- package/dist/commands/run/impl/run.impl.js.map +1 -0
- package/dist/core/Banner.d.ts +2 -0
- package/dist/core/Banner.d.ts.map +1 -0
- package/dist/core/Banner.js +11 -0
- package/dist/core/Banner.js.map +1 -0
- package/dist/core/BaseCommand.d.ts +6 -0
- package/dist/core/BaseCommand.d.ts.map +1 -0
- package/dist/core/BaseCommand.js +3 -0
- package/dist/core/BaseCommand.js.map +1 -0
- package/dist/core/CLI.d.ts +23 -0
- package/dist/core/CLI.d.ts.map +1 -0
- package/dist/core/CLI.js +119 -0
- package/dist/core/CLI.js.map +1 -0
- package/dist/core/CommandRegistry.d.ts +13 -0
- package/dist/core/CommandRegistry.d.ts.map +1 -0
- package/dist/core/CommandRegistry.js +42 -0
- package/dist/core/CommandRegistry.js.map +1 -0
- package/dist/core/ConfigLoader.d.ts +5 -0
- package/dist/core/ConfigLoader.d.ts.map +1 -0
- package/dist/core/ConfigLoader.js +14 -0
- package/dist/core/ConfigLoader.js.map +1 -0
- package/dist/core/EventBus.d.ts +9 -0
- package/dist/core/EventBus.d.ts.map +1 -0
- package/dist/core/EventBus.js +33 -0
- package/dist/core/EventBus.js.map +1 -0
- package/dist/core/Loader.d.ts +36 -0
- package/dist/core/Loader.d.ts.map +1 -0
- package/dist/core/Loader.js +127 -0
- package/dist/core/Loader.js.map +1 -0
- package/dist/core/Logger.d.ts +18 -0
- package/dist/core/Logger.d.ts.map +1 -0
- package/dist/core/Logger.js +67 -0
- package/dist/core/Logger.js.map +1 -0
- package/dist/core/PluginManager.d.ts +13 -0
- package/dist/core/PluginManager.d.ts.map +1 -0
- package/dist/core/PluginManager.js +47 -0
- package/dist/core/PluginManager.js.map +1 -0
- package/dist/core/QuikError.d.ts +52 -0
- package/dist/core/QuikError.d.ts.map +1 -0
- package/dist/core/QuikError.js +75 -0
- package/dist/core/QuikError.js.map +1 -0
- package/dist/core/TemplateRenderer.d.ts +27 -0
- package/dist/core/TemplateRenderer.d.ts.map +1 -0
- package/dist/core/TemplateRenderer.js +38 -0
- package/dist/core/TemplateRenderer.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/PackageInstaller.d.ts +17 -0
- package/dist/utils/PackageInstaller.d.ts.map +1 -0
- package/dist/utils/PackageInstaller.js +100 -0
- package/dist/utils/PackageInstaller.js.map +1 -0
- package/package.json +46 -0
package/README.md
ADDED
|
Binary file
|
package/bin/quik.dev.ts
ADDED
package/bin/quik.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseCommand } from "../core/BaseCommand.js";
|
|
2
|
+
import type { CommandContext } from "../types/index.js";
|
|
3
|
+
export declare class VersionCommand extends BaseCommand {
|
|
4
|
+
readonly meta: {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
aliases: string[];
|
|
8
|
+
category: string;
|
|
9
|
+
};
|
|
10
|
+
execute(context: CommandContext): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=VersionCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VersionCommand.d.ts","sourceRoot":"","sources":["../../src/commands/VersionCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,qBAAa,cAAe,SAAQ,WAAW;IAC7C,QAAQ,CAAC,IAAI;;;;;MAKX;IAEF,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;CAGvC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseCommand } from "../core/BaseCommand.js";
|
|
2
|
+
export class VersionCommand extends BaseCommand {
|
|
3
|
+
meta = {
|
|
4
|
+
name: "version",
|
|
5
|
+
description: "Show version information",
|
|
6
|
+
aliases: ["v", "--version"],
|
|
7
|
+
category: "general",
|
|
8
|
+
};
|
|
9
|
+
execute(context) {
|
|
10
|
+
context.logger.info("quik-cli v1.0.0");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=VersionCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VersionCommand.js","sourceRoot":"","sources":["../../src/commands/VersionCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,MAAM,OAAO,cAAe,SAAQ,WAAW;IACpC,IAAI,GAAG;QACd,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,0BAA0B;QACvC,OAAO,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC;QAC3B,QAAQ,EAAE,SAAS;KACpB,CAAC;IAEF,OAAO,CAAC,OAAuB;QAC7B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseCommand } from "../../core/BaseCommand.js";
|
|
2
|
+
import type { CommandContext } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* `quik init` — interactively scaffolds a new quik project.
|
|
5
|
+
* Asks for project name, API key, and framework, then creates folder structure.
|
|
6
|
+
*/
|
|
7
|
+
export declare class InitCommand extends BaseCommand {
|
|
8
|
+
readonly meta: {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
args: string;
|
|
12
|
+
aliases: string[];
|
|
13
|
+
category: string;
|
|
14
|
+
options: {
|
|
15
|
+
flag: string;
|
|
16
|
+
description: string;
|
|
17
|
+
}[];
|
|
18
|
+
};
|
|
19
|
+
execute(context: CommandContext): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=InitCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InitCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/init/InitCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;GAGG;AACH,qBAAa,WAAY,SAAQ,WAAW;IAC1C,QAAQ,CAAC,IAAI;;;;;;;;;;MASX;IAEI,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAItD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BaseCommand } from "../../core/BaseCommand.js";
|
|
2
|
+
/**
|
|
3
|
+
* `quik init` — interactively scaffolds a new quik project.
|
|
4
|
+
* Asks for project name, API key, and framework, then creates folder structure.
|
|
5
|
+
*/
|
|
6
|
+
export class InitCommand extends BaseCommand {
|
|
7
|
+
meta = {
|
|
8
|
+
name: "init",
|
|
9
|
+
description: "interactively scaffold a new quik project",
|
|
10
|
+
args: "[project-name]",
|
|
11
|
+
aliases: ["i"],
|
|
12
|
+
category: "setup",
|
|
13
|
+
options: [
|
|
14
|
+
{ flag: "-y, --yes", description: "accept defaults without prompting" },
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
async execute(context) {
|
|
18
|
+
const { executeInit } = await import("./impl/init.impl.js");
|
|
19
|
+
await executeInit(context);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=InitCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InitCommand.js","sourceRoot":"","sources":["../../../src/commands/init/InitCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD;;;GAGG;AACH,MAAM,OAAO,WAAY,SAAQ,WAAW;IACjC,IAAI,GAAG;QACd,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,2CAA2C;QACxD,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,CAAC,GAAG,CAAC;QACd,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,mCAAmC,EAAE;SACxE;KACF,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,OAAuB;QACnC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAC5D,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astro.scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/impl/astro.scaffold.ts"],"names":[],"mappings":"AASA,UAAU,OAAO;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { join, dirname } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
4
|
+
import { renderToFile } from "../../../core/TemplateRenderer.js";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
const TEMPLATES_DIR = join(__dirname, "../templates");
|
|
8
|
+
export async function scaffoldAstro(projectPath, env) {
|
|
9
|
+
// Create .env from template
|
|
10
|
+
await renderToFile(join(TEMPLATES_DIR, "astro/env.template"), join(projectPath, ".env"), {
|
|
11
|
+
TENANT_SLUG: env.tenantSlug,
|
|
12
|
+
TENANT_API_KEY: env.tenantApiKey,
|
|
13
|
+
API_BASE_URL: env.apiBaseUrl,
|
|
14
|
+
SECRET_KEY: env.secretKey,
|
|
15
|
+
});
|
|
16
|
+
// Create src/pages/[...slug].astro
|
|
17
|
+
await mkdir(join(projectPath, "src/pages"), { recursive: true });
|
|
18
|
+
await renderToFile(join(TEMPLATES_DIR, "astro/page.template"), join(projectPath, "src/pages/[...slug].astro"), {});
|
|
19
|
+
// Create src/pages/api/[...path].ts
|
|
20
|
+
await mkdir(join(projectPath, "src/pages/api"), { recursive: true });
|
|
21
|
+
await renderToFile(join(TEMPLATES_DIR, "astro/api-proxy.template"), join(projectPath, "src/pages/api/[...path].ts"), {});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=astro.scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"astro.scaffold.js","sourceRoot":"","sources":["../../../../src/commands/init/impl/astro.scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAEjE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAStD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB,EACnB,GAAY;IAEZ,4BAA4B;IAC5B,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,oBAAoB,CAAC,EACzC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB;QACE,WAAW,EAAE,GAAG,CAAC,UAAU;QAC3B,cAAc,EAAE,GAAG,CAAC,YAAY;QAChC,YAAY,EAAE,GAAG,CAAC,UAAU;QAC5B,UAAU,EAAE,GAAG,CAAC,SAAS;KAC1B,CACF,CAAC;IAEF,mCAAmC;IACnC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjE,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,qBAAqB,CAAC,EAC1C,IAAI,CAAC,WAAW,EAAE,2BAA2B,CAAC,EAC9C,EAAE,CACH,CAAC;IAEF,oCAAoC;IACpC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAErE,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,0BAA0B,CAAC,EAC/C,IAAI,CAAC,WAAW,EAAE,4BAA4B,CAAC,EAC/C,EAAE,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.impl.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/impl/init.impl.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAyE9D,wBAAsB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkLxE"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import enquirer from "enquirer";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { writeFile, mkdir, rm, readFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { randomBytes } from "node:crypto";
|
|
6
|
+
import { QuikError, ErrorCode } from "../../../core/QuikError.js";
|
|
7
|
+
import { loader } from "../../../core/Loader.js";
|
|
8
|
+
import { installGitHubPackage } from "../../../utils/PackageInstaller.js";
|
|
9
|
+
import { scaffoldNextjs } from "./nextjs.scaffold.js";
|
|
10
|
+
import { scaffoldAstro } from "./astro.scaffold.js";
|
|
11
|
+
const { prompt } = enquirer;
|
|
12
|
+
const GITHUB_PACKAGE = `@quikcr/quik-engine`;
|
|
13
|
+
/**
|
|
14
|
+
* Generates a secret key for AES-256 encryption.
|
|
15
|
+
*/
|
|
16
|
+
function generateSecretKey() {
|
|
17
|
+
return randomBytes(32).toString("base64");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fetches a GitHub token from an external API using the user's API key.
|
|
21
|
+
*/
|
|
22
|
+
async function fetchGitHubToken(apiKey) {
|
|
23
|
+
let response;
|
|
24
|
+
try {
|
|
25
|
+
response = await fetch("http://localhost:3000/github-token", {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: { "Content-Type": "application/json" },
|
|
28
|
+
body: JSON.stringify({ apiKey }),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
throw new QuikError(ErrorCode.NET_001, "network", `Network error: Unable to reach token API`, { cause: err instanceof Error ? err.message : String(err) });
|
|
33
|
+
}
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
throw new QuikError(ErrorCode.NET_001, "network", `Failed to fetch GitHub token: ${response.statusText}`, { details: { status: response.status, apiKeyPrefix: apiKey.slice(0, 8) + "..." } });
|
|
36
|
+
}
|
|
37
|
+
const data = (await response.json());
|
|
38
|
+
return data.token;
|
|
39
|
+
}
|
|
40
|
+
function runNpmInstall(cwd) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
43
|
+
const child = spawn(npmCmd, ["install"], {
|
|
44
|
+
cwd,
|
|
45
|
+
stdio: "inherit",
|
|
46
|
+
shell: process.platform === "win32",
|
|
47
|
+
windowsHide: true,
|
|
48
|
+
});
|
|
49
|
+
child.on("error", (err) => reject(err));
|
|
50
|
+
child.on("close", (code) => {
|
|
51
|
+
if (code === 0)
|
|
52
|
+
resolve();
|
|
53
|
+
else
|
|
54
|
+
reject(new Error(`npm install exited with code ${code}`));
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
export async function executeInit(context) {
|
|
59
|
+
const useDefaults = Boolean(context.options.yes);
|
|
60
|
+
const projectNameArg = context.args[0];
|
|
61
|
+
// Determine if in-place mode (no project name given)
|
|
62
|
+
const inPlace = !projectNameArg;
|
|
63
|
+
// In-place mode requires cwd to already be a project with package.json
|
|
64
|
+
if (inPlace) {
|
|
65
|
+
try {
|
|
66
|
+
await readFile(join(context.cwd, "package.json"), "utf-8");
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
throw new QuikError(ErrorCode.INIT_001, "init", "No package.json found. Run 'quik init <project-name>' to create a new project.");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const answers = useDefaults
|
|
73
|
+
? {
|
|
74
|
+
projectName: projectNameArg ?? "my-quik-app",
|
|
75
|
+
tenantSlug: "",
|
|
76
|
+
tenantApiKey: "",
|
|
77
|
+
apiBaseUrl: "",
|
|
78
|
+
framework: "nextjs",
|
|
79
|
+
}
|
|
80
|
+
: await prompt([
|
|
81
|
+
...(inPlace
|
|
82
|
+
? []
|
|
83
|
+
: [
|
|
84
|
+
{
|
|
85
|
+
type: "input",
|
|
86
|
+
name: "projectName",
|
|
87
|
+
message: "What is your project name?",
|
|
88
|
+
initial: projectNameArg ?? "my-quik-app",
|
|
89
|
+
},
|
|
90
|
+
]),
|
|
91
|
+
{
|
|
92
|
+
type: "input",
|
|
93
|
+
name: "tenantSlug",
|
|
94
|
+
message: "Enter your tenant slug:",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "input",
|
|
98
|
+
name: "tenantApiKey",
|
|
99
|
+
message: "Enter your tenant API key:",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: "input",
|
|
103
|
+
name: "apiBaseUrl",
|
|
104
|
+
message: "Enter your API base URL:",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: "select",
|
|
108
|
+
name: "framework",
|
|
109
|
+
message: "Which framework are you using?",
|
|
110
|
+
choices: ["nextjs", "astro", "remix", "none"],
|
|
111
|
+
initial: 0,
|
|
112
|
+
},
|
|
113
|
+
]);
|
|
114
|
+
// Set projectName from answers or default for new project
|
|
115
|
+
const projectName = answers.projectName || "my-quik-app";
|
|
116
|
+
const projectPath = inPlace ? context.cwd : join(context.cwd, projectName);
|
|
117
|
+
// Create project folder only for new (non-in-place) projects
|
|
118
|
+
if (!inPlace) {
|
|
119
|
+
await mkdir(projectPath, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
const minDisplayMs = 1500;
|
|
122
|
+
const startTime = Date.now();
|
|
123
|
+
try {
|
|
124
|
+
loader.start("Creating project files", "creating");
|
|
125
|
+
const secretKey = generateSecretKey();
|
|
126
|
+
if (!inPlace) {
|
|
127
|
+
// Write package.json for new projects
|
|
128
|
+
const packageJson = {
|
|
129
|
+
name: projectName,
|
|
130
|
+
version: "0.1.0",
|
|
131
|
+
type: "module",
|
|
132
|
+
scripts: {
|
|
133
|
+
dev: "quik dev",
|
|
134
|
+
build: "quik build",
|
|
135
|
+
},
|
|
136
|
+
dependencies: {
|
|
137
|
+
[GITHUB_PACKAGE]: "^1.0.29",
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
await loader.stepFor("Configuring package.json", "creating");
|
|
141
|
+
await writeFile(join(projectPath, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
|
|
142
|
+
}
|
|
143
|
+
// Fetch GitHub token and install private package
|
|
144
|
+
await loader.stepFor("Authenticating with GitHub registry", "webrequest");
|
|
145
|
+
const githubToken = await fetchGitHubToken(answers.tenantApiKey);
|
|
146
|
+
await loader.stepFor("Installing quik-engine", "installing", 2000, () => installGitHubPackage("@quikcr/quik-engine", "1.0.29", githubToken, projectPath));
|
|
147
|
+
if (!inPlace) {
|
|
148
|
+
// Run npm install only for new projects (existing projects already have node_modules)
|
|
149
|
+
await loader.stepFor("Installing dependencies", "installing", 2000, () => runNpmInstall(projectPath));
|
|
150
|
+
}
|
|
151
|
+
// Framework-specific scaffolding
|
|
152
|
+
if (answers.framework === "nextjs") {
|
|
153
|
+
await loader.stepFor("Scaffolding Next.js files", "creating");
|
|
154
|
+
await scaffoldNextjs(projectPath, {
|
|
155
|
+
secretKey,
|
|
156
|
+
tenantSlug: answers.tenantSlug,
|
|
157
|
+
tenantApiKey: answers.tenantApiKey,
|
|
158
|
+
apiBaseUrl: answers.apiBaseUrl,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else if (answers.framework === "astro") {
|
|
162
|
+
await loader.stepFor("Scaffolding Astro files", "creating");
|
|
163
|
+
await scaffoldAstro(projectPath, {
|
|
164
|
+
secretKey,
|
|
165
|
+
tenantSlug: answers.tenantSlug,
|
|
166
|
+
tenantApiKey: answers.tenantApiKey,
|
|
167
|
+
apiBaseUrl: answers.apiBaseUrl,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// Ensure loader was visible for at least 1.5s
|
|
171
|
+
const elapsed = Date.now() - startTime;
|
|
172
|
+
if (elapsed < minDisplayMs) {
|
|
173
|
+
await new Promise((resolve) => setTimeout(resolve, minDisplayMs - elapsed));
|
|
174
|
+
}
|
|
175
|
+
if (inPlace) {
|
|
176
|
+
loader.done("Quik setup complete!");
|
|
177
|
+
context.logger.success(".env configured");
|
|
178
|
+
context.logger.success("Quik engine installed");
|
|
179
|
+
context.logger.info(`Framework: ${answers.framework}`);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
loader.done(`Project ${projectName} initialized successfully!`);
|
|
183
|
+
context.logger.success(`Created ${projectName}/`);
|
|
184
|
+
context.logger.success(`Created ${projectName}/.env`);
|
|
185
|
+
context.logger.success(`Created ${projectName}/.npmrc`);
|
|
186
|
+
context.logger.success(`Created ${projectName}/package.json`);
|
|
187
|
+
context.logger.info(`Framework: ${answers.framework}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (!inPlace) {
|
|
192
|
+
// Rollback: remove project folder on failure (only for new projects)
|
|
193
|
+
await loader.stepFor("Cleaning up...", "deleting", 2000, async () => {
|
|
194
|
+
await rm(projectPath, { recursive: true, force: true });
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
loader.fail("Failed to initialize project");
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=init.impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.impl.js","sourceRoot":"","sources":["../../../../src/commands/init/impl/init.impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface EnvVars {
|
|
2
|
+
secretKey: string;
|
|
3
|
+
tenantSlug: string;
|
|
4
|
+
tenantApiKey: string;
|
|
5
|
+
apiBaseUrl: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function scaffoldNextjs(projectPath: string, env: EnvVars): Promise<void>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=nextjs.scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.scaffold.d.ts","sourceRoot":"","sources":["../../../../src/commands/init/impl/nextjs.scaffold.ts"],"names":[],"mappings":"AASA,UAAU,OAAO;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { join, dirname } from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
4
|
+
import { renderToFile } from "../../../core/TemplateRenderer.js";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
const TEMPLATES_DIR = join(__dirname, "../templates");
|
|
8
|
+
export async function scaffoldNextjs(projectPath, env) {
|
|
9
|
+
// Create .env from template
|
|
10
|
+
await renderToFile(join(TEMPLATES_DIR, "nextjs/env.template"), join(projectPath, ".env"), {
|
|
11
|
+
TENANT_SLUG: env.tenantSlug,
|
|
12
|
+
TENANT_API_KEY: env.tenantApiKey,
|
|
13
|
+
API_BASE_URL: env.apiBaseUrl,
|
|
14
|
+
SECRET_KEY: env.secretKey,
|
|
15
|
+
});
|
|
16
|
+
// Create src/layout.tsx
|
|
17
|
+
await renderToFile(join(TEMPLATES_DIR, "nextjs/layout.template"), join(projectPath, "src/app/layout.tsx"), {});
|
|
18
|
+
// Create src/app/[...slug] directory
|
|
19
|
+
await mkdir(join(projectPath, "src/app/[...slug]"), { recursive: true });
|
|
20
|
+
// Create the catch-all page
|
|
21
|
+
await renderToFile(join(TEMPLATES_DIR, "nextjs/page.template"), join(projectPath, "src/app/[...slug]/page.tsx"), {});
|
|
22
|
+
// Create src/app/api/[...path] directory
|
|
23
|
+
await mkdir(join(projectPath, "src/app/api/[...path]"), { recursive: true });
|
|
24
|
+
// Create the API proxy route
|
|
25
|
+
await renderToFile(join(TEMPLATES_DIR, "nextjs/api-proxy.template"), join(projectPath, "src/app/api/[...path]/route.ts"), {});
|
|
26
|
+
// Create nextjs config
|
|
27
|
+
await renderToFile(join(TEMPLATES_DIR, "nextjs/config.template"), join(projectPath, "next.config.ts"), {});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=nextjs.scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.scaffold.js","sourceRoot":"","sources":["../../../../src/commands/init/impl/nextjs.scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAEjE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAStD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,GAAY;IAEZ,4BAA4B;IAC5B,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,qBAAqB,CAAC,EAC1C,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB;QACE,WAAW,EAAE,GAAG,CAAC,UAAU;QAC3B,cAAc,EAAE,GAAG,CAAC,YAAY;QAChC,YAAY,EAAE,GAAG,CAAC,UAAU;QAC5B,UAAU,EAAE,GAAG,CAAC,SAAS;KAC1B,CACF,CAAC;IAEF,wBAAwB;IACxB,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,wBAAwB,CAAC,EAC7C,IAAI,CAAC,WAAW,EAAE,oBAAoB,CAAC,EACvC,EAAE,CACH,CAAC;IAEF,qCAAqC;IACrC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzE,4BAA4B;IAC5B,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,sBAAsB,CAAC,EAC3C,IAAI,CAAC,WAAW,EAAE,4BAA4B,CAAC,EAC/C,EAAE,CACH,CAAC;IAEF,yCAAyC;IACzC,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7E,6BAA6B;IAC7B,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,2BAA2B,CAAC,EAChD,IAAI,CAAC,WAAW,EAAE,gCAAgC,CAAC,EACnD,EAAE,CACH,CAAC;IAEA,uBAAuB;IACzB,MAAM,YAAY,CAChB,IAAI,CAAC,aAAa,EAAE,wBAAwB,CAAC,EAC7C,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,EACnC,EAAE,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Host runtime configuration.
|
|
2
|
+
# Variables prefixed with NEXT_PUBLIC_ are exposed to the browser by Next.js;
|
|
3
|
+
# the package's `<QuikConfigProvider>` reads them on the client.
|
|
4
|
+
# Variables without the prefix are server-only — the proxy route reads
|
|
5
|
+
# `PROXY_ENCRYPTION_KEY` from this file.
|
|
6
|
+
|
|
7
|
+
# Tenant identity forwarded to the package's transport layer.
|
|
8
|
+
NEXT_PUBLIC_TENANT_SLUG={{TENANT_SLUG}}
|
|
9
|
+
NEXT_PUBLIC_TENANT_API_KEY={{TENANT_API_KEY}}
|
|
10
|
+
|
|
11
|
+
# Where the package's `apiFetch` sends requests. The host decides where
|
|
12
|
+
# to mount the package's API proxy (or whether to point at the backend
|
|
13
|
+
# directly). This value flows through `<QuikConfigProvider apiBaseUrl=...>`
|
|
14
|
+
# into `apiFetch`. The package's internal `QUIK_API_BASE_URL` constant
|
|
15
|
+
# (in `src/lib/transport/api-config.ts`) acts as a fallback if this is
|
|
16
|
+
# unset.
|
|
17
|
+
NEXT_PUBLIC_API_BASE_URL={{API_BASE_URL}}
|
|
18
|
+
|
|
19
|
+
# E2E encryption (AES-256-GCM). Both keys must hold the same 32-byte
|
|
20
|
+
# base64-encoded secret for the round-trip to work. With either key
|
|
21
|
+
# absent, requests pass through as plain JSON.
|
|
22
|
+
PROXY_ENCRYPTION_KEY={{SECRET_KEY}}
|
|
23
|
+
NEXT_PUBLIC_ENCRYPTION_KEY={{SECRET_KEY}}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { APIRoute } from 'astro';
|
|
2
|
+
import { createProxyHandler } from '@qwik/shared';
|
|
3
|
+
|
|
4
|
+
// BE server URL - server-side only, never reaches the browser
|
|
5
|
+
const BE_URL = import.meta.env.APP_BASE_URL || 'http://localhost:3001';
|
|
6
|
+
const ENCRYPTION_KEY = import.meta.env.PROXY_ENCRYPTION_KEY;
|
|
7
|
+
|
|
8
|
+
export const ALL: APIRoute = (ctx) => createProxyHandler({ baseUrl: BE_URL, encryptionKey: ENCRYPTION_KEY })(ctx.request, { path: ctx.params.path as string | string[] });
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Host runtime configuration.
|
|
2
|
+
# Variables prefixed with NEXT_PUBLIC_ are exposed to the browser by Next.js;
|
|
3
|
+
# the package's `<QuikConfigProvider>` reads them on the client.
|
|
4
|
+
# Variables without the prefix are server-only — the proxy route reads
|
|
5
|
+
# `PROXY_ENCRYPTION_KEY` from this file.
|
|
6
|
+
|
|
7
|
+
# Tenant identity forwarded to the package's transport layer.
|
|
8
|
+
NEXT_PUBLIC_TENANT_SLUG={{TENANT_SLUG}}
|
|
9
|
+
NEXT_PUBLIC_TENANT_API_KEY={{TENANT_API_KEY}}
|
|
10
|
+
|
|
11
|
+
# Where the package's `apiFetch` sends requests. The host decides where
|
|
12
|
+
# to mount the package's API proxy (or whether to point at the backend
|
|
13
|
+
# directly). This value flows through `<QuikConfigProvider apiBaseUrl=...>`
|
|
14
|
+
# into `apiFetch`. The package's internal `QUIK_API_BASE_URL` constant
|
|
15
|
+
# (in `src/lib/transport/api-config.ts`) acts as a fallback if this is
|
|
16
|
+
# unset.
|
|
17
|
+
NEXT_PUBLIC_API_BASE_URL={{API_BASE_URL}}
|
|
18
|
+
|
|
19
|
+
# E2E encryption (AES-256-GCM). Both keys must hold the same 32-byte
|
|
20
|
+
# base64-encoded secret for the round-trip to work. With either key
|
|
21
|
+
# absent, requests pass through as plain JSON.
|
|
22
|
+
PROXY_ENCRYPTION_KEY={{SECRET_KEY}}
|
|
23
|
+
NEXT_PUBLIC_ENCRYPTION_KEY={{SECRET_KEY}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Layout from '../../layouts/Layout.astro';
|
|
3
|
+
import QwikEngine from '@qwik/engine';
|
|
4
|
+
|
|
5
|
+
const { slug } = Astro.params;
|
|
6
|
+
const currentPath = `/admin/${slug || ''}`;
|
|
7
|
+
// Astro [...slug] gives us "erm/financial" as a string, split to get array
|
|
8
|
+
const slugArray = slug ? slug.split('/') : [];
|
|
9
|
+
const params = { slug: slugArray };
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<Layout>
|
|
13
|
+
<QwikEngine params={params} currentPath={currentPath} client:load />
|
|
14
|
+
</Layout>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createProxyHandler } from "@quikcr/quik-engine";
|
|
2
|
+
import type { NextRequest } from "next/server";
|
|
3
|
+
|
|
4
|
+
// The proxy's upstream backend URL is owned by the package —
|
|
5
|
+
// `createProxyHandler` reads it from the internal QUIK_BACKEND_API_URL
|
|
6
|
+
// constant. Hosts do not need to configure or pass it.
|
|
7
|
+
const ENCRYPTION_KEY = process.env.PROXY_ENCRYPTION_KEY;
|
|
8
|
+
|
|
9
|
+
const proxy = createProxyHandler({
|
|
10
|
+
encryptionKey: ENCRYPTION_KEY,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const handler = async (
|
|
14
|
+
req: NextRequest,
|
|
15
|
+
{ params }: { params: Promise<{ path: string[] }> },
|
|
16
|
+
) => {
|
|
17
|
+
const { path } = await params;
|
|
18
|
+
return proxy(req, { path });
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const GET = handler;
|
|
22
|
+
export const POST = handler;
|
|
23
|
+
export const PUT = handler;
|
|
24
|
+
export const PATCH = handler;
|
|
25
|
+
export const DELETE = handler;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { NextConfig } from "next";
|
|
2
|
+
|
|
3
|
+
const nextConfig: NextConfig = {
|
|
4
|
+
/* config options here */ images: {
|
|
5
|
+
remotePatterns: [
|
|
6
|
+
{
|
|
7
|
+
protocol: "https",
|
|
8
|
+
hostname: "images.unsplash.com",
|
|
9
|
+
pathname: "/**",
|
|
10
|
+
},
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default nextConfig;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Host runtime configuration.
|
|
2
|
+
# Variables prefixed with NEXT_PUBLIC_ are exposed to the browser by Next.js;
|
|
3
|
+
# the package's `<QuikConfigProvider>` reads them on the client.
|
|
4
|
+
# Variables without the prefix are server-only — the proxy route reads
|
|
5
|
+
# `PROXY_ENCRYPTION_KEY` from this file.
|
|
6
|
+
|
|
7
|
+
# Tenant identity forwarded to the package's transport layer.
|
|
8
|
+
NEXT_PUBLIC_TENANT_SLUG={{TENANT_SLUG}}
|
|
9
|
+
NEXT_PUBLIC_TENANT_API_KEY={{TENANT_API_KEY}}
|
|
10
|
+
|
|
11
|
+
# Where the package's `apiFetch` sends requests. The host decides where
|
|
12
|
+
# to mount the package's API proxy (or whether to point at the backend
|
|
13
|
+
# directly). This value flows through `<QuikConfigProvider apiBaseUrl=...>`
|
|
14
|
+
# into `apiFetch`. The package's internal `QUIK_API_BASE_URL` constant
|
|
15
|
+
# (in `src/lib/transport/api-config.ts`) acts as a fallback if this is
|
|
16
|
+
# unset.
|
|
17
|
+
NEXT_PUBLIC_API_BASE_URL={{API_BASE_URL}}
|
|
18
|
+
|
|
19
|
+
# E2E encryption (AES-256-GCM). Both keys must hold the same 32-byte
|
|
20
|
+
# base64-encoded secret for the round-trip to work. With either key
|
|
21
|
+
# absent, requests pass through as plain JSON.
|
|
22
|
+
PROXY_ENCRYPTION_KEY={{SECRET_KEY}}
|
|
23
|
+
NEXT_PUBLIC_ENCRYPTION_KEY={{SECRET_KEY}}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { QuikConfigProvider, QuikThemeConfig } from "@quikcr/quik-engine";
|
|
2
|
+
import type { Metadata } from "next";
|
|
3
|
+
import { Poppins } from "next/font/google";
|
|
4
|
+
import type * as React from "react";
|
|
5
|
+
import "@quikcr/quik-engine/styles.css";
|
|
6
|
+
// import "./globals.css";
|
|
7
|
+
|
|
8
|
+
const poppins = Poppins({
|
|
9
|
+
variable: "--font-poppins",
|
|
10
|
+
subsets: ["latin"],
|
|
11
|
+
display: "swap",
|
|
12
|
+
weight: ["400", "500", "600", "700"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "QuikEngine — The operating system for SaaS products",
|
|
17
|
+
description:
|
|
18
|
+
"QuikEngine is a self-contained Next.js 16+ package that powers CRM, HRMS, Accounting, ERP, and more — built as the foundation for your next SaaS product.",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The host application's root layout.
|
|
23
|
+
*
|
|
24
|
+
* Owns the <html>/<body> shell. The package's compiled stylesheet is
|
|
25
|
+
* imported via @import inside `app/globals.css` (first line) so the
|
|
26
|
+
* host's :root / .dark overrides win on cascade.
|
|
27
|
+
*
|
|
28
|
+
* `<QuikConfigProvider>` is the package's opt-in channel for host
|
|
29
|
+
* configuration. The demo forwards NEXT_PUBLIC_API_URL and
|
|
30
|
+
* NEXT_PUBLIC_API_KEY so any future console screen that calls the host
|
|
31
|
+
* API can read them through `useQuikConfig()`.
|
|
32
|
+
*
|
|
33
|
+
* `suppressHydrationWarning` silences the expected `next-themes` warning
|
|
34
|
+
* when the package flips the `dark` class on <html> after mount.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
const theme: QuikThemeConfig = {
|
|
38
|
+
primaryColor: "#50C878",
|
|
39
|
+
fontFamily: "geist-sans",
|
|
40
|
+
fontSize: 0.9,
|
|
41
|
+
borderRadius: 0.75,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default function RootLayout({
|
|
45
|
+
children,
|
|
46
|
+
}: {
|
|
47
|
+
children: React.ReactNode;
|
|
48
|
+
}) {
|
|
49
|
+
return (
|
|
50
|
+
<html
|
|
51
|
+
lang="en"
|
|
52
|
+
className={`${poppins.variable} h-full antialiased`}
|
|
53
|
+
suppressHydrationWarning
|
|
54
|
+
>
|
|
55
|
+
<body className="min-h-full bg-background font-sans text-foreground">
|
|
56
|
+
<QuikConfigProvider
|
|
57
|
+
tenantSlug={process.env.NEXT_PUBLIC_TENANT_SLUG ?? ""}
|
|
58
|
+
tenantApiKey={process.env.NEXT_PUBLIC_TENANT_API_KEY ?? ""}
|
|
59
|
+
apiBaseUrl={process.env.NEXT_PUBLIC_API_BASE_URL ?? ""}
|
|
60
|
+
theme={theme}
|
|
61
|
+
>
|
|
62
|
+
{children}
|
|
63
|
+
</QuikConfigProvider>
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
|
66
|
+
);
|
|
67
|
+
}
|