@feedclip/sdk 0.1.0

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.
Files changed (43) hide show
  1. package/COMMERCIAL-LICENSE.md +32 -0
  2. package/COMPLIANCE.md +110 -0
  3. package/LICENSE +21 -0
  4. package/README.md +676 -0
  5. package/dist/FeedClip-BmVeLeSY.cjs +6 -0
  6. package/dist/FeedClip-Czdkvwzl.js +1176 -0
  7. package/dist/angular.cjs +1 -0
  8. package/dist/angular.js +42 -0
  9. package/dist/feedclip.cjs +2 -0
  10. package/dist/feedclip.css +3 -0
  11. package/dist/feedclip.js +133 -0
  12. package/dist/types/ai.d.ts +2 -0
  13. package/dist/types/angular.d.ts +15 -0
  14. package/dist/types/atom.d.ts +9 -0
  15. package/dist/types/components/Alert.d.ts +8 -0
  16. package/dist/types/components/Controls.d.ts +10 -0
  17. package/dist/types/components/FeedClip.d.ts +11 -0
  18. package/dist/types/components/FeedbackDetails.d.ts +14 -0
  19. package/dist/types/components/FeedbackResult.d.ts +7 -0
  20. package/dist/types/components/HandleUpload.d.ts +21 -0
  21. package/dist/types/components/PauseRecording.d.ts +8 -0
  22. package/dist/types/components/Reset.d.ts +11 -0
  23. package/dist/types/components/StartRecording.d.ts +15 -0
  24. package/dist/types/components/StopRecording.d.ts +7 -0
  25. package/dist/types/components/TrimControls.d.ts +10 -0
  26. package/dist/types/components/Video.d.ts +8 -0
  27. package/dist/types/configuration-context.d.ts +2 -0
  28. package/dist/types/configuration.d.ts +22 -0
  29. package/dist/types/entitlements.d.ts +6 -0
  30. package/dist/types/feedback.d.ts +55 -0
  31. package/dist/types/i18n.d.ts +33 -0
  32. package/dist/types/index.d.ts +17 -0
  33. package/dist/types/indexed-db-store.d.ts +11 -0
  34. package/dist/types/license.d.ts +30 -0
  35. package/dist/types/transport.d.ts +7 -0
  36. package/dist/types/uploaders.d.ts +14 -0
  37. package/dist/types/utils.d.ts +6 -0
  38. package/dist/types/vue.d.ts +18 -0
  39. package/dist/vue.cjs +1 -0
  40. package/dist/vue.js +23 -0
  41. package/package.json +118 -0
  42. package/scripts/generate-license-keypair.mjs +25 -0
  43. package/scripts/issue-license.mjs +69 -0
