docs: add a playground example per operation in the fs sharing recipe

One runnable example for each section of the recipe: share, mode,
listShared, getShares and unshare.
This commit is contained in:
Juan Castro authored and GitHub committed 2026-09-29 23:45:17 +07:00
1 parent 28e3742cba
commit d2e63825ee
6 files changed
+159

No files matched your search

+30
View File
@@ -450,6 +450,36 @@ const examples = [
slug: 'fs-getShareLink',
source: '/playground/examples/fs-getShareLink.html',
},
{
title: 'Recipe: share a file with someone',
description: 'Share a file with another Puter user by username or email with Puter.js filesystem API. Run and experiment with this example in the playground.',
slug: 'fs-share-a-file-share',
source: '/playground/examples/fs-share-a-file-share.html',
},
{
title: 'Recipe: choose how much access to give',
description: 'Grant read, write or manage access when sharing a file with Puter.js filesystem API. Run and modify this example instantly in your browser.',
slug: 'fs-share-a-file-mode',
source: '/playground/examples/fs-share-a-file-mode.html',
},
{
title: 'Recipe: see what has been shared with you',
description: 'List the files other Puter users have shared with you with Puter.js filesystem API. Run and experiment with this example in the playground.',
slug: 'fs-share-a-file-list',
source: '/playground/examples/fs-share-a-file-list.html',
},
{
title: 'Recipe: see who you shared something with',
description: 'Read the shares on one of your own files with Puter.js filesystem API. Run and modify this example directly in your browser.',
slug: 'fs-share-a-file-who',
source: '/playground/examples/fs-share-a-file-who.html',
},
{
title: 'Recipe: take access back',
description: 'Withdraw access to a file you shared with Puter.js filesystem API. Run and experiment with this example in the playground.',
slug: 'fs-share-a-file-unshare',
source: '/playground/examples/fs-share-a-file-unshare.html',
},
],
},
{
@@ -0,0 +1,22 @@
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<script>
(async () => {
// Resolves to { items, cursor? } — not to an array.
const { items } = await puter.fs.listShared();
if (items.length === 0) {
puter.print('Nothing has been shared with you yet.');
return;
}
for (const item of items) {
puter.print(`<b>${item.name}</b> — ${item.mode}, from ${item.owner}<br>`);
// Masked path: /<owner>/<uid>/<name>, usable with any puter.fs method.
puter.print(`${item.path}<br><br>`);
}
})();
</script>
</body>
</html>
@@ -0,0 +1,30 @@
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<input id="who" placeholder="username or email">
<select id="mode">
<option>read</option>
<option>write</option>
<option>manage</option>
</select>
<button id="go">Share</button>
<script>
document.getElementById('go').addEventListener('click', async () => {
const recipient = document.getElementById('who').value.trim();
if (!recipient) return;
const mode = document.getElementById('mode').value;
await puter.fs.write('budget.xlsx', 'a,b,c');
try {
// Sharing again replaces their access rather than adding a second share.
const [share] = await puter.fs.share('budget.xlsx', recipient, mode);
puter.print(`mode: ${share.mode}<br>`);
puter.print(`isNew: ${share.isNew}`);
} catch (e) {
puter.print(`Could not share: ${e.code ?? e.message}`);
}
});
</script>
</body>
</html>
@@ -0,0 +1,24 @@
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<input id="who" placeholder="username or email">
<button id="go">Share report.txt</button>
<script>
document.getElementById('go').addEventListener('click', async () => {
const recipient = document.getElementById('who').value.trim();
if (!recipient) return;
await puter.fs.write('report.txt', 'Quarterly numbers');
try {
// A string with an @ is read as an email, anything else as a username.
const [share] = await puter.fs.share('report.txt', recipient);
puter.print(`Shared with ${share.holder ?? recipient} as ${share.mode}<br>`);
puter.print(share.isNew ? 'New access' : 'They already had access');
} catch (e) {
puter.print(`Could not share: ${e.code ?? e.message}`);
}
});
</script>
</body>
</html>
@@ -0,0 +1,25 @@
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<input id="path" value="report.txt">
<input id="who" placeholder="username or email">
<button id="go">Stop sharing</button>
<script>
document.getElementById('go').addEventListener('click', async () => {
const path = document.getElementById('path').value.trim();
const recipient = document.getElementById('who').value.trim();
if (!recipient) return;
try {
const { revoked } = await puter.fs.unshare(path, recipient);
// 0 is not an error — there was simply nothing to withdraw.
puter.print(revoked > 0
? `Withdrew ${revoked} grant(s)`
: 'Nothing to withdraw');
} catch (e) {
puter.print(`Could not unshare: ${e.code ?? e.message}`);
}
});
</script>
</body>
</html>
@@ -0,0 +1,28 @@
<html>
<body>
<script src="https://js.puter.com/v2/"></script>
<input id="path" value="report.txt">
<button id="go">Who can see it?</button>
<script>
document.getElementById('go').addEventListener('click', async () => {
const path = document.getElementById('path').value.trim();
try {
const shares = await puter.fs.getShares(path);
if (shares.length === 0) {
puter.print('Not shared with anyone.');
return;
}
for (const share of shares) {
// holder is null for a team share, a link share, or a pending invite.
const who = share.holder ?? (share.pending ? share.recipientEmail : 'anyone with the link');
puter.print(`${who} — ${share.mode}`);
puter.print(share.inheritedFrom ? ` (from ${share.inheritedFrom})<br>` : '<br>');
}
} catch (e) {
puter.print(`Could not read shares: ${e.code ?? e.message}`);
}
});
</script>
</body>
</html>