@craftrpgs/cli 0.1.5 → 0.1.6
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/bin.js +159 -6
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -41900,7 +41900,7 @@ function describeRemoteSource(resolved) {
|
|
|
41900
41900
|
// package.json
|
|
41901
41901
|
var package_default = {
|
|
41902
41902
|
name: "@craftrpgs/cli",
|
|
41903
|
-
version: "0.1.
|
|
41903
|
+
version: "0.1.6",
|
|
41904
41904
|
description: "Sync Craft projects with a local folder — clone, edit with any coding agent, push back.",
|
|
41905
41905
|
license: "UNLICENSED",
|
|
41906
41906
|
homepage: "https://craftrpgs.com",
|
|
@@ -43837,7 +43837,8 @@ var LEADING_SLASH_RE = /^\//;
|
|
|
43837
43837
|
var CONTENT_EXTENSION_RE = /\.(json|md)$/i;
|
|
43838
43838
|
var UUID_RE3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
43839
43839
|
function entryName(entry) {
|
|
43840
|
-
const
|
|
43840
|
+
const livePath = entry.movedTo ?? entry.path;
|
|
43841
|
+
const base = (livePath.split("/").at(-1) ?? livePath).replace(CONTENT_EXTENSION_RE, "");
|
|
43841
43842
|
const suffix = `.${entry.fileType}`;
|
|
43842
43843
|
return base.endsWith(suffix) ? base.slice(0, -suffix.length) : base;
|
|
43843
43844
|
}
|
|
@@ -43889,6 +43890,13 @@ function resolveLink({
|
|
|
43889
43890
|
if (bySlug) {
|
|
43890
43891
|
return fromEntry(bySlug);
|
|
43891
43892
|
}
|
|
43893
|
+
const nameKey = generateSlug(trimmed.replace(/^<@|>$/g, ""));
|
|
43894
|
+
if (nameKey) {
|
|
43895
|
+
const byName = ledger.files.find((entry) => generateSlug(entryName(entry)) === nameKey);
|
|
43896
|
+
if (byName) {
|
|
43897
|
+
return fromEntry(byName);
|
|
43898
|
+
}
|
|
43899
|
+
}
|
|
43892
43900
|
return { status: "unknown" };
|
|
43893
43901
|
}
|
|
43894
43902
|
function referenceIdToPath({
|
|
@@ -44935,6 +44943,8 @@ var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V6 = "file-designation-metadata:v6"
|
|
|
44935
44943
|
var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V7 = "file-designation-metadata:v7";
|
|
44936
44944
|
var FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V8 = "file-designation-metadata:v8";
|
|
44937
44945
|
var GAME_START_OPENING_MAX_LENGTH = 1e4;
|
|
44946
|
+
var GAME_START_MAX_OPENING_BEATS = 50;
|
|
44947
|
+
var GAME_START_MAX_CHARACTER_OPENINGS = 100;
|
|
44938
44948
|
var GM_INSTRUCTION_TRIGGER_PHASES = [
|
|
44939
44949
|
"post_player_message",
|
|
44940
44950
|
"post_gm_message"
|
|
@@ -45137,10 +45147,25 @@ var GmInstructionMetadataSchema = exports_external.union([
|
|
|
45137
45147
|
GmInstructionToolMetadataSchema,
|
|
45138
45148
|
GmInstructionNarrativeMetadataSchema
|
|
45139
45149
|
]);
|
|
45150
|
+
var GameStartOpeningBeatSpeakerSchema = exports_external.discriminatedUnion("kind", [
|
|
45151
|
+
exports_external.object({ kind: exports_external.literal("gm") }),
|
|
45152
|
+
exports_external.object({
|
|
45153
|
+
kind: exports_external.literal("character"),
|
|
45154
|
+
fileReferenceId: exports_external.string().uuid(),
|
|
45155
|
+
name: exports_external.string().trim().max(200).optional()
|
|
45156
|
+
})
|
|
45157
|
+
]);
|
|
45158
|
+
var GameStartOpeningBeatSchema = exports_external.object({
|
|
45159
|
+
id: exports_external.string().uuid(),
|
|
45160
|
+
speaker: GameStartOpeningBeatSpeakerSchema,
|
|
45161
|
+
text: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH),
|
|
45162
|
+
expression: exports_external.string().trim().max(80).nullish()
|
|
45163
|
+
});
|
|
45140
45164
|
var GameStartOpeningSchema = exports_external.discriminatedUnion("kind", [
|
|
45141
45165
|
exports_external.object({
|
|
45142
45166
|
kind: exports_external.literal("static"),
|
|
45143
|
-
message: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH)
|
|
45167
|
+
message: exports_external.string().trim().min(1).max(GAME_START_OPENING_MAX_LENGTH),
|
|
45168
|
+
beats: exports_external.array(GameStartOpeningBeatSchema).max(GAME_START_MAX_OPENING_BEATS).optional()
|
|
45144
45169
|
}),
|
|
45145
45170
|
exports_external.object({
|
|
45146
45171
|
kind: exports_external.literal("dynamic"),
|
|
@@ -45150,16 +45175,55 @@ var GameStartOpeningSchema = exports_external.discriminatedUnion("kind", [
|
|
|
45150
45175
|
var GameStartCharacterSchema = exports_external.object({
|
|
45151
45176
|
fileReferenceId: exports_external.string().uuid()
|
|
45152
45177
|
});
|
|
45153
|
-
var
|
|
45178
|
+
var GameStartCharacterOpeningSchema = exports_external.object({
|
|
45179
|
+
characterFileReferenceId: exports_external.string().uuid(),
|
|
45180
|
+
opening: GameStartOpeningSchema
|
|
45181
|
+
});
|
|
45182
|
+
function combinedOpeningLength(opening) {
|
|
45183
|
+
if (opening.kind !== "static" || !opening.beats) {
|
|
45184
|
+
return 0;
|
|
45185
|
+
}
|
|
45186
|
+
return opening.beats.reduce((total, beat) => total + beat.text.length, 0);
|
|
45187
|
+
}
|
|
45188
|
+
var GameStartMetadataObjectSchema = exports_external.object({
|
|
45154
45189
|
startingLocationFileReferenceId: exports_external.string().uuid().nullable().optional(),
|
|
45155
45190
|
startingCharacters: exports_external.array(GameStartCharacterSchema).default([]),
|
|
45156
45191
|
opening: GameStartOpeningSchema.default({
|
|
45157
45192
|
kind: "static",
|
|
45158
45193
|
message: "Welcome to the game. What would you like to do first?"
|
|
45159
45194
|
}),
|
|
45195
|
+
characterOpenings: exports_external.array(GameStartCharacterOpeningSchema).max(GAME_START_MAX_CHARACTER_OPENINGS).default([]),
|
|
45160
45196
|
displayOrder: exports_external.number().int().default(0),
|
|
45161
45197
|
openingInstructions: exports_external.string().max(GAME_START_OPENING_MAX_LENGTH).default("")
|
|
45162
45198
|
});
|
|
45199
|
+
var GameStartMetadataSchema = GameStartMetadataObjectSchema.superRefine((metadata, ctx) => {
|
|
45200
|
+
if (combinedOpeningLength(metadata.opening) > GAME_START_OPENING_MAX_LENGTH) {
|
|
45201
|
+
ctx.addIssue({
|
|
45202
|
+
code: "custom",
|
|
45203
|
+
path: ["opening", "beats"],
|
|
45204
|
+
message: `Combined opening beats must be at most ${GAME_START_OPENING_MAX_LENGTH} characters.`
|
|
45205
|
+
});
|
|
45206
|
+
}
|
|
45207
|
+
const seenCharacterReferenceIds = new Set;
|
|
45208
|
+
metadata.characterOpenings.forEach((characterOpening, index) => {
|
|
45209
|
+
const referenceId = characterOpening.characterFileReferenceId.toLowerCase();
|
|
45210
|
+
if (seenCharacterReferenceIds.has(referenceId)) {
|
|
45211
|
+
ctx.addIssue({
|
|
45212
|
+
code: "custom",
|
|
45213
|
+
path: ["characterOpenings", index, "characterFileReferenceId"],
|
|
45214
|
+
message: "Each character can only have one opening override."
|
|
45215
|
+
});
|
|
45216
|
+
}
|
|
45217
|
+
seenCharacterReferenceIds.add(referenceId);
|
|
45218
|
+
if (combinedOpeningLength(characterOpening.opening) > GAME_START_OPENING_MAX_LENGTH) {
|
|
45219
|
+
ctx.addIssue({
|
|
45220
|
+
code: "custom",
|
|
45221
|
+
path: ["characterOpenings", index, "opening", "beats"],
|
|
45222
|
+
message: `Combined opening beats must be at most ${GAME_START_OPENING_MAX_LENGTH} characters.`
|
|
45223
|
+
});
|
|
45224
|
+
}
|
|
45225
|
+
});
|
|
45226
|
+
});
|
|
45163
45227
|
var FileDesignationMetadataV1Schema = exports_external.object({
|
|
45164
45228
|
schemaVersionId: exports_external.literal(FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V1).default(FILE_DESIGNATION_METADATA_SCHEMA_VERSION_V1),
|
|
45165
45229
|
map: MapDataV1Schema.optional(),
|
|
@@ -45669,7 +45733,12 @@ async function runMetaGet(argv) {
|
|
|
45669
45733
|
const gameStart = parsed?.gameStart ? {
|
|
45670
45734
|
...parsed.gameStart,
|
|
45671
45735
|
startingLocation: pathForReference(workspace, parsed.gameStart.startingLocationFileReferenceId),
|
|
45672
|
-
startingCharacters: parsed.gameStart.startingCharacters.map((character) => pathForReference(workspace, character.fileReferenceId) ?? character.fileReferenceId)
|
|
45736
|
+
startingCharacters: parsed.gameStart.startingCharacters.map((character) => pathForReference(workspace, character.fileReferenceId) ?? character.fileReferenceId),
|
|
45737
|
+
opening: projectOpeningForOutput(workspace, parsed.gameStart.opening),
|
|
45738
|
+
characterOpenings: parsed.gameStart.characterOpenings.map((characterOpening) => ({
|
|
45739
|
+
character: pathForReference(workspace, characterOpening.characterFileReferenceId) ?? characterOpening.characterFileReferenceId,
|
|
45740
|
+
opening: projectOpeningForOutput(workspace, characterOpening.opening)
|
|
45741
|
+
}))
|
|
45673
45742
|
} : null;
|
|
45674
45743
|
if (gameStart) {
|
|
45675
45744
|
gameStart.startingLocationFileReferenceId = undefined;
|
|
@@ -45690,6 +45759,24 @@ async function runMetaGet(argv) {
|
|
|
45690
45759
|
});
|
|
45691
45760
|
return 0;
|
|
45692
45761
|
}
|
|
45762
|
+
function projectOpeningForOutput(workspace, opening) {
|
|
45763
|
+
if (opening.kind !== "static" || !opening.beats?.length) {
|
|
45764
|
+
return opening;
|
|
45765
|
+
}
|
|
45766
|
+
return {
|
|
45767
|
+
kind: "static",
|
|
45768
|
+
beats: opening.beats.map((beat) => ({
|
|
45769
|
+
speaker: beat.speaker.kind === "gm" ? "gm" : pathForReference(workspace, beat.speaker.fileReferenceId) ?? beat.speaker.fileReferenceId,
|
|
45770
|
+
text: beat.text,
|
|
45771
|
+
...beat.expression ? { expression: beat.expression } : {}
|
|
45772
|
+
}))
|
|
45773
|
+
};
|
|
45774
|
+
}
|
|
45775
|
+
function speakerNameForLink(link) {
|
|
45776
|
+
const base = link.split("/").filter(Boolean).at(-1);
|
|
45777
|
+
const name = base?.split(".")[0]?.trim();
|
|
45778
|
+
return name || undefined;
|
|
45779
|
+
}
|
|
45693
45780
|
function translateGameStartInput(workspace, raw) {
|
|
45694
45781
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
45695
45782
|
throw new CliError("The game start JSON must be a single object.", 2);
|
|
@@ -45711,6 +45798,55 @@ function translateGameStartInput(workspace, raw) {
|
|
|
45711
45798
|
failures.push(resolution.status === "unpushed" ? `${where}: "${link}" has not been pushed yet — push it first` : `${where}: "${link}" does not resolve to a tracked file`);
|
|
45712
45799
|
return null;
|
|
45713
45800
|
};
|
|
45801
|
+
const translateOpening = (opening, where) => {
|
|
45802
|
+
if (typeof opening !== "object" || opening === null) {
|
|
45803
|
+
return opening;
|
|
45804
|
+
}
|
|
45805
|
+
const openingInput = { ...opening };
|
|
45806
|
+
if (!Array.isArray(openingInput.beats)) {
|
|
45807
|
+
return openingInput;
|
|
45808
|
+
}
|
|
45809
|
+
const beats = openingInput.beats.map((beat, index) => {
|
|
45810
|
+
if (typeof beat !== "object" || beat === null) {
|
|
45811
|
+
return beat;
|
|
45812
|
+
}
|
|
45813
|
+
const beatInput = { ...beat };
|
|
45814
|
+
if (typeof beatInput.id !== "string") {
|
|
45815
|
+
beatInput.id = crypto.randomUUID();
|
|
45816
|
+
}
|
|
45817
|
+
const speaker = beatInput.speaker;
|
|
45818
|
+
if (typeof speaker === "string" && speaker !== "gm") {
|
|
45819
|
+
beatInput.speaker = {
|
|
45820
|
+
kind: "character",
|
|
45821
|
+
fileReferenceId: resolve6(speaker, `${where}.beats[${index}].speaker`),
|
|
45822
|
+
name: speakerNameForLink(speaker)
|
|
45823
|
+
};
|
|
45824
|
+
} else if (speaker === "gm") {
|
|
45825
|
+
beatInput.speaker = { kind: "gm" };
|
|
45826
|
+
} else if (typeof speaker === "object" && speaker !== null && "character" in speaker) {
|
|
45827
|
+
const { character, ...speakerRest } = speaker;
|
|
45828
|
+
beatInput.speaker = {
|
|
45829
|
+
kind: "character",
|
|
45830
|
+
name: typeof character === "string" ? speakerNameForLink(character) : undefined,
|
|
45831
|
+
...speakerRest,
|
|
45832
|
+
fileReferenceId: resolve6(character, `${where}.beats[${index}].speaker.character`)
|
|
45833
|
+
};
|
|
45834
|
+
}
|
|
45835
|
+
return beatInput;
|
|
45836
|
+
});
|
|
45837
|
+
openingInput.beats = beats;
|
|
45838
|
+
if (typeof openingInput.message !== "string" && openingInput.kind === "static") {
|
|
45839
|
+
const projectable = beats.filter((beat) => typeof beat === "object" && beat !== null && typeof beat.text === "string");
|
|
45840
|
+
openingInput.message = projectable.map((beat) => {
|
|
45841
|
+
const speaker = beat.speaker;
|
|
45842
|
+
const name = speaker && speaker.kind === "character" && typeof speaker.name === "string" ? speaker.name : null;
|
|
45843
|
+
return name ? `${name}: ${beat.text}` : beat.text;
|
|
45844
|
+
}).join(`
|
|
45845
|
+
|
|
45846
|
+
`).slice(0, GAME_START_OPENING_MAX_LENGTH);
|
|
45847
|
+
}
|
|
45848
|
+
return openingInput;
|
|
45849
|
+
};
|
|
45714
45850
|
if ("startingLocation" in input) {
|
|
45715
45851
|
input.startingLocationFileReferenceId = resolve6(input.startingLocation, "startingLocation");
|
|
45716
45852
|
input.startingLocation = undefined;
|
|
@@ -45725,11 +45861,28 @@ function translateGameStartInput(workspace, raw) {
|
|
|
45725
45861
|
return character;
|
|
45726
45862
|
});
|
|
45727
45863
|
}
|
|
45864
|
+
if ("opening" in input) {
|
|
45865
|
+
input.opening = translateOpening(input.opening, "opening");
|
|
45866
|
+
}
|
|
45867
|
+
if (Array.isArray(input.characterOpenings)) {
|
|
45868
|
+
input.characterOpenings = input.characterOpenings.map((characterOpening, index) => {
|
|
45869
|
+
if (typeof characterOpening !== "object" || characterOpening === null) {
|
|
45870
|
+
return characterOpening;
|
|
45871
|
+
}
|
|
45872
|
+
const entry = { ...characterOpening };
|
|
45873
|
+
if ("character" in entry) {
|
|
45874
|
+
entry.characterFileReferenceId = resolve6(entry.character, `characterOpenings[${index}].character`);
|
|
45875
|
+
entry.character = undefined;
|
|
45876
|
+
}
|
|
45877
|
+
entry.opening = translateOpening(entry.opening, `characterOpenings[${index}].opening`);
|
|
45878
|
+
return entry;
|
|
45879
|
+
});
|
|
45880
|
+
}
|
|
45728
45881
|
if (failures.length > 0) {
|
|
45729
45882
|
throw new CliError(`Nothing was saved — some references do not resolve to pushed files:
|
|
45730
45883
|
` + `${failures.map((f) => ` ${f}`).join(`
|
|
45731
45884
|
`)}
|
|
45732
|
-
` + "Use workspace paths, slug.type tokens, or
|
|
45885
|
+
` + "Use workspace paths (preferred), slug.type tokens, slugs, or file names of PUSHED files.", 2);
|
|
45733
45886
|
}
|
|
45734
45887
|
return input;
|
|
45735
45888
|
}
|
package/package.json
CHANGED