Skip to content

Feature Request: juno storage command #495

@MAHDTech

Description

@MAHDTech

Overview

Not sure where juno datastore collections fit into the vision and I know the docs primarily mention the use case of user-generated assets, like in my example I use it for user profile avatars.

But what if we make it easier to use it for more, would you be open to this?

Juno has the hosting command for frontend assets and datastore collections, but what about poor neglected storage datastores? 😁

Motivation

I have been testing storing larger assets for a web game in different locations like

  • Amazon S3
  • StorJ
  • ICP Assets Canister
  • Juno Storage Collection

Cost & Feature Comparison

Amazon S3 StorJ ICP Assets Canister Juno Storage
Monthly min ~$0.50 $4/mo flat ~$0.50 (cycles) ~$0.50 (cycles)
Storage (1 GB) $0.023/GB included in $4 ~$5/GB/yr cycles ~$5/GB/yr cycles
Egress $0.09/GB $7/TB free (boundary nodes) free (boundary nodes)
Upload API/SDK API/SDK dfx CLI ❌ no CLI support
Prune stale assets manual/lifecycle rules manual manual ❌ no CLI support
Decentralized
On-chain certified

Result: Juno Storage Collections are the best fit for decentralized game assets — competitive on cost, on-chain certified, zero egress fees. The only missing piece is CLI tooling to deploy/prune/clear storage assets the same way juno hosting manages frontend assets.

Gap

There doesn't currently exist a way I can easily see to decoratively manage my game assets using juno.

Proposal

Would you be open to something like this?

  juno storage --help
  __  __ __  __  _  ____
__) ||  |  ||  \| |/    \
\___/ \___/ |_|\__|\____/ CLI vTEST

Deploy and manage assets in your satellite storage collections.

Usage: juno storage <subcommand> [options]

Subcommands:
  clear               Remove assets from your satellite storage collections.
  deploy              Deploy files to your satellite storage collections.
  prune               Remove stale assets from your satellite storage collections that are no longer in your lo
cal source.

You would define it something like this in your juno.config.mjs

import {defineConfig} from "@junobuild/config";
export default defineConfig(() => ({
  satellite: {
    ids: {
      development: "your-satellite-id",
    },
    source: "build",
    collections: {
      storage: [
        {collection: "audio", read: "public", write: "managed", memory: "heap"},
        {collection: "images", read: "public", write: "managed", memory: "heap"},
      ],
    },
    // Map local directories to storage collections for `juno storage deploy`.
    // Only collections listed here are affected by deploy/prune/clear.
    deploy: [
      {source: "storage/audio", collection: "audio"},
      {source: "storage/images", collection: "images"},
    ],
  },
}));

And use it in a similar way to hosting;

# Upload files from storage/audio/ → "audio" collection, storage/images/ → "images"
juno storage deploy --mode development

# Remove remote assets no longer in local directories
juno storage prune --mode development

# Or, to delete all assets from configured collections
juno storage clear --mode development

Design Decisions

  • Naming things is hard 😁
    • Current prototype uses deploy.
    • Could be config as it gets managed via juno config anyway?
    • Could be namespaced storage.deploy
    • Could be uploads
    • Could be sync

Issues

This doesn't solve the 40B instruction limit or having a single large asset, but splitting into multiple different storage collections has definitely helped keeping the certification tree smaller, reducing the per-upload storage costs.

My use case only involves HTTP access from boundary nodes, not streaming files in chunks.

Prototype

NOTE: Prototype PRs incoming for discussion...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions