mirror of
https://github.com/storytold/placeholder-artcraft.git
synced 2026-10-09 00:09:55 +00:00
mirror repo (WIP)
Need to remove secrets before entire repo can be made public.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nx/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# @frontend/billing
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test @frontend/billing` to execute the unit tests via [Vitest](https://vitest.dev/).
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export * from './lib/state/credits-state';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,2BAA2B,CAAC"}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import d from "react";
|
||||
const u = (t) => {
|
||||
let e;
|
||||
const r = /* @__PURE__ */ new Set(), o = (a, c) => {
|
||||
const s = typeof a == "function" ? a(e) : a;
|
||||
if (!Object.is(s, e)) {
|
||||
const D = e;
|
||||
e = c ?? (typeof s != "object" || s === null) ? s : Object.assign({}, e, s), r.forEach((S) => S(e, D));
|
||||
}
|
||||
}, n = () => e, i = { setState: o, getState: n, getInitialState: () => E, subscribe: (a) => (r.add(a), () => r.delete(a)) }, E = e = t(o, n, i);
|
||||
return i;
|
||||
}, W = (t) => t ? u(t) : u, y = (t) => t;
|
||||
function O(t, e = y) {
|
||||
const r = d.useSyncExternalStore(
|
||||
t.subscribe,
|
||||
() => e(t.getState()),
|
||||
() => e(t.getInitialState())
|
||||
);
|
||||
return d.useDebugValue(r), r;
|
||||
}
|
||||
const l = (t) => {
|
||||
const e = W(t), r = (o) => O(e, o);
|
||||
return Object.assign(r, e), r;
|
||||
}, I = (t) => t ? l(t) : l;
|
||||
async function f(t, e = {}, r) {
|
||||
return window.__TAURI_INTERNALS__.invoke(t, e, r);
|
||||
}
|
||||
const g = async () => {
|
||||
try {
|
||||
return await f("storyteller_get_credits_command");
|
||||
} catch (t) {
|
||||
throw t;
|
||||
}
|
||||
};
|
||||
var _;
|
||||
(function(t) {
|
||||
t.WINDOW_RESIZED = "tauri://resize", t.WINDOW_MOVED = "tauri://move", t.WINDOW_CLOSE_REQUESTED = "tauri://close-requested", t.WINDOW_DESTROYED = "tauri://destroyed", t.WINDOW_FOCUS = "tauri://focus", t.WINDOW_BLUR = "tauri://blur", t.WINDOW_SCALE_FACTOR_CHANGED = "tauri://scale-change", t.WINDOW_THEME_CHANGED = "tauri://theme-changed", t.WINDOW_CREATED = "tauri://window-created", t.WEBVIEW_CREATED = "tauri://webview-created", t.DRAG_ENTER = "tauri://drag-enter", t.DRAG_OVER = "tauri://drag-over", t.DRAG_DROP = "tauri://drag-drop", t.DRAG_LEAVE = "tauri://drag-leave";
|
||||
})(_ || (_ = {}));
|
||||
const m = I((t) => ({
|
||||
freeCredits: 0,
|
||||
monthlyCredits: 0,
|
||||
bankedCredits: 0,
|
||||
totalCredits: 0,
|
||||
// Call to fetch credits from the server
|
||||
fetchFromServer: async () => {
|
||||
let e;
|
||||
try {
|
||||
e = await g();
|
||||
} catch (r) {
|
||||
console.error("Error fetching credits", r);
|
||||
return;
|
||||
}
|
||||
console.log("Fetched credits from server: ", e), e.payload && t((r) => ({
|
||||
freeCredits: e.payload.free_credits,
|
||||
monthlyCredits: e.payload.monthly_credits,
|
||||
bankedCredits: e.payload.banked_credits,
|
||||
totalCredits: e.payload.sum_total_credits
|
||||
}));
|
||||
}
|
||||
}));
|
||||
export {
|
||||
m as useCreditsState
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
export interface CreditsState {
|
||||
freeCredits: number;
|
||||
monthlyCredits: number;
|
||||
bankedCredits: number;
|
||||
totalCredits: number;
|
||||
}
|
||||
export type CreditsActions = {
|
||||
fetchFromServer: () => Promise<void>;
|
||||
};
|
||||
export declare const useCreditsState: import('zustand').UseBoundStore<import('zustand').StoreApi<CreditsState & CreditsActions>>;
|
||||
//# sourceMappingURL=credits-state.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"credits-state.d.ts","sourceRoot":"","sources":["../../../src/lib/state/credits-state.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAE3B,WAAW,EAAE,MAAM,CAAC;IAGpB,cAAc,EAAE,MAAM,CAAC;IAGvB,aAAa,EAAE,MAAM,CAAC;IAGtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,cAAc,GAAG;IAE3B,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC,CAAA;AAED,eAAO,MAAM,eAAe,4FAyBzB,CAAA"}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@storyteller/credits",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"development": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
export * from './lib/state/credits-state';
|
||||
@@ -0,0 +1,48 @@
|
||||
import { create } from 'zustand'
|
||||
import { ArtcraftGetCredits } from "@storyteller/tauri-api";
|
||||
|
||||
export interface CreditsState {
|
||||
// Daily free credits (if/when we offer them)
|
||||
freeCredits: number,
|
||||
|
||||
// Credits refilled monthly with a subscription
|
||||
monthlyCredits: number,
|
||||
|
||||
// Credits the user purchases individually
|
||||
bankedCredits: number,
|
||||
|
||||
// Total credits available
|
||||
totalCredits: number,
|
||||
}
|
||||
|
||||
export type CreditsActions = {
|
||||
// Call to fetch credits from the server
|
||||
fetchFromServer: () => Promise<void>
|
||||
}
|
||||
|
||||
export const useCreditsState = create<CreditsState & CreditsActions>((set) => ({
|
||||
freeCredits: 0,
|
||||
monthlyCredits: 0,
|
||||
bankedCredits: 0,
|
||||
totalCredits: 0,
|
||||
|
||||
// Call to fetch credits from the server
|
||||
fetchFromServer: async () => {
|
||||
let data;
|
||||
try {
|
||||
data = await ArtcraftGetCredits();
|
||||
} catch (error) {
|
||||
console.error("Error fetching credits", error);
|
||||
return;
|
||||
}
|
||||
console.log("Fetched credits from server: ", data);
|
||||
if (!!data.payload) {
|
||||
set((state) => ({
|
||||
freeCredits: data.payload.free_credits,
|
||||
monthlyCredits: data.payload.monthly_credits,
|
||||
bankedCredits: data.payload.banked_credits,
|
||||
totalCredits: data.payload.sum_total_credits,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
],
|
||||
"extends": "../../../tsconfig.base.json"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"types": [
|
||||
"node",
|
||||
"@nx/react/typings/cssmodule.d.ts",
|
||||
"@nx/react/typings/image.d.ts",
|
||||
"vite/client"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"jsx": "react-jsx",
|
||||
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
|
||||
},
|
||||
"exclude": [
|
||||
"out-tsc",
|
||||
"dist",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx",
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/vitest",
|
||||
"types": [
|
||||
"vitest/globals",
|
||||
"vitest/importMeta",
|
||||
"vite/client",
|
||||
"node",
|
||||
"vitest"
|
||||
],
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import * as path from 'path';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../../node_modules/.vite/libs/state/credits',
|
||||
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
// Configuration for building your library.
|
||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||
build: {
|
||||
outDir: './dist',
|
||||
emptyOutDir: true,
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
lib: {
|
||||
// Could also be a dictionary or array of multiple entry points.
|
||||
entry: 'src/index.ts',
|
||||
name: '@frontend/credits',
|
||||
fileName: 'index',
|
||||
// Change this to the formats you want to support.
|
||||
// Don't forget to update your package.json as well.
|
||||
formats: ['es' as const]
|
||||
},
|
||||
rollupOptions: {
|
||||
// External packages that should not be bundled into your library.
|
||||
external: ['react','react-dom','react/jsx-runtime']
|
||||
},
|
||||
},
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './test-output/vitest/coverage',
|
||||
provider: 'v8' as const,
|
||||
}
|
||||
},
|
||||
}));
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"extends": [
|
||||
"../../../.eslintrc.json"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"!**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx",
|
||||
"*.js",
|
||||
"*.jsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.ts",
|
||||
"*.tsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.js",
|
||||
"*.jsx"
|
||||
],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.json"
|
||||
],
|
||||
"parser": "jsonc-eslint-parser",
|
||||
"rules": {
|
||||
"@nx/dependency-checks": [
|
||||
"error",
|
||||
{
|
||||
"ignoredFiles": [
|
||||
"{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}",
|
||||
"{projectRoot}/vite.config.{js,ts,mjs,mts}"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# subscription
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build subscription` to build the library.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test subscription` to execute the unit tests via [Vitest](https://vitest.dev/).
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './lib/subscription-plan-details';
|
||||
export * from './lib/subscription-plans';
|
||||
export * from './lib/subscription-state';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC"}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
import u from "react";
|
||||
const g = {
|
||||
slug: "free",
|
||||
name: "Free",
|
||||
isPaidPlan: !1,
|
||||
monthlyPrice: 0,
|
||||
yearlyPrice: 0,
|
||||
features: [
|
||||
{ text: "Free daily generations", included: !0 },
|
||||
{ text: "Limited access to ArtCraft tools", included: !0 }
|
||||
],
|
||||
colorScheme: "dark"
|
||||
}, y = [
|
||||
g,
|
||||
{
|
||||
slug: "artcraft_basic",
|
||||
name: "Basic",
|
||||
isPaidPlan: !0,
|
||||
monthlyPrice: 8,
|
||||
yearlyPrice: 96,
|
||||
originalMonthlyPrice: 10,
|
||||
originalYearlyPrice: 120,
|
||||
features: [
|
||||
{ text: "~1,010 Flux images", included: !0 },
|
||||
{ text: "~36,000 real-time images", included: !0 },
|
||||
{ text: "~180 enhanced images", included: !0 },
|
||||
{ text: "~6 training jobs", included: !0 },
|
||||
{ text: "Commercial license", included: !0 }
|
||||
],
|
||||
colorScheme: "green"
|
||||
},
|
||||
{
|
||||
slug: "artcraft_pro",
|
||||
name: "Pro",
|
||||
isPaidPlan: !0,
|
||||
monthlyPrice: 28,
|
||||
yearlyPrice: 336,
|
||||
originalMonthlyPrice: 35,
|
||||
originalYearlyPrice: 420,
|
||||
features: [
|
||||
{ text: "~5,048 Flux images", included: !0 },
|
||||
{ text: "~180,000 real-time images", included: !0 },
|
||||
{ text: "~900 enhanced images", included: !0 },
|
||||
{ text: "~30 training jobs", included: !0 },
|
||||
{ text: "Commercial license", included: !0 }
|
||||
],
|
||||
colorScheme: "purple"
|
||||
},
|
||||
{
|
||||
slug: "artcraft_max",
|
||||
name: "Max",
|
||||
isPaidPlan: !0,
|
||||
monthlyPrice: 48,
|
||||
yearlyPrice: 576,
|
||||
originalMonthlyPrice: 60,
|
||||
originalYearlyPrice: 720,
|
||||
features: [
|
||||
{ text: "~15,142 Flux images", included: !0 },
|
||||
{ text: "~540,000 real-time images", included: !0 },
|
||||
{ text: "~2,700 enhanced images", included: !0 },
|
||||
{ text: "~90 training jobs", included: !0 },
|
||||
{ text: "Commercial license", included: !0 }
|
||||
],
|
||||
colorScheme: "orange"
|
||||
}
|
||||
], O = new Map(
|
||||
y.map((e) => [e.slug, e])
|
||||
), l = (e) => {
|
||||
let i;
|
||||
const t = /* @__PURE__ */ new Set(), r = (n, s) => {
|
||||
const a = typeof n == "function" ? n(i) : n;
|
||||
if (!Object.is(a, i)) {
|
||||
const m = i;
|
||||
i = s ?? (typeof a != "object" || a === null) ? a : Object.assign({}, i, a), t.forEach((b) => b(i, m));
|
||||
}
|
||||
}, c = () => i, o = { setState: r, getState: c, getInitialState: () => p, subscribe: (n) => (t.add(n), () => t.delete(n)) }, p = i = e(r, c, o);
|
||||
return o;
|
||||
}, S = (e) => e ? l(e) : l, E = (e) => e;
|
||||
function P(e, i = E) {
|
||||
const t = u.useSyncExternalStore(
|
||||
e.subscribe,
|
||||
() => i(e.getState()),
|
||||
() => i(e.getInitialState())
|
||||
);
|
||||
return u.useDebugValue(t), t;
|
||||
}
|
||||
const d = (e) => {
|
||||
const i = S(e), t = (r) => P(i, r);
|
||||
return Object.assign(t, i), t;
|
||||
}, x = (e) => e ? d(e) : d;
|
||||
async function f(e, i = {}, t) {
|
||||
return window.__TAURI_INTERNALS__.invoke(e, i, t);
|
||||
}
|
||||
const D = async () => {
|
||||
try {
|
||||
return await f("storyteller_get_subscription_command");
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
var _;
|
||||
(function(e) {
|
||||
e.WINDOW_RESIZED = "tauri://resize", e.WINDOW_MOVED = "tauri://move", e.WINDOW_CLOSE_REQUESTED = "tauri://close-requested", e.WINDOW_DESTROYED = "tauri://destroyed", e.WINDOW_FOCUS = "tauri://focus", e.WINDOW_BLUR = "tauri://blur", e.WINDOW_SCALE_FACTOR_CHANGED = "tauri://scale-change", e.WINDOW_THEME_CHANGED = "tauri://theme-changed", e.WINDOW_CREATED = "tauri://window-created", e.WEBVIEW_CREATED = "tauri://webview-created", e.DRAG_ENTER = "tauri://drag-enter", e.DRAG_OVER = "tauri://drag-over", e.DRAG_DROP = "tauri://drag-drop", e.DRAG_LEAVE = "tauri://drag-leave";
|
||||
})(_ || (_ = {}));
|
||||
const A = x((e, i) => ({
|
||||
subscriptionInfo: void 0,
|
||||
// Returns true if the user has a paid plan.
|
||||
// (We do not store "free" as a plan.)
|
||||
hasPaidPlan: () => {
|
||||
var t;
|
||||
return ((t = i().subscriptionInfo) == null ? void 0 : t.subscriptionToken) !== void 0;
|
||||
},
|
||||
// Returns true if the user can cancel their plan.
|
||||
// (The user can't cancel an already set to cancel/expire plan again)
|
||||
canCancelPlan: () => {
|
||||
const t = i().subscriptionInfo;
|
||||
return (t == null ? void 0 : t.subscriptionToken) !== void 0 && (t == null ? void 0 : t.subscriptionEndAt) === void 0;
|
||||
},
|
||||
// Call to fetch credits from the server
|
||||
fetchFromServer: async () => {
|
||||
let t;
|
||||
try {
|
||||
t = await D();
|
||||
} catch (r) {
|
||||
console.error("Error fetching subscription", r);
|
||||
return;
|
||||
}
|
||||
if (console.log("Fetched subscription from server: ", t), t.payload) {
|
||||
let r;
|
||||
t.payload.active_subscription && (r = {
|
||||
subscriptionToken: t.payload.active_subscription.subscription_token,
|
||||
productSlug: t.payload.active_subscription.product_slug,
|
||||
namespace: t.payload.active_subscription.namespace,
|
||||
nextBillAt: t.payload.active_subscription.next_bill_at ? new Date(t.payload.active_subscription.next_bill_at) : void 0,
|
||||
subscriptionEndAt: t.payload.active_subscription.subscription_end_at ? new Date(t.payload.active_subscription.subscription_end_at) : void 0
|
||||
}), e((c) => ({
|
||||
subscriptionInfo: r
|
||||
}));
|
||||
}
|
||||
}
|
||||
}));
|
||||
export {
|
||||
g as FREE_PLAN,
|
||||
y as SUBSCRIPTION_PLANS,
|
||||
O as SUBSCRIPTION_PLANS_BY_SLUG,
|
||||
A as useSubscriptionState
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
export interface PricingFeature {
|
||||
text: string;
|
||||
included: boolean;
|
||||
tooltip?: string;
|
||||
}
|
||||
export interface SubscriptionPlanDetails {
|
||||
slug: string;
|
||||
name: string;
|
||||
isPaidPlan: boolean;
|
||||
monthlyPrice: number;
|
||||
yearlyPrice: number;
|
||||
originalMonthlyPrice?: number;
|
||||
originalYearlyPrice?: number;
|
||||
features: PricingFeature[];
|
||||
isPopular?: boolean;
|
||||
colorScheme: "dark" | "green" | "purple" | "orange";
|
||||
}
|
||||
//# sourceMappingURL=subscription-plan-details.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"subscription-plan-details.d.ts","sourceRoot":"","sources":["../../src/lib/subscription-plan-details.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IAEb,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IAEpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAK7B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACrD"}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { SubscriptionPlanDetails } from './subscription-plan-details.js';
|
||||
export declare const FREE_PLAN: SubscriptionPlanDetails;
|
||||
export declare const SUBSCRIPTION_PLANS: SubscriptionPlanDetails[];
|
||||
export declare const SUBSCRIPTION_PLANS_BY_SLUG: Map<string, SubscriptionPlanDetails>;
|
||||
//# sourceMappingURL=subscription-plans.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"subscription-plans.d.ts","sourceRoot":"","sources":["../../src/lib/subscription-plans.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,eAAO,MAAM,SAAS,EAAG,uBAWxB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAG,uBAAuB,EAqDxD,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAG,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAE5E,CAAC"}
|
||||
@@ -0,0 +1,18 @@
|
||||
export interface SubscriptionState {
|
||||
subscriptionInfo?: SubscriptionInfo;
|
||||
}
|
||||
interface SubscriptionInfo {
|
||||
subscriptionToken: string;
|
||||
productSlug: string;
|
||||
namespace: string;
|
||||
nextBillAt?: Date;
|
||||
subscriptionEndAt?: Date;
|
||||
}
|
||||
export type SubscriptionActions = {
|
||||
hasPaidPlan: () => boolean;
|
||||
canCancelPlan: () => boolean;
|
||||
fetchFromServer: () => Promise<void>;
|
||||
};
|
||||
export declare const useSubscriptionState: import('zustand').UseBoundStore<import('zustand').StoreApi<SubscriptionState & SubscriptionActions>>;
|
||||
export {};
|
||||
//# sourceMappingURL=subscription-state.d.ts.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"subscription-state.d.ts","sourceRoot":"","sources":["../../src/lib/subscription-state.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAEhC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC;AAED,UAAU,gBAAgB;IAExB,iBAAiB,EAAE,MAAM,CAAC;IAI1B,WAAW,EAAE,MAAM,CAAC;IAGpB,SAAS,EAAE,MAAM,CAAC;IAGlB,UAAU,CAAC,EAAE,IAAI,CAAC;IAGlB,iBAAiB,CAAC,EAAE,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,mBAAmB,GAAG;IAGhC,WAAW,EAAE,MAAM,OAAO,CAAC;IAI3B,aAAa,EAAE,MAAM,OAAO,CAAC;IAG7B,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACrC,CAAC;AAEF,eAAO,MAAM,oBAAoB,sGAyC9B,CAAA"}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "@storyteller/subscription",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"development": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './lib/subscription-plan-details';
|
||||
export * from './lib/subscription-plans';
|
||||
export * from './lib/subscription-state';
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
export interface PricingFeature {
|
||||
text: string;
|
||||
included: boolean;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export interface SubscriptionPlanDetails {
|
||||
slug: string;
|
||||
name: string;
|
||||
|
||||
isPaidPlan: boolean;
|
||||
monthlyPrice: number;
|
||||
yearlyPrice: number;
|
||||
|
||||
originalMonthlyPrice?: number;
|
||||
originalYearlyPrice?: number;
|
||||
|
||||
//monthlyPriceId?: string;
|
||||
//yearlyPriceId?: string;
|
||||
|
||||
features: PricingFeature[];
|
||||
isPopular?: boolean;
|
||||
colorScheme: "dark" | "green" | "purple" | "orange";
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { SubscriptionPlanDetails } from "./subscription-plan-details.js";
|
||||
|
||||
export const FREE_PLAN : SubscriptionPlanDetails = {
|
||||
slug: "free",
|
||||
name: "Free",
|
||||
isPaidPlan: false,
|
||||
monthlyPrice: 0,
|
||||
yearlyPrice: 0,
|
||||
features: [
|
||||
{ text: "Free daily generations", included: true },
|
||||
{ text: "Limited access to ArtCraft tools", included: true },
|
||||
],
|
||||
colorScheme: "dark" as const,
|
||||
};
|
||||
|
||||
export const SUBSCRIPTION_PLANS : SubscriptionPlanDetails[] = [
|
||||
FREE_PLAN,
|
||||
{
|
||||
slug: "artcraft_basic",
|
||||
name: "Basic",
|
||||
isPaidPlan: true,
|
||||
monthlyPrice: 8,
|
||||
yearlyPrice: 96,
|
||||
originalMonthlyPrice: 10,
|
||||
originalYearlyPrice: 120,
|
||||
features: [
|
||||
{ text: "~1,010 Flux images", included: true },
|
||||
{ text: "~36,000 real-time images", included: true },
|
||||
{ text: "~180 enhanced images", included: true },
|
||||
{ text: "~6 training jobs", included: true },
|
||||
{ text: "Commercial license", included: true },
|
||||
],
|
||||
colorScheme: "green" as const,
|
||||
},
|
||||
{
|
||||
slug: "artcraft_pro",
|
||||
name: "Pro",
|
||||
isPaidPlan: true,
|
||||
monthlyPrice: 28,
|
||||
yearlyPrice: 336,
|
||||
originalMonthlyPrice: 35,
|
||||
originalYearlyPrice: 420,
|
||||
features: [
|
||||
{ text: "~5,048 Flux images", included: true },
|
||||
{ text: "~180,000 real-time images", included: true },
|
||||
{ text: "~900 enhanced images", included: true },
|
||||
{ text: "~30 training jobs", included: true },
|
||||
{ text: "Commercial license", included: true },
|
||||
],
|
||||
colorScheme: "purple" as const,
|
||||
},
|
||||
{
|
||||
slug: "artcraft_max",
|
||||
name: "Max",
|
||||
isPaidPlan: true,
|
||||
monthlyPrice: 48,
|
||||
yearlyPrice: 576,
|
||||
originalMonthlyPrice: 60,
|
||||
originalYearlyPrice: 720,
|
||||
features: [
|
||||
{ text: "~15,142 Flux images", included: true },
|
||||
{ text: "~540,000 real-time images", included: true },
|
||||
{ text: "~2,700 enhanced images", included: true },
|
||||
{ text: "~90 training jobs", included: true },
|
||||
{ text: "Commercial license", included: true },
|
||||
],
|
||||
colorScheme: "orange" as const,
|
||||
},
|
||||
]
|
||||
|
||||
export const SUBSCRIPTION_PLANS_BY_SLUG : Map<string, SubscriptionPlanDetails> = new Map(
|
||||
SUBSCRIPTION_PLANS.map((plan) => [plan.slug, plan])
|
||||
);
|
||||
@@ -0,0 +1,81 @@
|
||||
import { create } from 'zustand'
|
||||
import { ArtcraftGetSubscription } from "@storyteller/tauri-api";
|
||||
|
||||
export interface SubscriptionState {
|
||||
/// If the user doesn't have a subscription, this will be undefined.
|
||||
subscriptionInfo?: SubscriptionInfo,
|
||||
}
|
||||
|
||||
interface SubscriptionInfo {
|
||||
/// The internal user unique ID for the subscription
|
||||
subscriptionToken: string,
|
||||
|
||||
// TODO: This should be an enum!
|
||||
/// The internal identifier of the subscription
|
||||
productSlug: string,
|
||||
|
||||
/// The namespace for the subscription ("artcraft" or "fakeyou")
|
||||
namespace: string,
|
||||
|
||||
/// The next billing date for the subscription (if it's active and not set to expire/cancel)
|
||||
nextBillAt?: Date,
|
||||
|
||||
/// The end date for the subscription (if it's expired or set to expire/cancel)
|
||||
subscriptionEndAt?: Date,
|
||||
}
|
||||
|
||||
export type SubscriptionActions = {
|
||||
// Returns true if the user has a paid plan.
|
||||
// (We do not store "free" as a plan.)
|
||||
hasPaidPlan: () => boolean;
|
||||
|
||||
// Returns true if the user can cancel their plan.
|
||||
// (The user can't cancel an already set to cancel/expire plan again)
|
||||
canCancelPlan: () => boolean;
|
||||
|
||||
// Call to fetch credits from the server
|
||||
fetchFromServer: () => Promise<void>
|
||||
};
|
||||
|
||||
export const useSubscriptionState = create<SubscriptionState & SubscriptionActions>((set, get) => ({
|
||||
subscriptionInfo: undefined,
|
||||
|
||||
// Returns true if the user has a paid plan.
|
||||
// (We do not store "free" as a plan.)
|
||||
hasPaidPlan: () => get().subscriptionInfo?.subscriptionToken !== undefined,
|
||||
|
||||
// Returns true if the user can cancel their plan.
|
||||
// (The user can't cancel an already set to cancel/expire plan again)
|
||||
canCancelPlan: () => {
|
||||
const info = get().subscriptionInfo;
|
||||
return info?.subscriptionToken !== undefined
|
||||
&& info?.subscriptionEndAt === undefined;
|
||||
},
|
||||
|
||||
// Call to fetch credits from the server
|
||||
fetchFromServer: async () => {
|
||||
let data;
|
||||
try {
|
||||
data = await ArtcraftGetSubscription();
|
||||
} catch (error) {
|
||||
console.error("Error fetching subscription", error);
|
||||
return;
|
||||
}
|
||||
console.log("Fetched subscription from server: ", data);
|
||||
if (!!data.payload) {
|
||||
let activeSubscription = undefined;
|
||||
if (!!data.payload.active_subscription) {
|
||||
activeSubscription = {
|
||||
subscriptionToken: data.payload.active_subscription.subscription_token,
|
||||
productSlug: data.payload.active_subscription.product_slug,
|
||||
namespace: data.payload.active_subscription.namespace,
|
||||
nextBillAt: data.payload.active_subscription.next_bill_at ? new Date(data.payload.active_subscription.next_bill_at) : undefined,
|
||||
subscriptionEndAt: data.payload.active_subscription.subscription_end_at ? new Date(data.payload.active_subscription.subscription_end_at) : undefined,
|
||||
};
|
||||
}
|
||||
set((state) => ({
|
||||
subscriptionInfo: activeSubscription,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}))
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
|
||||
"emitDeclarationOnly": true,
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"types": [
|
||||
"node",
|
||||
"vite/client"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"types": [
|
||||
"node",
|
||||
"@nx/react/typings/cssmodule.d.ts",
|
||||
"@nx/react/typings/image.d.ts",
|
||||
"vite/client"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"jsx": "react-jsx",
|
||||
"tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo"
|
||||
},
|
||||
"exclude": [
|
||||
"out-tsc",
|
||||
"dist",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx",
|
||||
"vite.config.ts",
|
||||
"vite.config.mts",
|
||||
"vitest.config.ts",
|
||||
"vitest.config.mts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.js",
|
||||
"src/**/*.jsx",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../tauri-api/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/// <reference types='vitest' />
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import dts from 'vite-plugin-dts';
|
||||
import * as path from 'path';
|
||||
|
||||
export default defineConfig(() => ({
|
||||
root: __dirname,
|
||||
cacheDir: '../../../node_modules/.vite/libs/state/subscription',
|
||||
plugins: [react(), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
||||
// Uncomment this if you are using workers.
|
||||
// worker: {
|
||||
// plugins: [ nxViteTsPaths() ],
|
||||
// },
|
||||
// Configuration for building your library.
|
||||
// See: https://vitejs.dev/guide/build.html#library-mode
|
||||
build: {
|
||||
outDir: './dist',
|
||||
emptyOutDir: true,
|
||||
reportCompressedSize: true,
|
||||
commonjsOptions: {
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
lib: {
|
||||
// Could also be a dictionary or array of multiple entry points.
|
||||
entry: 'src/index.ts',
|
||||
name: '@frontend/subscription',
|
||||
fileName: 'index',
|
||||
// Change this to the formats you want to support.
|
||||
// Don't forget to update your package.json as well.
|
||||
formats: ['es' as const]
|
||||
},
|
||||
rollupOptions: {
|
||||
// External packages that should not be bundled into your library.
|
||||
external: ['react','react-dom','react/jsx-runtime']
|
||||
},
|
||||
},
|
||||
test: {
|
||||
watch: false,
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
reporters: ['default'],
|
||||
coverage: {
|
||||
reportsDirectory: './test-output/vitest/coverage',
|
||||
provider: 'v8' as const,
|
||||
}
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user