@@ -0,0 +1,18 @@
1
+ import "./index.css";
2
+ import { PropType } from "vue";
3
+ import { Configuration } from "./configuration";
4
+ export declare const FeedClipVue: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
5
+ config: {
6
+ type: PropType<Configuration>;
7
+ required: true;
8
+ };
9
+ }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
10
+ [key: string]: any;
11
+ }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
12
+ config: {
13
+ type: PropType<Configuration>;
14
+ required: true;
15
+ };
16
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
17
+ export default FeedClipVue;
18
+ export type { Configuration } from "./configuration";
package/dist/vue.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./FeedClip-BmVeLeSY.cjs");let t=require("react"),n=require("react-dom/client"),r=require("vue");var i=(0,r.defineComponent)({name:`FeedClip`,props:{config:{type:Object,required:!0}},setup(i){let a=(0,r.ref)(null),o,s=()=>{a.value&&(o??=(0,n.createRoot)(a.value),o.render((0,t.createElement)(e.t,{config:i.config})))};return(0,r.onMounted)(s),(0,r.watch)(()=>i.config,s,{deep:!0}),(0,r.onUnmounted)(()=>o?.unmount()),()=>(0,r.h)(`div`,{ref:a,"data-feedclip-adapter":`vue`})}});exports.FeedClipVue=i,exports.default=i;
package/dist/vue.js ADDED
@@ -0,0 +1,23 @@
1
+ import { t as e } from "./FeedClip-Czdkvwzl.js";
2
+ import { createElement as t } from "react";
3
+ import { createRoot as n } from "react-dom/client";
4
+ import { defineComponent as r, h as i, onMounted as a, onUnmounted as o, ref as s, watch as c } from "vue";
5
+ //#region src/vue.ts
6
+ var l = r({
7
+ name: "FeedClip",
8
+ props: { config: {
9
+ type: Object,
10
+ required: !0
11
+ } },
12
+ setup(r) {
13
+ let l = s(null), u, d = () => {
14
+ l.value && (u ??= n(l.value), u.render(t(e, { config: r.config })));
15
+ };
16
+ return a(d), c(() => r.config, d, { deep: !0 }), o(() => u?.unmount()), () => i("div", {
17
+ ref: l,
18
+ "data-feedclip-adapter": "vue"
19
+ });
20
+ }
21
+ });
22
+ //#endregion
23
+ export { l as FeedClipVue, l as default };
package/package.json ADDED
@@ -0,0 +1,118 @@
1
+ {
2
+ "name": "@feedclip/sdk",
3
+ "private": false,
4
+ "version": "0.1.0",
5
+ "license": "MIT",
6
+ "description": "Video feedback SDK for React, Vue, and Angular",
7
+ "homepage": "https://github.com/andreyshedko/feedclip#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/andreyshedko/feedclip.git",
11
+ "directory": "packages/sdk"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/andreyshedko/feedclip/issues"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "sideEffects": [
23
+ "*.css"
24
+ ],
25
+ "type": "module",
26
+ "main": "./dist/feedclip.cjs",
27
+ "module": "./dist/feedclip.js",
28
+ "types": "./dist/types/index.d.ts",
29
+ "files": [
30
+ "dist",
31
+ "scripts",
32
+ "README.md",
33
+ "COMPLIANCE.md",
34
+ "LICENSE",
35
+ "COMMERCIAL-LICENSE.md"
36
+ ],
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/types/index.d.ts",
40
+ "import": "./dist/feedclip.js",
41
+ "require": "./dist/feedclip.cjs"
42
+ },
43
+ "./vue": {
44
+ "types": "./dist/types/vue.d.ts",
45
+ "import": "./dist/vue.js",
46
+ "require": "./dist/vue.cjs"
47
+ },
48
+ "./angular": {
49
+ "types": "./dist/types/angular.d.ts",
50
+ "import": "./dist/angular.js",
51
+ "require": "./dist/angular.cjs"
52
+ },
53
+ "./style.css": "./dist/feedclip.css"
54
+ },
55
+ "scripts": {
56
+ "prepack": "npm run build",
57
+ "dev": "vite",
58
+ "build": "tsc -b && vite build && tsc -p tsconfig.build.json",
59
+ "lint": "eslint .",
60
+ "test": "vitest run",
61
+ "license:keys": "node scripts/generate-license-keypair.mjs",
62
+ "license:issue": "node scripts/issue-license.mjs",
63
+ "preview": "vite preview"
64
+ },
65
+ "peerDependencies": {
66
+ "@angular/core": "^19.0.0",
67
+ "react": "^19.2.7",
68
+ "react-dom": "^19.2.7",
69
+ "vue": "^3.5.0"
70
+ },
71
+ "peerDependenciesMeta": {
72
+ "@angular/core": {
73
+ "optional": true
74
+ },
75
+ "vue": {
76
+ "optional": true
77
+ }
78
+ },
79
+ "dependencies": {
80
+ "jotai": "^2.12.4"
81
+ },
82
+ "devDependencies": {
83
+ "@angular/common": "^19.0.0",
84
+ "@angular/core": "^19.0.0",
85
+ "@angular/platform-browser": "^19.0.0",
86
+ "@eslint/js": "^9.39.0",
87
+ "@tailwindcss/vite": "^4.1.4",
88
+ "@testing-library/dom": "^10.4.1",
89
+ "@testing-library/jest-dom": "^6.9.1",
90
+ "@testing-library/react": "^16.3.2",
91
+ "@testing-library/user-event": "^14.6.1",
92
+ "@types/react": "^19.0.10",
93
+ "@types/react-dom": "^19.0.4",
94
+ "@vitejs/plugin-react": "^5.1.4",
95
+ "eslint": "^9.39.0",
96
+ "eslint-plugin-react-hooks": "^5.2.0",
97
+ "eslint-plugin-react-refresh": "^0.4.19",
98
+ "globals": "^16.0.0",
99
+ "jotai": "^2.12.4",
100
+ "jsdom": "^28.1.0",
101
+ "react": "^19.2.7",
102
+ "react-dom": "^19.2.7",
103
+ "rxjs": "^7.8.0",
104
+ "tailwindcss": "^4.1.4",
105
+ "tslib": "^2.8.0",
106
+ "typescript": "~5.7.2",
107
+ "typescript-eslint": "^8.26.1",
108
+ "vite": "^8.0.16",
109
+ "vitest": "^4.1.8",
110
+ "vue": "^3.5.0",
111
+ "zone.js": "^0.15.0"
112
+ },
113
+ "resolutions": {
114
+ "postcss": "^8.5.10",
115
+ "vite": "6.4.2"
116
+ },
117
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
118
+ }
@@ -0,0 +1,25 @@
1
+ import { webcrypto } from "node:crypto";
2
+
3
+ const keyPair = await webcrypto.subtle.generateKey(
4
+ { name: "ECDSA", namedCurve: "P-256" },
5
+ true,
6
+ ["sign", "verify"]
7
+ );
8
+
9
+ const [publicKey, privateKey] = await Promise.all([
10
+ webcrypto.subtle.exportKey("jwk", keyPair.publicKey),
11
+ webcrypto.subtle.exportKey("jwk", keyPair.privateKey),
12
+ ]);
13
+
14
+ process.stdout.write(
15
+ `${JSON.stringify(
16
+ {
17
+ publicKey,
18
+ privateKey,
19
+ warning:
20
+ "Store privateKey in a server-side secret manager. Never ship it to browsers or commit it.",
21
+ },
22
+ null,
23
+ 2
24
+ )}\n`
25
+ );
@@ -0,0 +1,69 @@
1
+ import { webcrypto } from "node:crypto";
2
+
3
+ const parseArguments = (values) => {
4
+ const parsed = {};
5
+ for (let index = 0; index < values.length; index += 2) {
6
+ const name = values[index]?.replace(/^--/, "");
7
+ const value = values[index + 1];
8
+ if (!name || value === undefined) {
9
+ throw new Error("Arguments must use --name value pairs");
10
+ }
11
+ parsed[name] = value;
12
+ }
13
+ return parsed;
14
+ };
15
+
16
+ const encodeBase64Url = (value) =>
17
+ Buffer.from(value).toString("base64url");
18
+
19
+ const args = parseArguments(process.argv.slice(2));
20
+ const plan = args.plan ?? "paid";
21
+ const allowedPlans = new Set(["free", "paid"]);
22
+
23
+ if (!allowedPlans.has(plan)) {
24
+ throw new Error(`Unknown plan: ${plan}`);
25
+ }
26
+ if (!args.project) {
27
+ throw new Error("--project is required");
28
+ }
29
+
30
+ const privateKeyJson = process.env.FEEDCLIP_PRIVATE_KEY_JWK;
31
+ if (!privateKeyJson) {
32
+ throw new Error("FEEDCLIP_PRIVATE_KEY_JWK is required");
33
+ }
34
+
35
+ const now = Math.floor(Date.now() / 1000);
36
+ const days = Number(args.days ?? "365");
37
+ const claims = {
38
+ iss: args.issuer ?? "https://feedclip.dev",
39
+ aud: args.audience ?? "@feedclip/sdk",
40
+ sub: args.license ?? webcrypto.randomUUID(),
41
+ projectId: args.project,
42
+ plan,
43
+ iat: now,
44
+ exp: now + days * 24 * 60 * 60,
45
+ ...(args.features ? { features: JSON.parse(args.features) } : {}),
46
+ };
47
+ const header = {
48
+ alg: "ES256",
49
+ typ: "FCL",
50
+ kid: args["key-id"] ?? process.env.FEEDCLIP_LICENSE_KEY_ID ?? "primary",
51
+ };
52
+ const encodedHeader = encodeBase64Url(JSON.stringify(header));
53
+ const encodedClaims = encodeBase64Url(JSON.stringify(claims));
54
+ const signingInput = `${encodedHeader}.${encodedClaims}`;
55
+ const privateKey = await webcrypto.subtle.importKey(
56
+ "jwk",
57
+ JSON.parse(privateKeyJson),
58
+ { name: "ECDSA", namedCurve: "P-256" },
59
+ false,
60
+ ["sign"]
61
+ );
62
+ const signature = await webcrypto.subtle.sign(
63
+ { name: "ECDSA", hash: "SHA-256" },
64
+ privateKey,
65
+ new TextEncoder().encode(signingInput)
66
+ );
67
+ const token = `${signingInput}.${Buffer.from(signature).toString("base64url")}`;
68
+
69
+ process.stdout.write(`${JSON.stringify({ token, claims }, null, 2)}\n`);