fedipod 1.36.6 → 1.40.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 (94) hide show
  1. package/README.md +29 -8
  2. package/architecture.md +8 -0
  3. package/bin/fedipod.mjs +6 -0
  4. package/cli.md +7 -1
  5. package/device-agent.md +3 -3
  6. package/gateway.md +69 -8
  7. package/groups.md +2 -1
  8. package/gui.md +3 -1
  9. package/lib/client/c2s.mjs +97 -43
  10. package/lib/client/masto/accounts.mjs +1 -0
  11. package/lib/client/masto/bridge.mjs +61 -0
  12. package/lib/client/masto/index.mjs +4 -1
  13. package/lib/client/masto/oauth.mjs +1 -1
  14. package/lib/client/masto/statuses.mjs +3 -0
  15. package/lib/connections/acctfeed.mjs +13 -9
  16. package/lib/connections/bskyfeed.mjs +13 -9
  17. package/lib/connections/tagfeed.mjs +14 -9
  18. package/lib/core/deliver.mjs +17 -1
  19. package/lib/core/intake/activities.mjs +18 -2
  20. package/lib/core/intake/group.mjs +3 -1
  21. package/lib/core/intake/index.mjs +226 -48
  22. package/lib/core/intake/notes.mjs +12 -5
  23. package/lib/core/intake/verify.mjs +11 -0
  24. package/lib/core/lease.mjs +15 -1
  25. package/lib/core/place.mjs +82 -0
  26. package/lib/core/pod-only.mjs +4 -0
  27. package/lib/core/publisher/collections.mjs +37 -2
  28. package/lib/core/publisher/index.mjs +25 -1
  29. package/lib/core/publisher/notes.mjs +73 -7
  30. package/lib/core/publisher/own.mjs +143 -0
  31. package/lib/core/publisher/questions.mjs +5 -3
  32. package/lib/core/scheduled.mjs +39 -0
  33. package/lib/core/social.mjs +62 -32
  34. package/lib/core/storage.mjs +67 -0
  35. package/lib/core/store.mjs +77 -5
  36. package/lib/core/wire.mjs +51 -15
  37. package/lib/device/admin/routes/lifecycle.mjs +1 -1
  38. package/lib/device/admin/routes/setup.mjs +17 -1
  39. package/lib/device/cli/commands/setup.mjs +50 -8
  40. package/lib/device/cli/context.mjs +1 -1
  41. package/lib/device/migrate.mjs +1 -1
  42. package/lib/device/setup.mjs +45 -8
  43. package/lib/gateway/account-agent.mjs +111 -0
  44. package/lib/gateway/copy.mjs +381 -0
  45. package/lib/gateway/front-core.mjs +74 -63
  46. package/lib/gateway/gateway-core.mjs +107 -9
  47. package/lib/gateway/held-mail.mjs +198 -0
  48. package/lib/gateway/keeper-due.mjs +39 -0
  49. package/lib/gateway/keeper-session.mjs +10 -0
  50. package/lib/gateway/keeper.mjs +72 -0
  51. package/lib/gateway/masto-gateway.mjs +510 -0
  52. package/lib/gateway/quiet.mjs +7 -2
  53. package/lib/gateway/relay-extras.mjs +89 -0
  54. package/lib/gateway/state-api.mjs +207 -0
  55. package/lib/gateway/token-claims.mjs +16 -0
  56. package/lib/pod/containers.mjs +17 -0
  57. package/lib/pod/location.mjs +52 -0
  58. package/lib/pod/notes.mjs +2 -4
  59. package/lib/pod/transport.mjs +214 -24
  60. package/lib/pod/type-index.mjs +101 -0
  61. package/lib/pod/urls.mjs +6 -0
  62. package/lib/server/embed.mjs +7 -6
  63. package/lib/session/README.md +5 -5
  64. package/lib/session/demo.html +1 -1
  65. package/lib/session/fedi-account.mjs +19 -10
  66. package/lib/session/package.json +2 -2
  67. package/package.json +2 -2
  68. package/run-agent.mjs +6 -16
  69. package/scripts/stage-site.mjs +17 -4
  70. package/web/admin/actors.js +2 -0
  71. package/web/admin/gateway.js +14 -1
  72. package/web/admin/index.html +13 -0
  73. package/web/admin/oauth-signin.mjs +1 -1
  74. package/web/admin/record.js +4 -1
  75. package/web/admin/setup/index.html +17 -1
  76. package/web/admin/setup/setup.js +18 -5
  77. package/web/app/README.md +2 -2
  78. package/web/app/admin-facade.mjs +12 -2
  79. package/web/app/agent.mjs +228 -51
  80. package/web/app/boot.mjs +75 -32
  81. package/web/app/copy-mode.mjs +223 -0
  82. package/web/app/dist/boot.js +498 -88
  83. package/web/app/dist/boot.js.map +4 -4
  84. package/web/app/dist/sw.js +4016 -2539
  85. package/web/app/dist/sw.js.map +4 -4
  86. package/web/app/index.html +16 -0
  87. package/web/app/signup.mjs +65 -26
  88. package/web/app/sw-src.mjs +15 -53
  89. package/web/app/update.js +3 -2
  90. package/web/app/warm-start.mjs +115 -0
  91. package/web/app-signin/app-signin.mjs +78 -0
  92. package/web/app-signin/index.html +41 -0
  93. package/web/front/run.html +7 -1
  94. package/web/front/run.js +30 -4
