@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.
@@ -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,CAwKtF;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"}
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("mkt_social_accounts").select("*").eq("tenant_id", tenantId).eq("is_active", true).order("created_at", { ascending: true });
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("mkt_social_accounts").update(payload).eq("id", input.id).select("*").single();
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("mkt_social_accounts").insert({
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("mkt_social_accounts").delete().eq("id", id);
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("mkt_content_plans").select("*").eq("tenant_id", tenantId).eq("account_id", accountId).order("created_at", { ascending: false });
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("mkt_content_plans").select("*").eq("id", id).maybeSingle();
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("mkt_content_plans").update(payload).eq("id", input.id).select("*").single();
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("mkt_content_plans").insert({
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("mkt_content_plans").delete().eq("id", id);
3155
+ await getClient().from(T.contentPlans).delete().eq("id", id);
3147
3156
  },
3148
3157
  async listPosts(planId) {
3149
- const { data } = await getClient().from("mkt_content_posts").select("*").eq("plan_id", planId).order("week_number", { ascending: true }).order("position", { ascending: true });
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("mkt_content_posts").select("*").eq("id", id).maybeSingle();
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("mkt_content_posts").update(payload).eq("id", input.id).select("*").single();
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("mkt_content_posts").select("position").eq("plan_id", input.planId).eq("week_number", week).order("position", { ascending: false }).limit(1);
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("mkt_content_posts").insert({
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("mkt_content_posts").delete().eq("id", id);
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: mkt_
3376
+ -- Prefix: plg_marketing_
3352
3377
  -- Social accounts + content plans + posts (Notion-style markdown pages).
3353
3378
 
3354
- CREATE TABLE IF NOT EXISTS public.mkt_social_accounts (
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 saas_core.tenants(id) ON DELETE CASCADE,
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.mkt_social_accounts ENABLE ROW LEVEL SECURITY;
3365
- CREATE INDEX IF NOT EXISTS idx_mkt_social_accounts_tenant ON public.mkt_social_accounts(tenant_id);
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.mkt_content_plans (
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 saas_core.tenants(id) ON DELETE CASCADE,
3370
- account_id uuid NOT NULL REFERENCES public.mkt_social_accounts(id) ON DELETE CASCADE,
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.mkt_content_plans ENABLE ROW LEVEL SECURITY;
3386
- CREATE INDEX IF NOT EXISTS idx_mkt_content_plans_tenant ON public.mkt_content_plans(tenant_id);
3387
- CREATE INDEX IF NOT EXISTS idx_mkt_content_plans_account ON public.mkt_content_plans(account_id);
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.mkt_content_posts (
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 saas_core.tenants(id) ON DELETE CASCADE,
3392
- plan_id uuid NOT NULL REFERENCES public.mkt_content_plans(id) ON DELETE CASCADE,
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.mkt_content_posts ENABLE ROW LEVEL SECURITY;
3408
- CREATE INDEX IF NOT EXISTS idx_mkt_content_posts_tenant ON public.mkt_content_posts(tenant_id);
3409
- CREATE INDEX IF NOT EXISTS idx_mkt_content_posts_plan ON public.mkt_content_posts(plan_id, week_number, position);
3410
- CREATE INDEX IF NOT EXISTS idx_mkt_content_posts_status ON public.mkt_content_posts(tenant_id, status);
3411
-
3412
- -- RLS policies for mkt_social_accounts
3413
- DROP POLICY IF EXISTS mkt_social_accounts_select ON public.mkt_social_accounts;
3414
- DROP POLICY IF EXISTS mkt_social_accounts_insert ON public.mkt_social_accounts;
3415
- DROP POLICY IF EXISTS mkt_social_accounts_update ON public.mkt_social_accounts;
3416
- DROP POLICY IF EXISTS mkt_social_accounts_delete ON public.mkt_social_accounts;
3417
- CREATE POLICY mkt_social_accounts_select ON public.mkt_social_accounts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3418
- CREATE POLICY mkt_social_accounts_insert ON public.mkt_social_accounts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
3419
- CREATE POLICY mkt_social_accounts_update ON public.mkt_social_accounts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3420
- CREATE POLICY mkt_social_accounts_delete ON public.mkt_social_accounts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3421
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.mkt_social_accounts TO authenticated;
3422
-
3423
- -- RLS policies for mkt_content_plans
3424
- DROP POLICY IF EXISTS mkt_content_plans_select ON public.mkt_content_plans;
3425
- DROP POLICY IF EXISTS mkt_content_plans_insert ON public.mkt_content_plans;
3426
- DROP POLICY IF EXISTS mkt_content_plans_update ON public.mkt_content_plans;
3427
- DROP POLICY IF EXISTS mkt_content_plans_delete ON public.mkt_content_plans;
3428
- CREATE POLICY mkt_content_plans_select ON public.mkt_content_plans FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3429
- CREATE POLICY mkt_content_plans_insert ON public.mkt_content_plans FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
3430
- CREATE POLICY mkt_content_plans_update ON public.mkt_content_plans FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3431
- CREATE POLICY mkt_content_plans_delete ON public.mkt_content_plans FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3432
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.mkt_content_plans TO authenticated;
3433
-
3434
- -- RLS policies for mkt_content_posts
3435
- DROP POLICY IF EXISTS mkt_content_posts_select ON public.mkt_content_posts;
3436
- DROP POLICY IF EXISTS mkt_content_posts_insert ON public.mkt_content_posts;
3437
- DROP POLICY IF EXISTS mkt_content_posts_update ON public.mkt_content_posts;
3438
- DROP POLICY IF EXISTS mkt_content_posts_delete ON public.mkt_content_posts;
3439
- CREATE POLICY mkt_content_posts_select ON public.mkt_content_posts FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3440
- CREATE POLICY mkt_content_posts_insert ON public.mkt_content_posts FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
3441
- CREATE POLICY mkt_content_posts_update ON public.mkt_content_posts FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3442
- CREATE POLICY mkt_content_posts_delete ON public.mkt_content_posts FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));
3443
- GRANT SELECT, INSERT, UPDATE, DELETE ON public.mkt_content_posts TO authenticated;`;
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.mkt_social_accounts
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 = 'mkt_social_accounts' AND column_name = 'platform'
3484
+ WHERE table_schema = 'public' AND table_name = 'plg_marketing_social_accounts' AND column_name = 'platform'
3459
3485
  ) THEN
3460
- UPDATE public.mkt_social_accounts
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.mkt_social_accounts DROP COLUMN platform;
3489
+ ALTER TABLE public.plg_marketing_social_accounts DROP COLUMN platform;
3464
3490
  END IF;
3465
3491
  END $$;
3466
3492
 
3467
- ALTER TABLE public.mkt_content_posts
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.mkt_content_posts
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.mkt_content_posts
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 mkt_media_read ON storage.objects;
3487
- DROP POLICY IF EXISTS mkt_media_insert ON storage.objects;
3488
- DROP POLICY IF EXISTS mkt_media_update ON storage.objects;
3489
- DROP POLICY IF EXISTS mkt_media_delete ON storage.objects;
3490
- CREATE POLICY mkt_media_read ON storage.objects FOR SELECT TO public USING (bucket_id = 'mkt-media');
3491
- CREATE POLICY mkt_media_insert ON storage.objects FOR INSERT TO authenticated WITH CHECK (bucket_id = 'mkt-media');
3492
- CREATE POLICY mkt_media_update ON storage.objects FOR UPDATE TO authenticated USING (bucket_id = 'mkt-media');
3493
- CREATE POLICY mkt_media_delete ON storage.objects FOR DELETE TO authenticated USING (bucket_id = 'mkt-media');`;
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 mkt_social_accounts, mkt_content_plans and mkt_content_posts tables"
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; mkt-media storage bucket"
4000
+ description: "Recording-day checklist + media asset URL on posts; content-media storage bucket"
3964
4001
  }
3965
4002
  ],
3966
4003
  aiTools: [