shifro 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,8 @@ Run `npm install shifro` to install the library as dependency for your project.
23
23
  #### Decrypting file using Node.js streams
24
24
 
25
25
  ```ts
26
- import { Decryption, Input, FilePathSource, KeyId, Key, Output, FilePathTarget } from 'shifro';
26
+ import { Decryption, FilePathSource, FilePathTarget, Input, Output } from 'shifro';
27
+ import type { Key, KeyId } from 'shifro';
27
28
 
28
29
  async function decrypt() {
29
30
  const decryption = await Decryption.init({
@@ -32,12 +33,21 @@ async function decrypt() {
32
33
  keys: new Map<KeyId, Key>([
33
34
  ['4d97930a3d7b55fa81d0028653f5e499', '429ec76475e7a952d224d8ef867f12b6'],
34
35
  ['d21373c0b8ab5ba9954742bcdfb5f48b', '150a6c7d7dee6a91b74dccfce5b31928'],
35
- ])
36
+ ]),
37
+ // Optinally, you can use this callback to handle encryption information (like key ID and PSSH boxes)
38
+ handleEncryptionInfo: ({ keyId, psshBoxes }) => {
39
+ console.group(`Key ID: ${keyId}`);
40
+ for (const psshBox of psshBoxes) {
41
+ console.log(`PSSH box: ${psshBox.systemId} (${psshBox.data.length} bytes)`);
42
+ }
43
+ console.groupEnd();
44
+ },
36
45
  }),
37
46
  output: new Output({ target: new FilePathTarget('./output.mp4') }),
38
47
  });
39
48
 
40
- decryption.onProgress = (progress) => process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`),
49
+ decryption.onProgress = (progress) =>
50
+ process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`);
41
51
 
42
52
  await decryption.execute();
43
53
  }
@@ -46,7 +56,8 @@ async function decrypt() {
46
56
  #### Decrypting file using browser's Web Streams API
47
57
 
48
58
  ```ts
49
- import { Decryption, Input, ReadableStreamSource, KeyId, Key, Output, StreamTarget } from 'shifro';
59
+ import { Decryption, Input, Output, ReadableStreamSource, StreamTarget } from 'shifro';
60
+ import type { Key, KeyId } from 'shifro';
50
61
 
51
62
  async function decryptFromBrowser() {
52
63
  const handleFileSelect = async () => {
@@ -54,12 +65,15 @@ async function decryptFromBrowser() {
54
65
  const input = document.querySelector<HTMLInputElement>('#input')!;
55
66
  input.addEventListener('change', () => resolve(input.files![0]));
56
67
  });
57
- }
68
+ };
58
69
 
59
70
  const inputFile = await handleFileSelect();
60
71
  const inputReadableStream = inputFile.stream();
61
72
 
62
- const outputFileHandle = window.showSaveFilePicker({ suggestedName: 'output.mp4', startIn: 'downloads' });
73
+ const outputFileHandle = window.showSaveFilePicker({
74
+ suggestedName: 'output.mp4',
75
+ startIn: 'downloads',
76
+ });
63
77
  const outputWritableStream = await outputFileHandle.createWritable();
64
78
 
65
79
  const decryption = await Decryption.init({
@@ -68,18 +82,18 @@ async function decryptFromBrowser() {
68
82
  keys: new Map<KeyId, Key>([
69
83
  ['4d97930a3d7b55fa81d0028653f5e499', '429ec76475e7a952d224d8ef867f12b6'],
70
84
  ['d21373c0b8ab5ba9954742bcdfb5f48b', '150a6c7d7dee6a91b74dccfce5b31928'],
71
- ])
85
+ ]),
72
86
  }),
73
87
  output: new Output({ target: new StreamTarget(outputWritableStream) }),
74
88
  });
75
89
 
76
- decryption.onProgress = (progress) => console.log(`Decrypting... [${Math.round(progress * 100)}%]`),
90
+ decryption.onProgress = (progress) =>
91
+ console.log(`Decrypting... [${Math.round(progress * 100)}%]`);
77
92
 
78
93
  await decryption.execute();
79
94
  }
