innernote 0.5.0 → 0.6.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.
Files changed (2) hide show
  1. package/dist/index.js +84 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1098,7 +1098,9 @@ function parseWhen(input) {
1098
1098
  return Number.isFinite(t) ? t : null;
1099
1099
  }
1100
1100
  async function queue(args) {
1101
- const { json, rest, value } = parseFlags(args, ["at"]);
1101
+ const { json, rest, value, has } = parseFlags(args, ["at"]);
1102
+ if (has("ready"))
1103
+ return queueReady(json, rest, value("at"));
1102
1104
  const ref = rest[0] ? resolveRef(rest[0]) : null;
1103
1105
  if (!ref) {
1104
1106
  fail("Which post?");
@@ -1133,6 +1135,40 @@ async function queue(args) {
1133
1135
  note(dim2("`week` to see where it landed"));
1134
1136
  return 0;
1135
1137
  }
1138
+ async function queueReady(json, rest, at) {
1139
+ if (rest.length || at !== undefined) {
1140
+ fail("--ready queues every Ready post in order, so it takes no post and no time.");
1141
+ note(dim2(`${CMD} queue --ready or ${CMD} queue <post-id>`));
1142
+ return 1;
1143
+ }
1144
+ const res = await request("/api/posts/queue-ready", { method: "POST", timeoutMs: 90000 });
1145
+ if (json) {
1146
+ out(JSON.stringify(res, null, 2));
1147
+ return 0;
1148
+ }
1149
+ if (res.queued.length === 0) {
1150
+ fail("Nothing was queued.");
1151
+ if (res.stopped)
1152
+ note(res.stopped);
1153
+ return 1;
1154
+ }
1155
+ const n = res.queued.length;
1156
+ ok(`Queued ${n} ${n === 1 ? "post" : "posts"}, in your Ready order. Each goes live on its own.`);
1157
+ for (const q of res.queued) {
1158
+ const when = new Date(q.scheduledFor).toLocaleString(undefined, {
1159
+ weekday: "short",
1160
+ day: "numeric",
1161
+ month: "short",
1162
+ hour: "numeric",
1163
+ minute: "2-digit"
1164
+ });
1165
+ out(` ${dim2(when.padEnd(22))} ${q.title || q.id}`);
1166
+ }
1167
+ if (res.waiting > 0)
1168
+ note(`${res.waiting} still in Ready. ${res.stopped ?? ""}`.trim());
1169
+ note(dim2("`week` to see where they landed"));
1170
+ return 0;
1171
+ }
1136
1172
  async function save(args) {
1137
1173
  const { json } = parseFlags(args);
1138
1174
  const held = getDraft();
@@ -1492,7 +1528,7 @@ async function showPost(refArg, json) {
1492
1528
  return 0;
1493
1529
  }
1494
1530
  async function edit(args) {
1495
- const { json, rest, value } = parseFlags(args, ["text", "file", "title", "first-comment", "series", "status"]);
1531
+ const { json, rest, value, has } = parseFlags(args, ["text", "file", "title", "first-comment", "series", "status", "after"]);
1496
1532
  const refArg = rest[0];
1497
1533
  if (!refArg) {
1498
1534
  fail("Edit which post?");
@@ -1504,17 +1540,23 @@ async function edit(args) {
1504
1540
  const firstComment = value("first-comment");
1505
1541
  const seriesName = value("series");
1506
1542
  const status = value("status");
1543
+ const first = has("first");
1544
+ const afterRef = value("after");
1507
1545
  const file = value("file");
1508
1546
  let text = value("text");
1509
1547
  if (file)
1510
1548
  text = await readFile2(file, "utf8");
1511
- const fieldsGiven = title !== undefined || firstComment !== undefined || seriesName !== undefined || status !== undefined;
1549
+ const fieldsGiven = title !== undefined || firstComment !== undefined || seriesName !== undefined || status !== undefined || first || afterRef !== undefined;
1512
1550
  if (text === undefined && !fieldsGiven) {
1513
1551
  text = await readStdin() ?? undefined;
1514
1552
  }
1515
1553
  if (text === undefined && !fieldsGiven) {
1516
1554
  fail("Nothing to change.");
1517
- note(dim2("--file, --text or piped text for the post, --title, --first-comment, --series, --status"));
1555
+ note(dim2("--file, --text or piped text for the post, --title, --first-comment, --series, --status, --first, --after"));
1556
+ return 1;
1557
+ }
1558
+ if (first && afterRef !== undefined) {
1559
+ fail("--first or --after, not both.");
1518
1560
  return 1;
1519
1561
  }
1520
1562
  if (status !== undefined && status !== "ready" && status !== "draft") {
@@ -1581,6 +1623,17 @@ async function edit(args) {
1581
1623
  await request(`/api/posts/${encodeURIComponent(post._id)}/ready`, { method: status === "ready" ? "POST" : "DELETE" });
1582
1624
  changed.push(`status (${status})`);
1583
1625
  }
1626
+ if (first || afterRef !== undefined) {
1627
+ let after = null;
1628
+ if (afterRef !== undefined) {
1629
+ const target = await postFromRef(afterRef, `${CMD} edit <post-id> --after <post-id>`);
1630
+ if (!target)
1631
+ return 1;
1632
+ after = target._id;
1633
+ }
1634
+ await request(`/api/posts/${encodeURIComponent(post._id)}/move`, { method: "POST", body: { after } });
1635
+ changed.push(after ? "place in Ready" : "place in Ready (top)");
1636
+ }
1584
1637
  if (json) {
1585
1638
  out(JSON.stringify({ id: post._id, changed }, null, 2));
1586
1639
  return 0;
@@ -1804,7 +1857,7 @@ var COMMANDS = {
1804
1857
  },
1805
1858
  edit: {
1806
1859
  summary: "change a saved post: its text, title, first comment, series or status",
1807
- usage: "innernote edit <id> [--file <path> | --text <text>] [--title <text>] [--first-comment <text>] [--series <name>] [--status ready|draft]",
1860
+ usage: "innernote edit <id> [--file <path> | --text <text>] [--title <text>] [--first-comment <text>] [--series <name>] [--status ready|draft] [--first | --after <id>]",
1808
1861
  detail: "Puts your own words into a saved post. New text comes from --file, --text or a pipe, and is saved the way the app saves a draft, so the old text is one Undo away in the post's history. A post already live on LinkedIn keeps its text. The id comes from `drafts --json` or `show`.",
1809
1862
  options: [
1810
1863
  ["--file <path>", "the new text of the post, from a file"],
@@ -1812,13 +1865,16 @@ var COMMANDS = {
1812
1865
  ["--title <text>", "the post's title in the app"],
1813
1866
  ["--first-comment <text>", "the comment posted under it when it goes live"],
1814
1867
  ["--series <name>", "file it into a series, or `none` to take it out"],
1815
- ["--status <ready|draft>", "mark it ready, or send it back to draft"]
1868
+ ["--status <ready|draft>", "mark it ready, or send it back to draft"],
1869
+ ["--first", "put a Ready post at the top of Ready, so it goes out next"],
1870
+ ["--after <id>", "put a Ready post right after another one in Ready"]
1816
1871
  ],
1817
1872
  examples: [
1818
1873
  "innernote edit p17abc... --file post.txt",
1819
1874
  "pbpaste | innernote edit p17abc...",
1820
1875
  'innernote edit p17abc... --title "The sales call" --first-comment "link: innernote.space"',
1821
- 'innernote edit p17abc... --series "Build in Public" --status ready'
1876
+ 'innernote edit p17abc... --series "Build in Public" --status ready',
1877
+ "innernote edit 3 --first"
1822
1878
  ]
1823
1879
  },
1824
1880
  captures: {
@@ -1961,10 +2017,13 @@ var COMMANDS = {
1961
2017
  },
1962
2018
  queue: {
1963
2019
  summary: "schedule a post into your next open slot",
1964
- usage: "innernote queue <post-id> [--at <time>]",
1965
- detail: "A queued post GOES LIVE on LinkedIn on its own at your next cadence slot. Nobody presses anything again. Needs a connection you allowed to publish: tick that box in Settings when you generate the code. Takes a number from the last list, or a full id. It never assumes the draft in hand: this is the one command that makes you say which post.",
1966
- options: [["--at <time>", `a time you pick, like "2026-10-12 12:31" (this machine's timezone), instead of the next open slot`]],
1967
- examples: ["innernote drafts", "innernote queue 3", "innernote queue p17a1yk936ywnan10643efjtc58dhkah"]
2020
+ usage: "innernote queue <post-id> [--at <time>] | queue --ready",
2021
+ detail: "A queued post GOES LIVE on LinkedIn on its own at your next cadence slot. Nobody presses anything again. Needs a connection you allowed to publish: tick that box in Settings when you generate the code. Takes a number from the last list, or a full id. It never assumes the draft in hand: this is the one command that makes you say which post. `--ready` queues every Ready post at once, in your Ready order, the top one first: Queue these in the app.",
2022
+ options: [
2023
+ ["--at <time>", `a time you pick, like "2026-10-12 12:31" (this machine's timezone), instead of the next open slot`],
2024
+ ["--ready", "every Ready post, in your Ready order, into your next open slots"]
2025
+ ],
2026
+ examples: ["innernote drafts", "innernote queue 3", "innernote queue p17a1yk936ywnan10643efjtc58dhkah", "innernote drafts ready", "innernote queue --ready"]
1968
2027
  }
1969
2028
  };
1970
2029
  function commandHelp(name) {
@@ -2077,7 +2136,7 @@ function suggest(state) {
2077
2136
  // package.json
2078
2137
  var package_default = {
2079
2138
  name: "innernote",
2080
- version: "0.5.0",
2139
+ version: "0.6.0",
2081
2140
  description: "Write LinkedIn posts in your voice, from the terminal.",
2082
2141
  keywords: [
2083
2142
  "linkedin",
@@ -2791,7 +2850,7 @@ var COMMANDS2 = {
2791
2850
  },
2792
2851
  edit: {
2793
2852
  summary: "change a saved post: its text, title, first comment, series or status",
2794
- usage: "innernote edit <id> [--file <path> | --text <text>] [--title <text>] [--first-comment <text>] [--series <name>] [--status ready|draft]",
2853
+ usage: "innernote edit <id> [--file <path> | --text <text>] [--title <text>] [--first-comment <text>] [--series <name>] [--status ready|draft] [--first | --after <id>]",
2795
2854
  detail: "Puts your own words into a saved post. New text comes from --file, --text or a pipe, and is saved the way the app saves a draft, so the old text is one Undo away in the post's history. A post already live on LinkedIn keeps its text. The id comes from `drafts --json` or `show`.",
2796
2855
  options: [
2797
2856
  ["--file <path>", "the new text of the post, from a file"],
@@ -2799,13 +2858,16 @@ var COMMANDS2 = {
2799
2858
  ["--title <text>", "the post's title in the app"],
2800
2859
  ["--first-comment <text>", "the comment posted under it when it goes live"],
2801
2860
  ["--series <name>", "file it into a series, or `none` to take it out"],
2802
- ["--status <ready|draft>", "mark it ready, or send it back to draft"]
2861
+ ["--status <ready|draft>", "mark it ready, or send it back to draft"],
2862
+ ["--first", "put a Ready post at the top of Ready, so it goes out next"],
2863
+ ["--after <id>", "put a Ready post right after another one in Ready"]
2803
2864
  ],
2804
2865
  examples: [
2805
2866
  "innernote edit p17abc... --file post.txt",
2806
2867
  "pbpaste | innernote edit p17abc...",
2807
2868
  'innernote edit p17abc... --title "The sales call" --first-comment "link: innernote.space"',
2808
- 'innernote edit p17abc... --series "Build in Public" --status ready'
2869
+ 'innernote edit p17abc... --series "Build in Public" --status ready',
2870
+ "innernote edit 3 --first"
2809
2871
  ]
2810
2872
  },
2811
2873
  captures: {
@@ -2948,10 +3010,13 @@ var COMMANDS2 = {
2948
3010
  },
2949
3011
  queue: {
2950
3012
  summary: "schedule a post into your next open slot",
2951
- usage: "innernote queue <post-id> [--at <time>]",
2952
- detail: "A queued post GOES LIVE on LinkedIn on its own at your next cadence slot. Nobody presses anything again. Needs a connection you allowed to publish: tick that box in Settings when you generate the code. Takes a number from the last list, or a full id. It never assumes the draft in hand: this is the one command that makes you say which post.",
2953
- options: [["--at <time>", `a time you pick, like "2026-10-12 12:31" (this machine's timezone), instead of the next open slot`]],
2954
- examples: ["innernote drafts", "innernote queue 3", "innernote queue p17a1yk936ywnan10643efjtc58dhkah"]
3013
+ usage: "innernote queue <post-id> [--at <time>] | queue --ready",
3014
+ detail: "A queued post GOES LIVE on LinkedIn on its own at your next cadence slot. Nobody presses anything again. Needs a connection you allowed to publish: tick that box in Settings when you generate the code. Takes a number from the last list, or a full id. It never assumes the draft in hand: this is the one command that makes you say which post. `--ready` queues every Ready post at once, in your Ready order, the top one first: Queue these in the app.",
3015
+ options: [
3016
+ ["--at <time>", `a time you pick, like "2026-10-12 12:31" (this machine's timezone), instead of the next open slot`],
3017
+ ["--ready", "every Ready post, in your Ready order, into your next open slots"]
3018
+ ],
3019
+ examples: ["innernote drafts", "innernote queue 3", "innernote queue p17a1yk936ywnan10643efjtc58dhkah", "innernote drafts ready", "innernote queue --ready"]
2955
3020
  }
2956
3021
  };
2957
3022
  function commandHelp2(name) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "innernote",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Write LinkedIn posts in your voice, from the terminal.",
5
5
  "keywords": [
6
6
  "linkedin",