@sleekcms/sync 1.4.1 → 1.4.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/dist/AGENT.md +4 -0
- package/dist/setup-site.js +40 -4
- package/dist/watcher.js +1 -1
- package/package.json +1 -1
package/dist/AGENT.md
CHANGED
|
@@ -246,6 +246,8 @@ The `_block` value is the block's key (e.g., `"hero"`, `"cta"`) — never a nume
|
|
|
246
246
|
|
|
247
247
|
Like blocks, stacks cannot be nested inside block models. Stack items themselves may contain groups, collections, and entry references, but not other stacks or blocks.
|
|
248
248
|
|
|
249
|
+
If the Blocks are only used in one page, simply structure the model as nested fields. Do not use Block or Stack fields in those cases.
|
|
250
|
+
|
|
249
251
|
**Entry reference** — Use `entry(key)` for one, `[entry(key)]` for many:
|
|
250
252
|
```
|
|
251
253
|
{
|
|
@@ -729,3 +731,5 @@ Template:
|
|
|
729
731
|
16. **Collection pages whose model qualifies as "markdown content" — page model, collection (key ends with `+`), exactly one top-level `markdown` field, no `richtext` or `stack` anywhere — are stored as `.md` files with JSON frontmatter at `content/pages/<key+>/<slug>.md` (not `.json`).** All non-markdown fields go into the JSON frontmatter object between the `---` markers; the single `markdown` field's value is the body. When creating or editing such a record, prefer `.md`; the server also accepts `.json` for the same model. Inside the `.md` file, frontmatter may be written as JSON (canonical), JSON5 (trailing commas, `//` or `/* */` comments, unquoted keys), or YAML — all three are parsed correctly on save. Pulls always re-emit JSON as the canonical form.
|
|
730
732
|
17. Always create RSS feed for blogs and link them in meta so it is discoverable. Use "rss.xml" as the key.
|
|
731
733
|
18. Make the sites extremely SEO friendly and sharing friendly.
|
|
734
|
+
19. When naming files for models, use - (dash) as word separator. Don't use _ (underscore) as it is mapped to / (slash) in path
|
|
735
|
+
|
package/dist/setup-site.js
CHANGED
|
@@ -172,11 +172,18 @@ async function pushLocalChanges(viewsDir, fileMap, apiBase, token) {
|
|
|
172
172
|
console.error("❌ Error saving files:", e.body || e.message);
|
|
173
173
|
return 0;
|
|
174
174
|
}
|
|
175
|
-
const errors = await
|
|
175
|
+
const errors = await getSessionErrors(viewsDir);
|
|
176
176
|
let pushed = 0;
|
|
177
|
+
const resultsByPath = indexSaveResultsByPath(results);
|
|
177
178
|
for (let i = 0; i < changes.length; i++) {
|
|
178
179
|
const c = changes[i];
|
|
179
|
-
const r =
|
|
180
|
+
const r = getSaveResult(c, i, results, resultsByPath);
|
|
181
|
+
if (!r) {
|
|
182
|
+
const msg = "No save response returned";
|
|
183
|
+
errors[c.rel] = msg;
|
|
184
|
+
console.error(`❌ Error saving ${c.rel}: ${msg}`);
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
180
187
|
if (r.error) {
|
|
181
188
|
errors[c.rel] = r.error;
|
|
182
189
|
console.error(`❌ Error saving ${c.rel}: ${r.error}`);
|
|
@@ -194,10 +201,37 @@ async function pushLocalChanges(viewsDir, fileMap, apiBase, token) {
|
|
|
194
201
|
console.log(`✅ ${c.prior ? "Updated" : "Created"} ${c.rel}`);
|
|
195
202
|
pushed++;
|
|
196
203
|
}
|
|
197
|
-
await
|
|
204
|
+
await dumpErrors(viewsDir, errors);
|
|
198
205
|
return pushed;
|
|
199
206
|
}
|
|
207
|
+
function indexSaveResultsByPath(results) {
|
|
208
|
+
const byPath = new Map();
|
|
209
|
+
for (const result of results) {
|
|
210
|
+
if (result.path)
|
|
211
|
+
byPath.set(result.path, result);
|
|
212
|
+
}
|
|
213
|
+
return byPath;
|
|
214
|
+
}
|
|
215
|
+
function getSaveResult(change, index, results, resultsByPath) {
|
|
216
|
+
const resultByPath = resultsByPath.get(change.rel);
|
|
217
|
+
if (resultByPath)
|
|
218
|
+
return resultByPath;
|
|
219
|
+
const resultByIndex = results[index];
|
|
220
|
+
if (!resultByIndex?.path || resultByIndex.path === change.rel)
|
|
221
|
+
return resultByIndex;
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
200
224
|
const ERROR_LOG = "sync-errors.log";
|
|
225
|
+
const syncErrorsByWorkspace = new Map();
|
|
226
|
+
async function getSessionErrors(viewsDir) {
|
|
227
|
+
const workspace = path_1.default.resolve(viewsDir);
|
|
228
|
+
const cached = syncErrorsByWorkspace.get(workspace);
|
|
229
|
+
if (cached)
|
|
230
|
+
return cached;
|
|
231
|
+
const errors = await loadErrors(workspace);
|
|
232
|
+
syncErrorsByWorkspace.set(workspace, errors);
|
|
233
|
+
return errors;
|
|
234
|
+
}
|
|
201
235
|
async function loadErrors(viewsDir) {
|
|
202
236
|
const file = path_1.default.join(viewsDir, ERROR_LOG);
|
|
203
237
|
if (!(await fs_extra_1.default.pathExists(file)))
|
|
@@ -211,7 +245,7 @@ async function loadErrors(viewsDir) {
|
|
|
211
245
|
}
|
|
212
246
|
return errors;
|
|
213
247
|
}
|
|
214
|
-
async function
|
|
248
|
+
async function dumpErrors(viewsDir, errors) {
|
|
215
249
|
const file = path_1.default.join(viewsDir, ERROR_LOG);
|
|
216
250
|
const entries = Object.entries(errors);
|
|
217
251
|
if (entries.length === 0) {
|
|
@@ -221,6 +255,8 @@ async function saveErrors(viewsDir, errors) {
|
|
|
221
255
|
await fs_extra_1.default.outputFile(file, entries.map(([p, msg]) => `${p}: ${msg}`).join("\n") + "\n");
|
|
222
256
|
}
|
|
223
257
|
async function pullServerState(viewsDir, apiBase, token) {
|
|
258
|
+
syncErrorsByWorkspace.delete(path_1.default.resolve(viewsDir));
|
|
259
|
+
await fs_extra_1.default.remove(path_1.default.join(viewsDir, ERROR_LOG));
|
|
224
260
|
console.log("📥 Fetching files...");
|
|
225
261
|
const files = await request(apiBase, token, "GET", "/get_files");
|
|
226
262
|
const fileMap = {};
|
package/dist/watcher.js
CHANGED
|
@@ -18,7 +18,7 @@ exports.stopWatching = stopWatching;
|
|
|
18
18
|
const path_1 = __importDefault(require("path"));
|
|
19
19
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
20
20
|
const DEBOUNCE_DELAY = 5000;
|
|
21
|
-
const IDLE_TIMEOUT_MS =
|
|
21
|
+
const IDLE_TIMEOUT_MS = 60 * 60 * 1000;
|
|
22
22
|
// Poll on a short interval and compare wall-clock time so the timeout still
|
|
23
23
|
// fires correctly after the system has been asleep (Node's setTimeout runs on
|
|
24
24
|
// a monotonic clock that pauses during sleep).
|