peam 0.1.1
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/LICENSE +201 -0
- package/README.md +67 -0
- package/dist/chunk-BJTO5JO5.mjs +10 -0
- package/dist/chunk-BJTO5JO5.mjs.map +1 -0
- package/dist/cli.js +251 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.mts +5 -0
- package/dist/client.d.ts +5 -0
- package/dist/client.js +14 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +3 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +250 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +238 -0
- package/dist/index.mjs.map +1 -0
- package/dist/logger.d.mts +1 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +12 -0
- package/dist/logger.js.map +1 -0
- package/dist/logger.mjs +4 -0
- package/dist/logger.mjs.map +1 -0
- package/dist/parser.d.mts +1 -0
- package/dist/parser.d.ts +1 -0
- package/dist/parser.js +24 -0
- package/dist/parser.js.map +1 -0
- package/dist/parser.mjs +4 -0
- package/dist/parser.mjs.map +1 -0
- package/dist/search.d.mts +1 -0
- package/dist/search.d.ts +1 -0
- package/dist/search.js +16 -0
- package/dist/search.js.map +1 -0
- package/dist/search.mjs +4 -0
- package/dist/search.mjs.map +1 -0
- package/dist/server.d.mts +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +14 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +3 -0
- package/dist/server.mjs.map +1 -0
- package/package.json +89 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var parser = require('@peam-ai/parser');
|
|
4
|
+
var search = require('@peam-ai/search');
|
|
5
|
+
var chalk = require('chalk');
|
|
6
|
+
var commander = require('commander');
|
|
7
|
+
var fg = require('fast-glob');
|
|
8
|
+
var fs = require('fs');
|
|
9
|
+
var path = require('path');
|
|
10
|
+
|
|
11
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
|
|
13
|
+
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
14
|
+
var fg__default = /*#__PURE__*/_interopDefault(fg);
|
|
15
|
+
|
|
16
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
17
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
18
|
+
}) : x)(function(x) {
|
|
19
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
20
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
21
|
+
});
|
|
22
|
+
var packageJson = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf-8"));
|
|
23
|
+
function parseExcludePatterns(value) {
|
|
24
|
+
return value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
25
|
+
}
|
|
26
|
+
var log = {
|
|
27
|
+
success: (message) => console.log(chalk__default.default.green("\u2713 ") + message),
|
|
28
|
+
error: (message) => console.error(chalk__default.default.red("\u2717 ") + message),
|
|
29
|
+
warn: (message) => console.warn(chalk__default.default.yellow("\u26A0 ") + message),
|
|
30
|
+
info: (message) => console.log(chalk__default.default.blue("\u2139 ") + message),
|
|
31
|
+
text: (message) => console.log(message),
|
|
32
|
+
cyan: (text) => chalk__default.default.cyan(text),
|
|
33
|
+
gray: (text) => chalk__default.default.gray(text),
|
|
34
|
+
bold: (text) => chalk__default.default.bold(text),
|
|
35
|
+
yellow: (text) => chalk__default.default.yellow(text),
|
|
36
|
+
red: (text) => chalk__default.default.red(text),
|
|
37
|
+
green: (text) => chalk__default.default.green(text)
|
|
38
|
+
};
|
|
39
|
+
async function discoverHtmlFiles(sourceDir, globPattern, projectDir) {
|
|
40
|
+
const pages = [];
|
|
41
|
+
try {
|
|
42
|
+
const sourceFullPath = path.join(projectDir, sourceDir);
|
|
43
|
+
const htmlFiles = await fg__default.default(globPattern, {
|
|
44
|
+
cwd: sourceFullPath,
|
|
45
|
+
absolute: true,
|
|
46
|
+
onlyFiles: true,
|
|
47
|
+
dot: false,
|
|
48
|
+
ignore: ["**/_next/**", "**/_astro/**", "**/404.{html,htm}", "**/500.{html,htm}"]
|
|
49
|
+
});
|
|
50
|
+
for (const htmlFilePath of htmlFiles) {
|
|
51
|
+
const relativePath = path.relative(sourceFullPath, htmlFilePath);
|
|
52
|
+
const pathname = parser.filePathToPathname(relativePath);
|
|
53
|
+
pages.push({
|
|
54
|
+
pathname,
|
|
55
|
+
htmlFilePath,
|
|
56
|
+
relativeHtmlPath: relativePath
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
} catch (error) {
|
|
60
|
+
log.warn(`Error discovering HTML files: ${error}`);
|
|
61
|
+
}
|
|
62
|
+
return pages;
|
|
63
|
+
}
|
|
64
|
+
async function indexPages(config) {
|
|
65
|
+
var _a;
|
|
66
|
+
log.text("\n" + log.bold(log.cyan("Peam Static Site Indexer")) + "\n");
|
|
67
|
+
log.text(log.bold("Configuration:"));
|
|
68
|
+
log.text(` Project Directory: ${log.gray(config.projectDir)}`);
|
|
69
|
+
log.text(` Source Directory: ${log.gray(config.source)}`);
|
|
70
|
+
log.text(` Glob Pattern: ${log.gray(config.glob)}`);
|
|
71
|
+
log.text(` Output Directory: ${log.gray(config.outputDir)}`);
|
|
72
|
+
log.text(` Index Filename: ${log.gray(config.indexFilename)}`);
|
|
73
|
+
log.text(` Respect robots.txt: ${log.gray(config.respectRobotsTxt.toString())}`);
|
|
74
|
+
if (config.exclude.length > 0) {
|
|
75
|
+
log.text(` Exclude Patterns: ${log.gray(config.exclude.join(", "))}`);
|
|
76
|
+
}
|
|
77
|
+
log.text("");
|
|
78
|
+
const sourcePath = path.join(config.projectDir, config.source);
|
|
79
|
+
if (!fs.existsSync(sourcePath)) {
|
|
80
|
+
log.error(`Source directory not found: ${sourcePath}`);
|
|
81
|
+
log.text(log.yellow(" Please build your site first or specify the correct --source directory"));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
const searchPaths = [path.join(config.source, "robots.txt"), "public/robots.txt", "robots.txt"];
|
|
85
|
+
const robotsResult = config.respectRobotsTxt ? parser.loadRobotsTxt(config.projectDir, searchPaths, config.robotsTxtPath) : null;
|
|
86
|
+
if (robotsResult && config.respectRobotsTxt) {
|
|
87
|
+
log.info(`robots.txt loaded from ${log.cyan(path.relative(config.projectDir, robotsResult.path))}`);
|
|
88
|
+
} else if (config.respectRobotsTxt) {
|
|
89
|
+
log.info("No robots.txt found, all paths will be indexed");
|
|
90
|
+
}
|
|
91
|
+
log.text(log.bold("Discovering HTML files..."));
|
|
92
|
+
log.text("");
|
|
93
|
+
log.text(` Scanning: ${log.gray(config.source)}`);
|
|
94
|
+
log.text(` Pattern: ${log.gray(config.glob)}`);
|
|
95
|
+
log.text("");
|
|
96
|
+
const discoveredPages = await discoverHtmlFiles(config.source, config.glob, config.projectDir);
|
|
97
|
+
if (discoveredPages.length === 0) {
|
|
98
|
+
log.text("");
|
|
99
|
+
log.warn("No HTML files found");
|
|
100
|
+
log.text(log.yellow(" Check that your source directory contains HTML files"));
|
|
101
|
+
log.text(log.yellow(` Source: ${sourcePath}`));
|
|
102
|
+
log.text(log.yellow(` Pattern: ${config.glob}`));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
const uniquePages = /* @__PURE__ */ new Map();
|
|
106
|
+
for (const page of discoveredPages) {
|
|
107
|
+
if (!uniquePages.has(page.pathname)) {
|
|
108
|
+
uniquePages.set(page.pathname, page);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
log.text("");
|
|
112
|
+
log.success(`Found ${log.bold(uniquePages.size.toString())} unique pages`);
|
|
113
|
+
log.text("");
|
|
114
|
+
log.text(log.bold("Processing pages..."));
|
|
115
|
+
log.text("");
|
|
116
|
+
const processedPages = [];
|
|
117
|
+
for (const [pathname, page] of uniquePages) {
|
|
118
|
+
const result = parser.shouldIncludePath(pathname, (_a = robotsResult == null ? void 0 : robotsResult.parser) != null ? _a : null, config.exclude, config.respectRobotsTxt);
|
|
119
|
+
if (!result.included) {
|
|
120
|
+
if (result.reason === "robots-txt") {
|
|
121
|
+
log.error(`Excluded by robots.txt: ${pathname}`);
|
|
122
|
+
} else if (result.reason === "exclude-pattern") {
|
|
123
|
+
log.error(`Excluded by pattern: ${pathname}`);
|
|
124
|
+
}
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const html = fs.readFileSync(page.htmlFilePath, "utf-8");
|
|
129
|
+
const structuredPage = parser.parseHTML(html);
|
|
130
|
+
if (!structuredPage) {
|
|
131
|
+
log.warn(`No content extracted from ${log.gray(pathname)}`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
log.success(`${log.cyan(pathname)}`);
|
|
135
|
+
processedPages.push({
|
|
136
|
+
path: pathname,
|
|
137
|
+
htmlFile: page.relativeHtmlPath,
|
|
138
|
+
structuredPage
|
|
139
|
+
});
|
|
140
|
+
} catch (error) {
|
|
141
|
+
log.error(`Error processing ${log.gray(pathname)}: ${error}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
log.text("");
|
|
145
|
+
log.success(`Successfully processed ${log.bold(processedPages.length.toString())} pages`);
|
|
146
|
+
log.text("");
|
|
147
|
+
log.text(log.bold("Creating search index..."));
|
|
148
|
+
log.text("");
|
|
149
|
+
const searchIndexData = await search.buildSearchIndex(processedPages);
|
|
150
|
+
log.success(`Added ${log.bold(processedPages.length.toString())} pages to search index`);
|
|
151
|
+
log.text("");
|
|
152
|
+
log.text(log.bold("Saving index..."));
|
|
153
|
+
log.text("");
|
|
154
|
+
const outputPath = path.join(config.projectDir, config.outputDir);
|
|
155
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
156
|
+
const generatedPath = path.join(outputPath, "generated");
|
|
157
|
+
fs.mkdirSync(generatedPath, { recursive: true });
|
|
158
|
+
const searchIndexFile = path.join(generatedPath, config.indexFilename);
|
|
159
|
+
fs.writeFileSync(searchIndexFile, JSON.stringify(searchIndexData));
|
|
160
|
+
const indexJsContent = `// Auto-generated by Peam - DO NOT EDIT THIS FILE
|
|
161
|
+
import index from "./generated/${config.indexFilename}";
|
|
162
|
+
export default index;
|
|
163
|
+
`;
|
|
164
|
+
const indexJsFile = path.join(outputPath, "index.js");
|
|
165
|
+
fs.writeFileSync(indexJsFile, indexJsContent);
|
|
166
|
+
log.success(`Index saved to: ${log.cyan(path.relative(config.projectDir, searchIndexFile))}`);
|
|
167
|
+
log.text(` Total pages indexed: ${log.bold(processedPages.length.toString())}`);
|
|
168
|
+
log.text(
|
|
169
|
+
` Index size: ${log.bold((Buffer.byteLength(JSON.stringify(searchIndexData), "utf8") / 1024).toFixed(2))} KB`
|
|
170
|
+
);
|
|
171
|
+
log.text("");
|
|
172
|
+
log.success(log.bold("Indexing complete!"));
|
|
173
|
+
log.text("");
|
|
174
|
+
}
|
|
175
|
+
function probeSourceDirectory(projectDir) {
|
|
176
|
+
const commonDirs = [".next", ".build", ".out"];
|
|
177
|
+
for (const dir of commonDirs) {
|
|
178
|
+
const fullPath = path.join(projectDir, dir);
|
|
179
|
+
if (fs.existsSync(fullPath)) {
|
|
180
|
+
return dir;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
async function main() {
|
|
186
|
+
const program = new commander.Command();
|
|
187
|
+
program.name("peam").description("Peam static site indexer (Next.js, Hugo, etc.)").version(packageJson.version).option("--source <path>", "Source directory containing HTML files (auto-detected if not provided)").option("--glob <pattern>", "Glob pattern for HTML files", "**/*.{html,htm}").option("--output-dir <path>", "Output directory for index", ".peam").option("--index-filename <name>", "Name of index file", "index.json").option("--ignore-robots-txt", "Disable robots.txt checking").option("--robots-path <path>", "Custom path to robots.txt file").option("--exclude <patterns>", "Comma-separated exclude patterns", parseExcludePatterns, []).option("--project-dir <path>", "Project root directory", process.cwd()).addHelpText(
|
|
188
|
+
"after",
|
|
189
|
+
`
|
|
190
|
+
Examples:
|
|
191
|
+
# Auto-detect build directory
|
|
192
|
+
$ peam
|
|
193
|
+
|
|
194
|
+
# Hugo
|
|
195
|
+
$ peam --source public
|
|
196
|
+
|
|
197
|
+
# Next.js
|
|
198
|
+
$ peam --source .next
|
|
199
|
+
|
|
200
|
+
# Custom output directory
|
|
201
|
+
$ peam --source dist --glob "**/*.html"
|
|
202
|
+
|
|
203
|
+
# Exclude patterns
|
|
204
|
+
$ peam --exclude "/admin/**,/api/*,/private-*"
|
|
205
|
+
|
|
206
|
+
For Next.js 15+, the @peam-ai/next integration is recommended for production use.
|
|
207
|
+
|
|
208
|
+
More information: https://peam.ai
|
|
209
|
+
`
|
|
210
|
+
).parse();
|
|
211
|
+
const options = program.opts();
|
|
212
|
+
try {
|
|
213
|
+
let sourceDir = options.source;
|
|
214
|
+
if (!sourceDir) {
|
|
215
|
+
const probedDir = probeSourceDirectory(options.projectDir);
|
|
216
|
+
if (probedDir) {
|
|
217
|
+
sourceDir = probedDir;
|
|
218
|
+
log.info(`Auto-detected source directory: ${log.cyan(probedDir)}`);
|
|
219
|
+
log.text("");
|
|
220
|
+
} else {
|
|
221
|
+
log.error("No build output directory found");
|
|
222
|
+
log.text(log.yellow(" Searched for: .next, .build, .out"));
|
|
223
|
+
log.text(log.yellow(" Please build your site first or specify --source <directory>"));
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const config = {
|
|
228
|
+
source: sourceDir,
|
|
229
|
+
glob: options.glob,
|
|
230
|
+
outputDir: options.outputDir,
|
|
231
|
+
indexFilename: options.indexFilename,
|
|
232
|
+
respectRobotsTxt: !options.ignoreRobotsTxt,
|
|
233
|
+
robotsTxtPath: options.robotsPath,
|
|
234
|
+
exclude: options.exclude,
|
|
235
|
+
projectDir: options.projectDir
|
|
236
|
+
};
|
|
237
|
+
await indexPages(config);
|
|
238
|
+
} catch (error) {
|
|
239
|
+
log.text("");
|
|
240
|
+
log.error(`Fatal error: ${error}`);
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (__require.main === module) {
|
|
245
|
+
main();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
exports.indexPages = indexPages;
|
|
249
|
+
//# sourceMappingURL=index.js.map
|
|
250
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"names":["readFileSync","join","chalk","fg","relative","filePathToPathname","existsSync","loadRobotsTxt","shouldIncludePath","parseHTML","buildSearchIndex","mkdirSync","writeFileSync","Command"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Peam Static Site Indexer\n *\n * Scans a static site output directory, discovers HTML files,\n * parses them into structured pages, and creates a searchable index.\n */\n\nimport { filePathToPathname, loadRobotsTxt, parseHTML, shouldIncludePath, type StructuredPage } from '@peam-ai/parser';\nimport { buildSearchIndex } from '@peam-ai/search';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport fg from 'fast-glob';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join, relative } from 'path';\n\nconst packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));\n\ninterface IndexerConfig {\n source: string;\n outputDir: string;\n indexFilename: string;\n respectRobotsTxt: boolean;\n robotsTxtPath?: string;\n exclude: string[];\n glob: string;\n projectDir: string;\n}\n\ninterface DiscoveredPage {\n pathname: string;\n htmlFilePath: string;\n relativeHtmlPath: string;\n}\n\nfunction parseExcludePatterns(value: string): string[] {\n return value\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n}\n\nconst log = {\n success: (message: string) => console.log(chalk.green('✓ ') + message),\n error: (message: string) => console.error(chalk.red('✗ ') + message),\n warn: (message: string) => console.warn(chalk.yellow('⚠ ') + message),\n info: (message: string) => console.log(chalk.blue('ℹ ') + message),\n text: (message: string) => console.log(message),\n\n cyan: (text: string) => chalk.cyan(text),\n gray: (text: string) => chalk.gray(text),\n bold: (text: string) => chalk.bold(text),\n yellow: (text: string) => chalk.yellow(text),\n red: (text: string) => chalk.red(text),\n green: (text: string) => chalk.green(text),\n};\n\nasync function discoverHtmlFiles(\n sourceDir: string,\n globPattern: string,\n projectDir: string\n): Promise<DiscoveredPage[]> {\n const pages: DiscoveredPage[] = [];\n\n try {\n const sourceFullPath = join(projectDir, sourceDir);\n\n const htmlFiles = await fg(globPattern, {\n cwd: sourceFullPath,\n absolute: true,\n onlyFiles: true,\n dot: false,\n ignore: ['**/_next/**', '**/_astro/**', '**/404.{html,htm}', '**/500.{html,htm}'],\n });\n\n for (const htmlFilePath of htmlFiles) {\n const relativePath = relative(sourceFullPath, htmlFilePath);\n const pathname = filePathToPathname(relativePath);\n\n pages.push({\n pathname,\n htmlFilePath,\n relativeHtmlPath: relativePath,\n });\n }\n } catch (error) {\n log.warn(`Error discovering HTML files: ${error}`);\n }\n\n return pages;\n}\n\nasync function indexPages(config: IndexerConfig): Promise<void> {\n log.text('\\n' + log.bold(log.cyan('Peam Static Site Indexer')) + '\\n');\n log.text(log.bold('Configuration:'));\n log.text(` Project Directory: ${log.gray(config.projectDir)}`);\n log.text(` Source Directory: ${log.gray(config.source)}`);\n log.text(` Glob Pattern: ${log.gray(config.glob)}`);\n log.text(` Output Directory: ${log.gray(config.outputDir)}`);\n log.text(` Index Filename: ${log.gray(config.indexFilename)}`);\n log.text(` Respect robots.txt: ${log.gray(config.respectRobotsTxt.toString())}`);\n if (config.exclude.length > 0) {\n log.text(` Exclude Patterns: ${log.gray(config.exclude.join(', '))}`);\n }\n log.text('');\n\n const sourcePath = join(config.projectDir, config.source);\n if (!existsSync(sourcePath)) {\n log.error(`Source directory not found: ${sourcePath}`);\n log.text(log.yellow(' Please build your site first or specify the correct --source directory'));\n process.exit(1);\n }\n\n const searchPaths = [join(config.source, 'robots.txt'), 'public/robots.txt', 'robots.txt'];\n\n const robotsResult = config.respectRobotsTxt\n ? loadRobotsTxt(config.projectDir, searchPaths, config.robotsTxtPath)\n : null;\n\n if (robotsResult && config.respectRobotsTxt) {\n log.info(`robots.txt loaded from ${log.cyan(relative(config.projectDir, robotsResult.path))}`);\n } else if (config.respectRobotsTxt) {\n log.info('No robots.txt found, all paths will be indexed');\n }\n\n log.text(log.bold('Discovering HTML files...'));\n log.text('');\n log.text(` Scanning: ${log.gray(config.source)}`);\n log.text(` Pattern: ${log.gray(config.glob)}`);\n log.text('');\n\n const discoveredPages = await discoverHtmlFiles(config.source, config.glob, config.projectDir);\n\n if (discoveredPages.length === 0) {\n log.text('');\n log.warn('No HTML files found');\n log.text(log.yellow(' Check that your source directory contains HTML files'));\n log.text(log.yellow(` Source: ${sourcePath}`));\n log.text(log.yellow(` Pattern: ${config.glob}`));\n process.exit(1);\n }\n\n const uniquePages = new Map<string, DiscoveredPage>();\n for (const page of discoveredPages) {\n if (!uniquePages.has(page.pathname)) {\n uniquePages.set(page.pathname, page);\n }\n }\n\n log.text('');\n log.success(`Found ${log.bold(uniquePages.size.toString())} unique pages`);\n log.text('');\n log.text(log.bold('Processing pages...'));\n log.text('');\n\n const processedPages: Array<{\n path: string;\n htmlFile: string;\n structuredPage: StructuredPage;\n }> = [];\n\n for (const [pathname, page] of uniquePages) {\n const result = shouldIncludePath(pathname, robotsResult?.parser ?? null, config.exclude, config.respectRobotsTxt);\n\n if (!result.included) {\n // Log the specific reason for exclusion\n if (result.reason === 'robots-txt') {\n log.error(`Excluded by robots.txt: ${pathname}`);\n } else if (result.reason === 'exclude-pattern') {\n log.error(`Excluded by pattern: ${pathname}`);\n }\n continue;\n }\n\n try {\n const html = readFileSync(page.htmlFilePath, 'utf-8');\n\n const structuredPage = parseHTML(html);\n\n if (!structuredPage) {\n log.warn(`No content extracted from ${log.gray(pathname)}`);\n continue;\n }\n\n log.success(`${log.cyan(pathname)}`);\n\n processedPages.push({\n path: pathname,\n htmlFile: page.relativeHtmlPath,\n structuredPage,\n });\n } catch (error) {\n log.error(`Error processing ${log.gray(pathname)}: ${error}`);\n }\n }\n\n log.text('');\n log.success(`Successfully processed ${log.bold(processedPages.length.toString())} pages`);\n log.text('');\n log.text(log.bold('Creating search index...'));\n log.text('');\n\n const searchIndexData = await buildSearchIndex(processedPages);\n\n log.success(`Added ${log.bold(processedPages.length.toString())} pages to search index`);\n log.text('');\n log.text(log.bold('Saving index...'));\n log.text('');\n\n const outputPath = join(config.projectDir, config.outputDir);\n mkdirSync(outputPath, { recursive: true });\n\n const generatedPath = join(outputPath, 'generated');\n mkdirSync(generatedPath, { recursive: true });\n\n const searchIndexFile = join(generatedPath, config.indexFilename);\n writeFileSync(searchIndexFile, JSON.stringify(searchIndexData));\n\n const indexJsContent = `// Auto-generated by Peam - DO NOT EDIT THIS FILE\nimport index from \"./generated/${config.indexFilename}\";\nexport default index;\n`;\n const indexJsFile = join(outputPath, 'index.js');\n writeFileSync(indexJsFile, indexJsContent);\n\n log.success(`Index saved to: ${log.cyan(relative(config.projectDir, searchIndexFile))}`);\n log.text(` Total pages indexed: ${log.bold(processedPages.length.toString())}`);\n log.text(\n ` Index size: ${log.bold((Buffer.byteLength(JSON.stringify(searchIndexData), 'utf8') / 1024).toFixed(2))} KB`\n );\n log.text('');\n log.success(log.bold('Indexing complete!'));\n log.text('');\n}\n\nfunction probeSourceDirectory(projectDir: string): string | null {\n const commonDirs = ['.next', '.build', '.out'];\n\n for (const dir of commonDirs) {\n const fullPath = join(projectDir, dir);\n if (existsSync(fullPath)) {\n return dir;\n }\n }\n\n return null;\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name('peam')\n .description('Peam static site indexer (Next.js, Hugo, etc.)')\n .version(packageJson.version)\n .option('--source <path>', 'Source directory containing HTML files (auto-detected if not provided)')\n .option('--glob <pattern>', 'Glob pattern for HTML files', '**/*.{html,htm}')\n .option('--output-dir <path>', 'Output directory for index', '.peam')\n .option('--index-filename <name>', 'Name of index file', 'index.json')\n .option('--ignore-robots-txt', 'Disable robots.txt checking')\n .option('--robots-path <path>', 'Custom path to robots.txt file')\n .option('--exclude <patterns>', 'Comma-separated exclude patterns', parseExcludePatterns, [])\n .option('--project-dir <path>', 'Project root directory', process.cwd())\n .addHelpText(\n 'after',\n `\nExamples:\n # Auto-detect build directory\n $ peam\n\n # Hugo\n $ peam --source public\n\n # Next.js\n $ peam --source .next\n\n # Custom output directory\n $ peam --source dist --glob \"**/*.html\"\n\n # Exclude patterns\n $ peam --exclude \"/admin/**,/api/*,/private-*\"\n\nFor Next.js 15+, the @peam-ai/next integration is recommended for production use.\n\nMore information: https://peam.ai\n `\n )\n .parse();\n\n const options = program.opts();\n\n try {\n let sourceDir = options.source;\n if (!sourceDir) {\n const probedDir = probeSourceDirectory(options.projectDir);\n if (probedDir) {\n sourceDir = probedDir;\n log.info(`Auto-detected source directory: ${log.cyan(probedDir)}`);\n log.text('');\n } else {\n log.error('No build output directory found');\n log.text(log.yellow(' Searched for: .next, .build, .out'));\n log.text(log.yellow(' Please build your site first or specify --source <directory>'));\n process.exit(1);\n }\n }\n\n const config: IndexerConfig = {\n source: sourceDir,\n glob: options.glob,\n outputDir: options.outputDir,\n indexFilename: options.indexFilename,\n respectRobotsTxt: !options.ignoreRobotsTxt,\n robotsTxtPath: options.robotsPath,\n exclude: options.exclude,\n projectDir: options.projectDir,\n };\n\n await indexPages(config);\n } catch (error) {\n log.text('');\n log.error(`Fatal error: ${error}`);\n process.exit(1);\n }\n}\n\nif (require.main === module) {\n main();\n}\n\nexport { indexPages, type IndexerConfig };\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { __require } from './chunk-BJTO5JO5.mjs';
|
|
2
|
+
import { loadRobotsTxt, shouldIncludePath, parseHTML, filePathToPathname } from '@peam-ai/parser';
|
|
3
|
+
import { buildSearchIndex } from '@peam-ai/search';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import fg from 'fast-glob';
|
|
7
|
+
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
8
|
+
import { join, relative } from 'path';
|
|
9
|
+
|
|
10
|
+
var packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
|
|
11
|
+
function parseExcludePatterns(value) {
|
|
12
|
+
return value.split(",").map((p) => p.trim()).filter(Boolean);
|
|
13
|
+
}
|
|
14
|
+
var log = {
|
|
15
|
+
success: (message) => console.log(chalk.green("\u2713 ") + message),
|
|
16
|
+
error: (message) => console.error(chalk.red("\u2717 ") + message),
|
|
17
|
+
warn: (message) => console.warn(chalk.yellow("\u26A0 ") + message),
|
|
18
|
+
info: (message) => console.log(chalk.blue("\u2139 ") + message),
|
|
19
|
+
text: (message) => console.log(message),
|
|
20
|
+
cyan: (text) => chalk.cyan(text),
|
|
21
|
+
gray: (text) => chalk.gray(text),
|
|
22
|
+
bold: (text) => chalk.bold(text),
|
|
23
|
+
yellow: (text) => chalk.yellow(text),
|
|
24
|
+
red: (text) => chalk.red(text),
|
|
25
|
+
green: (text) => chalk.green(text)
|
|
26
|
+
};
|
|
27
|
+
async function discoverHtmlFiles(sourceDir, globPattern, projectDir) {
|
|
28
|
+
const pages = [];
|
|
29
|
+
try {
|
|
30
|
+
const sourceFullPath = join(projectDir, sourceDir);
|
|
31
|
+
const htmlFiles = await fg(globPattern, {
|
|
32
|
+
cwd: sourceFullPath,
|
|
33
|
+
absolute: true,
|
|
34
|
+
onlyFiles: true,
|
|
35
|
+
dot: false,
|
|
36
|
+
ignore: ["**/_next/**", "**/_astro/**", "**/404.{html,htm}", "**/500.{html,htm}"]
|
|
37
|
+
});
|
|
38
|
+
for (const htmlFilePath of htmlFiles) {
|
|
39
|
+
const relativePath = relative(sourceFullPath, htmlFilePath);
|
|
40
|
+
const pathname = filePathToPathname(relativePath);
|
|
41
|
+
pages.push({
|
|
42
|
+
pathname,
|
|
43
|
+
htmlFilePath,
|
|
44
|
+
relativeHtmlPath: relativePath
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
log.warn(`Error discovering HTML files: ${error}`);
|
|
49
|
+
}
|
|
50
|
+
return pages;
|
|
51
|
+
}
|
|
52
|
+
async function indexPages(config) {
|
|
53
|
+
var _a;
|
|
54
|
+
log.text("\n" + log.bold(log.cyan("Peam Static Site Indexer")) + "\n");
|
|
55
|
+
log.text(log.bold("Configuration:"));
|
|
56
|
+
log.text(` Project Directory: ${log.gray(config.projectDir)}`);
|
|
57
|
+
log.text(` Source Directory: ${log.gray(config.source)}`);
|
|
58
|
+
log.text(` Glob Pattern: ${log.gray(config.glob)}`);
|
|
59
|
+
log.text(` Output Directory: ${log.gray(config.outputDir)}`);
|
|
60
|
+
log.text(` Index Filename: ${log.gray(config.indexFilename)}`);
|
|
61
|
+
log.text(` Respect robots.txt: ${log.gray(config.respectRobotsTxt.toString())}`);
|
|
62
|
+
if (config.exclude.length > 0) {
|
|
63
|
+
log.text(` Exclude Patterns: ${log.gray(config.exclude.join(", "))}`);
|
|
64
|
+
}
|
|
65
|
+
log.text("");
|
|
66
|
+
const sourcePath = join(config.projectDir, config.source);
|
|
67
|
+
if (!existsSync(sourcePath)) {
|
|
68
|
+
log.error(`Source directory not found: ${sourcePath}`);
|
|
69
|
+
log.text(log.yellow(" Please build your site first or specify the correct --source directory"));
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
const searchPaths = [join(config.source, "robots.txt"), "public/robots.txt", "robots.txt"];
|
|
73
|
+
const robotsResult = config.respectRobotsTxt ? loadRobotsTxt(config.projectDir, searchPaths, config.robotsTxtPath) : null;
|
|
74
|
+
if (robotsResult && config.respectRobotsTxt) {
|
|
75
|
+
log.info(`robots.txt loaded from ${log.cyan(relative(config.projectDir, robotsResult.path))}`);
|
|
76
|
+
} else if (config.respectRobotsTxt) {
|
|
77
|
+
log.info("No robots.txt found, all paths will be indexed");
|
|
78
|
+
}
|
|
79
|
+
log.text(log.bold("Discovering HTML files..."));
|
|
80
|
+
log.text("");
|
|
81
|
+
log.text(` Scanning: ${log.gray(config.source)}`);
|
|
82
|
+
log.text(` Pattern: ${log.gray(config.glob)}`);
|
|
83
|
+
log.text("");
|
|
84
|
+
const discoveredPages = await discoverHtmlFiles(config.source, config.glob, config.projectDir);
|
|
85
|
+
if (discoveredPages.length === 0) {
|
|
86
|
+
log.text("");
|
|
87
|
+
log.warn("No HTML files found");
|
|
88
|
+
log.text(log.yellow(" Check that your source directory contains HTML files"));
|
|
89
|
+
log.text(log.yellow(` Source: ${sourcePath}`));
|
|
90
|
+
log.text(log.yellow(` Pattern: ${config.glob}`));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
const uniquePages = /* @__PURE__ */ new Map();
|
|
94
|
+
for (const page of discoveredPages) {
|
|
95
|
+
if (!uniquePages.has(page.pathname)) {
|
|
96
|
+
uniquePages.set(page.pathname, page);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
log.text("");
|
|
100
|
+
log.success(`Found ${log.bold(uniquePages.size.toString())} unique pages`);
|
|
101
|
+
log.text("");
|
|
102
|
+
log.text(log.bold("Processing pages..."));
|
|
103
|
+
log.text("");
|
|
104
|
+
const processedPages = [];
|
|
105
|
+
for (const [pathname, page] of uniquePages) {
|
|
106
|
+
const result = shouldIncludePath(pathname, (_a = robotsResult == null ? void 0 : robotsResult.parser) != null ? _a : null, config.exclude, config.respectRobotsTxt);
|
|
107
|
+
if (!result.included) {
|
|
108
|
+
if (result.reason === "robots-txt") {
|
|
109
|
+
log.error(`Excluded by robots.txt: ${pathname}`);
|
|
110
|
+
} else if (result.reason === "exclude-pattern") {
|
|
111
|
+
log.error(`Excluded by pattern: ${pathname}`);
|
|
112
|
+
}
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const html = readFileSync(page.htmlFilePath, "utf-8");
|
|
117
|
+
const structuredPage = parseHTML(html);
|
|
118
|
+
if (!structuredPage) {
|
|
119
|
+
log.warn(`No content extracted from ${log.gray(pathname)}`);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
log.success(`${log.cyan(pathname)}`);
|
|
123
|
+
processedPages.push({
|
|
124
|
+
path: pathname,
|
|
125
|
+
htmlFile: page.relativeHtmlPath,
|
|
126
|
+
structuredPage
|
|
127
|
+
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
log.error(`Error processing ${log.gray(pathname)}: ${error}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
log.text("");
|
|
133
|
+
log.success(`Successfully processed ${log.bold(processedPages.length.toString())} pages`);
|
|
134
|
+
log.text("");
|
|
135
|
+
log.text(log.bold("Creating search index..."));
|
|
136
|
+
log.text("");
|
|
137
|
+
const searchIndexData = await buildSearchIndex(processedPages);
|
|
138
|
+
log.success(`Added ${log.bold(processedPages.length.toString())} pages to search index`);
|
|
139
|
+
log.text("");
|
|
140
|
+
log.text(log.bold("Saving index..."));
|
|
141
|
+
log.text("");
|
|
142
|
+
const outputPath = join(config.projectDir, config.outputDir);
|
|
143
|
+
mkdirSync(outputPath, { recursive: true });
|
|
144
|
+
const generatedPath = join(outputPath, "generated");
|
|
145
|
+
mkdirSync(generatedPath, { recursive: true });
|
|
146
|
+
const searchIndexFile = join(generatedPath, config.indexFilename);
|
|
147
|
+
writeFileSync(searchIndexFile, JSON.stringify(searchIndexData));
|
|
148
|
+
const indexJsContent = `// Auto-generated by Peam - DO NOT EDIT THIS FILE
|
|
149
|
+
import index from "./generated/${config.indexFilename}";
|
|
150
|
+
export default index;
|
|
151
|
+
`;
|
|
152
|
+
const indexJsFile = join(outputPath, "index.js");
|
|
153
|
+
writeFileSync(indexJsFile, indexJsContent);
|
|
154
|
+
log.success(`Index saved to: ${log.cyan(relative(config.projectDir, searchIndexFile))}`);
|
|
155
|
+
log.text(` Total pages indexed: ${log.bold(processedPages.length.toString())}`);
|
|
156
|
+
log.text(
|
|
157
|
+
` Index size: ${log.bold((Buffer.byteLength(JSON.stringify(searchIndexData), "utf8") / 1024).toFixed(2))} KB`
|
|
158
|
+
);
|
|
159
|
+
log.text("");
|
|
160
|
+
log.success(log.bold("Indexing complete!"));
|
|
161
|
+
log.text("");
|
|
162
|
+
}
|
|
163
|
+
function probeSourceDirectory(projectDir) {
|
|
164
|
+
const commonDirs = [".next", ".build", ".out"];
|
|
165
|
+
for (const dir of commonDirs) {
|
|
166
|
+
const fullPath = join(projectDir, dir);
|
|
167
|
+
if (existsSync(fullPath)) {
|
|
168
|
+
return dir;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
async function main() {
|
|
174
|
+
const program = new Command();
|
|
175
|
+
program.name("peam").description("Peam static site indexer (Next.js, Hugo, etc.)").version(packageJson.version).option("--source <path>", "Source directory containing HTML files (auto-detected if not provided)").option("--glob <pattern>", "Glob pattern for HTML files", "**/*.{html,htm}").option("--output-dir <path>", "Output directory for index", ".peam").option("--index-filename <name>", "Name of index file", "index.json").option("--ignore-robots-txt", "Disable robots.txt checking").option("--robots-path <path>", "Custom path to robots.txt file").option("--exclude <patterns>", "Comma-separated exclude patterns", parseExcludePatterns, []).option("--project-dir <path>", "Project root directory", process.cwd()).addHelpText(
|
|
176
|
+
"after",
|
|
177
|
+
`
|
|
178
|
+
Examples:
|
|
179
|
+
# Auto-detect build directory
|
|
180
|
+
$ peam
|
|
181
|
+
|
|
182
|
+
# Hugo
|
|
183
|
+
$ peam --source public
|
|
184
|
+
|
|
185
|
+
# Next.js
|
|
186
|
+
$ peam --source .next
|
|
187
|
+
|
|
188
|
+
# Custom output directory
|
|
189
|
+
$ peam --source dist --glob "**/*.html"
|
|
190
|
+
|
|
191
|
+
# Exclude patterns
|
|
192
|
+
$ peam --exclude "/admin/**,/api/*,/private-*"
|
|
193
|
+
|
|
194
|
+
For Next.js 15+, the @peam-ai/next integration is recommended for production use.
|
|
195
|
+
|
|
196
|
+
More information: https://peam.ai
|
|
197
|
+
`
|
|
198
|
+
).parse();
|
|
199
|
+
const options = program.opts();
|
|
200
|
+
try {
|
|
201
|
+
let sourceDir = options.source;
|
|
202
|
+
if (!sourceDir) {
|
|
203
|
+
const probedDir = probeSourceDirectory(options.projectDir);
|
|
204
|
+
if (probedDir) {
|
|
205
|
+
sourceDir = probedDir;
|
|
206
|
+
log.info(`Auto-detected source directory: ${log.cyan(probedDir)}`);
|
|
207
|
+
log.text("");
|
|
208
|
+
} else {
|
|
209
|
+
log.error("No build output directory found");
|
|
210
|
+
log.text(log.yellow(" Searched for: .next, .build, .out"));
|
|
211
|
+
log.text(log.yellow(" Please build your site first or specify --source <directory>"));
|
|
212
|
+
process.exit(1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const config = {
|
|
216
|
+
source: sourceDir,
|
|
217
|
+
glob: options.glob,
|
|
218
|
+
outputDir: options.outputDir,
|
|
219
|
+
indexFilename: options.indexFilename,
|
|
220
|
+
respectRobotsTxt: !options.ignoreRobotsTxt,
|
|
221
|
+
robotsTxtPath: options.robotsPath,
|
|
222
|
+
exclude: options.exclude,
|
|
223
|
+
projectDir: options.projectDir
|
|
224
|
+
};
|
|
225
|
+
await indexPages(config);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
log.text("");
|
|
228
|
+
log.error(`Fatal error: ${error}`);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (__require.main === module) {
|
|
233
|
+
main();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export { indexPages };
|
|
237
|
+
//# sourceMappingURL=index.mjs.map
|
|
238
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Peam Static Site Indexer\n *\n * Scans a static site output directory, discovers HTML files,\n * parses them into structured pages, and creates a searchable index.\n */\n\nimport { filePathToPathname, loadRobotsTxt, parseHTML, shouldIncludePath, type StructuredPage } from '@peam-ai/parser';\nimport { buildSearchIndex } from '@peam-ai/search';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport fg from 'fast-glob';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { join, relative } from 'path';\n\nconst packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));\n\ninterface IndexerConfig {\n source: string;\n outputDir: string;\n indexFilename: string;\n respectRobotsTxt: boolean;\n robotsTxtPath?: string;\n exclude: string[];\n glob: string;\n projectDir: string;\n}\n\ninterface DiscoveredPage {\n pathname: string;\n htmlFilePath: string;\n relativeHtmlPath: string;\n}\n\nfunction parseExcludePatterns(value: string): string[] {\n return value\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean);\n}\n\nconst log = {\n success: (message: string) => console.log(chalk.green('✓ ') + message),\n error: (message: string) => console.error(chalk.red('✗ ') + message),\n warn: (message: string) => console.warn(chalk.yellow('⚠ ') + message),\n info: (message: string) => console.log(chalk.blue('ℹ ') + message),\n text: (message: string) => console.log(message),\n\n cyan: (text: string) => chalk.cyan(text),\n gray: (text: string) => chalk.gray(text),\n bold: (text: string) => chalk.bold(text),\n yellow: (text: string) => chalk.yellow(text),\n red: (text: string) => chalk.red(text),\n green: (text: string) => chalk.green(text),\n};\n\nasync function discoverHtmlFiles(\n sourceDir: string,\n globPattern: string,\n projectDir: string\n): Promise<DiscoveredPage[]> {\n const pages: DiscoveredPage[] = [];\n\n try {\n const sourceFullPath = join(projectDir, sourceDir);\n\n const htmlFiles = await fg(globPattern, {\n cwd: sourceFullPath,\n absolute: true,\n onlyFiles: true,\n dot: false,\n ignore: ['**/_next/**', '**/_astro/**', '**/404.{html,htm}', '**/500.{html,htm}'],\n });\n\n for (const htmlFilePath of htmlFiles) {\n const relativePath = relative(sourceFullPath, htmlFilePath);\n const pathname = filePathToPathname(relativePath);\n\n pages.push({\n pathname,\n htmlFilePath,\n relativeHtmlPath: relativePath,\n });\n }\n } catch (error) {\n log.warn(`Error discovering HTML files: ${error}`);\n }\n\n return pages;\n}\n\nasync function indexPages(config: IndexerConfig): Promise<void> {\n log.text('\\n' + log.bold(log.cyan('Peam Static Site Indexer')) + '\\n');\n log.text(log.bold('Configuration:'));\n log.text(` Project Directory: ${log.gray(config.projectDir)}`);\n log.text(` Source Directory: ${log.gray(config.source)}`);\n log.text(` Glob Pattern: ${log.gray(config.glob)}`);\n log.text(` Output Directory: ${log.gray(config.outputDir)}`);\n log.text(` Index Filename: ${log.gray(config.indexFilename)}`);\n log.text(` Respect robots.txt: ${log.gray(config.respectRobotsTxt.toString())}`);\n if (config.exclude.length > 0) {\n log.text(` Exclude Patterns: ${log.gray(config.exclude.join(', '))}`);\n }\n log.text('');\n\n const sourcePath = join(config.projectDir, config.source);\n if (!existsSync(sourcePath)) {\n log.error(`Source directory not found: ${sourcePath}`);\n log.text(log.yellow(' Please build your site first or specify the correct --source directory'));\n process.exit(1);\n }\n\n const searchPaths = [join(config.source, 'robots.txt'), 'public/robots.txt', 'robots.txt'];\n\n const robotsResult = config.respectRobotsTxt\n ? loadRobotsTxt(config.projectDir, searchPaths, config.robotsTxtPath)\n : null;\n\n if (robotsResult && config.respectRobotsTxt) {\n log.info(`robots.txt loaded from ${log.cyan(relative(config.projectDir, robotsResult.path))}`);\n } else if (config.respectRobotsTxt) {\n log.info('No robots.txt found, all paths will be indexed');\n }\n\n log.text(log.bold('Discovering HTML files...'));\n log.text('');\n log.text(` Scanning: ${log.gray(config.source)}`);\n log.text(` Pattern: ${log.gray(config.glob)}`);\n log.text('');\n\n const discoveredPages = await discoverHtmlFiles(config.source, config.glob, config.projectDir);\n\n if (discoveredPages.length === 0) {\n log.text('');\n log.warn('No HTML files found');\n log.text(log.yellow(' Check that your source directory contains HTML files'));\n log.text(log.yellow(` Source: ${sourcePath}`));\n log.text(log.yellow(` Pattern: ${config.glob}`));\n process.exit(1);\n }\n\n const uniquePages = new Map<string, DiscoveredPage>();\n for (const page of discoveredPages) {\n if (!uniquePages.has(page.pathname)) {\n uniquePages.set(page.pathname, page);\n }\n }\n\n log.text('');\n log.success(`Found ${log.bold(uniquePages.size.toString())} unique pages`);\n log.text('');\n log.text(log.bold('Processing pages...'));\n log.text('');\n\n const processedPages: Array<{\n path: string;\n htmlFile: string;\n structuredPage: StructuredPage;\n }> = [];\n\n for (const [pathname, page] of uniquePages) {\n const result = shouldIncludePath(pathname, robotsResult?.parser ?? null, config.exclude, config.respectRobotsTxt);\n\n if (!result.included) {\n // Log the specific reason for exclusion\n if (result.reason === 'robots-txt') {\n log.error(`Excluded by robots.txt: ${pathname}`);\n } else if (result.reason === 'exclude-pattern') {\n log.error(`Excluded by pattern: ${pathname}`);\n }\n continue;\n }\n\n try {\n const html = readFileSync(page.htmlFilePath, 'utf-8');\n\n const structuredPage = parseHTML(html);\n\n if (!structuredPage) {\n log.warn(`No content extracted from ${log.gray(pathname)}`);\n continue;\n }\n\n log.success(`${log.cyan(pathname)}`);\n\n processedPages.push({\n path: pathname,\n htmlFile: page.relativeHtmlPath,\n structuredPage,\n });\n } catch (error) {\n log.error(`Error processing ${log.gray(pathname)}: ${error}`);\n }\n }\n\n log.text('');\n log.success(`Successfully processed ${log.bold(processedPages.length.toString())} pages`);\n log.text('');\n log.text(log.bold('Creating search index...'));\n log.text('');\n\n const searchIndexData = await buildSearchIndex(processedPages);\n\n log.success(`Added ${log.bold(processedPages.length.toString())} pages to search index`);\n log.text('');\n log.text(log.bold('Saving index...'));\n log.text('');\n\n const outputPath = join(config.projectDir, config.outputDir);\n mkdirSync(outputPath, { recursive: true });\n\n const generatedPath = join(outputPath, 'generated');\n mkdirSync(generatedPath, { recursive: true });\n\n const searchIndexFile = join(generatedPath, config.indexFilename);\n writeFileSync(searchIndexFile, JSON.stringify(searchIndexData));\n\n const indexJsContent = `// Auto-generated by Peam - DO NOT EDIT THIS FILE\nimport index from \"./generated/${config.indexFilename}\";\nexport default index;\n`;\n const indexJsFile = join(outputPath, 'index.js');\n writeFileSync(indexJsFile, indexJsContent);\n\n log.success(`Index saved to: ${log.cyan(relative(config.projectDir, searchIndexFile))}`);\n log.text(` Total pages indexed: ${log.bold(processedPages.length.toString())}`);\n log.text(\n ` Index size: ${log.bold((Buffer.byteLength(JSON.stringify(searchIndexData), 'utf8') / 1024).toFixed(2))} KB`\n );\n log.text('');\n log.success(log.bold('Indexing complete!'));\n log.text('');\n}\n\nfunction probeSourceDirectory(projectDir: string): string | null {\n const commonDirs = ['.next', '.build', '.out'];\n\n for (const dir of commonDirs) {\n const fullPath = join(projectDir, dir);\n if (existsSync(fullPath)) {\n return dir;\n }\n }\n\n return null;\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name('peam')\n .description('Peam static site indexer (Next.js, Hugo, etc.)')\n .version(packageJson.version)\n .option('--source <path>', 'Source directory containing HTML files (auto-detected if not provided)')\n .option('--glob <pattern>', 'Glob pattern for HTML files', '**/*.{html,htm}')\n .option('--output-dir <path>', 'Output directory for index', '.peam')\n .option('--index-filename <name>', 'Name of index file', 'index.json')\n .option('--ignore-robots-txt', 'Disable robots.txt checking')\n .option('--robots-path <path>', 'Custom path to robots.txt file')\n .option('--exclude <patterns>', 'Comma-separated exclude patterns', parseExcludePatterns, [])\n .option('--project-dir <path>', 'Project root directory', process.cwd())\n .addHelpText(\n 'after',\n `\nExamples:\n # Auto-detect build directory\n $ peam\n\n # Hugo\n $ peam --source public\n\n # Next.js\n $ peam --source .next\n\n # Custom output directory\n $ peam --source dist --glob \"**/*.html\"\n\n # Exclude patterns\n $ peam --exclude \"/admin/**,/api/*,/private-*\"\n\nFor Next.js 15+, the @peam-ai/next integration is recommended for production use.\n\nMore information: https://peam.ai\n `\n )\n .parse();\n\n const options = program.opts();\n\n try {\n let sourceDir = options.source;\n if (!sourceDir) {\n const probedDir = probeSourceDirectory(options.projectDir);\n if (probedDir) {\n sourceDir = probedDir;\n log.info(`Auto-detected source directory: ${log.cyan(probedDir)}`);\n log.text('');\n } else {\n log.error('No build output directory found');\n log.text(log.yellow(' Searched for: .next, .build, .out'));\n log.text(log.yellow(' Please build your site first or specify --source <directory>'));\n process.exit(1);\n }\n }\n\n const config: IndexerConfig = {\n source: sourceDir,\n glob: options.glob,\n outputDir: options.outputDir,\n indexFilename: options.indexFilename,\n respectRobotsTxt: !options.ignoreRobotsTxt,\n robotsTxtPath: options.robotsPath,\n exclude: options.exclude,\n projectDir: options.projectDir,\n };\n\n await indexPages(config);\n } catch (error) {\n log.text('');\n log.error(`Fatal error: ${error}`);\n process.exit(1);\n }\n}\n\nif (require.main === module) {\n main();\n}\n\nexport { indexPages, type IndexerConfig };\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { loggers } from '@peam-ai/logger';
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { loggers } from '@peam-ai/logger';
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var logger = require('@peam-ai/logger');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "loggers", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () { return logger.loggers; }
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=logger.js.map
|
|
12
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"logger.js","sourcesContent":[]}
|
package/dist/logger.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"logger.mjs","sourcesContent":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RobotsTxtResult, StructuredPage, createRobotsParser, loadRobotsTxt, parseHTML, shouldIncludePath } from '@peam-ai/parser';
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { RobotsTxtResult, StructuredPage, createRobotsParser, loadRobotsTxt, parseHTML, shouldIncludePath } from '@peam-ai/parser';
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var parser = require('@peam-ai/parser');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Object.defineProperty(exports, "createRobotsParser", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () { return parser.createRobotsParser; }
|
|
10
|
+
});
|
|
11
|
+
Object.defineProperty(exports, "loadRobotsTxt", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return parser.loadRobotsTxt; }
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, "parseHTML", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return parser.parseHTML; }
|
|
18
|
+
});
|
|
19
|
+
Object.defineProperty(exports, "shouldIncludePath", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return parser.shouldIncludePath; }
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=parser.js.map
|
|
24
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"parser.js","sourcesContent":[]}
|