sealmetrics 0.1.3 → 0.1.4

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.
@@ -21,8 +21,5 @@ export declare class ApiClient {
21
21
  provision(input: ProvisionInput): Promise<ProvisionResult>;
22
22
  /** GET /sites/{id}/pixel/status. Throws CliError(4) on network/backend errors. */
23
23
  pixelStatus(accountId: string, apiKey: string): Promise<PixelStatus>;
24
- private fetchWithTimeout;
25
- private json;
26
- private safeText;
27
24
  }
28
25
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIhE,8FAA8F;AAC9F,qBAAa,gBAAiB,SAAQ,KAAK;;CAK1C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AASD,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAKjD,yFAAyF;IACnF,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IA+EhE,kFAAkF;IAC5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;YA2B5D,gBAAgB;YAUhB,IAAI;YASJ,QAAQ;CAOvB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEhE,8FAA8F;AAC9F,qBAAa,gBAAiB,SAAQ,KAAK;;CAK1C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;IAKjD,yFAAyF;IACnF,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAqBhE,kFAAkF;IAC5E,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAS3E"}
@@ -1,11 +1,12 @@
1
1
  /**
2
- * HTTP client for the Fase 1 backend (Bloque 4). Consumes, never changes, the
3
- * existing contract: POST /provision (X-Provision-Key) and
4
- * GET /sites/{id}/pixel/status (X-API-Key). Response maps to events/exit codes
5
- * per RF-402.
2
+ * HTTP client for the Fase 1 backend (Bloque 4). The transport now lives in
3
+ * `@sealmetrics/setup-core` (`provision`, `fetchPixelStatus`), shared with the MCP
4
+ * write-path (RF-3102). This adapter keeps the CLI's surface identical: it maps
5
+ * setup-core's presentation-agnostic `ProvisionError` codes to the CLI's exit
6
+ * codes / `CliError` (RF-402) and re-exposes `EmailExistsError` + `ProvisionInput`.
6
7
  */
8
+ import { provision as coreProvision, fetchPixelStatus as coreFetchPixelStatus, ProvisionError, } from "@sealmetrics/setup-core";
7
9
  import { CliError, ExitCode } from "../exit-codes.js";
8
- const DEFAULT_TIMEOUT_MS = 30_000;
9
10
  /** Raised on 409 (email already exists) — init handles it as informative, exit 0 (RF-402). */
