mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-23 00:45:53 -05:00
Add nip136 code packages kind 1036
This commit is contained in:
parent
cc7cdd5a80
commit
3034fba59e
108
136.md
Normal file
108
136.md
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
Code packages
|
||||||
|
=============
|
||||||
|
|
||||||
|
This NIP handles distribution of code packages (akin to npm packages) in a decentralized way.
|
||||||
|
|
||||||
|
Code package consists of a list of files in directories. A code package event of kind `1036` contains a list of hashes of files along with their relative paths, directories are not listed. File contents are to be stored on Blossom or NIP-96 or other kinds of servers that use `sha256` for addressing.
|
||||||
|
|
||||||
|
The `content` field of the code package may contain human readable description of the package contents. Each file is an `f` tag containing sha256 file hash, relative file path within the package and a URL to download the file content. Other recommended meta tags are given as example below.
|
||||||
|
|
||||||
|
Code package also contains `x` tag - the `package hash`, which is a combined hash of included relative paths and file hashes. This `package hash` serves as a content-based package address, to allow apps to fetch packages with the same package hash. Events referring to code package events should use package event id with a relay hint, and may include package hash in the reference - if original event is not accessible, package hash can be searched on relays as a fallback.
|
||||||
|
|
||||||
|
Example package event:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"content":"",
|
||||||
|
"created_at":1718295088,
|
||||||
|
"id":"<event-id>",
|
||||||
|
"kind":1036,
|
||||||
|
"pubkey":"<author pubkey>",
|
||||||
|
"sig":"<signature>",
|
||||||
|
"tags":[
|
||||||
|
["title","Taste"],
|
||||||
|
["summary","A Ghost theme"],
|
||||||
|
["version","1.0.0"],
|
||||||
|
["changes","Great improvements"],
|
||||||
|
["license","MIT"],
|
||||||
|
["x", "<package-hash>"],
|
||||||
|
[
|
||||||
|
"f",
|
||||||
|
"7db7d6130b9b667001841b79ee67760619a80b9df305b8bfb872e22265313cf5","LICENSE",
|
||||||
|
"https://blossom.nostr.hu/7db7d6130b9b667001841b79ee67760619a80b9df305b8bfb872e22265313cf5"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"f",
|
||||||
|
"38117ebbd11b7571d6108a3fc642521c4f6f5c54c49dbcda5da0d15009c3013a",
|
||||||
|
"package.json",
|
||||||
|
"https://blossom.nostr.hu/38117ebbd11b7571d6108a3fc642521c4f6f5c54c49dbcda5da0d15009c3013a"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"f",
|
||||||
|
"c931b825e11cbc5149f41c21c83332fcf8c87d951065f2716f3b12dd875c414c",
|
||||||
|
"index.hbs",
|
||||||
|
"https://blossom.nostr.hu/c931b825e11cbc5149f41c21c83332fcf8c87d951065f2716f3b12dd875c414c"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"f",
|
||||||
|
"331c2869b4a7f8a9181089ecb158a987a92a5915cca95912a1a16b35898988ee",
|
||||||
|
"assets/built/screen.css",
|
||||||
|
"https://blossom.nostr.hu/331c2869b4a7f8a9181089ecb158a987a92a5915cca95912a1a16b35898988ee"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"f",
|
||||||
|
"ee737f159229961284f179a8d21024c599b07512825b049c900873fdc7e6df1a",
|
||||||
|
"assets/built/main.min.js",
|
||||||
|
"https://blossom.nostr.hu/ee737f159229961284f179a8d21024c599b07512825b049c900873fdc7e6df1a"
|
||||||
|
],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Pseudo-code to calculate package hash:
|
||||||
|
```
|
||||||
|
const pkg: {
|
||||||
|
hash: string, // hex hash of a file
|
||||||
|
path: string // relative file path w/o leading /
|
||||||
|
}[] = [...];
|
||||||
|
pkg.sort((a, b) => (a.hash > b.hash ? 1 : a.hash === b.hash ? 0 : -1));
|
||||||
|
const packageHash = bytesToHex(
|
||||||
|
sha256(pkg.map((e) => e.hash + e.entry).join(","))
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Test vector for a package hash:
|
||||||
|
```
|
||||||
|
const pkg = [
|
||||||
|
["094cdc9a24ebf462c6c38be09ab3046396e21ae243a31b874ed6ee74bf3e4364","default.hbs"],
|
||||||
|
["0a96d40dd8bac92d050ccdbd7f4b1d3fae8564892ae58584bfff090b27a0f862","partials/components/list-item.hbs"],
|
||||||
|
["20482ce13e4e75c219c459b3a1c3ef0acb1d1f3d01aeda8c16931dd6f855aa8b","partials/components/article.hbs"],
|
||||||
|
["25b4799d1e4a1da0875402c80fdf02da824e65535202000798e076f80fad0509","tag.hbs"],
|
||||||
|
["28d78dc6cbf6569496b2a968f71a7bbd663fb0a9eb98d3c5268f9bfd2f66f1ba","assets/css/screen.css"],
|
||||||
|
["331c2869b4a7f8a9181089ecb158a987a92a5915cca95912a1a16b35898988ee","assets/built/screen.css"],
|
||||||
|
["341dce30d1dc1495181779af7ce3c27de68b12752c6184f8ed21939161df0ec4","partials/icons/facebook.hbs"],
|
||||||
|
["38117ebbd11b7571d6108a3fc642521c4f6f5c54c49dbcda5da0d15009c3013a","package.json"],
|
||||||
|
["3af99992cacb7e466f37a390d899f8323ac0fc4eafe8ca12f1cecb272c86ef64","assets/built/main.min.js.map"],
|
||||||
|
["3be86ec65468322816a7c1468f88d6192a04affe02b30e83ea0bc50f7bb8dd02","partials/components/header-content.hbs"],
|
||||||
|
["4256eafe8a3e80b78072518861c5872aacca3c8c019829a48c44f6e43b351070","partials/icons/search.hbs"],
|
||||||
|
["509c6330788805349e0e8c90d97d6182b12038cc90de32657272fc3f88f1ec52","partials/components/list.hbs"],
|
||||||
|
["55b72665ed314a9920e911a0808d6f631c525314ee233908e317ca60805cd0a9","post.hbs"],
|
||||||
|
["6b561b27169e242b0656211e35b21210158713d566e5267aefc8ab92be699e41","gulpfile.js"],
|
||||||
|
["7db7d6130b9b667001841b79ee67760619a80b9df305b8bfb872e22265313cf5","LICENSE"],
|
||||||
|
["82e26e6c37d0bf92700fa3c9481be281758f2b79e4266cd8ed44138c9543512a","partials/components/author-header.hbs"],
|
||||||
|
["96e8b7d2ac50f83c7535a63b3c54f5872ff7e13d2743d4c0cdaedcb60d155770","partials/components/cta.hbs"],
|
||||||
|
["9c885f99ec47c0df2d9364888331be52f1e11dc77da28497950b8af1b0a3fd4c","assets/built/screen.css.map"],
|
||||||
|
["9f48de3029455d4d58a9f6fb86175e7c4555a8c7744502b4cef5b9ceb5b51a1b","partials/components/navbar.hbs"],
|
||||||
|
["a9e59ea2076c203ff5c68335cc1b16ac36f3e7bc26ed50bf376f29cd59fd15e8","partials/icons/twitter.hbs"],
|
||||||
|
["b659c9d0d5730eb61bb72265872c4521d1e3964e72fc099fde2e819000c6c62c","author.hbs"],
|
||||||
|
["c931b825e11cbc5149f41c21c83332fcf8c87d951065f2716f3b12dd875c414c","index.hbs"],
|
||||||
|
["dbb322d0e284169192f1f6cfd08ddb6241b183d7e110c89285348a27becdd0a5","page.hbs"],
|
||||||
|
["e819b4f518d24661e141a57be64fce163a828d987901c3ba0f529fc6f50dc4fc","partials/components/header.hbs"],
|
||||||
|
["ee737f159229961284f179a8d21024c599b07512825b049c900873fdc7e6df1a","assets/built/main.min.js"],
|
||||||
|
["f6072040f2d6845b43ef7b47c35313307610cde31b21ac70474d474f2c1faa39","partials/components/footer.hbs"],
|
||||||
|
["fa4a19ebf8724e761e963146977ef99560eea04ea1fe3a9106836284bf7de762","assets/js/main.js"],
|
||||||
|
["fac32039620932194df919c6f336b2e270f4a4210a8628bf4d5b0ffbcb091a8b","partials/pswp.hbs"],
|
||||||
|
["ffdbdcade1a6dd508d10b463bd8a3b4ad16fa51ef352099979c5f0eaa8571218","partials/components/tag-header.hbs"]
|
||||||
|
]
|
||||||
|
|
||||||
|
const packageHash = "a70bb6d5b24c09a7f590ff70cd7dea3fc90fbb5f3fd152af8c86865cee51f6db";
|
||||||
|
```
|
Loading…
Reference in New Issue
Block a user