80
95
  ```
81
96
 
82
-
83
97
  ## Credits
84
98
 
85
99
  - [mediabunny](https://github.com/Vanilagy/mediabunny)
package/dist/cli.mjs CHANGED
@@ -3,16 +3,20 @@ import { parseArgs } from "node:util";
3
3
  import { ALL_FORMATS, Conversion, FilePathSource, FilePathTarget, Input, Mp4OutputFormat, Output } from "mediabunny";
4
4
  //#region package.json
5
5
  var name = "shifro";
6
- var version = "1.0.0";
6
+ var version = "1.1.1";
7
7
  var author = "Vitaly Gashkov <vitalygashkov@vk.com>";
8
8
  //#endregion
9
- //#region src/main.ts
9
+ //#region src/index.ts
10
10
  var Input$1 = class extends Input {
11
- constructor({ keys, ...options }) {
11
+ constructor({ keys, handleEncryptionInfo, ...options }) {
12
12
  super({
13
13
  ...options,
14
14
  formats: ALL_FORMATS,
15
- formatOptions: { isobmff: { resolveKeyId: ({ keyId }) => {
15
+ formatOptions: { isobmff: { resolveKeyId: ({ keyId, psshBoxes }) => {
16
+ handleEncryptionInfo?.({
17
+ keyId,
18
+ psshBoxes
19
+ });
16
20
  const key = keys.get(keyId);
17
21
  if (!key) throw new Error("Unknown key ID.");
18
22
  return key;
@@ -56,7 +60,8 @@ const decryptFile = async () => {
56
60
  }),
57
61
  output: new Output$1({ target: new FilePathTarget(outputPath) })
58
62
  });
59
- decryption.onProgress = (progress) => process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`), await decryption.execute();
63
+ decryption.onProgress = (progress) => process.stdout.write(`\rDecrypting... [${Math.round(progress * 100)}%]`);
64
+ await decryption.execute();
60
65
  console.timeEnd("\nDone!");
61
66
  };
62
67
  const showHelp = () => {
@@ -1,15 +1,20 @@
1
- import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
1
+ import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, PsshBox, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
2
2
 
3
- //#region src/main.d.ts
3
+ //#region src/index.d.ts
4
4
  type KeyId = string;
5
5
  type Key = string;
6
6
  type KeyMap = Map<KeyId, Key>;
7
7
  declare class Input extends Input$1 {
8
8
  constructor({
9
9
  keys,
10
+ handleEncryptionInfo,
10
11
  ...options
11
12
  }: Omit<InputOptions, 'formats' | 'formatOptions'> & {
12
13
  keys: KeyMap;
14
+ handleEncryptionInfo?: (options: {
15
+ keyId: string;
16
+ psshBoxes: PsshBox[];
17
+ }) => void;
13
18
  });
14
19
  }
15
20
  declare class Output extends Output$1 {
@@ -20,4 +25,4 @@ declare class Output extends Output$1 {
20
25
  });
21
26
  }
22
27
  //#endregion
