@onlyworlds/sdk 4.62.0 → 4.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -1
- package/CHANGELOG.md +12 -0
- package/README.md +2 -0
- package/SCHEMA.md +1 -1
- package/dist/index.d.ts +30 -7
- package/dist/index.js +47 -2
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# For AI agents using @onlyworlds/sdk
|
|
2
2
|
|
|
3
|
-
**Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.
|
|
3
|
+
**Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.49** (canonical 00.33.00).
|
|
4
4
|
This line is asserted by `codegen:check` in CI — if the pin moves and this file is not
|
|
5
5
|
re-read against it, the check fails rather than letting this document rot quietly.
|
|
6
6
|
|
|
@@ -88,6 +88,8 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
|
|
|
88
88
|
§4.7 (`.owworld`): the reader checks the central directory before inflating
|
|
89
89
|
and ignores files beside the world's folder; the writer's output is byte-stable (marker
|
|
90
90
|
first, UTF-8 name order, 1980 stamps) and holds only `world.json` and the folder's parts.
|
|
91
|
+
Producers marked `"private": true` in `records/RECORDS.json` are left out whole unless
|
|
92
|
+
`writeWorldFile(files, topDir, { includePrivateRecords: true })` (since 4.63.0; OW-8).
|
|
91
93
|
- World calendars (since 4.20.0): `worldCalendars(elements)` finds the elements carrying
|
|
92
94
|
`atlas_calendar` (Atlas owns the field: read it, never write it); `resolveCalendarLens` picks
|
|
93
95
|
one; `formatStep(config, step)` names a point on the world's integer time line, `parseDate`
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.63.0] - 2026-10-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`writeWorldFile(files, topDir, { includePrivateRecords })`**, OW-8's private clause (folder format spec v0.3.15, §4.5 rule 11 and §4.7). By default the writer now leaves out, whole, every `records/<producer>/` directory whose entry in `records/RECORDS.json` says `"private": true`, so a tool's own notes do not travel the first time a world is shared. `RECORDS.json` itself travels byte-exact, its private entries kept, so a reader can see a producer was left out. Only the boolean `true` marks a directory private (`"true"`, a string, does not). A producer's name matches its directory by the archive's one fold (NFC, then simple case folding), so a manifest's `Fold` leaves out `records/fold/` on a disk that ignores case. With `includePrivateRecords: true` every record travels as before and the manifest is not read. No manifest, nothing is private. Type `OwWriteWorldFileOptions`.
|
|
13
|
+
- **A manifest the writer cannot read is refused, not guessed at**: a `RECORDS.json` that is not JSON, not an array, holds an entry that is not an object, or marks an entry private without a producer name throws a `TypeError` naming the file and the option, having written nothing, unless `includePrivateRecords: true` is passed. A world whose manifest is in an older shape now needs the option to be written. The options object refuses an unknown key, and an `includePrivateRecords` that is not a boolean, with a `TypeError`, before anything else.
|
|
14
|
+
- Tests: the conformance set's four private cases, written from its `sources.private` world (each source file checked by its sha256): the default side equals `pass-OW-8-private-left-out` and the asked side `pass-OW-8-private-asked`, entry for entry, and neither is `fail-OW-8-private-partial` or `fail-OW-8-private-manifest-rewritten`. Also the string `"true"`, a producer whose name is a prefix of another's, no manifest, each unreadable manifest refused and carried when asked, and the options. Each behaviour watched failing on its own mutant.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **Schema repinned to schema-dist `v0.33.0-dist.49`** (same canonical 00.33.00; no schema file moved, no generated type changed, `ONLYWORLDS_VERSION` still `'00.33.00'`). The `.owworld` conformance set grows to 85 zips with the four OW-8 private-records writer cases on `sources.private`; none of the earlier 81 moved.
|
|
19
|
+
|
|
8
20
|
## [4.62.0] - 2026-10-22
|
|
9
21
|
|
|
10
22
|
### Added
|
package/README.md
CHANGED
|
@@ -285,6 +285,8 @@ Files beside the world's folder and archive junk (`__MACOSX`, `.DS_Store`) are i
|
|
|
285
285
|
|
|
286
286
|
The writer gives the same bytes for the same files: the `mimetype` marker first, then every entry in the UTF-8 order of its name, stamped 1980-01-01 00:00. It writes `world.json`, `elements/`, `spatial/`, `media/` and `records/`, and leaves any other file out. A tool's dot-folder you hand it travels too, which makes the file a private copy rather than a portable `.owworld`.
|
|
287
287
|
|
|
288
|
+
`records/` travels byte for byte, except a producer's directory that `records/RECORDS.json` marks `"private": true`: that one is left out whole, and `RECORDS.json` itself travels unchanged, so the reader can see a producer was left out. Pass `writeWorldFile(files, topDir, { includePrivateRecords: true })` to carry private records too. A `RECORDS.json` that is not a JSON array of objects is refused with a `TypeError` unless you pass that option, since the writer cannot tell which records are private.
|
|
289
|
+
|
|
288
290
|
## World calendars
|
|
289
291
|
|
|
290
292
|
A world's time is an integer line (`time_range_current` is a point on it, and so is an Event's `start_date`). A calendar names its points: months, days, eras. Atlas keeps a calendar on an element (a Construct by convention) in its `atlas_calendar` field, and the SDK reads it with Atlas's own calendar code (since 4.20.0). Atlas owns that field and is its only writer; read it, never write it.
|
package/SCHEMA.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OnlyWorlds Schema Reference
|
|
2
2
|
|
|
3
|
-
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.
|
|
3
|
+
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.49** — canonical schema **00.33.00**, published 2026-10-22.
|
|
4
4
|
|
|
5
5
|
GENERATED from the canonical schema YAML — do not hand-edit (regenerate: `python codegen/generate_types.py`).
|
|
6
6
|
Written for both humans and AI agents reading this package locally.
|
package/dist/index.d.ts
CHANGED
|
@@ -4324,7 +4324,9 @@ declare function typeWord(world: object | null | undefined, type: string, opts?:
|
|
|
4324
4324
|
* THE WRITER emits a portable copy (OW-7, OW-12, OW-13): the `mimetype` marker
|
|
4325
4325
|
* first and stored, then only the folder's parts, every entry stamped
|
|
4326
4326
|
* 1980-01-01 00:00, in the UTF-8 byte order of its name, JSON deflated and
|
|
4327
|
-
* everything else stored.
|
|
4327
|
+
* everything else stored. `records/` travels whole and byte-exact, except the
|
|
4328
|
+
* producers `records/RECORDS.json` marks private, left out whole unless the
|
|
4329
|
+
* caller asks (OW-8, §4.5 rule 11).
|
|
4328
4330
|
*
|
|
4329
4331
|
* A tool's own `.<tool>/` folder is the tool's (spec §4): the reader returns
|
|
4330
4332
|
* it like any file (a caller leaves files out with `skip`), and the writer
|
|
@@ -4372,6 +4374,13 @@ declare function simpleCaseFold(text: string): string;
|
|
|
4372
4374
|
* nothing; the caller writes only what this returns.
|
|
4373
4375
|
*/
|
|
4374
4376
|
declare function readWorldFile(bytes: Uint8Array, opts?: OwReadWorldFileOptions): OwReadWorldFile;
|
|
4377
|
+
interface OwWriteWorldFileOptions {
|
|
4378
|
+
/**
|
|
4379
|
+
* Carry the producers marked private in `records/RECORDS.json` (spec §4.5
|
|
4380
|
+
* rule 11, OW-8). Left out or false, their directories are left out whole.
|
|
4381
|
+
*/
|
|
4382
|
+
includePrivateRecords?: boolean;
|
|
4383
|
+
}
|
|
4375
4384
|
/**
|
|
4376
4385
|
* Write a world file under one top-level folder `topDir`: the `mimetype`
|
|
4377
4386
|
* marker first and stored, then `world.json` (without `api`) and the folder's
|
|
@@ -4379,12 +4388,26 @@ declare function readWorldFile(bytes: Uint8Array, opts?: OwReadWorldFileOptions)
|
|
|
4379
4388
|
* deflated and everything else stored (spec §4.7, OW-6, OW-7, OW-12, OW-13).
|
|
4380
4389
|
* Any other file is left out. A tool's dot-folder in `files` travels, and
|
|
4381
4390
|
* makes the result a private copy, not a portable `.owworld` (OW-7): leave it
|
|
4382
|
-
* out of `files` for a portable one.
|
|
4383
|
-
*
|
|
4384
|
-
*
|
|
4385
|
-
*
|
|
4391
|
+
* out of `files` for a portable one.
|
|
4392
|
+
*
|
|
4393
|
+
* `records/` travels byte-exact, except private records (OW-8, spec §4.5 rule
|
|
4394
|
+
* 11): every `records/<producer>/` whose entry in `records/RECORDS.json` says
|
|
4395
|
+
* `"private": true` (the boolean; `"true"` is not private; the name matched by
|
|
4396
|
+
* OW-18's fold, so `Fold` names `records/fold/`) is left out whole,
|
|
4397
|
+
* and `RECORDS.json` itself travels byte-exact, its private entries kept, so a
|
|
4398
|
+
* reader learns a producer was left out. Pass `{ includePrivateRecords: true }`
|
|
4399
|
+
* to carry them; then the manifest is not read and every record travels. No
|
|
4400
|
+
* manifest, nothing is private.
|
|
4401
|
+
*
|
|
4402
|
+
* Throws a `TypeError`, having written nothing, for an unknown option, an
|
|
4403
|
+
* `includePrivateRecords` that is not a boolean, and (unless private records
|
|
4404
|
+
* are asked for) a `RECORDS.json` that is not a JSON array of objects or that
|
|
4405
|
+
* marks an entry private without a producer name. Refuses (`OwWorldFileError`)
|
|
4406
|
+
* an unsafe path or `topDir`, a duplicate path, a name some disk cannot hold,
|
|
4407
|
+
* two names that fold to one, and a world.json that is missing, will not parse
|
|
4408
|
+
* (it may hold a key, so it is never zipped raw) or has no `id`.
|
|
4386
4409
|
*/
|
|
4387
|
-
declare function writeWorldFile(files: OwWorldFileEntry[], topDir: string): Uint8Array;
|
|
4410
|
+
declare function writeWorldFile(files: OwWorldFileEntry[], topDir: string, opts?: OwWriteWorldFileOptions): Uint8Array;
|
|
4388
4411
|
|
|
4389
4412
|
/**
|
|
4390
4413
|
* World lookup: find the elements a plain-language question is about, in a
|
|
@@ -5195,4 +5218,4 @@ declare class TokenResource {
|
|
|
5195
5218
|
getEncryptionInfo(): Promise<EncryptionInfo>;
|
|
5196
5219
|
}
|
|
5197
5220
|
|
|
5198
|
-
export { AGENT_DOORS, ASK_LIMITS, type AccessKeyResponse, CALENDAR_FIELD, CALENDAR_SUPERTYPE, type CalendarConfig, type CalendarEra, type CalendarIntercalary, type CalendarMonths, type CalendarWeek, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, type EraDomain, FAMILY_COLORS, FAMILY_ORDER, FIELD_ACRONYMS, FIELD_SCHEMA, FILE_EXTENSIONS, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAccountWorld, type OwAgentJoined, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, type OwChange, type OwChangeDelete, type OwChangeUpsert, type OwChangesPage, type OwClientConfig, type OwCreatedWorldLink, type OwDeleteReason, type OwDraught, type OwDraughtComponent, type OwDraughtItem, type OwDraughtPolicy, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwFrontDoor, type OwHiddenRow, type OwJoinPreview, type OwJoined, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, type OwMintedKey, type OwNamesMap, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwProposal, type OwProposalAccepted, type OwProposalConflict, type OwProposalList, type OwProposalQuery, type OwProposalState, type OwProposeInput, type OwProposed, OwProposedError, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwSeat, type OwSeatCreated, type OwSignInBegin, type OwSignInBegun, type OwSignInComplete, OwSignInError, type OwSignInReason, type OwSignInResult, type OwSignInStorage, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, OwStaleProposalError, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWordPair, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWorldProposalQuery, type OwWorldPublicPage, type OwWriteDoor, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, ROOM_PAIRS, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type StepBreakdown, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, WORLD_FILE_MEDIA_TYPE, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, base64url, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, isRoomElement, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
|
|
5221
|
+
export { AGENT_DOORS, ASK_LIMITS, type AccessKeyResponse, CALENDAR_FIELD, CALENDAR_SUPERTYPE, type CalendarConfig, type CalendarEra, type CalendarIntercalary, type CalendarMonths, type CalendarWeek, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, type EraDomain, FAMILY_COLORS, FAMILY_ORDER, FIELD_ACRONYMS, FIELD_SCHEMA, FILE_EXTENSIONS, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAccountWorld, type OwAgentJoined, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, type OwChange, type OwChangeDelete, type OwChangeUpsert, type OwChangesPage, type OwClientConfig, type OwCreatedWorldLink, type OwDeleteReason, type OwDraught, type OwDraughtComponent, type OwDraughtItem, type OwDraughtPolicy, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwFrontDoor, type OwHiddenRow, type OwJoinPreview, type OwJoined, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, type OwMintedKey, type OwNamesMap, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwProposal, type OwProposalAccepted, type OwProposalConflict, type OwProposalList, type OwProposalQuery, type OwProposalState, type OwProposeInput, type OwProposed, OwProposedError, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwSeat, type OwSeatCreated, type OwSignInBegin, type OwSignInBegun, type OwSignInComplete, OwSignInError, type OwSignInReason, type OwSignInResult, type OwSignInStorage, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, OwStaleProposalError, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWordPair, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWorldProposalQuery, type OwWorldPublicPage, type OwWriteDoor, type OwWriteWorldFileOptions, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, ROOM_PAIRS, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type StepBreakdown, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, WORLD_FILE_MEDIA_TYPE, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, base64url, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, isRoomElement, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
|
package/dist/index.js
CHANGED
|
@@ -3249,7 +3249,47 @@ function carried(path) {
|
|
|
3249
3249
|
return !segs.some((s) => s.startsWith(".")) && !path.endsWith(".meta");
|
|
3250
3250
|
}
|
|
3251
3251
|
var STAMP = new Date(1980, 0, 1, 0, 0, 0);
|
|
3252
|
-
|
|
3252
|
+
var WRITE_OPTION_KEYS = ["includePrivateRecords"];
|
|
3253
|
+
var RECORDS_MANIFEST = "records/RECORDS.json";
|
|
3254
|
+
function asksPrivate(opts) {
|
|
3255
|
+
if (opts === void 0 || opts === null) return false;
|
|
3256
|
+
if (typeof opts !== "object") throw new TypeError(`writeWorldFile: options must be an object, such as { includePrivateRecords: true }. Nothing was written.`);
|
|
3257
|
+
for (const k of Object.keys(opts)) {
|
|
3258
|
+
if (!WRITE_OPTION_KEYS.includes(k)) {
|
|
3259
|
+
throw new TypeError(`writeWorldFile: unknown option '${k}'. The keys are ${WRITE_OPTION_KEYS.join(", ")}. Nothing was written.`);
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
const asked = opts.includePrivateRecords;
|
|
3263
|
+
if (asked !== void 0 && typeof asked !== "boolean") {
|
|
3264
|
+
throw new TypeError(`writeWorldFile: includePrivateRecords must be true or false; got ${JSON.stringify(asked) ?? String(asked)}. Nothing was written.`);
|
|
3265
|
+
}
|
|
3266
|
+
return asked === true;
|
|
3267
|
+
}
|
|
3268
|
+
function privateProducers(files) {
|
|
3269
|
+
const manifest = files.find((f) => f.path === RECORDS_MANIFEST);
|
|
3270
|
+
if (!manifest) return [];
|
|
3271
|
+
const unreadable = (why) => {
|
|
3272
|
+
throw new TypeError(`writeWorldFile: ${RECORDS_MANIFEST} ${why}, so which records are private cannot be read and none is left out by guess (spec \xA74.7, OW-8). Fix the manifest, or pass { includePrivateRecords: true } to carry every record. Nothing was written.`);
|
|
3273
|
+
};
|
|
3274
|
+
let doc;
|
|
3275
|
+
try {
|
|
3276
|
+
doc = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(manifest.data));
|
|
3277
|
+
} catch {
|
|
3278
|
+
unreadable("is not JSON");
|
|
3279
|
+
}
|
|
3280
|
+
if (!Array.isArray(doc)) unreadable("is not a JSON array of entries");
|
|
3281
|
+
const out = [];
|
|
3282
|
+
for (const entry of doc) {
|
|
3283
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry)) unreadable("holds an entry that is not an object");
|
|
3284
|
+
const { producer, private: isPrivate } = entry;
|
|
3285
|
+
if (isPrivate !== true) continue;
|
|
3286
|
+
if (typeof producer !== "string" || producer === "") unreadable("marks an entry private without a producer name");
|
|
3287
|
+
out.push(producer);
|
|
3288
|
+
}
|
|
3289
|
+
return out;
|
|
3290
|
+
}
|
|
3291
|
+
function writeWorldFile(files, topDir, opts = {}) {
|
|
3292
|
+
const includePrivate = asksPrivate(opts);
|
|
3253
3293
|
if (pathFault(topDir) || topDir.includes("/")) throw new OwWorldFileError("unsafe_path");
|
|
3254
3294
|
const seen = /* @__PURE__ */ new Set();
|
|
3255
3295
|
for (const f of files) {
|
|
@@ -3257,7 +3297,12 @@ function writeWorldFile(files, topDir) {
|
|
|
3257
3297
|
if (seen.has(f.path)) throw new OwWorldFileError("unsafe_path", `The path ${f.path} is listed twice.`);
|
|
3258
3298
|
seen.add(f.path);
|
|
3259
3299
|
}
|
|
3260
|
-
const
|
|
3300
|
+
const left = new Set(includePrivate ? [] : privateProducers(files).map(foldName));
|
|
3301
|
+
const inPrivate = (path) => {
|
|
3302
|
+
const segs = path.split("/");
|
|
3303
|
+
return segs.length > 2 && segs[0] === "records" && left.has(foldName(segs[1]));
|
|
3304
|
+
};
|
|
3305
|
+
const kept = files.filter((f) => carried(f.path) && !inPrivate(f.path));
|
|
3261
3306
|
if (!kept.some((f) => f.path === WORLD_FILE)) throw new OwWorldFileError("not_a_world");
|
|
3262
3307
|
const keys = kept.map((f) => `${topDir}/${f.path}`);
|
|
3263
3308
|
for (const key of keys) {
|