package/web/front/run.js CHANGED
@@ -88,8 +88,19 @@ function showPods(pods) {
88
88
  stop.onclick = () => runStart('opt-out', pod.podBase);
89
89
  actions.append(stop);
90
90
  } else {
91
+ // Where on the pod the account goes: a container named fedipod, inside
92
+ // the one named here (empty: the pod's own root).
93
+ const field = document.createElement('p'); field.className = 'field';
94
+ const id = `container-${k.children.length}`;
95
+ const label = say('label', 'Store your data in a container named fedipod, inside this container');
96
+ label.htmlFor = id;
97
+ const input = document.createElement('input');
98
+ input.type = 'text'; input.id = id; input.autocomplete = 'off'; input.spellcheck = false;
99
+ try { input.placeholder = new URL(pod.podBase).pathname; } catch { input.placeholder = '/'; }
100
+ field.append(label, input);
101
+ box.append(field);
91
102
  const go = say('button', 'Create a Fediverse account'); go.type = 'button'; go.className = 'primary';
92
- go.onclick = () => runStart('opt-in', pod.podBase);
103
+ go.onclick = () => runStart('opt-in', pod.podBase, input.value.trim());
93
104
  actions.append(go);
94
105
  }
95
106
  box.append(actions);
@@ -121,13 +132,15 @@ $('run-issuer').addEventListener('input', runFormCheck);
121
132
  // a filled-in form, with nothing to say why.
122
133
  runFormCheck();
123
134
 
124
- const runStart = async (action, podBase = null) => {
135
+ const runStart = async (action, podBase = null, container = null, createIndex = false) => {
125
136
  const n = $('run-note');
126
137
  const u = new URL(podBase || $('run-pod-url').value.trim());
127
138
  if (u.pathname === '') u.pathname = '/';
128
139
  if (!u.pathname.endsWith('/')) u.pathname += '/';
129
140
  u.search = ''; u.hash = '';
130
- const p = { podBase: u.href, action };
141
+ const p = { podBase: u.href, action,
142
+ container: container ?? ($('run-container') ? $('run-container').value.trim() : ''),
143
+ ...(createIndex ? { createIndex: true } : {}) };
131
144
 
132
145
  // A pod server issued the session this page is being read with, so ask it
133
146
  // first: where it knows who you are, there is nothing to sign in to again.
@@ -156,6 +169,18 @@ async function showReply(res, p) {
156
169
  const n = $('run-note');
157
170
  n.hidden = false;
158
171
  const d = res ? await res.json().catch(() => ({})) : {};
172
+ // No public type index: nothing has been written. Ask.
173
+ if (res && res.status === 409 && d.code === 'needs-index') {
174
+ n.replaceChildren(say('p', `${d.error} Create it? It will be readable by anyone, like your profile.`));
175
+ const yes = say('button', 'Create it and continue'); yes.type = 'button'; yes.className = 'primary';
176
+ const no = say('button', 'No, stop'); no.type = 'button';
177
+ yes.onclick = () => runStart(p.action, p.podBase, p.container || '', true);
178
+ no.onclick = () => { n.textContent = 'Stopped. Nothing was written to your pod.'; };
179
+ const row = document.createElement('p'); row.className = 'actions'; row.append(no, yes);
180
+ n.append(row);
181
+ yes.focus();
182
+ return;
183
+ }
159
184
  if (res && res.status === 201 && d.doorSecret) {
160
185
  // Built as nodes, not as a string of HTML. Three of the pieces below come
161
186
  // back from the server and one comes from sessionStorage, and pasting any
@@ -189,7 +214,8 @@ async function showReply(res, p) {
189
214
  // The signed fetch builds a DPoP proof from the URL, so it must be absolute.
190
215
  const res = await session.authFetch(location.origin + '/api/agent', {
191
216
  method: 'POST', headers: { 'content-type': 'application/json' },
192
- body: JSON.stringify({ action: p.action, podBase: p.podBase }),
217
+ body: JSON.stringify({ action: p.action, podBase: p.podBase, container: p.container || '',
218
+ ...(p.createIndex ? { createIndex: true } : {}) }),
193
219
  }).catch(() => null);
194
220
  await showReply(res, p);
195
221
  })();