@fayz-ai/plugin-marketing 0.2.1 → 0.8.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.
- package/README.md +2 -0
- package/dist/data/contentSupabase.d.ts.map +1 -1
- package/dist/data/tables.d.ts +6 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/index.cjs +121 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +121 -84
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +8 -3
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/schema/index.d.ts +44 -44
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema.cjs +9 -9
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +9 -9
- package/dist/schema.js.map +1 -1
- package/package.json +8 -5
- package/src/data/contentSupabase.ts +18 -17
- package/src/data/tables.ts +7 -0
- package/src/index.ts +12 -3
- package/src/migrations/000_plg_rename.sql +15 -0
- package/src/migrations/001_content_planner.sql +48 -48
- package/src/migrations/002_multi_platform.sql +5 -5
- package/src/migrations/003_recording_ops.sql +10 -10
- package/src/migrations/index.ts +99 -74
- package/src/schema/index.ts +9 -9
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAO/F,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAMjE,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACnE,OAAO,EAAqB,KAAK,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAChG,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAclE,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,6EAA6E;IAC7E,cAAc,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,sBAAsB,CAAA;KAAE,CAAA;IAC1D,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAA;IACxC,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,yEAAyE;IACzE,WAAW,CAAC,EAAE,sBAAsB,CAAA;CACrC;AAiCD,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAO/F,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,cAAc,CAAA;AAErB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAMjE,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACnE,OAAO,EAAqB,KAAK,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAChG,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAclE,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,eAAe,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAA;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,6EAA6E;IAC7E,cAAc,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,sBAAsB,CAAA;KAAE,CAAA;IAC1D,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,iBAAiB,EAAE,CAAA;IACxC,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC,yEAAyE;IACzE,WAAW,CAAC,EAAE,sBAAsB,CAAA;CACrC;AAiCD,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,cAAc,CAiLtF;AAED,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,kBAAkB,EAClB,eAAe,GAChB,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAA;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AACzD,YAAY,EACV,sBAAsB,EACtB,WAAW,EACX,WAAW,EACX,aAAa,EACb,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAA;AACrE,OAAO,EAAE,oCAAoC,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3028,6 +3028,15 @@ function createMockContentPlannerProvider() {
|
|
|
3028
3028
|
}
|
|
3029
3029
|
};
|
|
3030
3030
|
}
|
|
3031
|
+
|
|
3032
|
+
// src/data/tables.ts
|
|
3033
|
+
var T = {
|
|
3034
|
+
socialAccounts: "plg_marketing_social_accounts",
|
|
3035
|
+
contentPlans: "plg_marketing_content_plans",
|
|
3036
|
+
contentPosts: "plg_marketing_content_posts"
|
|
3037
|
+
};
|
|
3038
|
+
|
|
3039
|
+
// src/data/contentSupabase.ts
|
|
3031
3040
|
function getClient() {
|
|
3032
3041
|
const supabase = getSupabaseClientOptional();
|
|
3033
3042
|
if (!supabase) throw new Error("Supabase not initialized");
|
|
@@ -3069,7 +3078,7 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3069
3078
|
async listAccounts() {
|
|
3070
3079
|
const tenantId = getActiveTenantId();
|
|
3071
3080
|
if (!tenantId) return [];
|
|
3072
|
-
const { data } = await getClient().from(
|
|
3081
|
+
const { data } = await getClient().from(T.socialAccounts).select("*").eq("tenant_id", tenantId).eq("is_active", true).order("created_at", { ascending: true });
|
|
3073
3082
|
return (data ?? []).map(toAccount);
|
|
3074
3083
|
},
|
|
3075
3084
|
async saveAccount(input) {
|
|
@@ -3079,11 +3088,11 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3079
3088
|
if (input.handle !== void 0) payload.handle = input.handle;
|
|
3080
3089
|
if (input.platforms !== void 0) payload.platforms = input.platforms;
|
|
3081
3090
|
if (input.isActive !== void 0) payload.is_active = input.isActive;
|
|
3082
|
-
const { data: data2, error: error2 } = await getClient().from(
|
|
3091
|
+
const { data: data2, error: error2 } = await getClient().from(T.socialAccounts).update(payload).eq("id", input.id).select("*").single();
|
|
3083
3092
|
if (error2) throw error2;
|
|
3084
3093
|
return toAccount(data2);
|
|
3085
3094
|
}
|
|
3086
|
-
const { data, error } = await getClient().from(
|
|
3095
|
+
const { data, error } = await getClient().from(T.socialAccounts).insert({
|
|
3087
3096
|
tenant_id: requireTenantId(),
|
|
3088
3097
|
name: input.name,
|
|
3089
3098
|
handle: input.handle ?? null,
|
|
@@ -3094,17 +3103,17 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3094
3103
|
return toAccount(data);
|
|
3095
3104
|
},
|
|
3096
3105
|
async deleteAccount(id) {
|
|
3097
|
-
const { error } = await getClient().from(
|
|
3106
|
+
const { error } = await getClient().from(T.socialAccounts).delete().eq("id", id);
|
|
3098
3107
|
if (error) throw error;
|
|
3099
3108
|
},
|
|
3100
3109
|
async listPlans(accountId) {
|
|
3101
3110
|
const tenantId = getActiveTenantId();
|
|
3102
3111
|
if (!tenantId) return [];
|
|
3103
|
-
const { data } = await getClient().from(
|
|
3112
|
+
const { data } = await getClient().from(T.contentPlans).select("*").eq("tenant_id", tenantId).eq("account_id", accountId).order("created_at", { ascending: false });
|
|
3104
3113
|
return (data ?? []).map(toPlan);
|
|
3105
3114
|
},
|
|
3106
3115
|
async getPlan(id) {
|
|
3107
|
-
const { data } = await getClient().from(
|
|
3116
|
+
const { data } = await getClient().from(T.contentPlans).select("*").eq("id", id).maybeSingle();
|
|
3108
3117
|
return data ? toPlan(data) : null;
|
|
3109
3118
|
},
|
|
3110
3119
|
async savePlan(input) {
|
|
@@ -3120,12 +3129,12 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3120
3129
|
if (input.formats !== void 0) payload.formats = input.formats;
|
|
3121
3130
|
if (input.weeklyFrequency !== void 0) payload.weekly_frequency = input.weeklyFrequency;
|
|
3122
3131
|
if (input.briefMd !== void 0) payload.brief_md = input.briefMd;
|
|
3123
|
-
const { data: data2, error: error2 } = await getClient().from(
|
|
3132
|
+
const { data: data2, error: error2 } = await getClient().from(T.contentPlans).update(payload).eq("id", input.id).select("*").single();
|
|
3124
3133
|
if (error2) throw error2;
|
|
3125
3134
|
return toPlan(data2);
|
|
3126
3135
|
}
|
|
3127
3136
|
if (!input.accountId) throw new Error("accountId is required");
|
|
3128
|
-
const { data, error } = await getClient().from(
|
|
3137
|
+
const { data, error } = await getClient().from(T.contentPlans).insert({
|
|
3129
3138
|
tenant_id: requireTenantId(),
|
|
3130
3139
|
account_id: input.accountId,
|
|
3131
3140
|
name: input.name ?? "Novo plano",
|
|
@@ -3143,14 +3152,14 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3143
3152
|
return toPlan(data);
|
|
3144
3153
|
},
|
|
3145
3154
|
async deletePlan(id) {
|
|
3146
|
-
await getClient().from(
|
|
3155
|
+
await getClient().from(T.contentPlans).delete().eq("id", id);
|
|
3147
3156
|
},
|
|
3148
3157
|
async listPosts(planId) {
|
|
3149
|
-
const { data } = await getClient().from(
|
|
3158
|
+
const { data } = await getClient().from(T.contentPosts).select("*").eq("plan_id", planId).order("week_number", { ascending: true }).order("position", { ascending: true });
|
|
3150
3159
|
return (data ?? []).map(toPost);
|
|
3151
3160
|
},
|
|
3152
3161
|
async getPost(id) {
|
|
3153
|
-
const { data } = await getClient().from(
|
|
3162
|
+
const { data } = await getClient().from(T.contentPosts).select("*").eq("id", id).maybeSingle();
|
|
3154
3163
|
return data ? toPost(data) : null;
|
|
3155
3164
|
},
|
|
3156
3165
|
async savePost(input) {
|
|
@@ -3168,15 +3177,15 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3168
3177
|
if (input.hook !== void 0) payload.hook = input.hook;
|
|
3169
3178
|
if (input.cta !== void 0) payload.cta = input.cta;
|
|
3170
3179
|
if (input.contentMd !== void 0) payload.content_md = input.contentMd;
|
|
3171
|
-
const { data: data2, error: error2 } = await getClient().from(
|
|
3180
|
+
const { data: data2, error: error2 } = await getClient().from(T.contentPosts).update(payload).eq("id", input.id).select("*").single();
|
|
3172
3181
|
if (error2) throw error2;
|
|
3173
3182
|
return toPost(data2);
|
|
3174
3183
|
}
|
|
3175
3184
|
if (!input.planId) throw new Error("planId is required");
|
|
3176
3185
|
const week = input.weekNumber ?? 1;
|
|
3177
|
-
const { data: maxData } = await getClient().from(
|
|
3186
|
+
const { data: maxData } = await getClient().from(T.contentPosts).select("position").eq("plan_id", input.planId).eq("week_number", week).order("position", { ascending: false }).limit(1);
|
|
3178
3187
|
const maxPos = maxData?.[0]?.position ?? -1;
|
|
3179
|
-
const { data, error } = await getClient().from(
|
|
3188
|
+
const { data, error } = await getClient().from(T.contentPosts).insert({
|
|
3180
3189
|
tenant_id: requireTenantId(),
|
|
3181
3190
|
plan_id: input.planId,
|
|
3182
3191
|
week_number: week,
|
|
@@ -3196,7 +3205,7 @@ function createSupabaseContentPlannerProvider() {
|
|
|
3196
3205
|
return toPost(data);
|
|
3197
3206
|
},
|
|
3198
3207
|
async deletePost(id) {
|
|
3199
|
-
await getClient().from(
|
|
3208
|
+
await getClient().from(T.contentPosts).delete().eq("id", id);
|
|
3200
3209
|
}
|
|
3201
3210
|
};
|
|
3202
3211
|
}
|
|
@@ -3347,13 +3356,29 @@ function createContentPlannerStore(provider) {
|
|
|
3347
3356
|
}
|
|
3348
3357
|
|
|
3349
3358
|
// src/migrations/index.ts
|
|
3359
|
+
var MIGRATION_000_PLG_RENAME = `-- 000_plg_rename.sql \u2014 rename legacy marketing tables to plg_marketing_* for pools
|
|
3360
|
+
-- provisioned before the industry-pool rename. Guarded: fires only when legacy
|
|
3361
|
+
-- name exists and target does not, so fresh pools skip every branch.
|
|
3362
|
+
DO $$
|
|
3363
|
+
BEGIN
|
|
3364
|
+
IF to_regclass('public.mkt_social_accounts') IS NOT NULL AND to_regclass('public.plg_marketing_social_accounts') IS NULL THEN
|
|
3365
|
+
ALTER TABLE public.mkt_social_accounts RENAME TO plg_marketing_social_accounts;
|
|
3366
|
+
END IF;
|
|
3367
|
+
IF to_regclass('public.mkt_content_plans') IS NOT NULL AND to_regclass('public.plg_marketing_content_plans') IS NULL THEN
|
|
3368
|
+
ALTER TABLE public.mkt_content_plans RENAME TO plg_marketing_content_plans;
|
|
3369
|
+
END IF;
|
|
3370
|
+
IF to_regclass('public.mkt_content_posts') IS NOT NULL AND to_regclass('public.plg_marketing_content_posts') IS NULL THEN
|
|
3371
|
+
ALTER TABLE public.mkt_content_posts RENAME TO plg_marketing_content_posts;
|
|
3372
|
+
END IF;
|
|
3373
|
+
END $$;
|
|
3374
|
+
`;
|
|
3350
3375
|
var MIGRATION_001_CONTENT_PLANNER = `-- Marketing Plugin: Content Planner
|
|
3351
|
-
-- Prefix:
|
|
3376
|
+
-- Prefix: plg_marketing_
|
|
3352
3377
|
-- Social accounts + content plans + posts (Notion-style markdown pages).
|
|
3353
3378
|
|
|
3354
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
3379
|
+
CREATE TABLE IF NOT EXISTS public.plg_marketing_social_accounts (
|
|
3355
3380
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
3356
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
3381
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
3357
3382
|
name text NOT NULL,
|
|
3358
3383
|
handle text,
|
|
3359
3384
|
platform text NOT NULL DEFAULT 'instagram'
|
|
@@ -3361,13 +3386,13 @@ CREATE TABLE IF NOT EXISTS public.mkt_social_accounts (
|
|
|
3361
3386
|
is_active boolean NOT NULL DEFAULT true,
|
|
3362
3387
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
3363
3388
|
);
|
|
3364
|
-
ALTER TABLE public.
|
|
3365
|
-
CREATE INDEX IF NOT EXISTS
|
|
3389
|
+
ALTER TABLE public.plg_marketing_social_accounts ENABLE ROW LEVEL SECURITY;
|
|
3390
|
+
CREATE INDEX IF NOT EXISTS idx_plg_marketing_social_accounts_tenant ON public.plg_marketing_social_accounts(tenant_id);
|
|
3366
3391
|
|
|
3367
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
3392
|
+
CREATE TABLE IF NOT EXISTS public.plg_marketing_content_plans (
|
|
3368
3393
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
3369
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
3370
|
-
account_id uuid NOT NULL REFERENCES public.
|
|
3394
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
3395
|
+
account_id uuid NOT NULL REFERENCES public.plg_marketing_social_accounts(id) ON DELETE CASCADE,
|
|
3371
3396
|
name text NOT NULL,
|
|
3372
3397
|
status text NOT NULL DEFAULT 'active'
|
|
3373
3398
|
CHECK (status IN ('draft', 'active', 'archived')),
|
|
@@ -3382,14 +3407,14 @@ CREATE TABLE IF NOT EXISTS public.mkt_content_plans (
|
|
|
3382
3407
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
3383
3408
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
3384
3409
|
);
|
|
3385
|
-
ALTER TABLE public.
|
|
3386
|
-
CREATE INDEX IF NOT EXISTS
|
|
3387
|
-
CREATE INDEX IF NOT EXISTS
|
|
3410
|
+
ALTER TABLE public.plg_marketing_content_plans ENABLE ROW LEVEL SECURITY;
|
|
3411
|
+
CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_plans_tenant ON public.plg_marketing_content_plans(tenant_id);
|
|
3412
|
+
CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_plans_account ON public.plg_marketing_content_plans(account_id);
|
|
3388
3413
|
|
|
3389
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
3414
|
+
CREATE TABLE IF NOT EXISTS public.plg_marketing_content_posts (
|
|
3390
3415
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
3391
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
3392
|
-
plan_id uuid NOT NULL REFERENCES public.
|
|
3416
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
3417
|
+
plan_id uuid NOT NULL REFERENCES public.plg_marketing_content_plans(id) ON DELETE CASCADE,
|
|
3393
3418
|
week_number integer NOT NULL DEFAULT 1,
|
|
3394
3419
|
position integer NOT NULL DEFAULT 0,
|
|
3395
3420
|
title text NOT NULL,
|
|
@@ -3404,49 +3429,50 @@ CREATE TABLE IF NOT EXISTS public.mkt_content_posts (
|
|
|
3404
3429
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
3405
3430
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
3406
3431
|
);
|
|
3407
|
-
ALTER TABLE public.
|
|
3408
|
-
CREATE INDEX IF NOT EXISTS
|
|
3409
|
-
CREATE INDEX IF NOT EXISTS
|
|
3410
|
-
CREATE INDEX IF NOT EXISTS
|
|
3411
|
-
|
|
3412
|
-
-- RLS policies for
|
|
3413
|
-
DROP POLICY IF EXISTS
|
|
3414
|
-
DROP POLICY IF EXISTS
|
|
3415
|
-
DROP POLICY IF EXISTS
|
|
3416
|
-
DROP POLICY IF EXISTS
|
|
3417
|
-
CREATE POLICY
|
|
3418
|
-
CREATE POLICY
|
|
3419
|
-
CREATE POLICY
|
|
3420
|
-
CREATE POLICY
|
|
3421
|
-
GRANT SELECT, INSERT, UPDATE, DELETE ON public.
|
|
3422
|
-
|
|
3423
|
-
-- RLS policies for
|
|
3424
|
-
DROP POLICY IF EXISTS
|
|
3425
|
-
DROP POLICY IF EXISTS
|
|
3426
|
-
DROP POLICY IF EXISTS
|
|
3427
|
-
DROP POLICY IF EXISTS
|
|
3428
|
-
CREATE POLICY
|
|
3429
|
-
CREATE POLICY
|
|
3430
|
-
CREATE POLICY
|
|
3431
|
-
CREATE POLICY
|
|
3432
|
-
GRANT SELECT, INSERT, UPDATE, DELETE ON public.
|
|
3433
|
-
|
|
3434
|
-
-- RLS policies for
|
|
3435
|
-
DROP POLICY IF EXISTS
|
|
3436
|
-
DROP POLICY IF EXISTS
|
|
3437
|
-
DROP POLICY IF EXISTS
|
|
3438
|
-
DROP POLICY IF EXISTS
|
|
3439
|
-
CREATE POLICY
|
|
3440
|
-
CREATE POLICY
|
|
3441
|
-
CREATE POLICY
|
|
3442
|
-
CREATE POLICY
|
|
3443
|
-
GRANT SELECT, INSERT, UPDATE, DELETE ON public.
|
|
3432
|
+
ALTER TABLE public.plg_marketing_content_posts ENABLE ROW LEVEL SECURITY;
|
|
3433
|
+
CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_posts_tenant ON public.plg_marketing_content_posts(tenant_id);
|
|
3434
|
+
CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_posts_plan ON public.plg_marketing_content_posts(plan_id, week_number, position);
|
|
3435
|
+
CREATE INDEX IF NOT EXISTS idx_plg_marketing_content_posts_status ON public.plg_marketing_content_posts(tenant_id, status);
|
|
3436
|
+
|
|
3437
|
+
-- RLS policies for plg_marketing_social_accounts
|
|
3438
|
+
DROP POLICY IF EXISTS plg_marketing_social_accounts_select ON public.plg_marketing_social_accounts;
|
|
3439
|
+
DROP POLICY IF EXISTS plg_marketing_social_accounts_insert ON public.plg_marketing_social_accounts;
|
|
3440
|
+
DROP POLICY IF EXISTS plg_marketing_social_accounts_update ON public.plg_marketing_social_accounts;
|
|
3441
|
+
DROP POLICY IF EXISTS plg_marketing_social_accounts_delete ON public.plg_marketing_social_accounts;
|
|
3442
|
+
CREATE POLICY plg_marketing_social_accounts_select ON public.plg_marketing_social_accounts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3443
|
+
CREATE POLICY plg_marketing_social_accounts_insert ON public.plg_marketing_social_accounts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3444
|
+
CREATE POLICY plg_marketing_social_accounts_update ON public.plg_marketing_social_accounts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3445
|
+
CREATE POLICY plg_marketing_social_accounts_delete ON public.plg_marketing_social_accounts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3446
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_marketing_social_accounts TO authenticated;
|
|
3447
|
+
|
|
3448
|
+
-- RLS policies for plg_marketing_content_plans
|
|
3449
|
+
DROP POLICY IF EXISTS plg_marketing_content_plans_select ON public.plg_marketing_content_plans;
|
|
3450
|
+
DROP POLICY IF EXISTS plg_marketing_content_plans_insert ON public.plg_marketing_content_plans;
|
|
3451
|
+
DROP POLICY IF EXISTS plg_marketing_content_plans_update ON public.plg_marketing_content_plans;
|
|
3452
|
+
DROP POLICY IF EXISTS plg_marketing_content_plans_delete ON public.plg_marketing_content_plans;
|
|
3453
|
+
CREATE POLICY plg_marketing_content_plans_select ON public.plg_marketing_content_plans FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3454
|
+
CREATE POLICY plg_marketing_content_plans_insert ON public.plg_marketing_content_plans FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3455
|
+
CREATE POLICY plg_marketing_content_plans_update ON public.plg_marketing_content_plans FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3456
|
+
CREATE POLICY plg_marketing_content_plans_delete ON public.plg_marketing_content_plans FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3457
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_marketing_content_plans TO authenticated;
|
|
3458
|
+
|
|
3459
|
+
-- RLS policies for plg_marketing_content_posts
|
|
3460
|
+
DROP POLICY IF EXISTS plg_marketing_content_posts_select ON public.plg_marketing_content_posts;
|
|
3461
|
+
DROP POLICY IF EXISTS plg_marketing_content_posts_insert ON public.plg_marketing_content_posts;
|
|
3462
|
+
DROP POLICY IF EXISTS plg_marketing_content_posts_update ON public.plg_marketing_content_posts;
|
|
3463
|
+
DROP POLICY IF EXISTS plg_marketing_content_posts_delete ON public.plg_marketing_content_posts;
|
|
3464
|
+
CREATE POLICY plg_marketing_content_posts_select ON public.plg_marketing_content_posts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3465
|
+
CREATE POLICY plg_marketing_content_posts_insert ON public.plg_marketing_content_posts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3466
|
+
CREATE POLICY plg_marketing_content_posts_update ON public.plg_marketing_content_posts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3467
|
+
CREATE POLICY plg_marketing_content_posts_delete ON public.plg_marketing_content_posts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
3468
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON public.plg_marketing_content_posts TO authenticated;
|
|
3469
|
+
`;
|
|
3444
3470
|
var MIGRATION_002_MULTI_PLATFORM = `-- Marketing Plugin: multi-platform accounts + per-post targets.
|
|
3445
3471
|
-- An account is a brand/profile that publishes to MANY platforms (Instagram,
|
|
3446
3472
|
-- YouTube, TikTok, ...). Posts optionally narrow the target platforms; an
|
|
3447
3473
|
-- empty array means "inherit the account's platforms".
|
|
3448
3474
|
|
|
3449
|
-
ALTER TABLE public.
|
|
3475
|
+
ALTER TABLE public.plg_marketing_social_accounts
|
|
3450
3476
|
ADD COLUMN IF NOT EXISTS platforms text[] NOT NULL DEFAULT '{instagram}';
|
|
3451
3477
|
|
|
3452
3478
|
-- Backfill from the legacy single-platform column, then drop it (also drops
|
|
@@ -3455,26 +3481,27 @@ DO $$
|
|
|
3455
3481
|
BEGIN
|
|
3456
3482
|
IF EXISTS (
|
|
3457
3483
|
SELECT 1 FROM information_schema.columns
|
|
3458
|
-
WHERE table_schema = 'public' AND table_name = '
|
|
3484
|
+
WHERE table_schema = 'public' AND table_name = 'plg_marketing_social_accounts' AND column_name = 'platform'
|
|
3459
3485
|
) THEN
|
|
3460
|
-
UPDATE public.
|
|
3486
|
+
UPDATE public.plg_marketing_social_accounts
|
|
3461
3487
|
SET platforms = ARRAY[platform]
|
|
3462
3488
|
WHERE platform IS NOT NULL AND platforms = '{instagram}';
|
|
3463
|
-
ALTER TABLE public.
|
|
3489
|
+
ALTER TABLE public.plg_marketing_social_accounts DROP COLUMN platform;
|
|
3464
3490
|
END IF;
|
|
3465
3491
|
END $$;
|
|
3466
3492
|
|
|
3467
|
-
ALTER TABLE public.
|
|
3468
|
-
ADD COLUMN IF NOT EXISTS platforms text[] NOT NULL DEFAULT '{}'
|
|
3493
|
+
ALTER TABLE public.plg_marketing_content_posts
|
|
3494
|
+
ADD COLUMN IF NOT EXISTS platforms text[] NOT NULL DEFAULT '{}';
|
|
3495
|
+
`;
|
|
3469
3496
|
var MIGRATION_003_RECORDING_OPS = `-- Marketing Plugin: recording-day ops on posts.
|
|
3470
3497
|
-- checklist: shooting checklist items [{ id, text, done }] \u2014 the on-set
|
|
3471
3498
|
-- companion for recording day. media_url: uploaded asset (static posts get a
|
|
3472
3499
|
-- caption + final art instead of a script).
|
|
3473
3500
|
|
|
3474
|
-
ALTER TABLE public.
|
|
3501
|
+
ALTER TABLE public.plg_marketing_content_posts
|
|
3475
3502
|
ADD COLUMN IF NOT EXISTS checklist jsonb NOT NULL DEFAULT '[]';
|
|
3476
3503
|
|
|
3477
|
-
ALTER TABLE public.
|
|
3504
|
+
ALTER TABLE public.plg_marketing_content_posts
|
|
3478
3505
|
ADD COLUMN IF NOT EXISTS media_url text;
|
|
3479
3506
|
|
|
3480
3507
|
-- Public media bucket for content assets (mirrors the avatars-bucket pattern:
|
|
@@ -3483,14 +3510,15 @@ INSERT INTO storage.buckets (id, name, public)
|
|
|
3483
3510
|
VALUES ('mkt-media', 'mkt-media', true)
|
|
3484
3511
|
ON CONFLICT (id) DO NOTHING;
|
|
3485
3512
|
|
|
3486
|
-
DROP POLICY IF EXISTS
|
|
3487
|
-
DROP POLICY IF EXISTS
|
|
3488
|
-
DROP POLICY IF EXISTS
|
|
3489
|
-
DROP POLICY IF EXISTS
|
|
3490
|
-
CREATE POLICY
|
|
3491
|
-
CREATE POLICY
|
|
3492
|
-
CREATE POLICY
|
|
3493
|
-
CREATE POLICY
|
|
3513
|
+
DROP POLICY IF EXISTS plg_marketing_media_read ON storage.objects;
|
|
3514
|
+
DROP POLICY IF EXISTS plg_marketing_media_insert ON storage.objects;
|
|
3515
|
+
DROP POLICY IF EXISTS plg_marketing_media_update ON storage.objects;
|
|
3516
|
+
DROP POLICY IF EXISTS plg_marketing_media_delete ON storage.objects;
|
|
3517
|
+
CREATE POLICY plg_marketing_media_read ON storage.objects FOR SELECT TO public USING (bucket_id = 'mkt-media');
|
|
3518
|
+
CREATE POLICY plg_marketing_media_insert ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'mkt-media');
|
|
3519
|
+
CREATE POLICY plg_marketing_media_update ON storage.objects FOR UPDATE TO authenticated USING (bucket_id = 'mkt-media');
|
|
3520
|
+
CREATE POLICY plg_marketing_media_delete ON storage.objects FOR DELETE TO authenticated USING (bucket_id = 'mkt-media');
|
|
3521
|
+
`;
|
|
3494
3522
|
|
|
3495
3523
|
// src/locales/en.ts
|
|
3496
3524
|
var en = {
|
|
@@ -3908,6 +3936,9 @@ function createMarketingPlugin(options) {
|
|
|
3908
3936
|
version: "1.0.0",
|
|
3909
3937
|
scope: options?.scope ?? "universal",
|
|
3910
3938
|
verticalId: options?.verticalId,
|
|
3939
|
+
// Admin content-planning surface (campaigns, content calendar) — targets the
|
|
3940
|
+
// saas/admin Panel world, not the ecommerce storefront/operator console.
|
|
3941
|
+
scaffolds: ["saas"],
|
|
3911
3942
|
defaultEnabled: true,
|
|
3912
3943
|
dependencies: [],
|
|
3913
3944
|
declaredFeatures: [
|
|
@@ -3944,11 +3975,17 @@ function createMarketingPlugin(options) {
|
|
|
3944
3975
|
{ name: "marketing.content.post.updated", description: "A content post was updated" }
|
|
3945
3976
|
],
|
|
3946
3977
|
migrations: [
|
|
3978
|
+
{
|
|
3979
|
+
id: "marketing-000-plg-rename",
|
|
3980
|
+
version: "1.0.0",
|
|
3981
|
+
sql: MIGRATION_000_PLG_RENAME,
|
|
3982
|
+
description: "Rename legacy mkt_* tables to plg_marketing_* in-place for pools provisioned before the industry-pool rename (guarded no-op on fresh pools)"
|
|
3983
|
+
},
|
|
3947
3984
|
{
|
|
3948
3985
|
id: "marketing-001-content-planner",
|
|
3949
3986
|
version: "1.0.0",
|
|
3950
3987
|
sql: MIGRATION_001_CONTENT_PLANNER,
|
|
3951
|
-
description: "Create
|
|
3988
|
+
description: "Create plg_marketing_social_accounts, plg_marketing_content_plans and plg_marketing_content_posts"
|
|
3952
3989
|
},
|
|
3953
3990
|
{
|
|
3954
3991
|
id: "marketing-002-multi-platform",
|
|
@@ -3960,7 +3997,7 @@ function createMarketingPlugin(options) {
|
|
|
3960
3997
|
id: "marketing-003-recording-ops",
|
|
3961
3998
|
version: "1.2.0",
|
|
3962
3999
|
sql: MIGRATION_003_RECORDING_OPS,
|
|
3963
|
-
description: "Recording-day checklist + media asset URL on posts;
|
|
4000
|
+
description: "Recording-day checklist + media asset URL on posts; content-media storage bucket"
|
|
3964
4001
|
}
|
|
3965
4002
|
],
|
|
3966
4003
|
aiTools: [
|