Skip to content

Commit ce48605

Browse files
committed
add quickstart guide
1 parent a0304ab commit ce48605

File tree

1 file changed

+86
-55
lines changed

1 file changed

+86
-55
lines changed

README.md

Lines changed: 86 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# path-master
2-
31
[![JSR](https://jsr.io/badges/@midzdotdev/path-master)](https://jsr.io/@midzdotdev/path-master)
42
[![Release Workflow](https://github.com/midzdotdev/path-master/actions/workflows/release.yml/badge.svg)](https://github.com/midzdotdev/path-master/actions/workflows/release.yml)
53

@@ -10,21 +8,94 @@ You can think of `path-master` as providing structure to files in the same way t
108
Path Master provides a whole host of benefits:
119

1210
- 🏡 **Centralised:** a single source of truth for defining paths
13-
- 🧬 **Consistent:** standardises your path generation
14-
-**Type-safe:** parameters are typed, and path types are inferred
1511
- 📊 **Parameterised:** paths are as dynamic as you need
12+
-**Type-safe:** parameters are typed, and path types are inferred
1613
- 📈 **Incremental:** model a complete file structure or just parts of it
14+
- 🧬 **Consistent:** standardises your path generation
1715

1816
> This library does not modify any filesystem directly,
1917
> it's solely for modelling and generating paths.
2018
21-
The applications for this are endless, but commonly useful with:
19+
It can be used anywhere paths are used, such as:
2220

23-
- 💾 **Local Filesystem:** for local storage (e.g. via Node.js `fs` module)
2421
- ☁️ **S3 Buckets:** for remote storage in the cloud
22+
- 💾 **Local Filesystem:** for local storage (e.g. via Node.js `fs` module)
2523
- 🧭 **Origin Private File System:** for local storage in web apps
2624
- 🌎 **Relative URLs:** between resources on the web
2725

26+
## Quickstart Guide
27+
28+
1. **Model** your file structure with `dir` and `file`
29+
2. **Get paths**, either:
30+
- **to a file/dir** with `getPath`
31+
- **between files/dirs** with `getRelativeFsPath` or `getRelativeUrlPath`
32+
33+
Here is a model to represent a HLS video package file structure and how to get paths with `getPath` and `getRelativeUrlPath`.
34+
35+
```ts
36+
import { dir, file, getPath, getRelativeUrlPath } from '@midzdotdev/path-master'
37+
38+
/* This is the file structure we're modelling:
39+
40+
.
41+
└── videos
42+
└── [videoId]
43+
├── master.m3u8
44+
└── stream_[quality]
45+
├── playlist.m3u8
46+
└── segment_[segmentId].ts
47+
*/
48+
49+
const hlsPackageModel = dir(
50+
({ videoId }: { videoId: number }) => `videos/${videoId}`,
51+
{
52+
manifest: file(`master.m3u8`),
53+
variantStream: dir(
54+
({ quality }: { quality: 720 | 1080 }) => `stream_${quality}`,
55+
{
56+
playlist: file(`playlist.m3u8`),
57+
segment: file(
58+
({ segmentId }: { segmentId: number }) => `segment_${segmentId}.ts`
59+
),
60+
}
61+
),
62+
}
63+
)
64+
65+
const hlsPackagePath = getPath(hlsPackageModel, '', { videoId: 42 })
66+
// result: "videos/42/"
67+
68+
const streamPlaylist = getPath(hlsPackageModel, 'variantStream.playlist', {
69+
videoId: 42,
70+
quality: 720,
71+
})
72+
// result: "videos/42/stream_720/playlist.m3u8"
73+
74+
const masterPlaylistToVariantPlaylist = getRelativeUrlPath(
75+
hlsPackageModel,
76+
['manifest', { videoId: 42 }],
77+
['variantStream.playlist', { videoId: 42, quality: 720 }]
78+
)
79+
// result: "stream_720/playlist.m3u8"
80+
```
81+
82+
<p align="center">
83+
<img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExeTJxYmk3YnZyOXc1c2U5Y2cxdjdjbGJlanpmbGx1M3l5cGc0YWtraCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/a0h7sAqON67nO/giphy.gif" style="max-width: 300px"/>
84+
</p>
85+
86+
> If the Quickstart Guide doesn't make sense, don't worry! The rest of this README will cover everything you need to know.
87+
88+
# Table of Contents
89+
90+
- [Introduction](#introduction)
91+
- [Installation](#installation)
92+
- [Conceptualising Models](#conceptualising-models)
93+
- [Abstracting large models](#abstracting-large-models)
94+
- [Create a Model](#create-a-model)
95+
- [Get Paths](#get-paths)
96+
- [Get Relative Paths](#get-relative-paths)
97+
- [Contributing](#contributing)
98+
2899
## Introduction
29100

30101
Making storage paths in any language is a painful process.
@@ -83,8 +154,6 @@ The following table gives us some examples of concrete paths for different nodes
83154

84155
> Note that the path is relative to the root of the model (represented by `.` [in the psuedo-model](#psuedo-model)).
85156
86-
Hopefully now modelling a file structure make sense as a concept. Let's move onto the code.
87-
88157
## Create a Model
89158

90159
The library exposes two helper functions `file` and `dir` for us to build our model.
@@ -125,56 +194,18 @@ const deepDir = dir('deep_dir', {
125194
})
126195
```
127196

128-
### Example: Modelling our HLS package
129-
130-
Let's fully model [our original example](#psuedo-model).
131-
132-
Here is the desired psuedo-model copied for convenience:
197+
> The path of a node in the model can span across multiple directories (e.g. `videos/${videoId}` above).
198+
> This can help to produce a more concise model when dealing with deeply nested structures.
133199
134-
```
135-
.
136-
└── videos
137-
└── [videoId]
138-
├── master.m3u8
139-
└── stream_[quality]
140-
├── playlist.m3u8
141-
└── segment_[segmentId].ts
142-
```
143-
144-
Using our `dir` and `file` modelling functions, we can define our model:
145-
146-
```ts
147-
import { dir, file } from '@midzdotdev/path-master'
148-
149-
const hlsPackageModel = dir(
150-
({ videoId }: { videoId: number }) => `videos/${videoId}`,
151-
{
152-
manifest: file(`master.m3u8`),
153-
variantStream: dir(
154-
({ quality }: { quality: 720 | 1080 }) => `stream_${quality}`,
155-
{
156-
playlist: file(`playlist.m3u8`),
157-
segment: file(
158-
({ segmentId }: { segmentId: number }) => `segment_${segmentId}.ts`
159-
),
160-
}
161-
),
162-
}
163-
)
164-
```
165-
166-
The path of a node in the model can span across multiple directories (e.g. `videos/${videoId}` above).
167-
This can help to produce a more concise model when dealing with deeply nested structures.
168-
169-
### Abstracting large models
200+
## Abstracting large models
170201

171202
If you're working with a very large model, it might be clearer to define parts of a model separately, then join them together into one main model.
172203

173204
If all the parts are together in a single file, then you can `export` the main model to remove any ambiguity about which model should be used in other parts of your application.
174205

175206
Ideally a model should fully describe the structure of a storage destination. This way your model's root aligns with the storage's root and the paths given by `path-master` can be used directly as absolute paths.
176207

177-
## Getting Paths
208+
## Get Paths
178209

179210
Now that we have a model, let's address the reason that we're here in the first place! Let's get some paths.
180211

@@ -235,7 +266,7 @@ const segment11 = getPath(hlsPackageModel, 'variantStream.segment', {
235266

236267
> Notice that the type of the path is properly inferred from the model definition.
237268
238-
## Getting Relative Paths
269+
## Get Relative Paths
239270

240271
You can get relative paths between nodes, so long as they're in the same model.
241272

@@ -246,7 +277,7 @@ The relative path from `a/b` to `a/c/d`:
246277
- in a filesystem is `../c/d`
247278
- in a URL is `c/d`
248279

249-
> Have a play around with this yourself to better understand the difference.
280+
> You can have a play around with this yourself to better understand the difference.
250281
>
251282
> - Use the Node REPL with `path.relative(from, to)` for filesystem paths
252283
> - Use the browser console with `new URL(relativePath, fromUrl)` for URL paths
@@ -256,17 +287,17 @@ As a result we have two separate functions for each use-case:
256287
- filesystem paths: `getRelativeFsPath`
257288
- URL paths: `getRelativeUrlPath`
258289

259-
Both of these functions have an identical signature.
290+
Both of these functions have an identical signature that looks like this.
260291

261292
```ts
262293
declare const x: (
263-
model: FileNode | DirNode,
294+
model: DirNode,
264295
from: string | [keypath: string, dependencies: {}],
265296
to: string | [keypath: string, dependencies: {}]
266297
) => string
267298
```
268299
269-
> If the node specified by _from_ or _to_'s keypath does not require dependencies, then you can just pass the keypath string.
300+
> When the node specified for _from_ or _to_ has no dependencies, then you can just pass the keypath string.
270301
271302
Since our example model being a HLS package only concerns itself with URLs, we'll demonstrate with `getRelativeUrlPath`.
272303

0 commit comments

Comments
 (0)