Skip to content

Commit e358da8

Browse files
committed
Added pre-commit hook
- Using husky, execute pretty-quick on files staged for commit - Updated the README_INTERNAL.md with dev environment set up steps - Ran initial prettier (was surpised how few file were updated 😍)
1 parent 9e0940b commit e358da8

File tree

10 files changed

+354
-65
lines changed

10 files changed

+354
-65
lines changed

.husky/pre-commit

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env sh
2+
. "$(dirname -- "$0")/_/husky.sh"
3+
4+
npx pretty-quick --staged

.prettierignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
coverage
2+
dist
3+
node_modules
4+
*.vscode*
5+
*.md

.prettierrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"printWidth": 120,
3+
"singleQuote": true,
4+
"tabWidth": 2,
5+
"useTabs": false,
6+
"semi": true,
7+
"quoteProps": "as-needed",
8+
"jsxSingleQuote": false,
9+
"trailingComma": "es5",
10+
"bracketSpacing": true,
11+
"arrowParens": "always"
12+
}

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ yarn add [email protected]
3737
- A [Mux](https://mux.com) account
3838
- You will need both the **Access Token** and **Secret Key** scoped with "Full Access" permissions which can be created in the [Mux Dashboard](https://dashboard.mux.com/settings/access-tokens)
3939
- The **Webhook Signing Secret** which can be created in the [Mux Dashboard](https://dashboard.mux.com/settings/webhooks) (See the [Webhooks](#Webhooks) section for more info)
40-
- Tested with [Strapi](https://strapi.io/) v4.2.0 Community Edition
40+
- Tested with [Strapi](https://strapi.io/) v4.5.1 Community Edition
4141

4242
## ⚙️ Configuration
4343

@@ -61,12 +61,16 @@ Where `{STRAPI_BASE_URL}` is the publicly accessible hostname of your [Strapi](h
6161

6262
## 🧑‍⚖️ Permissions
6363

64-
Currently, anyone with "Super Admin" access to your [Strapi](https://strapi.io/) instance will be able to utilize the plugin for uploading and managing content.
64+
Currently, anyone with "Super Admin" access to your [Strapi](https://strapi.io/) instance will be able to utilize the plugin for uploading and managing content within the [Strapi](https://strapi.io/) CE version. More sophisticated permissions can be defined for [Strapi](https://strapi.io/) Enterprise users using [RBAC](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/rbac.html#declaring-new-conditions).
65+
66+
**Please note**: End Users can only have read operation permissions (`find`, `findOne` and `count`). Write operations are not supported due to potential security reasons.
6567

6668
## 🤝 Contributing
6769

6870
Contributions, issues and feature requests are welcome!
6971

72+
Developers for this plugin should take a look at the `README_INTERNAL.md` document for details on setting up dev environments.
73+
7074
If you encounter an error or have questions, please feel free to file inquiries on the [Issues](https://github.com/muxinc/strapi-plugin-mux-video-uploader/issues) page for `strapi-plugin-mux-video-uploader`.
7175

7276
## 🗣 FAQ

README_INTERNAL.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
1+
# Setting up your dev environment
2+
3+
Start by installing the (dev) dependencies—
4+
5+
```
6+
% yarn install
7+
```
8+
9+
Initialize [Husky](https://www.npmjs.com/package/husky) to get the pre-commit hook binary installed on your local development workstation—
10+
11+
```
12+
% yarn prepare
13+
```
14+
15+
When testing your builds with Strapi, it is best to compile the Typescript and use the JavaScript output in the `./dist` directory as your candidate (this is ultimately what is published to NPM). Generating a build can be done by running the following command—
16+
17+
```
18+
% yarn build
19+
```
20+
121
# Releasing
222

323
1. Merge feature branches, bug fixes, and whatever changes into `master` after CI passes and PRs are approved
424
1. Create a new branch off `master` when you're ready to release a new version
525
1. On this branch run `npm version [...]` (see `npm-version` [docs](https://docs.npmjs.com/cli/v7/commands/npm-version) for more info) which will bump the version in `package.json` and make a tag (for example `npm version patch -m "Bump for 3.1.2"`). Follow [SemVer rules](https://semver.org/) for patch/minor/major.
626
1. Push the version commit and the tag `git push && git push --tags origin`
727
1. Open Pull Request, "Rebase and merge" after approved
8-
1. Create a new release in the Github UI, give the release a name and add release notes (creating the release will kick off npm publish)
28+
1. Create a new release in the Github UI, give the release a name and add release notes (creating the release will kick off npm publish using Github Actions)
929
1. Checkout the `master` branch and pull the latest by running `git checkout master && git pull`
10-
1. Publish the new version to npmjs.com using the `npm publish` command

admin/src/components/preview-player/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ const MuxPlayerStyled = styled(MuxPlayer)`
1414
width: 100%;
1515
`;
1616

17-
const PreviewPlayer = (props:Props) => {
17+
const PreviewPlayer = (props: Props) => {
1818
const { muxAsset } = props;
1919

20-
if(muxAsset === undefined || !muxAsset.playback_id) return null;
21-
20+
if (muxAsset === undefined || !muxAsset.playback_id) return null;
21+
2222
const posterUrl = getThumbnail(muxAsset.playback_id);
2323

2424
return (
@@ -30,7 +30,7 @@ const PreviewPlayer = (props:Props) => {
3030
video_title: muxAsset.title,
3131
player_name: 'Strapi Admin Dashboard',
3232
player_version: pluginPkg.version,
33-
page_type: 'Preview Player'
33+
page_type: 'Preview Player',
3434
}}
3535
streamType="on-demand"
3636
/>

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"build": "yarn clean && tsc && yarn copy-files",
2727
"clean": "rimraf dist/",
2828
"copy-files": "copyfiles README.md yarn.lock dist/",
29-
"dev": "tsc --watch"
29+
"dev": "tsc --watch",
30+
"prepare": "husky install"
3031
},
3132
"dependencies": {
3233
"@mux/mux-node": "^6.4.0",
@@ -55,6 +56,9 @@
5556
"@types/react-router-dom": "^5.3.3",
5657
"@types/styled-components": "^5.1.25",
5758
"copyfiles": "^2.4.1",
59+
"husky": "^8.0.2",
60+
"prettier": "^2.7.1",
61+
"pretty-quick": "^3.1.3",
5862
"rimraf": "^3.0.2",
5963
"typescript": "^4.7.4"
6064
},

server/controllers/mux.ts

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,19 @@ const { Webhooks } = Mux;
1414

1515
const model = `plugin::${pluginId}.mux-asset`;
1616

17-
const resolveMuxAssets = async (filters:MuxAssetFilter) => {
17+
const resolveMuxAssets = async (filters: MuxAssetFilter) => {
1818
const params = { filters };
19-
19+
2020
const muxAssets = await strapi.entityService.findMany(model, params);
2121

2222
if (muxAssets.length === 1) {
2323
return muxAssets[0];
24-
}
25-
else {
24+
} else {
2625
throw new Error('Unable to resolve mux-asset');
2726
}
2827
};
2928

30-
const processWebhookEvent = async (webhookEvent:any) => {
29+
const processWebhookEvent = async (webhookEvent: any) => {
3130
const { type, data } = webhookEvent;
3231

3332
switch (type) {
@@ -36,8 +35,8 @@ const processWebhookEvent = async (webhookEvent:any) => {
3635
return [
3736
muxAsset.id,
3837
{
39-
data: { asset_id: data.asset_id }
40-
}
38+
data: { asset_id: data.asset_id },
39+
},
4140
];
4241
}
4342
case 'video.asset.ready': {
@@ -49,9 +48,9 @@ const processWebhookEvent = async (webhookEvent:any) => {
4948
playback_id: data.playback_ids[0].id,
5049
duration: data.duration,
5150
aspect_ratio: data.aspect_ratio,
52-
isReady: true
53-
}
54-
}
51+
isReady: true,
52+
},
53+
},
5554
];
5655
}
5756
case 'video.asset.errored': {
@@ -60,56 +59,54 @@ const processWebhookEvent = async (webhookEvent:any) => {
6059
muxAsset.id,
6160
{
6261
data: {
63-
error_message: `${data.errors.type}: ${data.errors.messages[0] || ''}`
64-
}
65-
}
62+
error_message: `${data.errors.type}: ${data.errors.messages[0] || ''}`,
63+
},
64+
},
6665
];
6766
}
68-
default: return undefined;
67+
default:
68+
return undefined;
6969
}
70-
}
70+
};
7171

7272
// Do not go gentle into that good night,
7373
// Old age should burn and rave at close of day;
7474
// Rage, rage against the dying of the light.
7575
const thumbnail = async (ctx: Context) => {
7676
const { playbackId } = ctx.params;
7777

78-
const response = await axios.get(
79-
`https://image.mux.com/${playbackId}/thumbnail.png`,
80-
{
81-
params: ctx.query,
82-
responseType: 'stream'
83-
}
84-
);
78+
const response = await axios.get(`https://image.mux.com/${playbackId}/thumbnail.png`, {
79+
params: ctx.query,
80+
responseType: 'stream',
81+
});
8582

8683
ctx.response.set('content-type', response.headers['content-type']);
8784
ctx.body = response.data;
8885
};
8986

90-
const submitDirectUpload = async (ctx:Context) => {
87+
const submitDirectUpload = async (ctx: Context) => {
9188
const { title, origin } = ctx.request.body;
9289

93-
const cors = origin || ctx.request.header.origin
90+
const cors = origin || ctx.request.header.origin;
9491

9592
const result = await getService('mux').getDirectUploadUrl(cors);
9693

9794
const data = {
9895
title,
99-
upload_id: result.id
96+
upload_id: result.id,
10097
};
10198

10299
await strapi.entityService.create(model, { data });
103100

104101
ctx.send(result);
105102
};
106103

107-
const submitRemoteUpload = async (ctx:Context) => {
104+
const submitRemoteUpload = async (ctx: Context) => {
108105
const { body } = ctx.request;
109106

110-
if(!body.url) {
111-
ctx.badRequest("ValidationError", { errors: { "url": ["url cannot be empty"]}});
112-
107+
if (!body.url) {
108+
ctx.badRequest('ValidationError', { errors: { url: ['url cannot be empty'] } });
109+
113110
return;
114111
}
115112

@@ -118,7 +115,7 @@ const submitRemoteUpload = async (ctx:Context) => {
118115
const data = {
119116
asset_id: result.id,
120117
title: body.title,
121-
url: body.url
118+
url: body.url,
122119
};
123120

124121
const response = await strapi.entityService.create(model, { data });
@@ -129,8 +126,8 @@ const submitRemoteUpload = async (ctx:Context) => {
129126
const deleteMuxAsset = async (ctx: Context) => {
130127
const { id, delete_on_mux } = ctx.request.body;
131128

132-
if(!id) {
133-
ctx.badRequest("ValidationError", { errors: { "id": ["id needs to be defined"]}});
129+
if (!id) {
130+
ctx.badRequest('ValidationError', { errors: { id: ['id needs to be defined'] } });
134131

135132
return;
136133
}
@@ -165,26 +162,29 @@ const deleteMuxAsset = async (ctx: Context) => {
165162
ctx.send(result);
166163
};
167164

168-
const muxWebhookHandler = async (ctx:Context) => {
165+
const muxWebhookHandler = async (ctx: Context) => {
169166
const body = ctx.request.body;
170167
const sigHttpHeader = ctx.request.headers['mux-signature'];
171168

172169
const config = await Config.getConfig('general');
173170

174-
if(sigHttpHeader === undefined || sigHttpHeader === '' || (Array.isArray(sigHttpHeader) && sigHttpHeader.length < 0)) {
171+
if (
172+
sigHttpHeader === undefined ||
173+
sigHttpHeader === '' ||
174+
(Array.isArray(sigHttpHeader) && sigHttpHeader.length < 0)
175+
) {
175176
ctx.throw(401, 'Webhook signature is missing');
176177
}
177-
178-
if(Array.isArray(sigHttpHeader) && sigHttpHeader.length > 1) {
178+
179+
if (Array.isArray(sigHttpHeader) && sigHttpHeader.length > 1) {
179180
ctx.throw(401, 'we have an unexpected amount of signatures');
180181
}
181182

182183
let sig;
183184

184-
if(Array.isArray(sigHttpHeader)){
185+
if (Array.isArray(sigHttpHeader)) {
185186
sig = sigHttpHeader[0];
186-
}
187-
else{
187+
} else {
188188
sig = sigHttpHeader;
189189
}
190190

@@ -193,7 +193,7 @@ const muxWebhookHandler = async (ctx:Context) => {
193193
// Koa.js request (the middleware used for parsing requests).
194194

195195
// let isSigValid;
196-
196+
197197
// try {
198198
// isSigValid = Webhooks.verifyHeader(JSON.stringify(body), sig, config.webhook_signing_secret);
199199
// } catch(err) {
@@ -219,5 +219,5 @@ export = {
219219
submitRemoteUpload,
220220
deleteMuxAsset,
221221
muxWebhookHandler,
222-
thumbnail
222+
thumbnail,
223223
};

server/services/mux.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { RequestOptions } from '@mux/mux-node/dist/RequestOptions';
33
import { Asset, Upload } from '@mux/mux-node/dist/video/domain';
44

55
import pluginPkg from './../../package.json';
6-
import { Config } from "./../utils";
6+
import { Config } from './../utils';
77

88
export interface MuxService {
99
getAssetById: (assetId: string) => Promise<Asset>;
@@ -15,47 +15,47 @@ export interface MuxService {
1515

1616
const getMuxClient = async () => {
1717
const { access_token, secret_key } = await Config.getConfig('general');
18-
const options:RequestOptions = { platform: { name: 'Strapi CMS', version: pluginPkg.version } };
18+
const options: RequestOptions = { platform: { name: 'Strapi CMS', version: pluginPkg.version } };
1919

2020
return new Mux(access_token, secret_key, options);
21-
}
21+
};
2222

2323
export default ({ strapi }: { strapi: any }) => ({
2424
async getAssetById(assetId: string): Promise<Asset> {
2525
const { Video } = await getMuxClient();
2626

2727
return await Video.Assets.get(assetId);
2828
},
29-
async getAssetByUploadId(uploadId:string): Promise<Asset> {
29+
async getAssetByUploadId(uploadId: string): Promise<Asset> {
3030
const { Video } = await getMuxClient();
3131

3232
const assets = await Video.Assets.list({ upload_id: uploadId });
3333

3434
return assets[0];
3535
},
36-
async getDirectUploadUrl(corsOrigin:string = "*"): Promise<Upload> {
36+
async getDirectUploadUrl(corsOrigin: string = '*'): Promise<Upload> {
3737
const { Video } = await getMuxClient();
3838

3939
return Video.Uploads.create({
4040
cors_origin: corsOrigin,
4141
new_asset_settings: {
42-
playback_policy: ['public']
43-
}
42+
playback_policy: ['public'],
43+
},
4444
});
4545
},
46-
async createAsset(url:string): Promise<Asset> {
46+
async createAsset(url: string): Promise<Asset> {
4747
const { Video } = await getMuxClient();
4848

4949
return Video.Assets.create({
5050
input: url,
51-
playback_policy: ['public']
51+
playback_policy: ['public'],
5252
});
5353
},
54-
async deleteAsset(assetId:string): Promise<boolean> {
54+
async deleteAsset(assetId: string): Promise<boolean> {
5555
const { Video } = await getMuxClient();
5656

5757
await Video.Assets.del(assetId);
58-
58+
5959
return true;
60-
}
60+
},
6161
});

0 commit comments

Comments
 (0)