@reliverse/dler 1.7.50 → 1.7.52
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 +8 -8
- package/bin/app/build/ppb-utils.js +1 -1
- package/bin/app/pack/cmd.d.ts +30 -6
- package/bin/app/pack/cmd.js +299 -97
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-define.d.ts +14 -14
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-repair.js +1 -1
- package/bin/libs/cfg/cfg-impl/rse-config/rse-impl/rse-update.js +1 -1
- package/bin/libs/sdk/sdk-impl/config/info.js +1 -1
- package/bin/libs/sdk/sdk-impl/config/init.js +1 -1
- package/bin/libs/sdk/sdk-mod.d.ts +0 -4
- package/bin/libs/sdk/sdk-mod.js +0 -15
- package/package.json +4 -3
- package/bin/app/unpack/cmd.d.ts +0 -37
- package/bin/app/unpack/cmd.js +0 -200
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-constants.d.ts +0 -6
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-constants.js +0 -7
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-file-utils.d.ts +0 -5
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-file-utils.js +0 -40
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-types.d.ts +0 -24
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pu-types.js +0 -0
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pub-json-utils.d.ts +0 -17
- package/bin/libs/sdk/sdk-impl/utils/pack-unpack/pub-json-utils.js +0 -46
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
### ⚡ developer experience
|
|
18
18
|
|
|
19
19
|
- **performance optimized** for speed with modern build pipelines and caching
|
|
20
|
-
- **
|
|
20
|
+
- **16 built-in commands** — comprehensive [dler commands](#dler-commands) for every workflow
|
|
21
21
|
- **path resolution magic** converts typescript aliases to relative imports automatically
|
|
22
22
|
- **highly configurable** via dedicated configuration files with sensible defaults
|
|
23
23
|
- **dual interface** — cli for everyday use, sdk for advanced programmatic control
|
|
@@ -148,7 +148,7 @@ bun dev # bun src/cli.ts --dev
|
|
|
148
148
|
|
|
149
149
|
## dler commands
|
|
150
150
|
|
|
151
|
-
dler ships with a flexible command system (prev. plugins) and **
|
|
151
|
+
dler ships with a flexible command system (prev. plugins) and **16 built-in commands** (from [reliverse addons](https://reliverse.org/addons) collection).
|
|
152
152
|
|
|
153
153
|
feel free to create your own commands. commands can be implemented as built-in directly in `src/app/<command>/impl/*` and then imported from `src/app/<command>/cmd.ts`; or implemented in your own library and then imported from `src/app/<command>/cmd.ts`.
|
|
154
154
|
|
|
@@ -156,7 +156,7 @@ if you run just `dler` — it will display a list of commands which you can laun
|
|
|
156
156
|
|
|
157
157
|
## **available commands**
|
|
158
158
|
|
|
159
|
-
[build](#1-build) — [pub](#2-pub) — [agg](#3-agg) — [check](#4-check) — [conv](#5-conv) — [copy](#6-copy) — [init](#7-init) — [inject](#8-inject) — [libs](#9-libs) — [merge](#10-merge) — [migrate](#11-migrate) — [rempts](#12-rempts) — [rename](#13-rename) — [spell](#14-magic) — [split](#15-split) — [pack](#16-pack)
|
|
159
|
+
[build](#1-build) — [pub](#2-pub) — [agg](#3-agg) — [check](#4-check) — [conv](#5-conv) — [copy](#6-copy) — [init](#7-init) — [inject](#8-inject) — [libs](#9-libs) — [merge](#10-merge) — [migrate](#11-migrate) — [rempts](#12-rempts) — [rename](#13-rename) — [spell](#14-magic) — [split](#15-split) — [pack](#16-pack)
|
|
160
160
|
|
|
161
161
|
### 1. `build`
|
|
162
162
|
|
|
@@ -798,7 +798,7 @@ output/
|
|
|
798
798
|
└── mod.ts
|
|
799
799
|
```
|
|
800
800
|
|
|
801
|
-
|
|
801
|
+
**--unpack**:
|
|
802
802
|
|
|
803
803
|
creates file structure from packed templates. This command is the counterpart to `pack` and is used to extract and restore template files from a packed template package.
|
|
804
804
|
|
|
@@ -818,16 +818,16 @@ creates file structure from packed templates. This command is the counterpart to
|
|
|
818
818
|
|
|
819
819
|
```bash
|
|
820
820
|
# Basic usage
|
|
821
|
-
dler
|
|
821
|
+
dler pack ./dist-templates --output ./my-project --unpack
|
|
822
822
|
|
|
823
823
|
# With custom output directory
|
|
824
|
-
dler
|
|
824
|
+
dler pack ./dist-templates --output ./custom-location --unpack
|
|
825
825
|
|
|
826
826
|
# Preview changes without applying
|
|
827
|
-
dler
|
|
827
|
+
dler pack ./dist-templates --output ./my-project --dry-run --unpack
|
|
828
828
|
|
|
829
829
|
# Clean up existing template files before unpacking
|
|
830
|
-
dler
|
|
830
|
+
dler pack ./dist-templates --output ./my-project --cleanup --unpack
|
|
831
831
|
```
|
|
832
832
|
|
|
833
833
|
**arguments:**
|
|
@@ -35,7 +35,7 @@ async function isCommandInPackageJson(command) {
|
|
|
35
35
|
const packageName = COMMAND_TO_PACKAGE[command];
|
|
36
36
|
if (!packageName) return false;
|
|
37
37
|
return packageName in (packageJson.dependencies || {}) || packageName in (packageJson.devDependencies || {});
|
|
38
|
-
} catch (
|
|
38
|
+
} catch (_error) {
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
41
|
}
|
package/bin/app/pack/cmd.d.ts
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
|
+
interface FileMetadata {
|
|
2
|
+
updatedAt?: string;
|
|
3
|
+
updatedHash?: string;
|
|
4
|
+
}
|
|
5
|
+
interface TemplatesFileContent {
|
|
6
|
+
content: FileContent;
|
|
7
|
+
type: "text" | "json" | "binary";
|
|
8
|
+
hasError?: boolean;
|
|
9
|
+
error?: string;
|
|
10
|
+
jsonComments?: Record<number, string>;
|
|
11
|
+
binaryHash?: string;
|
|
12
|
+
metadata?: FileMetadata;
|
|
13
|
+
}
|
|
14
|
+
type FileContent = string | Record<string, unknown>;
|
|
15
|
+
/** Escape back-`s, ${ and newlines for safe template literal embedding */
|
|
16
|
+
export declare const escapeTemplateString: (str: string) => string;
|
|
17
|
+
export declare const unescapeTemplateString: (str: string) => string;
|
|
18
|
+
export declare const hashFile: (file: string) => Promise<string>;
|
|
19
|
+
export declare const getFileMetadata: (file: string) => Promise<FileMetadata>;
|
|
20
|
+
/** Recursively walk a directory */
|
|
21
|
+
export declare const walkDir: (dir: string) => Promise<string[]>;
|
|
22
|
+
/** Process a file and return the TemplatesFileContent structure */
|
|
23
|
+
export declare const readFileForTemplate: (absPath: string, relPath: string, binariesOutDir: string) => Promise<TemplatesFileContent>;
|
|
1
24
|
declare const _default: import("@reliverse/rempts").Command<{
|
|
2
|
-
|
|
25
|
+
input: {
|
|
3
26
|
type: "positional";
|
|
4
27
|
required: true;
|
|
5
28
|
description: string;
|
|
@@ -11,7 +34,7 @@ declare const _default: import("@reliverse/rempts").Command<{
|
|
|
11
34
|
};
|
|
12
35
|
whitelabel: {
|
|
13
36
|
type: "string";
|
|
14
|
-
default:
|
|
37
|
+
default: string;
|
|
15
38
|
description: string;
|
|
16
39
|
};
|
|
17
40
|
cdn: {
|
|
@@ -28,10 +51,6 @@ declare const _default: import("@reliverse/rempts").Command<{
|
|
|
28
51
|
default: true;
|
|
29
52
|
description: string;
|
|
30
53
|
};
|
|
31
|
-
/**
|
|
32
|
-
* - Without --files: All files are checked and updated if they're newer or have different content
|
|
33
|
-
* - With --files: Only specified files are checked and updated if they're newer or have different content
|
|
34
|
-
*/
|
|
35
54
|
files: {
|
|
36
55
|
type: "string";
|
|
37
56
|
description: string;
|
|
@@ -40,5 +59,10 @@ declare const _default: import("@reliverse/rempts").Command<{
|
|
|
40
59
|
type: "string";
|
|
41
60
|
description: string;
|
|
42
61
|
};
|
|
62
|
+
unpack: {
|
|
63
|
+
type: "boolean";
|
|
64
|
+
default: false;
|
|
65
|
+
description: string;
|
|
66
|
+
};
|
|
43
67
|
}>;
|
|
44
68
|
export default _default;
|
package/bin/app/pack/cmd.js
CHANGED
|
@@ -1,73 +1,283 @@
|
|
|
1
1
|
import path from "@reliverse/pathkit";
|
|
2
2
|
import { relinka } from "@reliverse/relinka";
|
|
3
|
-
import {
|
|
3
|
+
import { defineCommand, defineArgs } from "@reliverse/rempts";
|
|
4
4
|
import { createJiti } from "jiti";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const jiti = createJiti(import.meta.url);
|
|
19
|
-
const hashFile = async (file) => {
|
|
20
|
-
const buff = await fs.readFile(file);
|
|
21
|
-
return createHash("sha1").update(buff).digest("hex").slice(0, 10);
|
|
6
|
+
import fs from "node:fs/promises";
|
|
7
|
+
import stripJsonComments from "strip-json-comments";
|
|
8
|
+
import { isBinaryExt } from "../../libs/sdk/sdk-impl/utils/binary.js";
|
|
9
|
+
const WHITELABEL_DEFAULT = "DLER";
|
|
10
|
+
const TEMPLATE_VAR = (name, whitelabel) => `${whitelabel}_TPL_${name.toUpperCase()}`;
|
|
11
|
+
const TPLS_DIR = "templates";
|
|
12
|
+
const BINARIES_DIR = "binaries";
|
|
13
|
+
export const escapeTemplateString = (str) => str.replace(/`/g, "\\`").replace(/\\\${/g, "\\u0024{").replace(/\$\{/g, "\\${").replace(/\\\{\{/g, "{{").replace(/\\\}\}/g, "}}").replace(/\r?\n/g, "\\n");
|
|
14
|
+
export const unescapeTemplateString = (str) => str.replace(/\\n/g, "\n").replace(/\\u0024\{/g, "\\${").replace(/\\\\`/g, "`").replace(/\\\\/g, "\\");
|
|
15
|
+
export const hashFile = async (file) => {
|
|
16
|
+
const buf = await fs.readFile(file);
|
|
17
|
+
return createHash("sha1").update(buf).digest("hex").slice(0, 10);
|
|
22
18
|
};
|
|
23
|
-
const getFileMetadata = async (file) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
export const getFileMetadata = async (file) => {
|
|
20
|
+
try {
|
|
21
|
+
const [stats, hash] = await Promise.all([fs.stat(file), hashFile(file)]);
|
|
22
|
+
return {
|
|
23
|
+
updatedAt: stats.mtime.toISOString(),
|
|
24
|
+
updatedHash: hash
|
|
25
|
+
};
|
|
26
|
+
} catch (err) {
|
|
27
|
+
relinka("warn", `Failed to get metadata for ${file}: ${err.message}`);
|
|
28
|
+
return {
|
|
29
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30
|
+
updatedHash: ""
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export const walkDir = async (dir) => {
|
|
35
|
+
let res = [];
|
|
36
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
const full = path.join(dir, entry.name);
|
|
39
|
+
if (entry.isDirectory()) {
|
|
40
|
+
res = res.concat(await walkDir(full));
|
|
41
|
+
} else {
|
|
42
|
+
res.push(full);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return res;
|
|
46
|
+
};
|
|
47
|
+
export const readFileForTemplate = async (absPath, relPath, binariesOutDir) => {
|
|
48
|
+
const metadata = await getFileMetadata(absPath);
|
|
49
|
+
try {
|
|
50
|
+
if (await isBinaryExt(absPath)) {
|
|
51
|
+
const hash = metadata.updatedHash;
|
|
52
|
+
const ext2 = path.extname(absPath);
|
|
53
|
+
const target = path.join(binariesOutDir, `${hash}${ext2}`);
|
|
54
|
+
try {
|
|
55
|
+
await fs.mkdir(binariesOutDir, { recursive: true });
|
|
56
|
+
await fs.copyFile(absPath, target).catch(async (err) => {
|
|
57
|
+
if (err.code !== "EEXIST") throw err;
|
|
58
|
+
});
|
|
59
|
+
} catch (err) {
|
|
60
|
+
relinka("error", `Failed copying binary ${relPath}: ${err.message}`);
|
|
61
|
+
return {
|
|
62
|
+
content: "",
|
|
63
|
+
type: "binary",
|
|
64
|
+
hasError: true,
|
|
65
|
+
error: err.message,
|
|
66
|
+
binaryHash: hash,
|
|
67
|
+
metadata
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
content: "",
|
|
72
|
+
type: "binary",
|
|
73
|
+
binaryHash: hash,
|
|
74
|
+
metadata
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const raw = await fs.readFile(absPath, "utf8");
|
|
78
|
+
const ext = path.extname(absPath).toLowerCase();
|
|
79
|
+
if (ext === ".json") {
|
|
80
|
+
const comments = {};
|
|
81
|
+
const lines = raw.split(/\r?\n/);
|
|
82
|
+
lines.forEach((line, idx) => {
|
|
83
|
+
const trimmed = line.trim();
|
|
84
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("/*")) comments[idx + 1] = line;
|
|
85
|
+
});
|
|
86
|
+
try {
|
|
87
|
+
const parsed = JSON.parse(stripJsonComments(raw));
|
|
88
|
+
return {
|
|
89
|
+
content: parsed,
|
|
90
|
+
type: "json",
|
|
91
|
+
jsonComments: Object.keys(comments).length ? comments : void 0,
|
|
92
|
+
metadata
|
|
93
|
+
};
|
|
94
|
+
} catch (err) {
|
|
95
|
+
relinka("warn", `Failed to parse JSON file ${relPath}: ${err.message}`);
|
|
96
|
+
return {
|
|
97
|
+
content: {},
|
|
98
|
+
type: "json",
|
|
99
|
+
hasError: true,
|
|
100
|
+
error: err.message,
|
|
101
|
+
jsonComments: Object.keys(comments).length ? comments : void 0,
|
|
102
|
+
metadata
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
content: raw,
|
|
108
|
+
type: "text",
|
|
109
|
+
metadata
|
|
110
|
+
};
|
|
111
|
+
} catch (err) {
|
|
112
|
+
relinka("warn", `Failed to read file ${relPath}: ${err.message}`);
|
|
113
|
+
return {
|
|
114
|
+
content: "",
|
|
115
|
+
type: "text",
|
|
116
|
+
hasError: true,
|
|
117
|
+
error: err.message,
|
|
118
|
+
metadata
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const findTemplatesObject = (mod) => {
|
|
123
|
+
if (mod.DLER_TEMPLATES && typeof mod.DLER_TEMPLATES === "object") {
|
|
124
|
+
return mod.DLER_TEMPLATES;
|
|
125
|
+
}
|
|
126
|
+
if (mod.default && typeof mod.default === "object") {
|
|
127
|
+
return mod.default;
|
|
128
|
+
}
|
|
129
|
+
for (const v of Object.values(mod)) {
|
|
130
|
+
if (v && typeof v === "object" && Object.values(v).every((t) => t && typeof t === "object" && "config" in t)) {
|
|
131
|
+
return v;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {};
|
|
135
|
+
};
|
|
136
|
+
const restoreFile = async (outRoot, relPath, meta, binsDir, force = false) => {
|
|
137
|
+
const dest = path.join(outRoot, relPath);
|
|
138
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
139
|
+
try {
|
|
140
|
+
if (!force) {
|
|
141
|
+
await fs.access(dest);
|
|
142
|
+
relinka("log", `Skipping existing file (use --force to overwrite): ${relPath}`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
}
|
|
147
|
+
if (meta.type === "binary") {
|
|
148
|
+
const ext = path.extname(relPath);
|
|
149
|
+
const src = path.join(binsDir, `${meta.binaryHash}${ext}`);
|
|
150
|
+
try {
|
|
151
|
+
await fs.copyFile(src, dest);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
relinka("error", `Missing binary ${src} for ${relPath}: ${err.message}`);
|
|
154
|
+
}
|
|
155
|
+
} else if (meta.type === "json") {
|
|
156
|
+
const jsonStr = JSON.stringify(meta.content, null, 2);
|
|
157
|
+
await fs.writeFile(dest, jsonStr, "utf8");
|
|
158
|
+
} else {
|
|
159
|
+
await fs.writeFile(dest, meta.content, "utf8");
|
|
160
|
+
}
|
|
161
|
+
if (meta.metadata?.updatedAt) {
|
|
162
|
+
const ts = new Date(meta.metadata.updatedAt);
|
|
163
|
+
await fs.utimes(dest, ts, ts);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const unpackTemplates = async (aggregatorPath, outDir, force = false) => {
|
|
167
|
+
const jiti = createJiti(process.cwd());
|
|
168
|
+
let mod;
|
|
169
|
+
try {
|
|
170
|
+
mod = await jiti.import(aggregatorPath);
|
|
171
|
+
} catch (err) {
|
|
172
|
+
throw new Error(`Failed to import aggregator file: ${err.message}`);
|
|
173
|
+
}
|
|
174
|
+
const templatesObj = findTemplatesObject(mod);
|
|
175
|
+
if (!Object.keys(templatesObj).length) {
|
|
176
|
+
throw new Error("No templates found in aggregator file.");
|
|
177
|
+
}
|
|
178
|
+
const binsDir = path.join(path.dirname(aggregatorPath), TPLS_DIR, BINARIES_DIR);
|
|
179
|
+
let unpackedFiles = 0;
|
|
180
|
+
for (const [tplName, tpl] of Object.entries(templatesObj)) {
|
|
181
|
+
relinka("info", `Unpacking template: ${tplName}`);
|
|
182
|
+
for (const [relPath, meta] of Object.entries(tpl.config.files)) {
|
|
183
|
+
try {
|
|
184
|
+
await restoreFile(outDir, relPath, meta, binsDir, force);
|
|
185
|
+
unpackedFiles++;
|
|
186
|
+
} catch (err) {
|
|
187
|
+
relinka("error", `Failed restoring ${relPath}: ${err.message}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
relinka("success", `Unpacked ${unpackedFiles} files into ${outDir}`);
|
|
192
|
+
};
|
|
193
|
+
const writeTypesFile = async (outRoot, outputName) => {
|
|
194
|
+
const typesFile = path.join(outRoot, `${outputName}-types.ts`);
|
|
195
|
+
const code = `// Auto-generated type declarations for templates.
|
|
196
|
+
export interface FileMetadata { updatedAt?: string; updatedHash?: string; }
|
|
197
|
+
export interface TemplatesFileContent { content: string | Record<string, unknown>; type: 'text' | 'json' | 'binary'; hasError?: boolean; error?: string; jsonComments?: Record<number, string>; binaryHash?: string; metadata?: FileMetadata; }
|
|
198
|
+
export interface Template { name: string; description: string; config: { files: Record<string, TemplatesFileContent> }; updatedAt?: string; }
|
|
199
|
+
`;
|
|
200
|
+
await fs.writeFile(typesFile, code, "utf8");
|
|
30
201
|
};
|
|
31
202
|
export default defineCommand({
|
|
32
203
|
meta: {
|
|
33
204
|
name: "pack",
|
|
34
|
-
version: "1.
|
|
35
|
-
description: "
|
|
205
|
+
version: "1.2.0",
|
|
206
|
+
description: "Pack templates into TS modules or --unpack them back to files"
|
|
36
207
|
},
|
|
37
208
|
args: defineArgs({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
209
|
+
input: {
|
|
210
|
+
type: "positional",
|
|
211
|
+
required: true,
|
|
212
|
+
description: "Input directory (pack) or aggregator file (unpack)"
|
|
213
|
+
},
|
|
214
|
+
output: {
|
|
215
|
+
type: "string",
|
|
216
|
+
default: "my-templates",
|
|
217
|
+
description: "Output dir"
|
|
218
|
+
},
|
|
219
|
+
whitelabel: {
|
|
220
|
+
type: "string",
|
|
221
|
+
default: WHITELABEL_DEFAULT,
|
|
222
|
+
description: "Rename DLER"
|
|
223
|
+
},
|
|
41
224
|
cdn: {
|
|
42
225
|
type: "string",
|
|
43
226
|
description: "Remote CDN for binary assets upload (not yet implemented)"
|
|
44
227
|
},
|
|
45
|
-
force: {
|
|
228
|
+
force: {
|
|
229
|
+
type: "boolean",
|
|
230
|
+
default: false,
|
|
231
|
+
description: "Force overwrite existing files"
|
|
232
|
+
},
|
|
46
233
|
update: {
|
|
47
234
|
type: "boolean",
|
|
48
235
|
default: true,
|
|
49
|
-
description: "Update existing templates and add new ones
|
|
236
|
+
description: "Update existing templates and add new ones (pack mode only)"
|
|
50
237
|
},
|
|
51
|
-
/**
|
|
52
|
-
* - Without --files: All files are checked and updated if they're newer or have different content
|
|
53
|
-
* - With --files: Only specified files are checked and updated if they're newer or have different content
|
|
54
|
-
*/
|
|
55
238
|
files: {
|
|
56
239
|
type: "string",
|
|
57
|
-
description: "Comma-separated list of specific files to update
|
|
240
|
+
description: "Comma-separated list of specific files to update"
|
|
58
241
|
},
|
|
59
242
|
lastUpdate: {
|
|
60
243
|
type: "string",
|
|
61
|
-
description: "Override lastUpdate timestamp (
|
|
244
|
+
description: "Override lastUpdate timestamp (pack mode only)"
|
|
245
|
+
},
|
|
246
|
+
unpack: {
|
|
247
|
+
type: "boolean",
|
|
248
|
+
default: false,
|
|
249
|
+
description: "Unpack templates from an aggregator file"
|
|
62
250
|
}
|
|
63
251
|
}),
|
|
64
252
|
async run({ args }) {
|
|
65
253
|
if (args.cdn) throw new Error("Remote CDN support is not implemented yet.");
|
|
66
|
-
|
|
254
|
+
if (args.unpack) {
|
|
255
|
+
const aggrPath = path.resolve(args.input);
|
|
256
|
+
const outDir2 = path.resolve(args.output);
|
|
257
|
+
try {
|
|
258
|
+
const stat = await fs.stat(aggrPath);
|
|
259
|
+
if (!stat.isFile() || !aggrPath.endsWith(".ts")) {
|
|
260
|
+
throw new Error("Input for --unpack must be a TypeScript aggregator file (*.ts)");
|
|
261
|
+
}
|
|
262
|
+
} catch (err) {
|
|
263
|
+
relinka("error", err.message);
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
relinka("info", `Unpacking templates from ${aggrPath} to ${outDir2}`);
|
|
267
|
+
try {
|
|
268
|
+
await unpackTemplates(aggrPath, outDir2, args.force);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
relinka("error", err.message);
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const dirToProcess = path.resolve(args.input);
|
|
67
276
|
const outDir = path.resolve(args.output);
|
|
68
277
|
const outDirName = path.basename(outDir);
|
|
69
278
|
const typesFile = `${outDirName}-types.ts`;
|
|
70
279
|
const modFile = `${outDirName}-mod.ts`;
|
|
280
|
+
relinka("info", `Packing templates from ${dirToProcess} to ${outDir}`);
|
|
71
281
|
const filesToUpdate = args.files ? new Set(args.files.split(",").map((f) => f.trim())) : null;
|
|
72
282
|
let existingTemplates = {};
|
|
73
283
|
try {
|
|
@@ -84,6 +294,7 @@ export default defineCommand({
|
|
|
84
294
|
if (args.update) {
|
|
85
295
|
try {
|
|
86
296
|
const modPath = path.join(outDir, modFile);
|
|
297
|
+
const jiti = createJiti(process.cwd());
|
|
87
298
|
const mod2 = await jiti.import(modPath);
|
|
88
299
|
existingTemplates = mod2?.DLER_TEMPLATES || mod2?.default || {};
|
|
89
300
|
} catch (loadError) {
|
|
@@ -105,36 +316,13 @@ export default defineCommand({
|
|
|
105
316
|
try {
|
|
106
317
|
await fs.access(path.join(outDir, typesFile));
|
|
107
318
|
} catch {
|
|
108
|
-
|
|
109
|
-
export interface FileMetadata {
|
|
110
|
-
updatedAt?: string;
|
|
111
|
-
updatedHash?: string;
|
|
112
|
-
}
|
|
113
|
-
export interface TemplatesFileContent {
|
|
114
|
-
content: FileContent;
|
|
115
|
-
type: "text" | "json" | "binary";
|
|
116
|
-
hasError?: boolean;
|
|
117
|
-
jsonComments?: Record<number, string>;
|
|
118
|
-
binaryHash?: string;
|
|
119
|
-
metadata?: FileMetadata;
|
|
120
|
-
}
|
|
121
|
-
export interface TemplateConfig {
|
|
122
|
-
files: Record<string, TemplatesFileContent>;
|
|
123
|
-
}
|
|
124
|
-
export interface Template {
|
|
125
|
-
name: string;
|
|
126
|
-
description: string;
|
|
127
|
-
config: TemplateConfig;
|
|
128
|
-
updatedAt?: string;
|
|
129
|
-
}
|
|
130
|
-
export interface Templates extends Record<string, Template> {}
|
|
131
|
-
`;
|
|
132
|
-
await fs.writeFile(path.join(outDir, typesFile), typesContent);
|
|
319
|
+
await writeTypesFile(outDir, outDirName);
|
|
133
320
|
}
|
|
134
321
|
const aggregatedImports = [];
|
|
135
322
|
const aggregatedEntries = [];
|
|
136
323
|
const mapEntries = [];
|
|
137
324
|
for (const tplName of templateDirs) {
|
|
325
|
+
relinka("info", `Processing template: ${tplName}`);
|
|
138
326
|
const absTplDir = path.join(dirToProcess, tplName);
|
|
139
327
|
const allFiles = await walkDir(absTplDir);
|
|
140
328
|
const filesRecord = {};
|
|
@@ -151,11 +339,15 @@ export interface Templates extends Record<string, Template> {}
|
|
|
151
339
|
const fileMetadata = await getFileMetadata(absFile);
|
|
152
340
|
const existingFile = existingFiles[rel];
|
|
153
341
|
const existingMetadata = existingFile?.metadata;
|
|
154
|
-
if (existingMetadata && (existingMetadata.updatedHash === fileMetadata.updatedHash || fileMetadata.updatedAt <= existingMetadata.updatedAt)) {
|
|
342
|
+
if (existingMetadata?.updatedHash && fileMetadata.updatedHash && (existingMetadata.updatedHash === fileMetadata.updatedHash || fileMetadata.updatedAt && existingMetadata.updatedAt && fileMetadata.updatedAt <= existingMetadata.updatedAt)) {
|
|
155
343
|
filesRecord[rel] = existingFile;
|
|
156
344
|
continue;
|
|
157
345
|
}
|
|
158
|
-
const meta = await readFileForTemplate(
|
|
346
|
+
const meta = await readFileForTemplate(
|
|
347
|
+
absFile,
|
|
348
|
+
rel,
|
|
349
|
+
path.join(outDir, TPLS_DIR, BINARIES_DIR)
|
|
350
|
+
);
|
|
159
351
|
if (meta.type === "binary") {
|
|
160
352
|
const hash = await hashFile(absFile);
|
|
161
353
|
const ext = path.extname(absFile);
|
|
@@ -176,12 +368,6 @@ export interface Templates extends Record<string, Template> {}
|
|
|
176
368
|
continue;
|
|
177
369
|
}
|
|
178
370
|
if (meta.type === "json") {
|
|
179
|
-
if (rel.endsWith("package.json")) {
|
|
180
|
-
meta.content.__satisfies = "PackageJson";
|
|
181
|
-
}
|
|
182
|
-
if (rel.endsWith("tsconfig.json")) {
|
|
183
|
-
meta.content.__satisfies = "TSConfig";
|
|
184
|
-
}
|
|
185
371
|
}
|
|
186
372
|
filesRecord[rel] = {
|
|
187
373
|
...meta,
|
|
@@ -190,10 +376,11 @@ export interface Templates extends Record<string, Template> {}
|
|
|
190
376
|
}
|
|
191
377
|
const varName = TEMPLATE_VAR(tplName, args.whitelabel);
|
|
192
378
|
const code = [];
|
|
193
|
-
const hasPackageJson = Object.values(filesRecord).some(
|
|
379
|
+
const hasPackageJson = Object.keys(filesRecord).some((rel) => rel.endsWith("package.json")) || Object.values(filesRecord).some(
|
|
194
380
|
(f) => f.type === "json" && f.content && typeof f.content === "object" && "name" in f.content
|
|
195
381
|
);
|
|
196
|
-
const
|
|
382
|
+
const tsconfigPathRe = /(?:^|\/)tsconfig(?:\.[^/]+)?\.json$/;
|
|
383
|
+
const hasTSConfig = Object.keys(filesRecord).some((rel) => tsconfigPathRe.test(rel)) || Object.values(filesRecord).some(
|
|
197
384
|
(f) => f.type === "json" && f.content && typeof f.content === "object" && "compilerOptions" in f.content
|
|
198
385
|
);
|
|
199
386
|
if (hasPackageJson || hasTSConfig) {
|
|
@@ -219,7 +406,7 @@ export interface Templates extends Record<string, Template> {}
|
|
|
219
406
|
if (meta.jsonComments)
|
|
220
407
|
code.push(` jsonComments: ${JSON.stringify(meta.jsonComments, null, 2)},`);
|
|
221
408
|
if (meta.metadata) {
|
|
222
|
-
const metadataStr = JSON.stringify(meta.metadata, null, 2).replace(/^/gm, " ").replace(/^ {7} {/m, " {").replace(/^ {8}}/m, " }").replace(/"([a-zA-Z0-9_]+)":/g, "$1:").replace(/}$/m, "},");
|
|
409
|
+
const metadataStr = JSON.stringify(meta.metadata, null, 2).replace(/^/gm, " ").replace(/^ {7} {/m, " {").replace(/^ {8}}/m, " }").replace(/"([a-zA-Z0-9_]+)":/g, "$1:").replace(/\n(\s*)}/, ",\n$1}").replace(/}$/m, "},");
|
|
223
410
|
code.push(` metadata:${metadataStr}`);
|
|
224
411
|
}
|
|
225
412
|
if (meta.type === "binary") {
|
|
@@ -230,31 +417,33 @@ export interface Templates extends Record<string, Template> {}
|
|
|
230
417
|
code.push(` content: \`${escapeTemplateString(meta.content)}\`,`);
|
|
231
418
|
code.push(' type: "text",');
|
|
232
419
|
} else {
|
|
233
|
-
|
|
420
|
+
let clone;
|
|
234
421
|
let sat = "";
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
422
|
+
try {
|
|
423
|
+
clone = JSON.parse(JSON.stringify(meta.content));
|
|
424
|
+
if (rel.endsWith("package.json")) {
|
|
425
|
+
sat = " satisfies PackageJson";
|
|
426
|
+
} else if (tsconfigPathRe.test(rel)) {
|
|
427
|
+
sat = " satisfies TSConfig";
|
|
428
|
+
}
|
|
429
|
+
} catch (error) {
|
|
430
|
+
clone = {};
|
|
431
|
+
relinka("error", `Failed to process JSON content for ${rel}: ${error}`);
|
|
239
432
|
}
|
|
240
|
-
const jsonStr = JSON.stringify(
|
|
241
|
-
clone,
|
|
242
|
-
(key, value) => {
|
|
243
|
-
if (typeof key === "string" && /^[a-zA-Z0-9_]+$/.test(key)) {
|
|
244
|
-
return value;
|
|
245
|
-
}
|
|
246
|
-
return value;
|
|
247
|
-
},
|
|
248
|
-
2
|
|
249
|
-
).split("\n").map((line, i) => {
|
|
433
|
+
const jsonStr = JSON.stringify(clone, null, 2).split("\n").map((line, i) => {
|
|
250
434
|
if (i === 0) return line;
|
|
251
|
-
return
|
|
252
|
-
}).join("\n").replace(
|
|
435
|
+
return ` ${line.replace(/"([a-zA-Z0-9_]+)":/g, "$1:")}`;
|
|
436
|
+
}).join("\n").replace(/\n(\s*)}/, ",\n$1}").replace(/,\s*,/g, ",");
|
|
253
437
|
code.push(` content: ${jsonStr}${sat},`);
|
|
254
438
|
code.push(' type: "json",');
|
|
255
439
|
}
|
|
256
|
-
if (meta.hasError)
|
|
257
|
-
|
|
440
|
+
if (meta.hasError) {
|
|
441
|
+
code.push(" hasError: true,");
|
|
442
|
+
if (meta.error) {
|
|
443
|
+
code.push(` error: "${escapeTemplateString(meta.error)}",`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
code.push(` }${isLast ? "" : ","}`);
|
|
258
447
|
});
|
|
259
448
|
code.push(" },");
|
|
260
449
|
code.push(" },");
|
|
@@ -281,6 +470,13 @@ export interface Templates extends Record<string, Template> {}
|
|
|
281
470
|
} else if (!args.update) {
|
|
282
471
|
relinka("log", `Creating template: ${tplName}`);
|
|
283
472
|
}
|
|
473
|
+
const filesWithErrors = Object.entries(filesRecord).filter(([_, meta]) => meta.hasError);
|
|
474
|
+
if (filesWithErrors.length > 0) {
|
|
475
|
+
relinka("warn", `Template ${tplName} has files with errors:`);
|
|
476
|
+
for (const [file, meta] of filesWithErrors) {
|
|
477
|
+
relinka("warn", ` - ${file}: ${meta.error || "Unknown error"}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
284
480
|
await fs.writeFile(templatePath, code.join("\n"));
|
|
285
481
|
aggregatedImports.push(`import { ${varName} } from "./${TPLS_DIR}/${tplName}";`);
|
|
286
482
|
aggregatedEntries.push(` ${tplName}: ${varName},`);
|
|
@@ -294,11 +490,11 @@ export interface Templates extends Record<string, Template> {}
|
|
|
294
490
|
...aggregatedEntries,
|
|
295
491
|
"};",
|
|
296
492
|
"",
|
|
297
|
-
`export const ${WL}_TEMPLATES = ${WL}_TEMPLATES_OBJ
|
|
493
|
+
`export const ${WL}_TEMPLATES = ${WL}_TEMPLATES_OBJ;`,
|
|
298
494
|
"",
|
|
299
|
-
`export
|
|
495
|
+
`export type ${WL}_TEMPLATE_NAMES = keyof typeof ${WL}_TEMPLATES;`,
|
|
300
496
|
"",
|
|
301
|
-
`export const
|
|
497
|
+
`export const ${WL.toLowerCase()}TemplatesMap: Record<string, ${WL}_TEMPLATE_NAMES> = {`,
|
|
302
498
|
...mapEntries,
|
|
303
499
|
"};"
|
|
304
500
|
];
|
|
@@ -306,9 +502,15 @@ export interface Templates extends Record<string, Template> {}
|
|
|
306
502
|
const templatePaths = templateDirs.map(
|
|
307
503
|
(tpl) => path.relative(process.cwd(), path.join(outDir, TPLS_DIR, `${tpl}.ts`))
|
|
308
504
|
);
|
|
309
|
-
relinka("
|
|
505
|
+
relinka("success", `Packed ${templateDirs.length} templates into ${modFile}:`);
|
|
310
506
|
for (const p of templatePaths) {
|
|
311
507
|
relinka("log", `- ${p}`);
|
|
312
508
|
}
|
|
509
|
+
const binaryCount = Object.values(existingTemplates).reduce((count, template) => {
|
|
510
|
+
return count + Object.values(template.config.files).filter((file) => file.type === "binary").length;
|
|
511
|
+
}, 0);
|
|
512
|
+
if (binaryCount > 0) {
|
|
513
|
+
relinka("info", ` - ${TPLS_DIR}/${BINARIES_DIR}/* (${binaryCount} binary files)`);
|
|
514
|
+
}
|
|
313
515
|
}
|
|
314
516
|
});
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { RseConfig } from "./rse-types";
|
|
2
2
|
export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
3
|
-
version?: string | undefined;
|
|
4
3
|
$schema?: "./schema.json" | "https://reliverse.org/schema.json" | undefined;
|
|
5
4
|
projectName?: string | undefined;
|
|
6
5
|
projectAuthor?: string | undefined;
|
|
7
6
|
projectDescription?: string | undefined;
|
|
7
|
+
version?: string | undefined;
|
|
8
8
|
projectLicense?: string | undefined;
|
|
9
9
|
projectRepository?: string | undefined;
|
|
10
10
|
projectDomain?: string | undefined;
|
|
11
11
|
projectGitService?: "none" | "github" | "gitlab" | "bitbucket" | undefined;
|
|
12
12
|
projectDeployService?: "none" | "vercel" | "netlify" | "railway" | "deno" | undefined;
|
|
13
|
-
projectPackageManager?: "
|
|
14
|
-
projectState?: "
|
|
15
|
-
projectCategory?: "cli" | "unknown" | "
|
|
13
|
+
projectPackageManager?: "npm" | "pnpm" | "bun" | "yarn" | undefined;
|
|
14
|
+
projectState?: "creating" | "created" | undefined;
|
|
15
|
+
projectCategory?: "cli" | "unknown" | "website" | "vscode" | "browser" | "library" | "mobile" | undefined;
|
|
16
16
|
projectSubcategory?: "unknown" | "e-commerce" | "tool" | undefined;
|
|
17
|
-
projectFramework?: "rempts" | "npm-jsr" | "unknown" | "
|
|
17
|
+
projectFramework?: "rempts" | "npm-jsr" | "unknown" | "vscode" | "nextjs" | "vite" | "svelte" | "remix" | "astro" | "nuxt" | "solid" | "qwik" | "vue" | "wxt" | "lynx" | "react-native" | "expo" | "capacitor" | "ionic" | "electron" | "tauri" | "neutralino" | "citty" | "commander" | "cac" | "meow" | "yargs" | "webextension" | "browser-extension" | undefined;
|
|
18
18
|
projectTemplate?: "unknown" | "blefnk/relivator-nextjs-template" | "blefnk/relivator-docker-template" | "blefnk/next-react-ts-src-minimal" | "blefnk/all-in-one-nextjs-template" | "blefnk/create-t3-app" | "blefnk/create-next-app" | "blefnk/astro-starlight-template" | "blefnk/versator-nextjs-template" | "blefnk/relivator-lynxjs-template" | "blefnk/relivator-react-native-template" | "reliverse/template-browser-extension" | "microsoft/vscode-extension-samples" | "microsoft/vscode-extension-template" | "rsetarter-template" | "blefnk/deno-cli-tutorial" | undefined;
|
|
19
19
|
projectTemplateDate?: string | undefined;
|
|
20
20
|
features?: {
|
|
@@ -38,15 +38,15 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
38
38
|
analytics?: "unknown" | "vercel" | undefined;
|
|
39
39
|
authentication?: "unknown" | "better-auth" | "clerk" | "next-auth" | "supabase-auth" | "auth0" | undefined;
|
|
40
40
|
api?: "rest" | "unknown" | "hono" | "trpc" | "graphql" | undefined;
|
|
41
|
-
testing?: "
|
|
41
|
+
testing?: "unknown" | "bun" | "vitest" | "jest" | "playwright" | "cypress" | undefined;
|
|
42
42
|
stateManagement?: "unknown" | "zustand" | "jotai" | "redux-toolkit" | undefined;
|
|
43
43
|
formManagement?: "unknown" | "react-hook-form" | "formik" | undefined;
|
|
44
|
-
styling?: "unknown" | "
|
|
44
|
+
styling?: "unknown" | "tailwind" | "styled-components" | "css-modules" | "sass" | undefined;
|
|
45
45
|
uiComponents?: "unknown" | "shadcn-ui" | "chakra-ui" | "material-ui" | undefined;
|
|
46
46
|
databaseLibrary?: "unknown" | "drizzle" | "prisma" | "supabase" | undefined;
|
|
47
|
-
databaseProvider?: "
|
|
48
|
-
linting?: "
|
|
49
|
-
formatting?: "
|
|
47
|
+
databaseProvider?: "sqlite" | "unknown" | "pg" | "mysql" | "mongodb" | undefined;
|
|
48
|
+
linting?: "unknown" | "eslint" | undefined;
|
|
49
|
+
formatting?: "unknown" | "biome" | undefined;
|
|
50
50
|
payment?: "unknown" | "stripe" | undefined;
|
|
51
51
|
monitoring?: "unknown" | "sentry" | undefined;
|
|
52
52
|
logging?: "unknown" | "axiom" | undefined;
|
|
@@ -75,7 +75,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
75
75
|
indentStyle?: "space" | "tab" | undefined;
|
|
76
76
|
quoteMark?: "single" | "double" | undefined;
|
|
77
77
|
semicolons?: boolean | undefined;
|
|
78
|
-
trailingComma?: "
|
|
78
|
+
trailingComma?: "none" | "es5" | "all" | undefined;
|
|
79
79
|
bracketSpacing?: boolean | undefined;
|
|
80
80
|
arrowParens?: "always" | "avoid" | undefined;
|
|
81
81
|
tabWidth?: number | undefined;
|
|
@@ -83,7 +83,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
83
83
|
dontRemoveComments?: boolean | undefined;
|
|
84
84
|
shouldAddComments?: boolean | undefined;
|
|
85
85
|
typeOrInterface?: "type" | "interface" | "mixed" | undefined;
|
|
86
|
-
importOrRequire?: "
|
|
86
|
+
importOrRequire?: "mixed" | "import" | "require" | undefined;
|
|
87
87
|
cjsToEsm?: boolean | undefined;
|
|
88
88
|
modernize?: {
|
|
89
89
|
replaceFs?: boolean | undefined;
|
|
@@ -96,7 +96,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
96
96
|
importSymbol?: string | undefined;
|
|
97
97
|
} | undefined;
|
|
98
98
|
monorepo?: {
|
|
99
|
-
type?: "
|
|
99
|
+
type?: "none" | "turborepo" | "nx" | "pnpm" | "bun" | undefined;
|
|
100
100
|
packages?: string[] | undefined;
|
|
101
101
|
sharedPackages?: string[] | undefined;
|
|
102
102
|
} | undefined;
|
|
@@ -113,7 +113,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
|
|
|
113
113
|
repoBranch?: string | undefined;
|
|
114
114
|
repoPrivacy?: "unknown" | "public" | "private" | undefined;
|
|
115
115
|
projectArchitecture?: "unknown" | "fullstack" | "separated" | undefined;
|
|
116
|
-
projectRuntime?: "bun" | "
|
|
116
|
+
projectRuntime?: "bun" | "deno" | "node" | undefined;
|
|
117
117
|
skipPromptsUseAutoBehavior?: boolean | undefined;
|
|
118
118
|
deployBehavior?: "prompt" | "autoYes" | "autoNo" | undefined;
|
|
119
119
|
depsBehavior?: "prompt" | "autoYes" | "autoNo" | undefined;
|
|
@@ -10,7 +10,7 @@ import { getBackupAndTempPaths } from "./rse-utils.js";
|
|
|
10
10
|
function deepMerge(target, source) {
|
|
11
11
|
const result = { ...target };
|
|
12
12
|
for (const key in source) {
|
|
13
|
-
if (!Object.
|
|
13
|
+
if (!Object.hasOwn(source, key)) continue;
|
|
14
14
|
const sourceValue = source[key];
|
|
15
15
|
const targetValue = target[key];
|
|
16
16
|
if (sourceValue !== void 0) {
|
|
@@ -9,7 +9,7 @@ export async function ensureDlerConfig(isDev) {
|
|
|
9
9
|
const configExists = await fs.pathExists(configPath);
|
|
10
10
|
if (configExists) return;
|
|
11
11
|
try {
|
|
12
|
-
let pkgDescription
|
|
12
|
+
let pkgDescription;
|
|
13
13
|
try {
|
|
14
14
|
const pkg = await readPackageJSON();
|
|
15
15
|
if (pkg && typeof pkg.description === "string" && pkg.description.trim()) {
|
|
@@ -75,10 +75,6 @@ export type { CommentStyle, FileExtension, CommentMapping } from "./sdk-impl/uti
|
|
|
75
75
|
export { DEFAULT_COMMENT, COMMENT_MAP, getCommentPrefix } from "./sdk-impl/utils/comments.js";
|
|
76
76
|
export { detectFileType, detectBufferType, detectStreamType, isBinary, getMimeType, } from "./sdk-impl/utils/file-type.js";
|
|
77
77
|
export { finalizeBuild, finalizePub } from "./sdk-impl/utils/finalize.js";
|
|
78
|
-
export { WHITELABEL_DEFAULT, JSON_EXTS, TEMPLATE_VAR, TPLS_DIR, BINARIES_DIR, isJsonExt, } from "./sdk-impl/utils/pack-unpack/pu-constants.js";
|
|
79
|
-
export { walkDir, detectFileTypePU, readFileForTemplate, escapeTemplateString, } from "./sdk-impl/utils/pack-unpack/pu-file-utils.js";
|
|
80
|
-
export type { FileContent, FileType, FileMetadata, TemplatesFileContent, TemplateConfig, Template, Templates, } from "./sdk-impl/utils/pack-unpack/pu-types.js";
|
|
81
|
-
export { extractJsonComments, stripComments } from "./sdk-impl/utils/pack-unpack/pub-json-utils.js";
|
|
82
78
|
export { resolveCrossLibs, resolveAllCrossLibs } from "./sdk-impl/utils/resolve-cross-libs.js";
|
|
83
79
|
export { useAggregator } from "./sdk-impl/utils/tools-agg.js";
|
|
84
80
|
export { printUsage } from "./sdk-impl/utils/tools-impl.js";
|
package/bin/libs/sdk/sdk-mod.js
CHANGED
|
@@ -164,21 +164,6 @@ export {
|
|
|
164
164
|
getMimeType
|
|
165
165
|
} from "./sdk-impl/utils/file-type.js";
|
|
166
166
|
export { finalizeBuild, finalizePub } from "./sdk-impl/utils/finalize.js";
|
|
167
|
-
export {
|
|
168
|
-
WHITELABEL_DEFAULT,
|
|
169
|
-
JSON_EXTS,
|
|
170
|
-
TEMPLATE_VAR,
|
|
171
|
-
TPLS_DIR,
|
|
172
|
-
BINARIES_DIR,
|
|
173
|
-
isJsonExt
|
|
174
|
-
} from "./sdk-impl/utils/pack-unpack/pu-constants.js";
|
|
175
|
-
export {
|
|
176
|
-
walkDir,
|
|
177
|
-
detectFileTypePU,
|
|
178
|
-
readFileForTemplate,
|
|
179
|
-
escapeTemplateString
|
|
180
|
-
} from "./sdk-impl/utils/pack-unpack/pu-file-utils.js";
|
|
181
|
-
export { extractJsonComments, stripComments } from "./sdk-impl/utils/pack-unpack/pub-json-utils.js";
|
|
182
167
|
export { resolveCrossLibs, resolveAllCrossLibs } from "./sdk-impl/utils/resolve-cross-libs.js";
|
|
183
168
|
export { useAggregator } from "./sdk-impl/utils/tools-agg.js";
|
|
184
169
|
export { printUsage } from "./sdk-impl/utils/tools-impl.js";
|
package/package.json
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"@reliverse/rempts": "^1.7.28",
|
|
10
10
|
"@reliverse/runtime": "^1.0.3",
|
|
11
11
|
"@rollup/plugin-alias": "^5.1.1",
|
|
12
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
12
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
13
13
|
"@rollup/plugin-json": "^6.1.0",
|
|
14
14
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
15
15
|
"@rollup/plugin-replace": "^6.0.2",
|
|
16
|
-
"@rollup/pluginutils": "^5.
|
|
16
|
+
"@rollup/pluginutils": "^5.2.0",
|
|
17
17
|
"@sinclair/typebox": "^0.34.35",
|
|
18
18
|
"autoprefixer": "^10.4.21",
|
|
19
19
|
"c12": "^3.0.4",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"rollup-plugin-dts": "^6.2.1",
|
|
45
45
|
"scule": "^1.3.0",
|
|
46
46
|
"semver": "^7.7.2",
|
|
47
|
+
"strip-json-comments": "^5.0.2",
|
|
47
48
|
"tinyglobby": "^0.2.14",
|
|
48
49
|
"ts-morph": "^26.0.0",
|
|
49
50
|
"untyped": "^2.0.0"
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"license": "MIT",
|
|
54
55
|
"name": "@reliverse/dler",
|
|
55
56
|
"type": "module",
|
|
56
|
-
"version": "1.7.
|
|
57
|
+
"version": "1.7.52",
|
|
57
58
|
"keywords": [
|
|
58
59
|
"reliverse",
|
|
59
60
|
"cli",
|
package/bin/app/unpack/cmd.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
declare const _default: import("@reliverse/rempts").Command<{
|
|
2
|
-
templatesDir: {
|
|
3
|
-
type: "positional";
|
|
4
|
-
required: true;
|
|
5
|
-
description: string;
|
|
6
|
-
};
|
|
7
|
-
output: {
|
|
8
|
-
type: "string";
|
|
9
|
-
default: string;
|
|
10
|
-
description: string;
|
|
11
|
-
};
|
|
12
|
-
cdn: {
|
|
13
|
-
type: "string";
|
|
14
|
-
description: string;
|
|
15
|
-
};
|
|
16
|
-
deleteTemplates: {
|
|
17
|
-
type: "boolean";
|
|
18
|
-
description: string;
|
|
19
|
-
default: false;
|
|
20
|
-
};
|
|
21
|
-
"dry-run": {
|
|
22
|
-
type: "boolean";
|
|
23
|
-
description: string;
|
|
24
|
-
default: false;
|
|
25
|
-
};
|
|
26
|
-
force: {
|
|
27
|
-
type: "boolean";
|
|
28
|
-
description: string;
|
|
29
|
-
default: false;
|
|
30
|
-
};
|
|
31
|
-
cleanup: {
|
|
32
|
-
type: "boolean";
|
|
33
|
-
description: string;
|
|
34
|
-
default: false;
|
|
35
|
-
};
|
|
36
|
-
}>;
|
|
37
|
-
export default _default;
|
package/bin/app/unpack/cmd.js
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import path from "@reliverse/pathkit";
|
|
2
|
-
import { relinka } from "@reliverse/relinka";
|
|
3
|
-
import { defineArgs, defineCommand } from "@reliverse/rempts";
|
|
4
|
-
import { createJiti } from "jiti";
|
|
5
|
-
import { promises as fs } from "node:fs";
|
|
6
|
-
import { TPLS_DIR, BINARIES_DIR } from "../../libs/sdk/sdk-impl/utils/pack-unpack/pu-constants.js";
|
|
7
|
-
const jiti = createJiti(import.meta.url);
|
|
8
|
-
async function removeEmptyDirs(dirPath) {
|
|
9
|
-
if (!await fs.access(dirPath).then(() => true).catch(() => false))
|
|
10
|
-
return;
|
|
11
|
-
const entries = await fs.readdir(dirPath);
|
|
12
|
-
if (entries.length === 0) {
|
|
13
|
-
await fs.rmdir(dirPath);
|
|
14
|
-
const parentDir = path.dirname(dirPath);
|
|
15
|
-
if (parentDir !== dirPath) {
|
|
16
|
-
await removeEmptyDirs(parentDir);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
async function deleteTemplates(templatesDir, templatesDirName, dryRun) {
|
|
21
|
-
const modFile = `${templatesDirName}-mod.ts`;
|
|
22
|
-
const typesFile = `${templatesDirName}-types.ts`;
|
|
23
|
-
const implDir = path.join(templatesDir, TPLS_DIR);
|
|
24
|
-
const binariesDir = path.join(implDir, BINARIES_DIR);
|
|
25
|
-
const filesToRemove = [path.join(templatesDir, modFile), path.join(templatesDir, typesFile)];
|
|
26
|
-
try {
|
|
27
|
-
const templateFiles = await fs.readdir(implDir);
|
|
28
|
-
for (const file of templateFiles) {
|
|
29
|
-
if (file.endsWith(".ts")) {
|
|
30
|
-
filesToRemove.push(path.join(implDir, file));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
} catch (error) {
|
|
34
|
-
if (error.code !== "ENOENT") {
|
|
35
|
-
throw error;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
for (const file of filesToRemove) {
|
|
39
|
-
if (dryRun) {
|
|
40
|
-
relinka("log", `[DRY RUN] Would remove: ${file}`);
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
try {
|
|
44
|
-
await fs.unlink(file);
|
|
45
|
-
relinka("log", `Removed: ${file}`);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
if (error.code !== "ENOENT") {
|
|
48
|
-
relinka("warn", `Failed to remove ${file}: ${error.message}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
if (await fs.access(binariesDir).then(() => true).catch(() => false)) {
|
|
54
|
-
if (dryRun) {
|
|
55
|
-
relinka("log", `[DRY RUN] Would remove directory: ${binariesDir}`);
|
|
56
|
-
} else {
|
|
57
|
-
await fs.rm(binariesDir, { recursive: true });
|
|
58
|
-
relinka("log", `Removed directory: ${binariesDir}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
} catch (error) {
|
|
62
|
-
relinka("warn", `Failed to remove binaries directory: ${error.message}`);
|
|
63
|
-
}
|
|
64
|
-
await removeEmptyDirs(implDir);
|
|
65
|
-
await removeEmptyDirs(templatesDir);
|
|
66
|
-
}
|
|
67
|
-
export default defineCommand({
|
|
68
|
-
meta: {
|
|
69
|
-
name: "unpack",
|
|
70
|
-
version: "1.1.0",
|
|
71
|
-
description: "Creates file structure from packed templates"
|
|
72
|
-
},
|
|
73
|
-
args: defineArgs({
|
|
74
|
-
templatesDir: { type: "positional", required: true, description: "Dir containing *-mod.ts" },
|
|
75
|
-
output: { type: "string", default: "unpacked", description: "Where to write files" },
|
|
76
|
-
cdn: {
|
|
77
|
-
type: "string",
|
|
78
|
-
description: "Remote CDN base for binary assets download (not yet implemented)"
|
|
79
|
-
},
|
|
80
|
-
deleteTemplates: {
|
|
81
|
-
type: "boolean",
|
|
82
|
-
description: "Delete template implementation files (*-mod.ts, *-types.ts, etc.)",
|
|
83
|
-
default: false
|
|
84
|
-
},
|
|
85
|
-
"dry-run": {
|
|
86
|
-
type: "boolean",
|
|
87
|
-
description: "Preview changes without applying them",
|
|
88
|
-
default: false
|
|
89
|
-
},
|
|
90
|
-
force: {
|
|
91
|
-
type: "boolean",
|
|
92
|
-
description: "Force overwrite existing files",
|
|
93
|
-
default: false
|
|
94
|
-
},
|
|
95
|
-
cleanup: {
|
|
96
|
-
type: "boolean",
|
|
97
|
-
description: "Delete output directory before unpacking",
|
|
98
|
-
default: false
|
|
99
|
-
}
|
|
100
|
-
}),
|
|
101
|
-
async run({ args }) {
|
|
102
|
-
if (args.cdn) throw new Error("Remote CDN support is not implemented yet.");
|
|
103
|
-
const templatesDir = path.resolve(args.templatesDir);
|
|
104
|
-
const templatesDirName = path.basename(templatesDir);
|
|
105
|
-
const modFile = `${templatesDirName}-mod.ts`;
|
|
106
|
-
const modPath = path.join(templatesDir, modFile);
|
|
107
|
-
if (args.deleteTemplates) {
|
|
108
|
-
await deleteTemplates(templatesDir, templatesDirName, args["dry-run"]);
|
|
109
|
-
if (args["dry-run"]) {
|
|
110
|
-
relinka("log", "[DRY RUN] Templates deletion completed");
|
|
111
|
-
} else {
|
|
112
|
-
relinka("log", "Templates deletion completed");
|
|
113
|
-
}
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
if (args.cleanup) {
|
|
117
|
-
try {
|
|
118
|
-
await fs.rm(args.output, { recursive: true, force: true });
|
|
119
|
-
await fs.mkdir(args.output, { recursive: true });
|
|
120
|
-
relinka("log", `Cleaned output directory: ${args.output}`);
|
|
121
|
-
} catch (error) {
|
|
122
|
-
if (error.code !== "ENOENT") {
|
|
123
|
-
throw error;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
const mod = await jiti.import(modPath);
|
|
128
|
-
const templatesObj = mod?.DLER_TEMPLATES || mod?.default || (() => {
|
|
129
|
-
throw new Error(`Invalid ${modFile}`);
|
|
130
|
-
})();
|
|
131
|
-
for (const tpl of Object.values(templatesObj)) {
|
|
132
|
-
await restoreTemplate(tpl, templatesDir, args.output, args.force);
|
|
133
|
-
}
|
|
134
|
-
const relativeOutput = path.relative(process.cwd(), args.output);
|
|
135
|
-
relinka(
|
|
136
|
-
"log",
|
|
137
|
-
`Unpacked ${Object.keys(templatesObj).length} templates from ${modFile} into ${relativeOutput}${args.force ? " (--force is true, dir was overwritten)" : ""}`
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
const restoreTemplate = async (tpl, templatesRoot, outRoot, force) => {
|
|
142
|
-
const existingFiles = [];
|
|
143
|
-
for (const [rel, meta] of Object.entries(tpl.config.files)) {
|
|
144
|
-
const destAbs = path.join(outRoot, rel);
|
|
145
|
-
if (!force) {
|
|
146
|
-
try {
|
|
147
|
-
await fs.access(destAbs);
|
|
148
|
-
existingFiles.push(rel);
|
|
149
|
-
continue;
|
|
150
|
-
} catch {
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
await fs.mkdir(path.dirname(destAbs), { recursive: true });
|
|
154
|
-
switch (meta.type) {
|
|
155
|
-
case "binary": {
|
|
156
|
-
if (!meta.binaryHash) {
|
|
157
|
-
await fs.writeFile(destAbs, "");
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
|
-
const ext = path.extname(rel);
|
|
161
|
-
const binPath = path.join(
|
|
162
|
-
templatesRoot,
|
|
163
|
-
TPLS_DIR,
|
|
164
|
-
BINARIES_DIR,
|
|
165
|
-
`${meta.binaryHash}${ext}`
|
|
166
|
-
);
|
|
167
|
-
await fs.copyFile(binPath, destAbs);
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
case "text": {
|
|
171
|
-
await fs.writeFile(destAbs, meta.content, "utf8");
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
case "json": {
|
|
175
|
-
const txt = JSON.stringify(meta.content, null, 2);
|
|
176
|
-
const withComments = meta.jsonComments ? injectComments(txt, meta.jsonComments) : txt;
|
|
177
|
-
await fs.writeFile(destAbs, withComments, "utf8");
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
if (existingFiles.length > 0) {
|
|
183
|
-
throw new Error(
|
|
184
|
-
`Cannot unpack: ${existingFiles.length} file(s) already exist. Use --force to overwrite existing files`
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
};
|
|
188
|
-
const injectComments = (json, comments) => {
|
|
189
|
-
const lines = json.split("\n");
|
|
190
|
-
const entries = Object.entries(comments).map(([k, v]) => [Number(k), v]).sort((a, b) => a[0] - b[0]);
|
|
191
|
-
let offset = 0;
|
|
192
|
-
for (const [ln, comment] of entries) {
|
|
193
|
-
const idx = ln - 1 + offset;
|
|
194
|
-
const indent = lines[idx]?.match(/^\s*/)?.[0] ?? "";
|
|
195
|
-
const block = comment.split("\n").map((l) => indent + l);
|
|
196
|
-
lines.splice(idx, 0, ...block);
|
|
197
|
-
offset += block.length;
|
|
198
|
-
}
|
|
199
|
-
return lines.join("\n") + "\n";
|
|
200
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare const WHITELABEL_DEFAULT = "DLER";
|
|
2
|
-
export declare const JSON_EXTS: Set<string>;
|
|
3
|
-
export declare const TEMPLATE_VAR: (tpl: string, wl: string) => string;
|
|
4
|
-
export declare const TPLS_DIR = "tpls";
|
|
5
|
-
export declare const BINARIES_DIR = "binaries";
|
|
6
|
-
export declare const isJsonExt: (f: string) => boolean;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import path from "@reliverse/pathkit";
|
|
2
|
-
export const WHITELABEL_DEFAULT = "DLER";
|
|
3
|
-
export const JSON_EXTS = /* @__PURE__ */ new Set(["json", "jsonc", "json5", "jsonl"]);
|
|
4
|
-
export const TEMPLATE_VAR = (tpl, wl) => `${tpl.toUpperCase()}_${wl.toUpperCase()}_TEMPLATE`;
|
|
5
|
-
export const TPLS_DIR = "tpls";
|
|
6
|
-
export const BINARIES_DIR = "binaries";
|
|
7
|
-
export const isJsonExt = (f) => JSON_EXTS.has(path.extname(f).slice(1).toLowerCase());
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { FileType, TemplatesFileContent } from "./pu-types";
|
|
2
|
-
export declare const walkDir: (dir: string) => Promise<string[]>;
|
|
3
|
-
export declare const detectFileTypePU: (file: string) => Promise<FileType>;
|
|
4
|
-
export declare const readFileForTemplate: (absPath: string) => Promise<TemplatesFileContent>;
|
|
5
|
-
export declare const escapeTemplateString: (src: string) => string;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import path from "@reliverse/pathkit";
|
|
2
|
-
import { promises as fs } from "node:fs";
|
|
3
|
-
import { isBinaryExt } from "../binary.js";
|
|
4
|
-
import { isJsonExt } from "./pu-constants.js";
|
|
5
|
-
import { extractJsonComments, stripComments } from "./pub-json-utils.js";
|
|
6
|
-
export const walkDir = async (dir) => {
|
|
7
|
-
const entries = [];
|
|
8
|
-
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
|
|
9
|
-
const full = path.join(dir, entry.name);
|
|
10
|
-
if (entry.isDirectory()) {
|
|
11
|
-
entries.push(...await walkDir(full));
|
|
12
|
-
} else {
|
|
13
|
-
entries.push(full);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return entries;
|
|
17
|
-
};
|
|
18
|
-
export const detectFileTypePU = async (file) => {
|
|
19
|
-
if (await isBinaryExt(file)) return "binary";
|
|
20
|
-
if (isJsonExt(file)) return "json";
|
|
21
|
-
return "text";
|
|
22
|
-
};
|
|
23
|
-
export const readFileForTemplate = async (absPath) => {
|
|
24
|
-
const type = await detectFileTypePU(absPath);
|
|
25
|
-
try {
|
|
26
|
-
if (type === "binary") {
|
|
27
|
-
return { type, content: "" };
|
|
28
|
-
}
|
|
29
|
-
const data = await fs.readFile(absPath, "utf8");
|
|
30
|
-
if (type === "json") {
|
|
31
|
-
const jsonComments = extractJsonComments(data);
|
|
32
|
-
const json = JSON.parse(stripComments(data));
|
|
33
|
-
return { type, content: json, jsonComments };
|
|
34
|
-
}
|
|
35
|
-
return { type, content: data };
|
|
36
|
-
} catch {
|
|
37
|
-
return { type, content: "", hasError: true };
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
export const escapeTemplateString = (src) => src.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type FileContent = string | Record<string, unknown>;
|
|
2
|
-
export type FileType = "text" | "json" | "binary";
|
|
3
|
-
export interface FileMetadata {
|
|
4
|
-
updatedAt: string;
|
|
5
|
-
updatedHash: string;
|
|
6
|
-
}
|
|
7
|
-
export interface TemplatesFileContent {
|
|
8
|
-
content: FileContent;
|
|
9
|
-
type: FileType;
|
|
10
|
-
hasError?: boolean;
|
|
11
|
-
jsonComments?: Record<number, string>;
|
|
12
|
-
binaryHash?: string;
|
|
13
|
-
metadata?: FileMetadata;
|
|
14
|
-
}
|
|
15
|
-
export interface TemplateConfig {
|
|
16
|
-
files: Record<string, TemplatesFileContent>;
|
|
17
|
-
}
|
|
18
|
-
export interface Template {
|
|
19
|
-
name: string;
|
|
20
|
-
description: string;
|
|
21
|
-
config: TemplateConfig;
|
|
22
|
-
updatedAt: string;
|
|
23
|
-
}
|
|
24
|
-
export type Templates = Record<string, Template>;
|
|
File without changes
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helpers for reading / writing JSON-with-comments files while
|
|
3
|
-
* preserving (or later reinjecting) on–line and block comments.
|
|
4
|
-
*
|
|
5
|
-
* Supported comment styles:
|
|
6
|
-
* // single-line
|
|
7
|
-
* /* … *\/
|
|
8
|
-
* /** … *\/
|
|
9
|
-
*/
|
|
10
|
-
export declare const extractJsonComments: (raw: string) => Record<number, string> | undefined;
|
|
11
|
-
/**
|
|
12
|
-
* Very small "strip comments" helper:
|
|
13
|
-
* removes // … and /* … *\/ (including multi-line).
|
|
14
|
-
* This is intentionally simple; for complex JSONC we may want
|
|
15
|
-
* use something like `strip-json-comments` in the future.
|
|
16
|
-
*/
|
|
17
|
-
export declare const stripComments: (raw: string) => string;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export const extractJsonComments = (raw) => {
|
|
2
|
-
const out = {};
|
|
3
|
-
const lines = raw.split("\n");
|
|
4
|
-
for (let i = 0; i < lines.length; ) {
|
|
5
|
-
const line = lines[i];
|
|
6
|
-
if (!line) {
|
|
7
|
-
i += 1;
|
|
8
|
-
continue;
|
|
9
|
-
}
|
|
10
|
-
const trimmed = line.trimStart();
|
|
11
|
-
const indent = line.length - trimmed.length;
|
|
12
|
-
if (trimmed.startsWith("//")) {
|
|
13
|
-
out[i + 1] = trimmed.slice(2).trimStart();
|
|
14
|
-
i += 1;
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
if (trimmed.startsWith("/*")) {
|
|
18
|
-
const isSupported = trimmed.startsWith("/**") || trimmed.startsWith("/*");
|
|
19
|
-
if (!isSupported) {
|
|
20
|
-
i += 1;
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
const buff = [trimmed];
|
|
24
|
-
let j = i + 1;
|
|
25
|
-
while (j < lines.length) {
|
|
26
|
-
const currentLine = lines[j];
|
|
27
|
-
if (!currentLine) {
|
|
28
|
-
j += 1;
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
if (currentLine.trimEnd().endsWith("*/")) {
|
|
32
|
-
buff.push(currentLine.slice(indent));
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
35
|
-
buff.push(currentLine.slice(indent));
|
|
36
|
-
j += 1;
|
|
37
|
-
}
|
|
38
|
-
out[i + 1] = buff.join("\n");
|
|
39
|
-
i = j + 1;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
i += 1;
|
|
43
|
-
}
|
|
44
|
-
return Object.keys(out).length ? out : void 0;
|
|
45
|
-
};
|
|
46
|
-
export const stripComments = (raw) => raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\r\n]*/g, "");
|