23
- export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, InputOptions, Key, KeyId, KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource };
28
+ export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, type InputOptions, type Key, type KeyId, type KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, type OutputFormat, type OutputOptions, ReadableStreamSource, StreamSource, type StreamSourceOptions, StreamTarget, type StreamTargetOptions, UrlSource };
package/dist/index.mjs ADDED
@@ -0,0 +1,29 @@
1
+ import { ALL_FORMATS, Conversion, FilePathSource, FilePathTarget, Input as Input$1, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, ReadableStreamSource, StreamSource, StreamTarget, UrlSource } from "mediabunny";
2
+ //#region src/index.ts
3
+ var Input = class extends Input$1 {
4
+ constructor({ keys, handleEncryptionInfo, ...options }) {
5
+ super({
6
+ ...options,
7
+ formats: ALL_FORMATS,
8
+ formatOptions: { isobmff: { resolveKeyId: ({ keyId, psshBoxes }) => {
9
+ handleEncryptionInfo?.({
10
+ keyId,
11
+ psshBoxes
12
+ });
13
+ const key = keys.get(keyId);
14
+ if (!key) throw new Error("Unknown key ID.");
15
+ return key;
16
+ } } }
17
+ });
18
+ }
19
+ };
20
+ var Output = class extends Output$1 {
21
+ constructor({ ...options }) {
22
+ super({
23
+ ...options,
24
+ format: options.format ?? new Mp4OutputFormat()
25
+ });
26
+ }
27
+ };
28
+ //#endregion
29
+ export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, ReadableStreamSource, StreamSource, StreamTarget, UrlSource };
package/package.json CHANGED
@@ -1,40 +1,21 @@
1
1
  {
2
2
  "name": "shifro",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "A lightweight library for decrypting MP4 files, directly in the browser",
5
5
  "files": [
6
6
  "dist"
7
7
  ],
8
- "scripts": {
9
- "start": "node ./dist/cli.mjs",
10
- "web": "vite",
11
- "build": "npm run bundle:lib && npm run bundle:cli",
12
- "bundle:lib": "tsdown ./src/index.ts --format cjs --format esm --dts --platform neutral",
13
- "bundle:cli": "tsdown ./src/cli.ts --format esm --no-clean",
14
- "build:cli": "npm run build:cli:mac && npm run build:cli:linux && npm run build:cli:win",
15
- "build:cli:mac": "bun build --compile --minify --bytecode --target=bun-darwin-arm64 ./src/cli.ts --outfile shifro-windows.exe",
16
- "build:cli:linux": "bun build --compile --minify --bytecode --target=bun-linux-x64 ./src/cli.ts --outfile shifro-linux",
17
- "build:cli:win": "bun build --compile --minify --bytecode --target=bun-windows-x64 ./src/cli.ts --outfile shifro-macos",
18
- "typecheck": "tsc --noEmit",
19
- "test": "vitest",
20
- "prepublishOnly": "npm run build"
21
- },
22
8
  "bin": {
23
9
  "shifro": "./dist/cli.mjs"
24
10
  },
25
11
  "type": "module",
26
- "main": "./dist/index.js",
27
- "types": "./dist/index.d.ts",
12
+ "main": "./dist/index.mjs",
13
+ "types": "./dist/index.d.mts",
28
14
  "exports": {
29
15
  ".": {
30
- "require": {
31
- "types": "./dist/index.d.cts",
32
- "default": "./dist/index.cjs"
33
- },
34
- "import": {
35
- "types": "./dist/index.d.ts",
36
- "default": "./dist/index.js"
37
- }
16
+ "types": "./dist/index.d.mts",
17
+ "module-sync": "./dist/index.mjs",
18
+ "default": "./dist/index.mjs"
38
19
  }
39
20
  },
40
21
  "repository": {
@@ -74,12 +55,31 @@
74
55
  "node": ">=22"
75
56
  },
76
57
  "dependencies": {
77
- "mediabunny": "^1.42.0-beta.5"
58
+ "mediabunny": "^1.42.0-beta.7"
78
59
  },
79
60
  "devDependencies": {
80
61
  "@types/node": "^24.5.2",
62
+ "oxfmt": "^0.46.0",
63
+ "oxlint": "^1.61.0",
81
64
  "tsdown": "^0.21.10",
82
- "typescript": "^5.9.2",
65
+ "typescript": "~6.0.3",
83
66
  "vitest": "^4.1.5"
67
+ },
68
+ "scripts": {
69
+ "start": "node ./dist/cli.mjs",
70
+ "web": "vite",
71
+ "build": "pnpm run bundle:lib && pnpm run bundle:cli",
72
+ "bundle:lib": "tsdown ./src/index.ts --format esm --dts --platform neutral --fixed-extension",
73
+ "bundle:cli": "tsdown ./src/cli.ts --format esm --no-clean",
74
+ "build:cli": "pnpm run build:cli:mac && pnpm run build:cli:linux && pnpm run build:cli:win",
75
+ "build:cli:mac": "bun build --compile --minify --bytecode --target=bun-darwin-arm64 ./src/cli.ts --outfile shifro-windows.exe",
76
+ "build:cli:linux": "bun build --compile --minify --bytecode --target=bun-linux-x64 ./src/cli.ts --outfile shifro-linux",
77
+ "build:cli:win": "bun build --compile --minify --bytecode --target=bun-windows-x64 ./src/cli.ts --outfile shifro-macos",
78
+ "fmt": "oxfmt .",
79
+ "fmt:check": "oxfmt --check .",
80
+ "lint": "oxlint .",
81
+ "lint:fix": "oxlint --fix .",
82
+ "typecheck": "tsc --noEmit",
83
+ "test": "vitest"
84
84
  }
85
- }
85
+ }
package/dist/index.cjs DELETED
@@ -1,43 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- let mediabunny = require("mediabunny");
3
- //#region src/main.ts
4
- var Input = class extends mediabunny.Input {
5
- constructor({ keys, ...options }) {
6
- super({
7
- ...options,
8
- formats: mediabunny.ALL_FORMATS,
9
- formatOptions: { isobmff: { resolveKeyId: ({ keyId }) => {
10
- const key = keys.get(keyId);
11
- if (!key) throw new Error("Unknown key ID.");
12
- return key;
13
- } } }
14
- });
15
- }
16
- };
17
- var Output = class extends mediabunny.Output {
18
- constructor({ ...options }) {
19
- super({
20
- ...options,
21
- format: options.format ?? new mediabunny.Mp4OutputFormat()
22
- });
23
- }
24
- };
25
- //#endregion
26
- exports.Decryption = mediabunny.Conversion;
27
- exports.FilePathSource = mediabunny.FilePathSource;
28
- exports.FilePathTarget = mediabunny.FilePathTarget;
29
- exports.Input = Input;
30
- exports.InputOptions = mediabunny.InputOptions;
31
- exports.MkvOutputFormat = mediabunny.MkvOutputFormat;
32
- exports.MovOutputFormat = mediabunny.MovOutputFormat;
33
- exports.Mp3OutputFormat = mediabunny.Mp3OutputFormat;
34
- exports.Mp4OutputFormat = mediabunny.Mp4OutputFormat;
35
- exports.Output = Output;
36
- exports.OutputFormat = mediabunny.OutputFormat;
37
- exports.OutputOptions = mediabunny.OutputOptions;
38
- exports.ReadableStreamSource = mediabunny.ReadableStreamSource;
39
- exports.StreamSource = mediabunny.StreamSource;
40
- exports.StreamSourceOptions = mediabunny.StreamSourceOptions;
41
- exports.StreamTarget = mediabunny.StreamTarget;
42
- exports.StreamTargetOptions = mediabunny.StreamTargetOptions;
43
- exports.UrlSource = mediabunny.UrlSource;
package/dist/index.d.ts DELETED
@@ -1,23 +0,0 @@
1
- import { Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
2
-
3
- //#region src/main.d.ts
4
- type KeyId = string;
5
- type Key = string;
6
- type KeyMap = Map<KeyId, Key>;
7
- declare class Input extends Input$1 {
8
- constructor({
9
- keys,
10
- ...options
11
- }: Omit<InputOptions, 'formats' | 'formatOptions'> & {
12
- keys: KeyMap;
13
- });
14
- }
15
- declare class Output extends Output$1 {
16
- constructor({
17
- ...options
18
- }: Omit<OutputOptions, 'format'> & {
19
- format?: OutputFormat;
20
- });
21
- }
22
- //#endregion
23
- export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, InputOptions, Key, KeyId, KeyMap, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource };
package/dist/index.js DELETED
@@ -1,25 +0,0 @@
1
- import { ALL_FORMATS, Conversion, FilePathSource, FilePathTarget, Input as Input$1, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output as Output$1, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource } from "mediabunny";
2
- //#region src/main.ts
3
- var Input = class extends Input$1 {
4
- constructor({ keys, ...options }) {
5
- super({
6
- ...options,
7
- formats: ALL_FORMATS,
8
- formatOptions: { isobmff: { resolveKeyId: ({ keyId }) => {
9
- const key = keys.get(keyId);
10
- if (!key) throw new Error("Unknown key ID.");
11
- return key;
12
- } } }
13
- });
14
- }
15
- };
16
- var Output = class extends Output$1 {
17
- constructor({ ...options }) {
18
- super({
19
- ...options,
20
- format: options.format ?? new Mp4OutputFormat()
21
- });
22
- }
23
- };
24
- //#endregion
25
- export { Conversion as Decryption, FilePathSource, FilePathTarget, Input, InputOptions, MkvOutputFormat, MovOutputFormat, Mp3OutputFormat, Mp4OutputFormat, Output, OutputFormat, OutputOptions, ReadableStreamSource, StreamSource, StreamSourceOptions, StreamTarget, StreamTargetOptions, UrlSource };