@lakshmanshankar/pagwrite-astro 0.1.3
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/CLI.md +110 -0
- package/README.md +155 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +136 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +119 -0
- package/dist/client.js.map +1 -0
- package/dist/fs.d.ts +3 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +8 -0
- package/dist/fs.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/token.d.ts +4 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +13 -0
- package/dist/token.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +7 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +73 -0
- package/dist/utils.js.map +1 -0
- package/package.json +47 -0
package/CLI.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Pagewrite Content CLI
|
|
2
|
+
|
|
3
|
+
`pagewrite-content` fetches Pagewrite CMS content without running an Astro build. Use it in CI, predeploy steps, or local checks when you want MDX files written into an Astro content directory ahead of time.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The CLI is included with `@lakshmanshankar/pagwrite-astro`:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm add @lakshmanshankar/pagwrite-astro
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
After installation, run it through your package manager:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm pagewrite-content --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Authentication
|
|
20
|
+
|
|
21
|
+
By default, the CLI reads the build token from `REMOTE_MDX_TOKEN`:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
REMOTE_MDX_TOKEN=rmx_live_xxxxxxxxxxxx
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
You can also pass a token directly with `--token`, or point to another environment variable with `--token-env`.
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pagewrite-content fetch --site-id <siteId> [options]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The `fetch` command stages the site content by fetching the static file tree and paginated file documents, adding `title` and `slug` frontmatter, and writing `.mdx` files to the output directory.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pagewrite-content fetch --site-id your-site-id --out src/content/docs
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Options
|
|
42
|
+
|
|
43
|
+
| Option | Default | Description |
|
|
44
|
+
| ------ | ------- | ----------- |
|
|
45
|
+
| `--site-id <id>` | required | Pagewrite site id to fetch. |
|
|
46
|
+
| `--out <dir>` | `src/content/docs` | Output directory for generated MDX files. |
|
|
47
|
+
| `--output-dir <dir>` | `src/content/docs` | Alias for `--out`. |
|
|
48
|
+
| `--token <token>` | env lookup | Build token value. |
|
|
49
|
+
| `--token-env <name>` | `REMOTE_MDX_TOKEN` | Environment variable name that contains the build token. |
|
|
50
|
+
| `--token-env-var <name>` | `REMOTE_MDX_TOKEN` | Alias for `--token-env`. |
|
|
51
|
+
| `--clean` | `false` | Remove the output directory before writing files. |
|
|
52
|
+
| `--dry-run` | `false` | Fetch and validate content, then remove temporary output. |
|
|
53
|
+
| `--page-size <number>` | `100` | File document page size. |
|
|
54
|
+
| `--timeout-ms <number>` | `30000` | Request timeout in milliseconds. |
|
|
55
|
+
| `-h`, `--help` | none | Show CLI help. |
|
|
56
|
+
|
|
57
|
+
## Examples
|
|
58
|
+
|
|
59
|
+
Fetch content into the default Astro content directory:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pagewrite-content fetch --site-id your-site-id
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Fetch into a custom collection directory:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pagewrite-content fetch --site-id your-site-id --out src/content/blog
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Clean the target directory before writing fresh content:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pagewrite-content fetch --site-id your-site-id --out src/content/docs --clean
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use a custom token environment variable:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
PAGEWRITE_BUILD_TOKEN=rmx_live_xxxxxxxxxxxx \
|
|
81
|
+
pagewrite-content fetch --site-id your-site-id --token-env PAGEWRITE_BUILD_TOKEN
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Validate remote content without keeping files on disk:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pagewrite-content fetch --site-id your-site-id --dry-run
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## CI Integration
|
|
91
|
+
|
|
92
|
+
Run the CLI before your framework build:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"scripts": {
|
|
97
|
+
"content:fetch": "pagewrite-content fetch --site-id $PAGEWRITE_SITE_ID --out src/content/docs --clean",
|
|
98
|
+
"prebuild": "pnpm content:fetch",
|
|
99
|
+
"build": "astro build"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Make sure `REMOTE_MDX_TOKEN` and `PAGEWRITE_SITE_ID` are configured as CI secrets or environment variables.
|
|
105
|
+
|
|
106
|
+
## Notes
|
|
107
|
+
|
|
108
|
+
- Build tokens should be read-only and scoped to fetch site content.
|
|
109
|
+
- `--clean` is ignored during `--dry-run`; dry runs write to a temporary directory and remove it afterward.
|
|
110
|
+
- Unsafe absolute paths and path traversal entries from the remote file tree are rejected before files are written.
|
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @lakshmanshankar/pagwrite-astro
|
|
2
|
+
|
|
3
|
+
Astro integration for fetching Pagewrite CMS content at build time and writing it as MDX files into your Astro content directory.
|
|
4
|
+
|
|
5
|
+
This package is currently focused on the Astro fetch/write integration. The lower-level fetch and staging functions are exported so they can later be reused by another adapter, such as Next.js or Fumadocs.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
Pagewrite CMS User's Astro project
|
|
11
|
+
------------- --------------------
|
|
12
|
+
Build token secret ---> REMOTE_MDX_TOKEN
|
|
13
|
+
siteId ---> @lakshmanshankar/pagwrite-astro config
|
|
14
|
+
|
|
|
15
|
+
v
|
|
16
|
+
astro build
|
|
17
|
+
|
|
|
18
|
+
v
|
|
19
|
+
fetch static file tree
|
|
20
|
+
fetch paginated file documents
|
|
21
|
+
|
|
|
22
|
+
v
|
|
23
|
+
src/content/docs/*.mdx
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pnpm add @lakshmanshankar/pagwrite-astro
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Setup
|
|
33
|
+
|
|
34
|
+
Set a build token in your local or CI environment:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
REMOTE_MDX_TOKEN=rmx_live_xxxxxxxxxxxx
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Configure the integration before content-related integrations in `astro.config.mjs`:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
import { defineConfig } from "astro/config";
|
|
44
|
+
import mdx from "@astrojs/mdx";
|
|
45
|
+
import pagewriteAstro from "@lakshmanshankar/pagwrite-astro";
|
|
46
|
+
|
|
47
|
+
export default defineConfig({
|
|
48
|
+
integrations: [
|
|
49
|
+
pagewriteAstro({
|
|
50
|
+
siteId: "your-site-id",
|
|
51
|
+
}),
|
|
52
|
+
mdx(),
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Options
|
|
58
|
+
|
|
59
|
+
| Option | Type | Default | Description |
|
|
60
|
+
| ------ | ---- | ------- | ----------- |
|
|
61
|
+
| `siteId` | `string` | required | Pagewrite site to fetch and stage. |
|
|
62
|
+
| `token` | `string` | none | Build token value. Takes priority over env lookup. |
|
|
63
|
+
| `tokenEnvVar` | `string` | `REMOTE_MDX_TOKEN` | Environment variable name to read the token from. |
|
|
64
|
+
| `outputDir` | `string` | `src/content/docs` | Directory where MDX files are written, relative to the Astro project root. |
|
|
65
|
+
| `clean` | `boolean` | `false` | Remove `outputDir` before writing fetched files. |
|
|
66
|
+
| `verbose` | `boolean` | `false` | Reserved for more detailed sync logging. |
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Custom Output Directory
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
pagewriteAstro({
|
|
74
|
+
siteId: "your-site-id",
|
|
75
|
+
outputDir: "src/content/blog",
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Clean Sync For CI
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
pagewriteAstro({
|
|
83
|
+
siteId: "your-site-id",
|
|
84
|
+
clean: true,
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Custom Token Env Var
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
pagewriteAstro({
|
|
92
|
+
siteId: "your-site-id",
|
|
93
|
+
tokenEnvVar: "PAGEWRITE_BUILD_TOKEN",
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## Ad-Hoc Fetching
|
|
99
|
+
|
|
100
|
+
You can fetch content outside the Astro build by running the CLI in a predeploy step, CI job, or local verification command:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pagewrite-content fetch --site-id your-site-id --out src/content/docs
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For CI, wire it before your framework build:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"scripts": {
|
|
111
|
+
"content:fetch": "pagewrite-content fetch --site-id $PAGEWRITE_SITE_ID --out src/content/docs --clean",
|
|
112
|
+
"prebuild": "pnpm content:fetch",
|
|
113
|
+
"build": "astro build"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
To verify the remote content without keeping files on disk, use dry run:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pagewrite-content fetch --site-id your-site-id --dry-run
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
CLI options mirror the integration defaults: `--token`, `--token-env`, `--clean`, `--page-size`, and `--timeout-ms` are available.
|
|
125
|
+
|
|
126
|
+
See [CLI.md](./CLI.md) for the full command reference and CI examples.
|
|
127
|
+
|
|
128
|
+
## Lower-Level API
|
|
129
|
+
|
|
130
|
+
The package also exports the reusable content staging primitives:
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import {
|
|
134
|
+
fetchStaticFileTree,
|
|
135
|
+
fetchAllFileDocuments,
|
|
136
|
+
stageSiteContent,
|
|
137
|
+
} from "@lakshmanshankar/pagwrite-astro";
|
|
138
|
+
|
|
139
|
+
await stageSiteContent("your-site-id", process.env.REMOTE_MDX_TOKEN!, "./content/docs");
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`stageSiteContent` fetches the static file tree and paginated file documents, converts file tree paths into safe MDX file paths, upserts `title` and `slug` frontmatter, and writes files to the target directory.
|
|
143
|
+
|
|
144
|
+
## Publishing
|
|
145
|
+
|
|
146
|
+
Package publishing is handled by GitHub Actions. Configure an `NPM_TOKEN` repository secret with permission to publish `@lakshmanshankar/pagwrite-astro`, then publish a GitHub release to run the npm publish workflow.
|
|
147
|
+
|
|
148
|
+
The workflow installs dependencies with pnpm, runs typecheck, tests, and build, then publishes to the npm registry with provenance enabled. It can also be started manually from the Actions tab with `workflow_dispatch`.
|
|
149
|
+
|
|
150
|
+
## Security Notes
|
|
151
|
+
|
|
152
|
+
- Never commit build tokens.
|
|
153
|
+
- Build tokens should be read-only and scoped to fetch site content.
|
|
154
|
+
- File tree paths are normalized and checked before writing.
|
|
155
|
+
- Missing tokens, API failures, invalid tree responses, and disk write errors fail the Astro build.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { stageSiteContent } from "./client.js";
|
|
5
|
+
import { resolveToken } from "./token.js";
|
|
6
|
+
const HELP = `Usage:
|
|
7
|
+
pagewrite-content fetch --site-id <siteId> [options]
|
|
8
|
+
|
|
9
|
+
Options:
|
|
10
|
+
--site-id <id> Pagewrite site id to fetch. Required.
|
|
11
|
+
--out <dir> Output directory. Default: src/content/docs
|
|
12
|
+
--token <token> Build token. Defaults to env lookup.
|
|
13
|
+
--token-env <name> Token env var. Default: REMOTE_MDX_TOKEN
|
|
14
|
+
--clean Remove output directory before writing.
|
|
15
|
+
--dry-run Fetch and validate content without keeping written files.
|
|
16
|
+
--page-size <number> File document page size. Default: 100
|
|
17
|
+
--timeout-ms <number> Request timeout in milliseconds. Default: 30000
|
|
18
|
+
-h, --help Show this help.
|
|
19
|
+
`;
|
|
20
|
+
async function main(argv) {
|
|
21
|
+
const options = parseArgs(argv);
|
|
22
|
+
if (options.command === "help") {
|
|
23
|
+
console.log(HELP);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!options.siteId) {
|
|
27
|
+
throw new Error("Missing required --site-id option.");
|
|
28
|
+
}
|
|
29
|
+
const token = resolveToken({
|
|
30
|
+
siteId: options.siteId,
|
|
31
|
+
token: options.token,
|
|
32
|
+
tokenEnvVar: options.tokenEnvVar,
|
|
33
|
+
});
|
|
34
|
+
const outputDir = path.resolve(process.cwd(), options.outDir);
|
|
35
|
+
const targetDir = options.dryRun
|
|
36
|
+
? await fs.mkdtemp(path.join(await fs.realpath("/tmp"), "pagewrite-content-"))
|
|
37
|
+
: outputDir;
|
|
38
|
+
try {
|
|
39
|
+
if (options.clean && !options.dryRun) {
|
|
40
|
+
await fs.rm(targetDir, { recursive: true, force: true });
|
|
41
|
+
}
|
|
42
|
+
const result = await stageSiteContent(options.siteId, token, targetDir, {
|
|
43
|
+
logger: createConsoleLogger(),
|
|
44
|
+
pageSize: options.pageSize,
|
|
45
|
+
timeoutMs: options.timeoutMs,
|
|
46
|
+
});
|
|
47
|
+
if (options.dryRun) {
|
|
48
|
+
console.log(`Pagewrite dry run complete: fetched ${result.files.length} file(s) for site ${options.siteId}.`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.log(`Pagewrite fetch complete: wrote ${result.files.length} file(s) to ${outputDir}.`);
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
if (options.dryRun) {
|
|
55
|
+
await fs.rm(targetDir, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function parseArgs(argv) {
|
|
60
|
+
const options = {
|
|
61
|
+
command: "fetch",
|
|
62
|
+
outDir: "src/content/docs",
|
|
63
|
+
clean: false,
|
|
64
|
+
dryRun: false,
|
|
65
|
+
};
|
|
66
|
+
const [firstArg, ...rest] = argv;
|
|
67
|
+
const args = firstArg === "fetch" ? rest : argv;
|
|
68
|
+
if (firstArg === "help" || firstArg === "--help" || firstArg === "-h") {
|
|
69
|
+
return { ...options, command: "help" };
|
|
70
|
+
}
|
|
71
|
+
if (firstArg && firstArg !== "fetch" && firstArg.startsWith("-") === false) {
|
|
72
|
+
throw new Error(`Unknown command: ${firstArg}`);
|
|
73
|
+
}
|
|
74
|
+
for (let index = 0; index < args.length; index++) {
|
|
75
|
+
const arg = args[index];
|
|
76
|
+
switch (arg) {
|
|
77
|
+
case "--site-id":
|
|
78
|
+
options.siteId = readValue(args, ++index, arg);
|
|
79
|
+
break;
|
|
80
|
+
case "--out":
|
|
81
|
+
case "--output-dir":
|
|
82
|
+
options.outDir = readValue(args, ++index, arg);
|
|
83
|
+
break;
|
|
84
|
+
case "--token":
|
|
85
|
+
options.token = readValue(args, ++index, arg);
|
|
86
|
+
break;
|
|
87
|
+
case "--token-env":
|
|
88
|
+
case "--token-env-var":
|
|
89
|
+
options.tokenEnvVar = readValue(args, ++index, arg);
|
|
90
|
+
break;
|
|
91
|
+
case "--clean":
|
|
92
|
+
options.clean = true;
|
|
93
|
+
break;
|
|
94
|
+
case "--dry-run":
|
|
95
|
+
options.dryRun = true;
|
|
96
|
+
break;
|
|
97
|
+
case "--page-size":
|
|
98
|
+
options.pageSize = parsePositiveInteger(readValue(args, ++index, arg), arg);
|
|
99
|
+
break;
|
|
100
|
+
case "--timeout-ms":
|
|
101
|
+
options.timeoutMs = parsePositiveInteger(readValue(args, ++index, arg), arg);
|
|
102
|
+
break;
|
|
103
|
+
case "--help":
|
|
104
|
+
case "-h":
|
|
105
|
+
return { ...options, command: "help" };
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return options;
|
|
111
|
+
}
|
|
112
|
+
function readValue(args, index, option) {
|
|
113
|
+
const value = args[index];
|
|
114
|
+
if (!value || value.startsWith("--")) {
|
|
115
|
+
throw new Error(`Missing value for ${option}.`);
|
|
116
|
+
}
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
function parsePositiveInteger(value, option) {
|
|
120
|
+
const parsed = Number(value);
|
|
121
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
122
|
+
throw new Error(`${option} must be a positive integer.`);
|
|
123
|
+
}
|
|
124
|
+
return parsed;
|
|
125
|
+
}
|
|
126
|
+
function createConsoleLogger() {
|
|
127
|
+
return {
|
|
128
|
+
warn: (message) => console.warn(`[pagewrite-content] ${message}`),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
main(process.argv.slice(2)).catch((error) => {
|
|
132
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
133
|
+
console.error(`[pagewrite-content] ${message}`);
|
|
134
|
+
process.exitCode = 1;
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FileDocument, RemoteMdxLogger, SitePages, StagedSiteContent } from "./types.js";
|
|
2
|
+
export declare const STATIC_FILE_TREE_URL = "https://getstaticfiletree-hhjkelprqq-uc.a.run.app";
|
|
3
|
+
export declare const PAGINATED_FILE_DOCUMENTS_URL = "https://us-central1-sanity-freeform.cloudfunctions.net/getPaginatedFileDocuments";
|
|
4
|
+
export declare const DEFAULT_PAGE_SIZE = 100;
|
|
5
|
+
export interface FetchSiteContentOptions {
|
|
6
|
+
fetchImpl?: typeof fetch;
|
|
7
|
+
logger?: Pick<RemoteMdxLogger, "warn">;
|
|
8
|
+
pageSize?: number;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function fetchStaticFileTree(siteId: string, token: string, options?: FetchSiteContentOptions): Promise<SitePages>;
|
|
12
|
+
export declare function fetchAllFileDocuments(siteId: string, token: string, options?: FetchSiteContentOptions): Promise<Map<string, FileDocument>>;
|
|
13
|
+
export declare function stageSiteContent(siteId: string, token: string, contentDir: string, options?: FetchSiteContentOptions): Promise<StagedSiteContent>;
|
|
14
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EAEZ,eAAe,EACf,SAAS,EACT,iBAAiB,EAElB,MAAM,YAAY,CAAC;AASpB,eAAO,MAAM,oBAAoB,sDAAsD,CAAC;AACxF,eAAO,MAAM,4BAA4B,qFAC2C,CAAC;AACrF,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyCD,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,SAAS,CAAC,CA8CpB;AAED,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CA4BpC;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAqC5B"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { ensureDir, writeTextFile } from "./fs.js";
|
|
3
|
+
import { flattenFileNodes, safeRelativePath, toSegment, toSlug, upsertFrontmatter, } from "./utils.js";
|
|
4
|
+
export const STATIC_FILE_TREE_URL = "https://getstaticfiletree-hhjkelprqq-uc.a.run.app";
|
|
5
|
+
export const PAGINATED_FILE_DOCUMENTS_URL = "https://us-central1-sanity-freeform.cloudfunctions.net/getPaginatedFileDocuments";
|
|
6
|
+
export const DEFAULT_PAGE_SIZE = 100;
|
|
7
|
+
async function fetchJson(url, token, body, errorPrefix, options = {}) {
|
|
8
|
+
const controller = new AbortController();
|
|
9
|
+
const timeoutId = setTimeout(() => controller.abort(), options.timeoutMs ?? 30_000);
|
|
10
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetchImpl(url, {
|
|
13
|
+
method: "POST",
|
|
14
|
+
headers: {
|
|
15
|
+
"Content-Type": "application/json",
|
|
16
|
+
Authorization: `Bearer ${token}`,
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify(body),
|
|
19
|
+
signal: controller.signal,
|
|
20
|
+
});
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
const errorText = await response.text();
|
|
23
|
+
throw new Error(`${errorPrefix}: ${response.status} - ${errorText}`);
|
|
24
|
+
}
|
|
25
|
+
return (await response.json());
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
29
|
+
throw new Error(`${errorPrefix}: request timed out after ${options.timeoutMs ?? 30_000}ms`);
|
|
30
|
+
}
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
clearTimeout(timeoutId);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function fetchStaticFileTree(siteId, token, options = {}) {
|
|
38
|
+
const responseData = await fetchJson(STATIC_FILE_TREE_URL, token, { siteId }, "Failed to fetch static file tree", options);
|
|
39
|
+
const root = responseData.root;
|
|
40
|
+
if (!root || !root.isFolder) {
|
|
41
|
+
throw new Error("Invalid file tree response: root folder is missing");
|
|
42
|
+
}
|
|
43
|
+
const walkFolder = (children, parentPath) => children.map((child) => {
|
|
44
|
+
const title = typeof child.title === "string" && child.title.trim().length > 0 ? child.title : child.id;
|
|
45
|
+
const childPath = parentPath ? `${parentPath}/${toSegment(title, child.id)}` : toSegment(title, child.id);
|
|
46
|
+
if (child.isFolder) {
|
|
47
|
+
return {
|
|
48
|
+
id: child.id,
|
|
49
|
+
type: "folder",
|
|
50
|
+
title,
|
|
51
|
+
path: childPath,
|
|
52
|
+
databaseType: child.databaseType,
|
|
53
|
+
lang: child.lang,
|
|
54
|
+
children: walkFolder(child.children ?? [], childPath),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
id: child.id,
|
|
59
|
+
type: "file",
|
|
60
|
+
title,
|
|
61
|
+
path: childPath,
|
|
62
|
+
storageFile: "",
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
siteId,
|
|
67
|
+
rootFolderId: root.id,
|
|
68
|
+
pages: walkFolder(root.children ?? [], ""),
|
|
69
|
+
tags: {},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export async function fetchAllFileDocuments(siteId, token, options = {}) {
|
|
73
|
+
const documents = new Map();
|
|
74
|
+
let pageToken = null;
|
|
75
|
+
do {
|
|
76
|
+
const responseData = await fetchJson(PAGINATED_FILE_DOCUMENTS_URL, token, {
|
|
77
|
+
siteId,
|
|
78
|
+
pageSize: options.pageSize ?? DEFAULT_PAGE_SIZE,
|
|
79
|
+
pageToken,
|
|
80
|
+
}, "Failed to fetch paginated file documents", options);
|
|
81
|
+
for (const document of responseData.documents ?? []) {
|
|
82
|
+
documents.set(document.id, document);
|
|
83
|
+
}
|
|
84
|
+
pageToken = responseData.nextPageToken ?? null;
|
|
85
|
+
} while (pageToken);
|
|
86
|
+
return documents;
|
|
87
|
+
}
|
|
88
|
+
export async function stageSiteContent(siteId, token, contentDir, options = {}) {
|
|
89
|
+
const [sitePages, documents] = await Promise.all([
|
|
90
|
+
fetchStaticFileTree(siteId, token, options),
|
|
91
|
+
fetchAllFileDocuments(siteId, token, options),
|
|
92
|
+
]);
|
|
93
|
+
const fileNodes = flattenFileNodes(sitePages.pages);
|
|
94
|
+
await ensureDir(contentDir);
|
|
95
|
+
const files = [];
|
|
96
|
+
for (const fileNode of fileNodes) {
|
|
97
|
+
const normalizedPath = safeRelativePath(fileNode.path);
|
|
98
|
+
const relPath = `${normalizedPath}.mdx`;
|
|
99
|
+
const absolutePath = path.join(contentDir, relPath);
|
|
100
|
+
const document = documents.get(fileNode.id);
|
|
101
|
+
if (!document) {
|
|
102
|
+
options.logger?.warn(`Document not found for file node: ${fileNode.id} (${fileNode.title})`);
|
|
103
|
+
}
|
|
104
|
+
const slug = toSlug(normalizedPath);
|
|
105
|
+
const contentWithFrontmatter = upsertFrontmatter(document?.mdxString ?? "", fileNode.title, slug);
|
|
106
|
+
await ensureDir(path.dirname(absolutePath));
|
|
107
|
+
await writeTextFile(absolutePath, contentWithFrontmatter);
|
|
108
|
+
files.push({
|
|
109
|
+
id: fileNode.id,
|
|
110
|
+
relPath,
|
|
111
|
+
absolutePath,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
sitePages,
|
|
116
|
+
files,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/fs.d.ts
ADDED
package/dist/fs.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAEA,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpF"}
|
package/dist/fs.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
export async function ensureDir(dirPath) {
|
|
3
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
4
|
+
}
|
|
5
|
+
export async function writeTextFile(filePath, content) {
|
|
6
|
+
await fs.writeFile(filePath, content, "utf8");
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=fs.js.map
|
package/dist/fs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.js","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe;IACnE,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AstroIntegration } from "astro";
|
|
2
|
+
import type { RemoteMdxOptions } from "./types.js";
|
|
3
|
+
export type { FileDocument, PageTreeFileNode, PageTreeFolderNode, PageTreeNode, RemoteMdxOptions, SitePages, StagedSiteContent, StaticTreeChild, } from "./types.js";
|
|
4
|
+
export { DEFAULT_PAGE_SIZE, PAGINATED_FILE_DOCUMENTS_URL, STATIC_FILE_TREE_URL, fetchAllFileDocuments, fetchStaticFileTree, stageSiteContent, } from "./client.js";
|
|
5
|
+
export { resolveToken } from "./token.js";
|
|
6
|
+
export { flattenFileNodes, safeRelativePath, toSegment, toSlug, upsertFrontmatter } from "./utils.js";
|
|
7
|
+
export default function pagewriteAstro(options: RemoteMdxOptions): AstroIntegration;
|
|
8
|
+
export declare function remoteMdx(options: RemoteMdxOptions): AstroIntegration;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAK9C,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEpE,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtG,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAElF;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,gBAAgB,CAyBrE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { stageSiteContent } from "./client.js";
|
|
5
|
+
import { resolveToken } from "./token.js";
|
|
6
|
+
export { DEFAULT_PAGE_SIZE, PAGINATED_FILE_DOCUMENTS_URL, STATIC_FILE_TREE_URL, fetchAllFileDocuments, fetchStaticFileTree, stageSiteContent, } from "./client.js";
|
|
7
|
+
export { resolveToken } from "./token.js";
|
|
8
|
+
export { flattenFileNodes, safeRelativePath, toSegment, toSlug, upsertFrontmatter } from "./utils.js";
|
|
9
|
+
export default function pagewriteAstro(options) {
|
|
10
|
+
return remoteMdx(options);
|
|
11
|
+
}
|
|
12
|
+
export function remoteMdx(options) {
|
|
13
|
+
return {
|
|
14
|
+
name: "@lakshmanshankar/pagwrite-astro",
|
|
15
|
+
hooks: {
|
|
16
|
+
"astro:config:setup": async ({ config, logger }) => {
|
|
17
|
+
const integrationLogger = createLogger(logger);
|
|
18
|
+
const token = resolveToken(options);
|
|
19
|
+
const root = fileURLToPath(config.root);
|
|
20
|
+
const outputDir = path.resolve(root, options.outputDir ?? "src/content/docs");
|
|
21
|
+
if (options.clean ?? false) {
|
|
22
|
+
logger.info(`Cleaning Pagewrite content directory: ${outputDir}`);
|
|
23
|
+
await fs.rm(outputDir, { recursive: true, force: true });
|
|
24
|
+
}
|
|
25
|
+
logger.info("Fetching Pagewrite site content");
|
|
26
|
+
const result = await stageSiteContent(options.siteId, token, outputDir, {
|
|
27
|
+
logger: integrationLogger,
|
|
28
|
+
});
|
|
29
|
+
logger.info(`Pagewrite content sync complete: ${result.files.length} file(s) written`);
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function createLogger(logger) {
|
|
35
|
+
return {
|
|
36
|
+
info: (message) => logger.info(message),
|
|
37
|
+
warn: (message) => logger.warn(message),
|
|
38
|
+
error: (message) => logger.error(message),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc1C,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtG,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAyB;IAC9D,OAAO,SAAS,CAAC,OAAO,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,OAAyB;IACjD,OAAO;QACL,IAAI,EAAE,iCAAiC;QACvC,KAAK,EAAE;YACL,oBAAoB,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;gBACjD,MAAM,iBAAiB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;gBACpC,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC,CAAC;gBAE9E,IAAI,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC;oBAC3B,MAAM,CAAC,IAAI,CAAC,yCAAyC,SAAS,EAAE,CAAC,CAAC;oBAClE,MAAM,EAAE,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3D,CAAC;gBAED,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;gBAE/C,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE;oBACtE,MAAM,EAAE,iBAAiB;iBAC1B,CAAC,CAAC;gBAEH,MAAM,CAAC,IAAI,CAAC,oCAAoC,MAAM,CAAC,KAAK,CAAC,MAAM,kBAAkB,CAAC,CAAC;YACzF,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,MAIrB;IACC,OAAO;QACL,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;QACvC,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;QACvC,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;KAC1C,CAAC;AACJ,CAAC"}
|
package/dist/token.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,eAAO,MAAM,qBAAqB,qBAAqB,CAAC;AAExD,wBAAgB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAe9D"}
|
package/dist/token.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const DEFAULT_TOKEN_ENV_VAR = "REMOTE_MDX_TOKEN";
|
|
2
|
+
export function resolveToken(options) {
|
|
3
|
+
if (options.token?.trim()) {
|
|
4
|
+
return options.token.trim();
|
|
5
|
+
}
|
|
6
|
+
const envVar = options.tokenEnvVar ?? DEFAULT_TOKEN_ENV_VAR;
|
|
7
|
+
const token = process.env[envVar]?.trim();
|
|
8
|
+
if (token) {
|
|
9
|
+
return token;
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`[pagewrite:astro] Build token not found. Set ${envVar} or pass token in the integration options.`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAExD,MAAM,UAAU,YAAY,CAAC,OAAyB;IACpD,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,IAAI,qBAAqB,CAAC;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;IAE1C,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,KAAK,CACb,gDAAgD,MAAM,4CAA4C,CACnG,CAAC;AACJ,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface RemoteMdxOptions {
|
|
2
|
+
siteId: string;
|
|
3
|
+
token?: string;
|
|
4
|
+
tokenEnvVar?: string;
|
|
5
|
+
outputDir?: string;
|
|
6
|
+
clean?: boolean;
|
|
7
|
+
verbose?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface StaticTreeChild {
|
|
10
|
+
id: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
isFolder: boolean;
|
|
13
|
+
children?: StaticTreeChild[];
|
|
14
|
+
databaseType?: string;
|
|
15
|
+
lang?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface PageTreeFolderNode {
|
|
18
|
+
id: string;
|
|
19
|
+
type: "folder";
|
|
20
|
+
title: string;
|
|
21
|
+
path: string;
|
|
22
|
+
databaseType?: string;
|
|
23
|
+
lang?: string;
|
|
24
|
+
children: PageTreeNode[];
|
|
25
|
+
}
|
|
26
|
+
export interface PageTreeFileNode {
|
|
27
|
+
id: string;
|
|
28
|
+
type: "file";
|
|
29
|
+
title: string;
|
|
30
|
+
path: string;
|
|
31
|
+
storageFile: string;
|
|
32
|
+
}
|
|
33
|
+
export type PageTreeNode = PageTreeFolderNode | PageTreeFileNode;
|
|
34
|
+
export interface SitePages {
|
|
35
|
+
siteId: string;
|
|
36
|
+
rootFolderId: string;
|
|
37
|
+
pages: PageTreeNode[];
|
|
38
|
+
tags: Record<string, unknown>;
|
|
39
|
+
}
|
|
40
|
+
export interface FileDocument {
|
|
41
|
+
id: string;
|
|
42
|
+
mdxString?: string;
|
|
43
|
+
[key: string]: unknown;
|
|
44
|
+
}
|
|
45
|
+
export interface StagedSiteContentFile {
|
|
46
|
+
id: string;
|
|
47
|
+
relPath: string;
|
|
48
|
+
absolutePath: string;
|
|
49
|
+
}
|
|
50
|
+
export interface StagedSiteContent {
|
|
51
|
+
sitePages: SitePages;
|
|
52
|
+
files: StagedSiteContentFile[];
|
|
53
|
+
}
|
|
54
|
+
export interface RemoteMdxLogger {
|
|
55
|
+
info(message: string): void;
|
|
56
|
+
warn(message: string): void;
|
|
57
|
+
error(message: string): void;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,gBAAgB,CAAC;AAEjE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,qBAAqB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PageTreeFileNode, PageTreeNode } from "./types.js";
|
|
2
|
+
export declare function flattenFileNodes(nodes: PageTreeNode[]): PageTreeFileNode[];
|
|
3
|
+
export declare function safeRelativePath(value: string): string;
|
|
4
|
+
export declare function toSegment(title: string, fallback: string): string;
|
|
5
|
+
export declare function toSlug(relativePath: string): string;
|
|
6
|
+
export declare function upsertFrontmatter(content: string, title: string, slug: string): string;
|
|
7
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,gBAAgB,EAAE,CAY1E;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAuBtD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,wBAAgB,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAwBtF"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function flattenFileNodes(nodes) {
|
|
3
|
+
const files = [];
|
|
4
|
+
for (const node of nodes) {
|
|
5
|
+
if (node.type === "file") {
|
|
6
|
+
files.push(node);
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
files.push(...flattenFileNodes(node.children));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return files;
|
|
13
|
+
}
|
|
14
|
+
export function safeRelativePath(value) {
|
|
15
|
+
const normalizedSlashes = value.replace(/\\/g, "/").trim();
|
|
16
|
+
if (!normalizedSlashes || normalizedSlashes.includes("\0")) {
|
|
17
|
+
throw new Error("Invalid empty content path");
|
|
18
|
+
}
|
|
19
|
+
if (path.posix.isAbsolute(normalizedSlashes)) {
|
|
20
|
+
throw new Error(`Unsafe absolute content path: ${value}`);
|
|
21
|
+
}
|
|
22
|
+
const normalized = path.posix.normalize(normalizedSlashes);
|
|
23
|
+
if (normalized === "." ||
|
|
24
|
+
normalized === ".." ||
|
|
25
|
+
normalized.startsWith("../") ||
|
|
26
|
+
normalized.includes("/../")) {
|
|
27
|
+
throw new Error(`Unsafe relative content path: ${value}`);
|
|
28
|
+
}
|
|
29
|
+
return normalized;
|
|
30
|
+
}
|
|
31
|
+
export function toSegment(title, fallback) {
|
|
32
|
+
const slug = slugify(title);
|
|
33
|
+
return slug || slugify(fallback) || fallback;
|
|
34
|
+
}
|
|
35
|
+
export function toSlug(relativePath) {
|
|
36
|
+
return safeRelativePath(relativePath)
|
|
37
|
+
.split("/")
|
|
38
|
+
.map((segment) => toSegment(segment, segment))
|
|
39
|
+
.join("/");
|
|
40
|
+
}
|
|
41
|
+
export function upsertFrontmatter(content, title, slug) {
|
|
42
|
+
const normalizedContent = content.replace(/^\uFEFF/, "");
|
|
43
|
+
const titleLine = `title: ${quoteYamlString(title)}`;
|
|
44
|
+
const slugLine = `slug: ${quoteYamlString(slug)}`;
|
|
45
|
+
if (!normalizedContent.startsWith("---\n")) {
|
|
46
|
+
return `---\n${titleLine}\n${slugLine}\n---\n\n${normalizedContent}`;
|
|
47
|
+
}
|
|
48
|
+
const endIndex = normalizedContent.indexOf("\n---", 4);
|
|
49
|
+
if (endIndex === -1) {
|
|
50
|
+
return `---\n${titleLine}\n${slugLine}\n---\n\n${normalizedContent}`;
|
|
51
|
+
}
|
|
52
|
+
const existingFrontmatter = normalizedContent.slice(4, endIndex);
|
|
53
|
+
const bodyStart = normalizedContent.startsWith("\n", endIndex + 4) ? endIndex + 5 : endIndex + 4;
|
|
54
|
+
const body = normalizedContent.slice(bodyStart);
|
|
55
|
+
const remainingLines = existingFrontmatter
|
|
56
|
+
.split("\n")
|
|
57
|
+
.filter((line) => !/^title\s*:/.test(line) && !/^slug\s*:/.test(line))
|
|
58
|
+
.filter((line, index, lines) => line.trim() !== "" || index < lines.length - 1);
|
|
59
|
+
const nextFrontmatter = [titleLine, slugLine, ...remainingLines].join("\n").trim();
|
|
60
|
+
return `---\n${nextFrontmatter}\n---${body.startsWith("\n") ? "" : "\n"}${body}`;
|
|
61
|
+
}
|
|
62
|
+
function slugify(value) {
|
|
63
|
+
return value
|
|
64
|
+
.normalize("NFKD")
|
|
65
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
66
|
+
.toLowerCase()
|
|
67
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
68
|
+
.replace(/^-+|-+$/g, "");
|
|
69
|
+
}
|
|
70
|
+
function quoteYamlString(value) {
|
|
71
|
+
return JSON.stringify(value);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,MAAM,UAAU,gBAAgB,CAAC,KAAqB;IACpD,MAAM,KAAK,GAAuB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,iBAAiB,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAE3D,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAE3D,IACE,UAAU,KAAK,GAAG;QAClB,UAAU,KAAK,IAAI;QACnB,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC;QAC5B,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAC3B,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,QAAgB;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,OAAO,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,YAAoB;IACzC,OAAO,gBAAgB,CAAC,YAAY,CAAC;SAClC,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SAC7C,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,KAAa,EAAE,IAAY;IAC5E,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACzD,MAAM,SAAS,GAAG,UAAU,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAG,SAAS,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;IAElD,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,OAAO,QAAQ,SAAS,KAAK,QAAQ,YAAY,iBAAiB,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACvD,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,OAAO,QAAQ,SAAS,KAAK,QAAQ,YAAY,iBAAiB,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACjE,MAAM,SAAS,GAAG,iBAAiB,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;IACjG,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,cAAc,GAAG,mBAAmB;SACvC,KAAK,CAAC,IAAI,CAAC;SACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACrE,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAClF,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAEnF,OAAO,QAAQ,eAAe,QAAQ,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;AACnF,CAAC;AAED,SAAS,OAAO,CAAC,KAAa;IAC5B,OAAO,KAAK;SACT,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lakshmanshankar/pagwrite-astro",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Astro integration for fetching Pagewrite MDX content at build time.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"CLI.md"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"astro",
|
|
21
|
+
"mdx",
|
|
22
|
+
"pagewrite"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"astro": ">=4.0.0 || >=5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20.14.0",
|
|
30
|
+
"astro": "^5.0.0",
|
|
31
|
+
"typescript": "^5.5.0",
|
|
32
|
+
"vitest": "^2.0.0",
|
|
33
|
+
"tsx": "^4.19.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.17.0"
|
|
37
|
+
},
|
|
38
|
+
"bin": {
|
|
39
|
+
"pagewrite-content": "./dist/cli.js"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "pnpm run clean && tsc -p tsconfig.json",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
45
|
+
"clean": "node scripts/clean-dist.mjs"
|
|
46
|
+
}
|
|
47
|
+
}
|