@irbisadm/simple-sdp 0.1.0 → 0.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/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- const e=(e,t)=>e.replace(`${t}=`,"").split(" "),t=/^\d+$/,r=e=>{if(!t.test(e))throw new Error(`"${e}" is not an integer.`);return parseInt(e)},s=e=>{const t={d:86400,h:86400,m:60,s:1};if(Object.keys(t).includes(e.slice(-1))){const s=e.slice(-1),n=e.slice(0,e.length-1),a=r(n);return t[s]*a}return r(e)},n=e=>e.split("/").map((e=>parseInt(e))),a=t=>{const r=e(t,"m");switch(r[0]){case"audio":return(e=>{const t={type:e[0],ports:n(e[1]),proto:e[2]};if(e.length>3){t.fmtp=[];for(let r=3;r<e.length;r++)t.fmtp.push(parseInt(e[r]))}return t})(r);case"application":return(e=>({type:"application",ports:n(e[1]),proto:e[2],description:e[3]}))(r);default:return(e=>{const t={type:e[0],ports:n(e[1]),proto:e[2]};if(e.length>3){t.fmtp=[];for(let r=3;r<e.length;r++)t.fmtp.push(e[r])}return t})(r)}},i=e=>{const t=e.replace("k=",""),[s,n]=t.split(":");return{bwtype:s,bandwidth:r(n)}},o=t=>{const r=e(t,"c");return{netType:"IN"===r[0]?"IN":void 0,addrType:["IP4","IP6"].includes(r[1])?r[1]:void 0,connectionAddress:r[2]}},c=(e,t,r)=>{e.ice||(e.ice={ufrag:"",pwd:"",options:[]}),e.ice[t]=r},p=(e,t,r)=>{e.dtls||(e.dtls={algorithm:"",fingerprint:"",setup:"actpass"}),e.dtls[t]=r},l=(e,t)=>{e.attributes||(e.attributes={});const r=t.replace("a=",""),[s,...n]=r.split(":"),a=n.join(":");switch(s){case"mid":e.mid=a;break;case"ice-ufrag":c(e,"ufrag",a);break;case"ice-pwd":c(e,"pwd",a);break;case"ice-options":c(e,"options",a.split(" "));break;case"fingerprint":{const[t,r]=a.split(" ");p(e,"algorithm",t),p(e,"fingerprint",r);break}case"setup":p(e,"setup",a);break;case"sendrecv":e.direction=s;break;default:if(e.attributes[s]){Array.isArray(e.attributes[s])||(e.attributes[s]=[e.attributes[s]]),e.attributes[s].push(a);break}e.attributes[s]=0===n.length||a}return e},u=t=>{const r=t.split("\r\n"),n={};let c=null;return r.forEach(((t,p)=>{if(0!==t.length){if("="!==t[1])throw new Error(`Invalid line structure in line "${t}"`);switch(t[0]){case"v":n.protocolVersion=(e=>parseInt(e.replace("v=","")))(t);break;case"o":n.origin=(t=>{const r=e(t,"o"),s=parseInt(r[2]),n="IN"===r[3]?"IN":void 0,a=["IP4","IP6"].includes(r[4])?r[4]:void 0;return{username:r[0],sessId:r[1],sessVersion:s,netType:n,addrType:a,unicastAddress:r[5]}})(t);break;case"s":n.sessionName=(e=>e.replace("s=",""))(t);break;case"t":n.timing||(n.timing=[]),n.timing.push((t=>{const r=e(t,"t"),s=parseInt(r[0]),n=isNaN(s)?0:s,a=parseInt(r[1]);return{startTime:n,stopTime:isNaN(a)?0:a}})(t));break;case"r":n.repeat||(n.repeat=[]),n.repeat.push((t=>{const r=e(t,"r"),n={repeatInterval:s(r[0]),activeDuration:s(r[0])};if(r.length>3){n.offsets=[];for(let e=2;e<r.length;e++)n.offsets.push(s(r[e]))}return n})(t));break;case"i":n.sessionInformation=(e=>e.replace("i=",""))(t);break;case"u":n.sessionInformation=(e=>e.replace("u=",""))(t);break;case"e":n.emailAddress=(e=>e.replace("e=",""))(t);break;case"p":n.phoneNumber=(e=>e.replace("p=",""))(t);break;case"k":n.encryptionKeys||(n.encryptionKeys=[]),n.encryptionKeys.push((e=>{const t=e.replace("k=",""),[r,s]=t.split(":");if(!["clear","base64","uri","prompt"].includes(r))throw new Error(`Encryption method "${r}" is not supported by RFC-4566`);return{method:r,encryptionKey:s}})(t));break;case"m":const r=a(t);c=r,n.media||(n.media=[]),n.media.push(r);break;case"b":c?c.bandwidthInformation=i(t):n.bandwidthInformation=i(t);break;case"c":c?c.connectionInformation=o(t):n.connectionInformation=o(t);break;case"a":l(c||n,t);break;default:throw Error(`Unknown line type "${t[0]}"`)}}else if(p!==r.length-1)throw new Error(`Empty line at "${p}" after ${r[p-1]}`)})),n},d={parse:u,isValid:(e,t=!1)=>{try{return u(e),!0}catch(e){return t&&console.error(e),!1}}},b="0.1.0";export{d as sdpReader,b as version};
1
+ const e=(e,t)=>e.replace(`${t}=`,"").split(" "),t=/^\d+$/,r=e=>{if(!t.test(e))throw new Error(`"${e}" is not an integer.`);return parseInt(e)},s=e=>{const t={d:86400,h:86400,m:60,s:1};if(Object.keys(t).includes(e.slice(-1))){const s=e.slice(-1),n=e.slice(0,e.length-1),a=r(n);return t[s]*a}return r(e)},n=e=>e.split("/").map((e=>parseInt(e))),a=t=>{const r=e(t,"m");switch(r[0]){case"audio":return(e=>{const t={type:e[0],ports:n(e[1]),proto:e[2]};if(e.length>3){t.fmtp=[];for(let r=3;r<e.length;r++)t.fmtp.push(parseInt(e[r]))}return t})(r);case"application":return(e=>({type:"application",ports:n(e[1]),proto:e[2],description:e[3]}))(r);default:return(e=>{const t={type:e[0],ports:n(e[1]),proto:e[2]};if(e.length>3){t.fmtp=[];for(let r=3;r<e.length;r++)t.fmtp.push(e[r])}return t})(r)}},i=e=>{const t=e.replace("k=",""),[s,n]=t.split(":");return{bwtype:s,bandwidth:r(n)}},o=t=>{const r=e(t,"c");return{netType:"IN"===r[0]?"IN":void 0,addrType:["IP4","IP6"].includes(r[1])?r[1]:void 0,connectionAddress:r[2]}},p=(e,t,r)=>{e.ice||(e.ice={ufrag:"",pwd:"",options:[]}),e.ice[t]=r},c=(e,t,r)=>{e.dtls||(e.dtls={algorithm:"",fingerprint:"",setup:"actpass"}),e.dtls[t]=r},l=(e,t)=>{e.attributes||(e.attributes={});const r=t.replace("a=",""),[s,...n]=r.split(":"),a=n.join(":");switch(s){case"mid":e.mid=a;break;case"ice-ufrag":p(e,"ufrag",a);break;case"ice-pwd":p(e,"pwd",a);break;case"ice-options":p(e,"options",a.split(" "));break;case"fingerprint":{const[t,r]=a.split(" ");c(e,"algorithm",t),c(e,"fingerprint",r);break}case"setup":c(e,"setup",a);break;case"sendrecv":e.direction=s;break;case"group":((e,t)=>{e.group||(e.group=[]);const[r,...s]=t.split(" ");["LS","FID","SRF","ANAT","FEC","DDP","BUNDLE"].includes(r)&&e.group.push({token:r,mids:s})})(e,a);break;default:if(e.attributes[s]){Array.isArray(e.attributes[s])||(e.attributes[s]=[e.attributes[s]]),e.attributes[s].push(a);break}e.attributes[s]=0===n.length||a}return e},u=t=>{const r=t.split("\r\n"),n={};let p=null;return r.forEach(((t,c)=>{if(0!==t.length){if("="!==t[1])throw new Error(`Invalid line structure in line "${t}"`);switch(t[0]){case"v":n.protocolVersion=(e=>parseInt(e.replace("v=","")))(t);break;case"o":n.origin=(t=>{const r=e(t,"o"),s=parseInt(r[2]),n="IN"===r[3]?"IN":void 0,a=["IP4","IP6"].includes(r[4])?r[4]:void 0;return{username:r[0],sessId:r[1],sessVersion:s,netType:n,addrType:a,unicastAddress:r[5]}})(t);break;case"s":n.sessionName=(e=>e.replace("s=",""))(t);break;case"t":n.timing||(n.timing=[]),n.timing.push((t=>{const r=e(t,"t"),s=parseInt(r[0]),n=isNaN(s)?0:s,a=parseInt(r[1]);return{startTime:n,stopTime:isNaN(a)?0:a}})(t));break;case"r":n.repeat||(n.repeat=[]),n.repeat.push((t=>{const r=e(t,"r"),n={repeatInterval:s(r[0]),activeDuration:s(r[0])};if(r.length>3){n.offsets=[];for(let e=2;e<r.length;e++)n.offsets.push(s(r[e]))}return n})(t));break;case"i":n.sessionInformation=(e=>e.replace("i=",""))(t);break;case"u":n.sessionInformation=(e=>e.replace("u=",""))(t);break;case"e":n.emailAddress=(e=>e.replace("e=",""))(t);break;case"p":n.phoneNumber=(e=>e.replace("p=",""))(t);break;case"k":n.encryptionKeys||(n.encryptionKeys=[]),n.encryptionKeys.push((e=>{const t=e.replace("k=",""),[r,s]=t.split(":");if(!["clear","base64","uri","prompt"].includes(r))throw new Error(`Encryption method "${r}" is not supported by RFC-4566`);return{method:r,encryptionKey:s}})(t));break;case"m":const r=a(t);p=r,n.media||(n.media=[]),n.media.push(r);break;case"b":p?p.bandwidthInformation=i(t):n.bandwidthInformation=i(t);break;case"c":p?p.connectionInformation=o(t):n.connectionInformation=o(t);break;case"a":l(p||n,t);break;default:throw Error(`Unknown line type "${t[0]}"`)}}else if(c!==r.length-1)throw new Error(`Empty line at "${c}" after ${r[c-1]}`)})),n},d={parse:u,isValid:(e,t=!1)=>{try{return u(e),!0}catch(e){return t&&console.error(e),!1}}},b="0.1.1";export{d as sdpReader,b as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@irbisadm/simple-sdp",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "MIT",
5
5
  "description": "WebRTC SDP parser and validator influenced by pjsip library.",
6
6
  "author": {
@@ -14,6 +14,7 @@
14
14
  "module": "./dist/index.mjs",
15
15
  "main": "./dist/index.mjs",
16
16
  "types": "./types/index.d.ts",
17
+ "keywords": ["sdp","webrtc","rfc8866","sdp parser","sdp validator"],
17
18
  "files": [
18
19
  "./dist/index.mjs",
19
20
  "./types/index.d.ts",
package/readme.md CHANGED
@@ -1,15 +1,15 @@
1
1
  ![license MIT](https://badgen.net/npm/license/@irbisadm/simple-sdp)
2
- ![license MIT](https://badgen.net/npm/v/@irbisadm/simple-sdp)
3
- ![license MIT](https://badgen.net/npm/types/@irbisadm/simple-sdp)
4
- ![license MIT](https://badgen.net/bundlephobia/minzip/@irbisadm/simple-sdp)
5
- ![license MIT](https://badgen.net/bundlephobia/dependency-count/@irbisadm/simple-sdp)
6
- ![license MIT](https://badgen.net/bundlephobia/tree-shaking/@irbisadm/simple-sdp)
2
+ ![npm version](https://badgen.net/npm/v/@irbisadm/simple-sdp)
3
+ ![npm types](https://badgen.net/npm/types/@irbisadm/simple-sdp)
4
+ ![bundlephobia min-zip size](https://badgen.net/bundlephobia/minzip/@irbisadm/simple-sdp)
5
+ ![bundlephobia dependency count](https://badgen.net/bundlephobia/dependency-count/@irbisadm/simple-sdp)
6
+ ![bundlephobia tree-shaking](https://badgen.net/bundlephobia/tree-shaking/@irbisadm/simple-sdp)
7
7
  # Simple SDP tools
8
8
  This project is a TypeScript library that provides a comprehensive set of tools for working with Session Description Protocol (SDP) messages in WebRTC applications. SDP is a text-based format that describes the multimedia communication sessions between peers.
9
9
  With this library, you can:
10
10
  - Parse and generate SDP messages from and to TypeScript objects
11
11
  - Manipulate SDP data by adding, removing, or modifying media streams, codecs, candidates, and other attributes
12
- - Validate SDP messages according to the [RFC 4566](https://www.rfc-editor.org/rfc/rfc8866) specification and WebRTC best practices
12
+ - Validate SDP messages according to the [RFC 8866](https://www.rfc-editor.org/rfc/rfc8866) specification and WebRTC best practices
13
13
  - Track and verify the SDP history for a single PeerConnection instance
14
14
 
15
15
  This project aims to help WebRTC beginners learn the SDP format and its components, as well as provide a clear and easy-to-use TypeScript API for advanced users. This project was inspired by the [pjsip](https://github.com/pjsip/pjproject) library written in C++.
package/types/index.d.ts CHANGED
@@ -58,6 +58,7 @@ interface Sdp extends SdpCommonAttributes {
58
58
  media?: SdpMediaSection[];
59
59
  bandwidthInformation?: SdpBandwidthInformation;
60
60
  connectionInformation?: SdpConnectionInformation;
61
+ group?: SdpGroup[];
61
62
  }
62
63
  /**
63
64
  * The "o=" field gives the originator of the session (her username and the address of the user's host) plus a session
@@ -273,12 +274,30 @@ interface SdpPair {
273
274
  offer: Sdp;
274
275
  answer: Sdp;
275
276
  }
277
+ /**
278
+ * rfc5888 and rfc9143 groups
279
+ */
280
+ interface SdpGroup {
281
+ /**
282
+ * Semantics Token Reference
283
+ * --------------------------------- ----- -----------
284
+ * Lip Synchronization LS [RFC5888]
285
+ * Flow Identification FID [RFC5888]
286
+ * Single Reservation Flow SRF [RFC3524]
287
+ * Alternative Network Address Types ANAT [RFC4091]
288
+ * Forward Error Correction FEC [RFC4756]
289
+ * Decoding Dependency DDP [RFC5583]
290
+ * Bundle BUNDLE [RFC9143]
291
+ */
292
+ token: 'LS' | 'FID' | 'SRF' | 'ANAT' | 'FEC' | 'DDP' | 'BUNDLE';
293
+ mids: string[];
294
+ }
276
295
 
277
296
  declare const sdpReader: {
278
297
  parse: (sdp: string) => Sdp;
279
298
  isValid: (sdp: string, writeLog?: boolean) => boolean;
280
299
  };
281
300
 
282
- declare const version = "0.1.0";
301
+ declare const version = "0.1.1";
283
302
 
284
303
  export { Sdp, SdpEncryptionKey, SdpMediaSection, SdpOrigin, SdpPair, SdpRepeatTimes, SdpTiming, sdpReader, version };