10
11
  export class EmailExistsError extends Error {
11
12
  constructor() {
@@ -22,126 +23,67 @@ export class ApiClient {
22
23
  }
23
24
  /** POST /provision. Throws CliError (3/4) or EmailExistsError on the mapped statuses. */
24
25
  async provision(input) {
25
- const body = {
26
- site_name: input.siteName,
27
- domain: input.domain,
28
- email: input.email,
29
- name: input.name,
30
- accept_terms: true,
31
- install_source: input.installSource,
32
- timezone: input.timezone,
33
- };
34
- let res;
35
26
  try {
36
- res = await this.fetchWithTimeout(`${this.baseUrl}/provision`, {
37
- method: "POST",
38
- headers: {
39
- "Content-Type": "application/json",
40
- Accept: "application/json",
41
- "X-Provision-Key": this.provisionKey,
42
- },
43
- body: JSON.stringify(body),
44
- });
27
+ return await coreProvision({
28
+ siteName: input.siteName,
29
+ domain: input.domain,
30
+ email: input.email,
31
+ name: input.name,
32
+ installSource: input.installSource,
33
+ timezone: input.timezone,
34
+ }, { baseUrl: this.baseUrl, provisionKey: this.provisionKey });
45
35
  }
46
36
  catch (e) {
47
- throw new CliError(ExitCode.NETWORK, "network_error", `Could not reach the SealMetrics API at ${this.baseUrl}.`, {
37
+ if (e instanceof ProvisionError) {
38
+ throw mapProvisionError(e, input, this.baseUrl);
39
+ }
40
+ throw e;
41
+ }
42
+ }
43
+ /** GET /sites/{id}/pixel/status. Throws CliError(4) on network/backend errors. */
44
+ async pixelStatus(accountId, apiKey) {
45
+ try {
46
+ return await coreFetchPixelStatus(accountId, { baseUrl: this.baseUrl, apiKey });
47
+ }
48
+ catch (e) {
49
+ throw new CliError(ExitCode.NETWORK, "pixel_status_error", "Pixel status check failed.", {
48
50
  hint: e instanceof Error ? e.message : undefined,
49
51
  });
50
52
  }
51
- if (res.status === 200) {
52
- const json = (await this.json(res));
53
- const data = json.data;
54
- if (!data || !data.account_id || !data.api_key) {
55
- throw new CliError(ExitCode.NETWORK, "bad_response", "Provisioning returned an unexpected response.");
56
- }
57
- return data;
58
- }
59
- if (res.status === 401) {
60
- throw new CliError(ExitCode.AUTH_REQUIRED, "AUTH_REQUIRED", "The provision key was rejected (invalid or revoked).", {
53
+ }
54
+ }
55
+ /** Map setup-core's transport-level error to the CLI's exit-coded CliError (RF-402). */
56
+ function mapProvisionError(e, input, baseUrl) {
57
+ switch (e.code) {
58
+ case "EMAIL_EXISTS":
59
+ return new EmailExistsError();
60
+ case "AUTH_REQUIRED":
61
+ return new CliError(ExitCode.AUTH_REQUIRED, "AUTH_REQUIRED", e.message, {
61
62
  hint: "Re-run with a valid publishable provision key.",
62
63
  extra: {
63
64
  command: input.reinvokeCommand ??
64
65
  "npx sealmetrics init --provision-key <YOUR_KEY> --email <email> --accept-tos",
65
66
  },
66
67
  });
67
- }
68
- if (res.status === 409) {
69
- throw new EmailExistsError();
70
- }
71
- if (res.status === 429) {
72
- const retryAfter = parseRetryAfter(res.headers.get("Retry-After"));
73
- throw new CliError(ExitCode.NETWORK, "rate_limited", "Provisioning is rate-limited. Please wait and retry.", {
74
- extra: retryAfter ? { retry_after: retryAfter } : undefined,
68
+ case "RATE_LIMITED":
69
+ return new CliError(ExitCode.NETWORK, "rate_limited", e.message, {
70
+ extra: e.retryAfter ? { retry_after: e.retryAfter } : undefined,
75
71
  });
76
- }
77
- if (res.status === 503) {
78
- throw new CliError(ExitCode.NETWORK, "provisioning_disabled", "Provisioning is currently disabled on the server.", { hint: "The free-tier channel is not enabled yet. Try again later." });
79
- }
80
- const detail = await this.safeText(res);
81
- throw new CliError(ExitCode.NETWORK, "backend_error", `Provisioning failed (HTTP ${res.status}).`, {
82
- hint: detail.slice(0, 200) || undefined,
83
- });
84
- }
85
- /** GET /sites/{id}/pixel/status. Throws CliError(4) on network/backend errors. */
86
- async pixelStatus(accountId, apiKey) {
87
- const url = `${this.baseUrl}/sites/${encodeURIComponent(accountId)}/pixel/status`;
88
- let res;
89
- try {
90
- res = await this.fetchWithTimeout(url, {
91
- method: "GET",
92
- headers: { "X-API-Key": apiKey, Accept: "application/json" },
72
+ case "PROVISIONING_DISABLED":
73
+ return new CliError(ExitCode.NETWORK, "provisioning_disabled", e.message, {
74
+ hint: "The free-tier channel is not enabled yet. Try again later.",
93
75
  });
94
- }
95
- catch (e) {
96
- throw new CliError(ExitCode.NETWORK, "network_error", "Could not reach the SealMetrics API.", {
97
- hint: e instanceof Error ? e.message : undefined,
76
+ case "BAD_RESPONSE":
77
+ return new CliError(ExitCode.NETWORK, "bad_response", e.message);
78
+ case "NETWORK":
79
+ return new CliError(ExitCode.NETWORK, "network_error", `Could not reach the SealMetrics API at ${baseUrl}.`, {
80
+ hint: e.detail,
98
81
  });
99
- }
100
- if (res.status !== 200) {
101
- const detail = await this.safeText(res);
102
- throw new CliError(ExitCode.NETWORK, "pixel_status_error", `Pixel status check failed (HTTP ${res.status}).`, {
103
- hint: detail.slice(0, 200) || undefined,
82
+ case "BACKEND_ERROR":
83
+ default:
84
+ return new CliError(ExitCode.NETWORK, "backend_error", e.message, {
85
+ hint: e.detail,
104
86
  });
105
- }
106
- const json = (await this.json(res));
107
- const data = json.data;
108
- if (!data || typeof data.installed !== "boolean") {
109
- throw new CliError(ExitCode.NETWORK, "bad_response", "Pixel status returned an unexpected response.");
110
- }
111
- return data;
112
- }
113
- async fetchWithTimeout(url, init) {
114
- const controller = new AbortController();
115
- const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
116
- try {
117
- return await fetch(url, { ...init, signal: controller.signal });
118
- }
119
- finally {
120
- clearTimeout(timeout);
121
- }
122
- }
123
- async json(res) {
124
- const text = await res.text();
125
- try {
126
- return JSON.parse(text);
127
- }
128
- catch {
129
- throw new CliError(ExitCode.NETWORK, "bad_response", "The API returned invalid JSON.");
130
- }
131
87
  }
132
- async safeText(res) {
133
- try {
134
- return await res.text();
135
- }
136
- catch {
137
- return "";
138
- }
139
- }
140
- }
141
- function parseRetryAfter(header) {
142
- if (!header)
143
- return undefined;
144
- const n = parseInt(header, 10);
145
- return Number.isFinite(n) && n > 0 ? n : undefined;
146
88
  }
147
89
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
- import type { Platform } from "../types.js";
2
- /** Official plugin/module install hint per platform, surfaced in next_steps (RF-306). */
3
- export declare const PLATFORM_PLUGIN_HINT: Record<Platform, string>;
4
- export declare function detectPlatform(cwd: string): Platform | undefined;
1
+ /**
2
+ * CMS / ecommerce platform detection (RF-305). The logic now lives in
3
+ * `@sealmetrics/setup-core` (shared with the MCP write-path, RF-3102); this module
4
+ * re-exports it so the rest of the CLI keeps importing from `./cms.js` unchanged.
5
+ */
6
+ export { detectPlatform, PLATFORM_PLUGIN_HINT } from "@sealmetrics/setup-core";
5
7
  //# sourceMappingURL=cms.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cms.d.ts","sourceRoot":"","sources":["../../src/detect/cms.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,yFAAyF;AACzF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAezD,CAAC;AAEF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAmChE"}
1
+ {"version":3,"file":"cms.d.ts","sourceRoot":"","sources":["../../src/detect/cms.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,52 +1,7 @@
1
1
  /**
2
- * CMS / ecommerce platform detection (RF-305). When SealMetrics already ships an
3
- * official plugin/module for the platform, the CLI does NOT edit PHP/theme files
4
- * (RF-306) it provisions and points the user at the plugin. Best-effort markers
5
- * only; conservative (VAL-305).
2
+ * CMS / ecommerce platform detection (RF-305). The logic now lives in
3
+ * `@sealmetrics/setup-core` (shared with the MCP write-path, RF-3102); this module
4
+ * re-exports it so the rest of the CLI keeps importing from `./cms.js` unchanged.
6
5
  */
7
- import { existsSync } from "node:fs";
8
- import { join } from "node:path";
9
- /** Official plugin/module install hint per platform, surfaced in next_steps (RF-306). */
10
- export const PLATFORM_PLUGIN_HINT = {
11
- woocommerce: "Install the official SealMetrics for WooCommerce plugin and paste your account_id in its settings.",
12
- wordpress: "Install the official SealMetrics for WordPress plugin and paste your account_id in its settings.",
13
- prestashop: "Install the official SealMetrics PrestaShop module and paste your account_id in its settings.",
14
- magento2: "Install the official SealMetrics Magento 2 extension and paste your account_id in its settings.",
15
- drupal: "Install the official SealMetrics Drupal module and paste your account_id in its settings.",
16
- joomla: "Install the official SealMetrics Joomla plugin and paste your account_id in its settings.",
17
- opencart: "Install the official SealMetrics OpenCart extension and paste your account_id in its settings.",
18
- };
19
- export function detectPlatform(cwd) {
20
- const has = (...rel) => rel.some((r) => existsSync(join(cwd, r)));
21
- // WordPress family (Woo is WordPress + the plugin dir).
22
- if (has("wp-config.php", "wp-content")) {
23
- if (has("wp-content/plugins/woocommerce", "wp-content/plugins/woocommerce/woocommerce.php")) {
24
- return "woocommerce";
25
- }
26
- return "wordpress";
27
- }
28
- // PrestaShop
29
- if (has("config/settings.inc.php", "app/config/parameters.php") && has("prestashop", "classes/PrestaShopAutoload.php")) {
30
- return "prestashop";
31
- }
32
- if (has("classes/PrestaShopAutoload.php"))
33
- return "prestashop";
34
- // Magento 2
35
- if (has("bin/magento", "app/etc/env.php") && has("app/etc/di.xml", "vendor/magento")) {
36
- return "magento2";
37
- }
38
- if (has("bin/magento"))
39
- return "magento2";
40
- // Drupal
41
- if (has("core/lib/Drupal.php"))
42
- return "drupal";
43
- // Joomla
44
- if (has("configuration.php") && has("libraries/joomla", "administrator/manifests")) {
45
- return "joomla";
46
- }
47
- // OpenCart
48
- if (has("system/startup.php") && has("catalog/controller"))
49
- return "opencart";
50
- return undefined;
51
- }
6
+ export { detectPlatform, PLATFORM_PLUGIN_HINT } from "@sealmetrics/setup-core";
52
7
  //# sourceMappingURL=cms.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cms.js","sourceRoot":"","sources":["../../src/detect/cms.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,yFAAyF;AACzF,MAAM,CAAC,MAAM,oBAAoB,GAA6B;IAC5D,WAAW,EACT,oGAAoG;IACtG,SAAS,EACP,kGAAkG;IACpG,UAAU,EACR,+FAA+F;IACjG,QAAQ,EACN,iGAAiG;IACnG,MAAM,EACJ,2FAA2F;IAC7F,MAAM,EACJ,2FAA2F;IAC7F,QAAQ,EACN,gGAAgG;CACnG,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,MAAM,GAAG,GAAG,CAAC,GAAG,GAAa,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5E,wDAAwD;IACxD,IAAI,GAAG,CAAC,eAAe,EAAE,YAAY,CAAC,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,gCAAgC,EAAE,gDAAgD,CAAC,EAAE,CAAC;YAC5F,OAAO,aAAa,CAAC;QACvB,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,aAAa;IACb,IAAI,GAAG,CAAC,yBAAyB,EAAE,2BAA2B,CAAC,IAAI,GAAG,CAAC,YAAY,EAAE,gCAAgC,CAAC,EAAE,CAAC;QACvH,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IAAI,GAAG,CAAC,gCAAgC,CAAC;QAAE,OAAO,YAAY,CAAC;IAE/D,YAAY;IACZ,IAAI,GAAG,CAAC,aAAa,EAAE,iBAAiB,CAAC,IAAI,GAAG,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACrF,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,GAAG,CAAC,aAAa,CAAC;QAAE,OAAO,UAAU,CAAC;IAE1C,SAAS;IACT,IAAI,GAAG,CAAC,qBAAqB,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEhD,SAAS;IACT,IAAI,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,kBAAkB,EAAE,yBAAyB,CAAC,EAAE,CAAC;QACnF,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,WAAW;IACX,IAAI,GAAG,CAAC,oBAAoB,CAAC,IAAI,GAAG,CAAC,oBAAoB,CAAC;QAAE,OAAO,UAAU,CAAC;IAE9E,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"cms.js","sourceRoot":"","sources":["../../src/detect/cms.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,5 +1,8 @@
1
- import type { Detection } from "../types.js";
2
- export declare function detect(cwd: string, opts?: {
3
- noInject?: boolean;
4
- }): Detection;
1
+ /**
2
+ * Project detection (Bloque 3). The detection logic now lives in
3
+ * `@sealmetrics/setup-core` (shared with the MCP write-path, RF-3102) and is
4
+ * re-exported here so the rest of the CLI keeps importing `detect` from
5
+ * `./index.js` unchanged. Read-only, best-effort, conservative — see setup-core.
6
+ */
7
+ export { detect, detectFramework } from "@sealmetrics/setup-core";
5
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detect/index.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAC;AAyDlE,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CA6B5E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/detect/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,155 +1,8 @@
1
1
  /**
2
- * Project detection (Bloque 3). Read-only (RF-1003): classifies the project by
3
- * reading markers (package.json deps/scripts, config files, tree) and maps it to
4
- * an *informative* recommended snippet location (RF-302). The CLI never writes
5
- * to that location — it only tells the agent/human where the snippet goes.
6
- *
7
- * Best-effort and conservative (VAL-301): when in doubt it returns `unknown`
8
- * and falls back to the manual path rather than guessing wrong.
2
+ * Project detection (Bloque 3). The detection logic now lives in
3
+ * `@sealmetrics/setup-core` (shared with the MCP write-path, RF-3102) and is
4
+ * re-exported here so the rest of the CLI keeps importing `detect` from
5
+ * `./index.js` unchanged. Read-only, best-effort, conservative see setup-core.
9
6
  */
10
- import { existsSync, readFileSync, readdirSync } from "node:fs";
11
- import { join } from "node:path";
12
- import { detectPlatform } from "./cms.js";
13
- const LOCATIONS = {
14
- "next-app": {
15
- location: "app/layout.tsx",
16
- hint: "inside <head>, or via a next/script <Script> component",
17
- strategy: "next-app-router-layout",
18
- },
19
- "next-pages": {
20
- location: "pages/_document.tsx",
21
- hint: "inside <Head> in _document (or pages/_app.tsx)",
22
- strategy: "next-pages-document",
23
- },
24
- astro: {
25
- location: "src/layouts/Layout.astro",
26
- hint: "inside <head> of your root layout",
27
- strategy: "astro-layout-head",
28
- },
29
- remix: {
30
- location: "app/root.tsx",
31
- hint: "inside the <head> region of the root route",
32
- strategy: "remix-root-head",
33
- },
34
- nuxt: {
35
- location: "nuxt.config.ts",
36
- hint: "in app.head.script (or app.vue <head>)",
37
- strategy: "nuxt-config-head",
38
- },
39
- sveltekit: {
40
- location: "src/app.html",
41
- hint: "inside <head>, above %sveltekit.head%",
42
- strategy: "sveltekit-app-html",
43
- },
44
- vite: {
45
- location: "index.html",
46
- hint: "just before </head>",
47
- strategy: "vite-index-html",
48
- },
49
- html: {
50
- location: "index.html",
51
- hint: "just before </head>",
52
- strategy: "static-html-head",
53
- },
54
- unknown: {
55
- location: "your site's root HTML / <head>",
56
- hint: "just before the closing </head> tag on every page",
57
- strategy: "manual",
58
- },
59
- };
60
- export function detect(cwd, opts) {
61
- // RF-304: provision-only when forced or when there's nothing to place into.
62
- if (opts?.noInject) {
63
- return makeDetection("unknown", { provisionOnly: true });
64
- }
65
- const platform = detectPlatform(cwd);
66
- if (platform) {
67
- // RF-305/306: CMS with an official plugin — do NOT edit PHP/theme files.
68
- return makeDetection("unknown", { platform, provisionOnly: false });
69
- }
70
- const pkg = readPackageJson(cwd);
71
- if (pkg) {
72
- const fw = detectFromPackageJson(cwd, pkg);
73
- return makeDetection(fw, { provisionOnly: false });
74
- }
75
- // No package.json — a static site if there's an index.html, else nothing to place into.
76
- if (findIndexHtml(cwd)) {
77
- return makeDetection("html", { provisionOnly: false });
78
- }
79
- if (isEmptyish(cwd)) {
80
- return makeDetection("unknown", { provisionOnly: true });
81
- }
82
- // There IS a repo but we don't recognise it (RF-303): manual, not provision-only.
83
- return makeDetection("unknown", { provisionOnly: false });
84
- }
85
- function detectFromPackageJson(cwd, pkg) {
86
- const deps = { ...pkg.dependencies, ...pkg.devDependencies };
87
- const has = (name) => Object.prototype.hasOwnProperty.call(deps, name);
88
- if (has("next")) {
89
- return hasAppRouter(cwd) ? "next-app" : "next-pages";
90
- }
91
- if (has("astro"))
92
- return "astro";
93
- if (has("@remix-run/react") || has("@remix-run/node") || has("@remix-run/serve"))
94
- return "remix";
95
- if (has("nuxt") || has("nuxt3") || has("nuxt-edge"))
96
- return "nuxt";
97
- if (has("@sveltejs/kit"))
98
- return "sveltekit";
99
- if (has("vite"))
100
- return "vite";
101
- // A package.json with none of the markers but an index.html → treat as static.
102
- if (findIndexHtml(cwd))
103
- return "html";
104
- return "unknown";
105
- }
106
- function hasAppRouter(cwd) {
107
- // App router if app/ exists (and is preferred); fall back to pages/.
108
- const appDirs = ["app", "src/app"];
109
- const pagesDirs = ["pages", "src/pages"];
110
- const hasApp = appDirs.some((d) => existsSync(join(cwd, d)));
111
- const hasPages = pagesDirs.some((d) => existsSync(join(cwd, d)));
112
- if (hasApp)
113
- return true;
114
- if (hasPages)
115
- return false;
116
- // Default for modern Next.js is the app router.
117
- return true;
118
- }
119
- function readPackageJson(cwd) {
120
- const p = join(cwd, "package.json");
121
- if (!existsSync(p))
122
- return null;
123
- try {
124
- return JSON.parse(readFileSync(p, "utf8"));
125
- }
126
- catch {
127
- return null;
128
- }
129
- }
130
- function findIndexHtml(cwd) {
131
- return ["index.html", "public/index.html", "src/index.html"].some((f) => existsSync(join(cwd, f)));
132
- }
133
- function isEmptyish(cwd) {
134
- try {
135
- const entries = readdirSync(cwd).filter((e) => !e.startsWith(".") && e !== "seal.config.json");
136
- return entries.length === 0;
137
- }
138
- catch {
139
- return true;
140
- }
141
- }
142
- function makeDetection(framework, extra) {
143
- const loc = LOCATIONS[framework];
144
- const detection = {
145
- framework,
146
- strategy: extra.platform ? `cms-plugin-${extra.platform}` : loc.strategy,
147
- recommendedLocation: loc.location,
148
- placementHint: loc.hint,
149
- provisionOnly: extra.provisionOnly,
150
- };
151
- if (extra.platform)
152
- detection.platform = extra.platform;
153
- return detection;
154
- }
7
+ export { detect, detectFramework } from "@sealmetrics/setup-core";
155
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detect/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/detect/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/handoff/install.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAiC7C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CA+CxE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CA2DT"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/handoff/install.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAgC7C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CA+CxE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,MAAM,CAmET"}
@@ -7,8 +7,8 @@
7
7
  */
8
8
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
9
9
  import { join } from "node:path";
10
+ import { getStackGuide, PLATFORM_PLUGIN_HINT } from "@sealmetrics/setup-core";
10
11
  import { SNIPPET_MARKER } from "../embedded.js";
11
- import { PLATFORM_PLUGIN_HINT } from "../detect/cms.js";
12
12
  const SKIP_DIRS = new Set([
13
13
  "node_modules",
14
14
  ".git",
@@ -105,11 +105,18 @@ export function isSnippetPresent(cwd, accountId) {
105
105
  */
106
106
  export function buildInstallMarkdown(args) {
107
107
  const { snippet, accountId, detection, dashboardUrl } = args;
108
+ // Framework-specific loading knowledge (RF-3501) — single source: setup-core.
109
+ const stackNotes = detection.platform
110
+ ? ""
111
+ : `\n\n**${detection.framework} — how to load it correctly:**\n` +
112
+ getStackGuide(detection.framework)
113
+ .notes.map((n) => `- ${n}`)
114
+ .join("\n");
108
115
  const placement = detection.platform
109
116
  ? `**Platform detected: ${detection.platform}.** ${PLATFORM_PLUGIN_HINT[detection.platform]}\n\n` +
110
117
  `Do **not** paste the snippet into theme files by hand — the official plugin is the supported path.`
111
118
  : `**Recommended location:** \`${detection.recommendedLocation}\` — ${detection.placementHint}.\n\n` +
112
- `Place the snippet there so it loads on **every** page. The CLI did not edit any source file; you (or your agent) place it.`;
119
+ `Place the snippet there so it loads on **every** page. The CLI did not edit any source file; you (or your agent) place it.${stackNotes}`;
113
120
  return `${SNIPPET_MARKER}
114
121
  # Install SealMetrics tracking
115
122
 
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/handoff/install.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,cAAc;IACd,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,aAAa;IACb,OAAO;IACP,QAAQ;IACR,UAAU;IACV,cAAc;CACf,CAAC,CAAC;AAEH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,OAAO;IACP,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,KAAK;IACL,QAAQ;IACR,MAAM;IACN,SAAS;IACT,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,SAAiB;IAC7D,MAAM,QAAQ,GAAG,WAAW,SAAS,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,KAAa,EAAQ,EAAE;QAChD,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO;QAC/B,IAAI,OAAiB,CAAC;QACtB,IAAI,CAAC;YACH,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,KAAK;gBAAE,OAAO;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,IAAI,EAAE,CAAC;YACP,IAAI,CAAC;gBACH,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAClC,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACxB,CAAC;iBAAM,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC9C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;oBAAE,SAAS;gBACxC,IAAI,EAAE,CAAC,IAAI,GAAG,SAAS;oBAAE,SAAS;gBAClC,IAAI,OAAe,CAAC;gBACpB,IAAI,CAAC;oBACH,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;gBACvC,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;gBACD,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC9F,KAAK,GAAG,IAAI,CAAC;oBACb,OAAO;gBACT,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACb,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAKpC;IACC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;IAE7D,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ;QAClC,CAAC,CAAC,wBAAwB,SAAS,CAAC,QAAQ,OAAO,oBAAoB,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM;YAC/F,oGAAoG;QACtG,CAAC,CAAC,+BAA+B,SAAS,CAAC,mBAAmB,QAAQ,SAAS,CAAC,aAAa,OAAO;YAClG,4HAA4H,CAAC;IAEjI,OAAO,GAAG,cAAc;;;gBAGV,SAAS;aACZ,YAAY;;;;;;;EAOvB,OAAO;;;EAGP,SAAS;;;;;;;;;iBASM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BzB,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/handoff/install.ts"],"names":[],"mappings":"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"}