@native-marketing/sdk 0.3.6 → 0.3.7
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/dist/http.js +270 -25
- package/dist/index.js +854 -53
- package/package.json +11 -1
- package/release.json +2 -2
- package/types/contracts/client-lifecycle.d.ts +55 -0
- package/types/contracts/client-update-policy.d.ts +84 -0
- package/types/contracts/generated/client-release.d.ts +14 -0
- package/types/contracts/index.d.ts +2 -0
- package/types/http/client-version.d.ts +35 -0
- package/types/http/client.d.ts +1 -0
- package/types/http/index.d.ts +2 -0
- package/types/sdk/capability-definition.d.ts +1 -0
- package/types/sdk/cli/run.d.ts +1 -0
- package/types/sdk/client.d.ts +5 -0
- package/types/sdk/index.d.ts +3 -0
- package/types/sdk/transport.d.ts +6 -1
- package/types/sdk/updates/commands.d.ts +11 -0
- package/types/sdk/updates/install.d.ts +20 -0
- package/types/sdk/updates/registry.d.ts +26 -0
- package/types/sdk/updates/store.d.ts +14 -0
- package/types/sdk/updates/version.d.ts +93 -0
package/dist/http.js
CHANGED
|
@@ -66,31 +66,6 @@ function guardHttpMethods(client, validate) {
|
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// packages/api-client/src/client.ts
|
|
70
|
-
function createContentFactoryClient(options = {}) {
|
|
71
|
-
const baseUrl = options.baseUrl ?? "/api/v1";
|
|
72
|
-
const policy = httpRequestPolicy(
|
|
73
|
-
baseUrl,
|
|
74
|
-
options.fetch ?? ((request) => globalThis.fetch(request))
|
|
75
|
-
);
|
|
76
|
-
const client = createClient({
|
|
77
|
-
baseUrl,
|
|
78
|
-
credentials: "include",
|
|
79
|
-
redirect: "error",
|
|
80
|
-
fetch: policy.fetch
|
|
81
|
-
});
|
|
82
|
-
client.use({
|
|
83
|
-
onRequest({ request }) {
|
|
84
|
-
if (!["POST", "DELETE"].includes(request.method) || request.body !== null) return request;
|
|
85
|
-
const headers = new Headers(request.headers);
|
|
86
|
-
headers.set("content-type", "application/json");
|
|
87
|
-
headers.delete("content-length");
|
|
88
|
-
return new Request(request, { headers, body: "{}" });
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
return guardHttpMethods(client, policy.validateInit);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
69
|
// packages/contracts/src/business-code.ts
|
|
95
70
|
import { z } from "zod";
|
|
96
71
|
var businessCodeKindSchema = z.enum([
|
|
@@ -686,6 +661,175 @@ function readingDocument(content) {
|
|
|
686
661
|
return { body, title };
|
|
687
662
|
}
|
|
688
663
|
|
|
664
|
+
// packages/contracts/src/client-lifecycle.ts
|
|
665
|
+
import { z as z5 } from "zod";
|
|
666
|
+
|
|
667
|
+
// packages/contracts/src/generated/client-release.ts
|
|
668
|
+
var nativeClientRelease = {
|
|
669
|
+
schemaVersion: 1,
|
|
670
|
+
product: "native-marketing",
|
|
671
|
+
version: "0.3.7",
|
|
672
|
+
packages: {
|
|
673
|
+
sdk: "@native-marketing/sdk",
|
|
674
|
+
cli: "@native-marketing/cli"
|
|
675
|
+
},
|
|
676
|
+
contractVersion: 1,
|
|
677
|
+
minimumClientVersion: "0.3.6",
|
|
678
|
+
apiMajor: 1,
|
|
679
|
+
nodeMajor: 24,
|
|
680
|
+
changes: [
|
|
681
|
+
"Unified SDK, CLI and MCP release discovery and compatibility checks.",
|
|
682
|
+
"Configurable CLI update notifications, pins and compatible automatic updates.",
|
|
683
|
+
"Upgrade verification and explicit continuation without replaying business commands."
|
|
684
|
+
]
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
// packages/contracts/src/client-lifecycle.ts
|
|
688
|
+
var releaseVersionSchema = z5.string().max(128).regex(
|
|
689
|
+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/
|
|
690
|
+
);
|
|
691
|
+
var clientIdentitySchema = z5.object({
|
|
692
|
+
version: releaseVersionSchema,
|
|
693
|
+
contractVersion: z5.number().int().positive(),
|
|
694
|
+
apiMajor: z5.number().int().positive()
|
|
695
|
+
});
|
|
696
|
+
var clientReleaseSchema = z5.object({
|
|
697
|
+
schemaVersion: z5.literal(1),
|
|
698
|
+
product: z5.literal("native-marketing"),
|
|
699
|
+
version: releaseVersionSchema,
|
|
700
|
+
packages: z5.object({
|
|
701
|
+
sdk: z5.literal("@native-marketing/sdk"),
|
|
702
|
+
cli: z5.literal("@native-marketing/cli")
|
|
703
|
+
}),
|
|
704
|
+
contractVersion: z5.number().int().positive(),
|
|
705
|
+
minimumClientVersion: releaseVersionSchema,
|
|
706
|
+
apiMajor: z5.number().int().positive(),
|
|
707
|
+
nodeMajor: z5.number().int().positive(),
|
|
708
|
+
changes: z5.array(z5.string().min(1).max(240)).max(8).default([])
|
|
709
|
+
});
|
|
710
|
+
var updatePolicySchema = z5.object({
|
|
711
|
+
mode: z5.enum(["off", "notify", "auto"]).default("notify"),
|
|
712
|
+
channel: z5.enum(["latest", "next", "beta"]).default("latest"),
|
|
713
|
+
pin: releaseVersionSchema.nullable().default(null),
|
|
714
|
+
intervalHours: z5.number().int().min(1).max(168).default(24)
|
|
715
|
+
}).strict();
|
|
716
|
+
var defaultUpdatePolicy = updatePolicySchema.parse({});
|
|
717
|
+
function compareReleaseVersions(left, right) {
|
|
718
|
+
const parse = (raw) => releaseVersionSchema.parse(raw).split("+")[0].split(/-(.*)/s);
|
|
719
|
+
const a = parse(left), b = parse(right);
|
|
720
|
+
const numbers = (x, y) => BigInt(x) < BigInt(y) ? -1 : BigInt(x) > BigInt(y) ? 1 : 0;
|
|
721
|
+
const ac = a[0].split("."), bc = b[0].split(".");
|
|
722
|
+
for (let i = 0; i < 3; i++) {
|
|
723
|
+
const order = numbers(ac[i], bc[i]);
|
|
724
|
+
if (order) return order;
|
|
725
|
+
}
|
|
726
|
+
if (a[1] === b[1]) return 0;
|
|
727
|
+
if (!a[1] || !b[1]) return a[1] ? -1 : 1;
|
|
728
|
+
const ap = a[1].split("."), bp = b[1].split(".");
|
|
729
|
+
for (let i = 0; i < Math.max(ap.length, bp.length); i++) {
|
|
730
|
+
const x = ap[i], y = bp[i];
|
|
731
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
732
|
+
if (x === y) continue;
|
|
733
|
+
const xn = /^\d+$/.test(x), yn = /^\d+$/.test(y);
|
|
734
|
+
return xn && yn ? numbers(x, y) : xn !== yn ? xn ? -1 : 1 : x < y ? -1 : 1;
|
|
735
|
+
}
|
|
736
|
+
return 0;
|
|
737
|
+
}
|
|
738
|
+
function assessNativeCompatibility(client, server) {
|
|
739
|
+
client = clientIdentitySchema.parse(client);
|
|
740
|
+
const result = (status, reason) => ({ status, reason, client, server: server ?? null });
|
|
741
|
+
if (!server) return result("UNKNOWN", "SERVER_METADATA_UNAVAILABLE");
|
|
742
|
+
server = clientReleaseSchema.parse(server);
|
|
743
|
+
if (client.contractVersion !== server.contractVersion)
|
|
744
|
+
return result("INCOMPATIBLE", "CONTRACT_MISMATCH");
|
|
745
|
+
if (client.apiMajor !== server.apiMajor) return result("INCOMPATIBLE", "API_MISMATCH");
|
|
746
|
+
if (compareReleaseVersions(client.version, server.minimumClientVersion) < 0)
|
|
747
|
+
return result("INCOMPATIBLE", "CLIENT_TOO_OLD");
|
|
748
|
+
return compareReleaseVersions(client.version, server.version) < 0 ? result("UPGRADE_RECOMMENDED", "NEWER_CLIENT_AVAILABLE") : result("COMPATIBLE", "CURRENT");
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
// packages/contracts/src/client-update-policy.ts
|
|
752
|
+
import { z as z6 } from "zod";
|
|
753
|
+
var registryReleaseSchema = z6.object({
|
|
754
|
+
name: z6.enum(["@native-marketing/sdk", "@native-marketing/cli"]),
|
|
755
|
+
version: releaseVersionSchema,
|
|
756
|
+
deprecated: z6.string().optional(),
|
|
757
|
+
nativeMarketing: z6.object({
|
|
758
|
+
contractVersion: z6.number().int().positive(),
|
|
759
|
+
apiMajor: z6.number().int().positive(),
|
|
760
|
+
nodeMajor: z6.number().int().positive(),
|
|
761
|
+
changes: z6.array(z6.string().min(1).max(240)).max(8).optional()
|
|
762
|
+
}).optional(),
|
|
763
|
+
dist: z6.object({
|
|
764
|
+
integrity: z6.string().max(512).regex(/^sha512-[A-Za-z0-9+/]{86}==$/)
|
|
765
|
+
})
|
|
766
|
+
});
|
|
767
|
+
var clientUpdateStateSchema = z6.object({
|
|
768
|
+
schemaVersion: z6.literal(1),
|
|
769
|
+
policy: updatePolicySchema,
|
|
770
|
+
lastCheck: z6.object({
|
|
771
|
+
at: z6.number().int().nonnegative(),
|
|
772
|
+
selector: z6.string().max(160),
|
|
773
|
+
target: registryReleaseSchema
|
|
774
|
+
}).strict().optional(),
|
|
775
|
+
lastAttempt: z6.object({ at: z6.number().int().nonnegative(), selector: z6.string().max(160) }).strict().optional()
|
|
776
|
+
}).strict();
|
|
777
|
+
function planNativeUpdate(input) {
|
|
778
|
+
const target = registryReleaseSchema.parse(input.target);
|
|
779
|
+
const current = releaseVersionSchema.parse(input.currentVersion ?? nativeClientRelease.version);
|
|
780
|
+
const policy = updatePolicySchema.parse(input.policy ?? {});
|
|
781
|
+
const spec = `${target.name}@${target.version}`;
|
|
782
|
+
const cli = target.name === nativeClientRelease.packages.cli;
|
|
783
|
+
const result = (status, reason, eligible = false) => ({
|
|
784
|
+
package: target.name,
|
|
785
|
+
currentVersion: current,
|
|
786
|
+
targetVersion: target.version,
|
|
787
|
+
status,
|
|
788
|
+
reason,
|
|
789
|
+
eligibleForAutoUpdate: eligible,
|
|
790
|
+
policy,
|
|
791
|
+
commands: {
|
|
792
|
+
npm: [
|
|
793
|
+
"npm",
|
|
794
|
+
"install",
|
|
795
|
+
...cli ? ["--global"] : ["--save-exact"],
|
|
796
|
+
spec,
|
|
797
|
+
"--ignore-scripts",
|
|
798
|
+
"--registry=https://registry.npmjs.org/",
|
|
799
|
+
"--@native-marketing:registry=https://registry.npmjs.org/"
|
|
800
|
+
],
|
|
801
|
+
pnpm: ["pnpm", "add", ...cli ? ["--global"] : ["--save-exact"], spec, "--ignore-scripts"],
|
|
802
|
+
yarn: cli ? null : ["yarn", "add", "--exact", spec]
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
if (policy.pin && policy.pin !== target.version) return result("BLOCKED", "PIN_MISMATCH");
|
|
806
|
+
if (!policy.pin && policy.channel === "latest" && target.version.split("+")[0].includes("-"))
|
|
807
|
+
return result("BLOCKED", "CHANNEL_MISMATCH");
|
|
808
|
+
const order = compareReleaseVersions(target.version, current);
|
|
809
|
+
if (order < 0) return result("BLOCKED", "DOWNGRADE_FORBIDDEN");
|
|
810
|
+
if (target.deprecated !== void 0) return result("BLOCKED", "DEPRECATED");
|
|
811
|
+
if (!target.nativeMarketing) return result("BLOCKED", "METADATA_UNAVAILABLE");
|
|
812
|
+
const metadata = target.nativeMarketing;
|
|
813
|
+
if (metadata.nodeMajor !== (input.nodeMajor ?? nativeClientRelease.nodeMajor))
|
|
814
|
+
return result("BLOCKED", "NODE_MISMATCH");
|
|
815
|
+
if (metadata.contractVersion !== nativeClientRelease.contractVersion || metadata.apiMajor !== nativeClientRelease.apiMajor)
|
|
816
|
+
return result("BLOCKED", "CONTRACT_MISMATCH");
|
|
817
|
+
if (input.server && assessNativeCompatibility(
|
|
818
|
+
{
|
|
819
|
+
version: target.version,
|
|
820
|
+
contractVersion: metadata.contractVersion,
|
|
821
|
+
apiMajor: metadata.apiMajor
|
|
822
|
+
},
|
|
823
|
+
input.server
|
|
824
|
+
).status === "INCOMPATIBLE")
|
|
825
|
+
return result("BLOCKED", "SERVER_INCOMPATIBLE");
|
|
826
|
+
if (order === 0) return result("CURRENT", "CURRENT");
|
|
827
|
+
const from = current.split(/[.+-]/), to = target.version.split(/[.+-]/);
|
|
828
|
+
const compatibleLine = from[0] === to[0] && (from[0] !== "0" || from[1] === to[1]);
|
|
829
|
+
const stable = !current.split("+")[0].includes("-") && !target.version.split("+")[0].includes("-");
|
|
830
|
+
return compatibleLine && stable ? result("UPDATE_AVAILABLE", "COMPATIBLE_UPDATE", true) : result("UPDATE_AVAILABLE", "REVIEW_REQUIRED");
|
|
831
|
+
}
|
|
832
|
+
|
|
689
833
|
// packages/api-client/src/errors.ts
|
|
690
834
|
var ApiClientError = class extends Error {
|
|
691
835
|
constructor(status, code, message, requestId) {
|
|
@@ -710,6 +854,102 @@ function requireApiData(result) {
|
|
|
710
854
|
);
|
|
711
855
|
}
|
|
712
856
|
|
|
857
|
+
// packages/api-client/src/client-version.ts
|
|
858
|
+
function getNativeClientVersion() {
|
|
859
|
+
return clientReleaseSchema.parse(nativeClientRelease);
|
|
860
|
+
}
|
|
861
|
+
async function checkNativeHttpVersion(options = {}) {
|
|
862
|
+
const base = options.baseUrl ?? "/api/v1";
|
|
863
|
+
const policy = httpRequestPolicy(base, options.fetch ?? ((request) => fetch(request)));
|
|
864
|
+
const timeout = options.timeoutMs ?? 5e3;
|
|
865
|
+
if (!Number.isInteger(timeout) || timeout < 100 || timeout > 12e4)
|
|
866
|
+
throw new TypeError("Timeout must be 100\u2013120000 milliseconds.");
|
|
867
|
+
const endpoint = new URL(
|
|
868
|
+
`${base.replace(/\/+$/, "")}/client-release`,
|
|
869
|
+
globalThis.location?.origin
|
|
870
|
+
);
|
|
871
|
+
let server;
|
|
872
|
+
try {
|
|
873
|
+
const response = await policy.fetch(
|
|
874
|
+
new Request(endpoint, {
|
|
875
|
+
credentials: "omit",
|
|
876
|
+
redirect: "error",
|
|
877
|
+
signal: AbortSignal.timeout(timeout)
|
|
878
|
+
})
|
|
879
|
+
);
|
|
880
|
+
if (response.status !== 404) {
|
|
881
|
+
if (!response.ok || !response.body) throw new Error();
|
|
882
|
+
const reader = response.body.getReader();
|
|
883
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
884
|
+
let size = 0, raw = "";
|
|
885
|
+
try {
|
|
886
|
+
for (; ; ) {
|
|
887
|
+
const { value, done } = await reader.read();
|
|
888
|
+
if (done) break;
|
|
889
|
+
size += value.byteLength;
|
|
890
|
+
if (size > 32 * 1024) throw new Error();
|
|
891
|
+
raw += decoder.decode(value, { stream: true });
|
|
892
|
+
}
|
|
893
|
+
raw += decoder.decode();
|
|
894
|
+
} finally {
|
|
895
|
+
await reader.cancel().catch(() => void 0);
|
|
896
|
+
reader.releaseLock();
|
|
897
|
+
}
|
|
898
|
+
server = clientReleaseSchema.parse(JSON.parse(raw));
|
|
899
|
+
}
|
|
900
|
+
} catch {
|
|
901
|
+
throw new ApiClientError(
|
|
902
|
+
0,
|
|
903
|
+
"VERSION_CHECK_UNAVAILABLE",
|
|
904
|
+
"Cannot verify the configured service release."
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
const compatibility = assessNativeCompatibility(nativeClientRelease, server);
|
|
908
|
+
if (compatibility.status === "INCOMPATIBLE" || options.requireCompatibility && compatibility.status === "UNKNOWN")
|
|
909
|
+
throw new ApiClientError(
|
|
910
|
+
0,
|
|
911
|
+
"CLIENT_INCOMPATIBLE",
|
|
912
|
+
"The client cannot confirm compatibility with this service."
|
|
913
|
+
);
|
|
914
|
+
return { client: getNativeClientVersion(), compatibility };
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// packages/api-client/src/client.ts
|
|
918
|
+
function createContentFactoryClient(options = {}) {
|
|
919
|
+
const baseUrl = options.baseUrl ?? "/api/v1";
|
|
920
|
+
const policy = httpRequestPolicy(
|
|
921
|
+
baseUrl,
|
|
922
|
+
options.fetch ?? ((request) => globalThis.fetch(request))
|
|
923
|
+
);
|
|
924
|
+
let versionCheck;
|
|
925
|
+
const client = createClient({
|
|
926
|
+
baseUrl,
|
|
927
|
+
credentials: "include",
|
|
928
|
+
redirect: "error",
|
|
929
|
+
fetch: async (request) => {
|
|
930
|
+
if (options.compatibility) {
|
|
931
|
+
versionCheck ??= checkNativeHttpVersion({
|
|
932
|
+
baseUrl,
|
|
933
|
+
...options.fetch ? { fetch: options.fetch } : {},
|
|
934
|
+
requireCompatibility: options.compatibility === "require"
|
|
935
|
+
});
|
|
936
|
+
await versionCheck;
|
|
937
|
+
}
|
|
938
|
+
return policy.fetch(request);
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
client.use({
|
|
942
|
+
onRequest({ request }) {
|
|
943
|
+
if (!["POST", "DELETE"].includes(request.method) || request.body !== null) return request;
|
|
944
|
+
const headers = new Headers(request.headers);
|
|
945
|
+
headers.set("content-type", "application/json");
|
|
946
|
+
headers.delete("content-length");
|
|
947
|
+
return new Request(request, { headers, body: "{}" });
|
|
948
|
+
}
|
|
949
|
+
});
|
|
950
|
+
return guardHttpMethods(client, policy.validateInit);
|
|
951
|
+
}
|
|
952
|
+
|
|
713
953
|
// packages/api-client/src/personal-survey.ts
|
|
714
954
|
var personalSurveyInputLimits = {
|
|
715
955
|
professionalIdentity: 2e3,
|
|
@@ -1320,9 +1560,13 @@ function suggestProjectKey(name) {
|
|
|
1320
1560
|
}
|
|
1321
1561
|
export {
|
|
1322
1562
|
ApiClientError,
|
|
1563
|
+
assessNativeCompatibility,
|
|
1564
|
+
checkNativeHttpVersion,
|
|
1323
1565
|
contentProgramInputLimits,
|
|
1324
1566
|
createContentFactoryClient,
|
|
1567
|
+
defaultUpdatePolicy,
|
|
1325
1568
|
distributionDestinationInputLimits,
|
|
1569
|
+
getNativeClientVersion,
|
|
1326
1570
|
humanActionInputLimits,
|
|
1327
1571
|
matchesHumanRequirementMedia,
|
|
1328
1572
|
mediaInputLimits,
|
|
@@ -1330,6 +1574,7 @@ export {
|
|
|
1330
1574
|
personalIpDefinitionInputLimits,
|
|
1331
1575
|
personalSurveyInputLimits,
|
|
1332
1576
|
personalSurveyToResponses,
|
|
1577
|
+
planNativeUpdate,
|
|
1333
1578
|
programActivationRequirements,
|
|
1334
1579
|
programGoalMetricDefinitions,
|
|
1335
1580
|
publicationInputLimits,
|