@snowplow/snowtype
Version:
A code generator CLI for faster and type-safe Snowplow tracking code
117 lines (93 loc) • 49.9 kB
JavaScript
;var di=Object.create;var he=Object.defineProperty;var li=Object.getOwnPropertyDescriptor;var gi=Object.getOwnPropertyNames;var mi=Object.getPrototypeOf,fi=Object.prototype.hasOwnProperty;var hi=(t,e,n,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of gi(e))!fi.call(t,o)&&o!==n&&he(t,o,{get:()=>e[o],enumerable:!(i=li(e,o))||i.enumerable});return t};var h=(t,e,n)=>(n=t!=null?di(mi(t)):{},hi(e||!t||!t.__esModule?he(n,"default",{value:t,enumerable:!0}):n,t));var qn=h(require("process")),$=require("@commander-js/extra-typings");var Si={AuthError:"Authentication failed. Check if your API key and organization ID are correct.",ConfigAlreadyExists:"Snowtype config file already exists.",ConfigNotExists:"Snowtype config file does not exist in current directory. Start with running 'init'.",ConfigInvalid:"Snowtype config exists but it is invalid.",InternalError:"An internal error occured.",InvalidOption:"Invalid option provided.",MissingOptions:"Action called with no options.",WriteLockFile:"Failed writing lock file.",ReadLockFile:"Lock file is invalid or corrupted. Please recover it or delete it, and run `snowtype generate` so a new one will be created.",GenerationFailed:"Something went wrong with code generation.",PatchingNotSupported:"Patching is only supported using a Snowtype config file in JSON format.",DevNotAllowed:"Code generation using schemas in DEV environment not allowed. Publish the schemas and retry.",AuthCredentialsMissing:"Required API key credentials not detected. Please refer to https://docs.snowplow.io/docs/collecting-data/code-generation/using-the-cli/#authenticating-with-the-console"},vi="Please report a bug.",y=class extends Error{code;constructor(e,n=""){let i=Si[e].concat(n);super(i),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=e}},ut=class extends y{constructor(){super("GenerationFailed")}},tt=class extends y{constructor(){super("ConfigAlreadyExists")}},dt=class extends y{constructor(){super("ConfigNotExists")}},lt=class extends y{constructor(e){super("ConfigInvalid",e)}},gt=class extends y{constructor(e){super("InternalError",e.concat(vi))}},B=class extends y{constructor(e,n){let i=`Value ${n} is an invalid ${e}.`;super("InvalidOption",i)}},mt=class extends y{constructor(){super("MissingOptions")}},O=class extends y{constructor(){super("AuthError")}},H=class extends y{constructor(){super("WriteLockFile")}},ft=class extends y{constructor(e){super("ReadLockFile",` ${e}`)}},ht=class extends y{constructor(){super("PatchingNotSupported")}},St=class extends y{constructor(){super("DevNotAllowed")}},vt=class extends y{constructor(){super("AuthCredentialsMissing")}};var Se=h(require("got"));async function ve({schema:t}){return(await(0,Se.default)(`https://raw.githubusercontent.com/snowplow/iglu-central/master/schemas/${t.replace("iglu:","")}`)).body}var rt=h(require("got"));var xe=require("js-sha256"),Gt=h(require("node:assert"));var u=h(require("joi")),Et=require("@snowplow/snowtype-core");var Ut=h(require("node:assert"));var et="snowtype.config",yt=".js",wt=".ts",It=".json",ye=Object.freeze([yt,wt,It]),J=".snowtype-lock.json",_t="snowplow";var nt={"google-tag-manager":[{value:"javascript-gtm",name:"JavaScript"}],"@snowplow/javascript-tracker":[{value:"javascript",name:"JavaScript"}],"@snowplow/browser-tracker":[{value:"javascript",name:"JavaScript"},{value:"typescript",name:"TypeScript"}],"@snowplow/node-tracker":[{value:"javascript",name:"JavaScript"},{value:"typescript",name:"TypeScript"}],"snowplow-android-tracker":[{value:"kotlin",name:"Kotlin"}],"snowplow-ios-tracker":[{value:"swift",name:"Swift"}],"snowplow-golang-tracker":[{value:"go",name:"Go"}],"@snowplow/react-native-tracker":[{value:"typescript",name:"TypeScript"}],"snowplow-flutter-tracker":[{value:"dart",name:"Dart"}],"snowplow-java-tracker":[{value:"java",name:"Java"}]},we={commands:{generate:{instructions:!1,validations:!1,disallowDevSchemas:!1,deprecateOnlyOnProdAvailableUpdates:!1},update:{maximumBump:"major",showOnlyProdUpdates:!1,regenerateOnUpdate:!1},patch:{regenerateOnPatch:!1}}},Ie=["iglu:com.snowplowanalytics.snowplow/page_ping/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/link_click/jsonschema/1-0-1","iglu:com.snowplowanalytics.snowplow/page_view/jsonschema/1-0-0","iglu:com.snowplowanalytics.mobile/screen_view/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/button_click/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/application_background/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/application_foreground/jsonschema/1-0-0","iglu:com.snowplowanalytics.mobile/application_install/jsonschema/1-0-0","iglu:com.snowplowanalytics.mobile/screen_end/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/custom_event/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/expose_element/jsonschema/1-0-0","iglu:com.snowplowanalytics.snowplow/create_element/jsonschema/1-0-0"],Ee="iglu:com.snowplowanalytics.snowplow.ecommerce";var Pt=require("lodash");function Ce(t){let e=t.split("-");(0,Ut.default)(e.length===3,"invalid SchemaVer"),(0,Ut.default)(e.filter(n=>isNaN(parseInt(n))).length===0,"invalid SchemaVer")}function k(t){t.options=(0,Pt.merge)((0,Pt.cloneDeep)(we),t.options||{})}var Pe=new RegExp("^iglu:[a-zA-Z0-9-_.]+/[a-zA-Z0-9-_]+/[a-zA-Z0-9-_]+/[0-9]+-[0-9]+-[0-9]+$"),yi=new RegExp("^[A-Z][a-zA-Z0-9]*$"),wi=u.default.object().required().keys({tracker:u.default.string().required().valid(...Et.trackerTemplates),language:u.default.string().required().valid(...Et.languageIds),outpath:u.default.string().required(),namespace:u.default.when("language",{is:"swift",then:u.default.string().regex(yi).optional(),otherwise:u.default.forbidden().messages({"any.unknown":"namespace is only supported for 'swift' language"})}),organizationId:u.default.string().when("dataStructures",{is:u.default.array().min(1),then:u.default.required(),otherwise:u.default.optional()}).when("eventSpecificationIds",{is:u.default.array().min(1),then:u.default.required(),otherwise:u.default.optional()}).when("dataProductIds",{is:u.default.array().min(1),then:u.default.required(),otherwise:u.default.optional()}),igluCentralSchemas:u.default.array().optional().items(u.default.string().regex(Pe)),repositories:u.default.array().optional().items(u.default.string()),dataStructures:u.default.array().optional().items(u.default.string().regex(Pe)),eventSpecificationIds:u.default.array().optional().items(u.default.string()),dataProductIds:u.default.array().optional().items(u.default.string()),options:u.default.object().optional().keys({commands:u.default.object().optional().keys({generate:u.default.object().optional().keys({instructions:u.default.boolean().optional(),validations:u.default.boolean().optional(),disallowDevSchemas:u.default.boolean().optional(),deprecateOnlyOnProdAvailableUpdates:u.default.boolean().optional()}),patch:u.default.object().optional().keys({regenerateOnPatch:u.default.boolean().optional()}),update:u.default.object().optional().keys({maximumBump:u.default.string().valid("major","minor","patch").optional(),regenerateOnUpdate:u.default.boolean().optional(),showOnlyProdUpdates:u.default.boolean().optional()})})})}),K=t=>{let e=wi.validate(t,{abortEarly:!1,convert:!1});if(e.error)throw new lt(e.error.annotate());return t};function Ii(t){let e=xe.sha256.create();return e.update(t),e.hex()}function Ae(t,e){let{vendor:n,name:i,format:o}=T(t);return Ii(`${e}-${n}-${i}-${o}`)}function T(t){let e=t.replace("iglu:",""),[n,i,o,r]=e.split("/");return(0,Gt.default)(typeof n=="string"&&typeof i=="string"&&typeof o=="string"&&typeof r=="string",`invalid iglu uri ${t}`),Ce(r),{vendor:n,name:i,format:o,version:r}}function De(t,{vendor:e,name:n,format:i,version:o}){let r=t.replace("iglu:",""),[a,s,c,p]=r.split("/");return`iglu:${e||a}/${n||s}/${i||c}/${o||p}`}function be(t){return t.some(e=>e.eventSchema.isEcomTemplateSchema)}function it(t){let[e,n,i]=t.split("-").map(o=>parseInt(o));return{model:e,revision:n,addition:i}}function Oe(t,e,n=0){if(t===e&&n!==0)return"patch";let{model:i,revision:o,addition:r}=it(t),{model:a,revision:s,addition:c}=it(e);if(i!==a)return"major";if(o!==s)return"minor";if(r!==c)return"patch";(0,Gt.default)(!1,"SchemaVer checking went wrong")}var ot=class extends Error{response;constructor(e){let n=e.response?.statusCode||0,{method:i,url:o}=e.options,r=e.response?.body||e.message,a=[[n,i,o].filter(Boolean).join(" "),r].filter(Boolean).join(`
`);super(a),this.response={statusCode:n,body:r}}};function zt(t){return!!Object.hasOwn(t||{},"response")}var j="0.17.3";var ke=h(require("p-limit")),A=class t{apiKeyId;apiKey;organizationId;accessToken;pLimit;dataProductsCache=new Map;eventSpecsCache=new Map;schemaVersionsDraftsCache=new Map;schemaVersionsDevCache=new Map;schemaVersionsProdCache=new Map;sourceApplicationsCache=new Map;apiUrl=process.env.SNOWPLOW_CONSOLE_API_URL||"https://console.snowplowanalytics.com/api/msc";constructor({apiKeyId:e,apiKey:n,organizationId:i,requestLimit:o=20}){this.apiKeyId=e,this.apiKey=n,this.organizationId=i,this.pLimit=(0,ke.default)(o)}static async create(e){let n=new t(e);return await n.initialize(e),n}static createLazy(e){return new t(e)}async initialize(e){await this.fetchAccessToken(),e.enableSupportForNonDataProductsTier?await Promise.all([this.bulkFetchAllSchemaDraftsVersions(),this.bulkFetchAllSchemaVersions("DEV"),this.bulkFetchAllSchemaVersions("PROD")]):await Promise.all([this.bulkFetchAllDataProducts(),this.bulkFetchAllEventSpecifications(),this.bulkFetchAllSchemaDraftsVersions(),this.bulkFetchAllSchemaVersions("DEV"),this.bulkFetchAllSchemaVersions("PROD")])}async bulkFetchAllDataProducts(){let e=`${this.apiUrl}/v1/organizations/${this.organizationId}/data-products/v2`,n=await this.fetchResource(e);n.data.forEach(i=>this.dataProductsCache.set(i.id,i)),n.includes.sourceApplications?.forEach(i=>{this.sourceApplicationsCache.set(i.id,i)})}async bulkFetchAllEventSpecifications(){let e=`${this.apiUrl}/v1/organizations/${this.organizationId}/event-specs/v1`,n=await this.fetchResource(e);n.data.forEach(i=>{let o={...n.metadata,outdatedDsWarnings:n.metadata?.outdatedDsWarnings.filter(a=>a.id===i.id)||[],hiddenDsWarnings:n.metadata?.hiddenDsWarnings.filter(a=>a.id===i.id)||[],metrics:n.metadata?.metrics.filter(a=>a.id===i.id)||[]},r={data:i,metadata:o};this.eventSpecsCache.set(i.id,r)})}async bulkFetchAllSchemaVersions(e){let n=`${this.apiUrl}/v1/organizations/${this.organizationId}/data-structures/v1/schemas/versions?env=${e}`,i=await this.fetchResource(n),o=e==="DEV"?this.schemaVersionsDevCache:this.schemaVersionsProdCache;i.forEach(r=>{let a=`iglu:${r.self.vendor}/${r.self.name}/${r.self.format}/${r.self.version}`;o.set(a,r)})}async bulkFetchAllSchemaDraftsVersions(){let e=`${this.apiUrl}/v1/organizations/${this.organizationId}/data-structure-drafts/v1/schemas`,n=await this.fetchResource(e),i=this.schemaVersionsDraftsCache;n.forEach(o=>{let r=`iglu:${o.self.vendor}/${o.self.name}/${o.self.format}/${o.self.version}`;i.set(r,o)})}async fetchAccessToken(){if(this.accessToken)return this.accessToken;let e=`${this.apiUrl}/v1/organizations/${this.organizationId}/credentials/v3/token`,{accessToken:n}=await(0,rt.default)(e,{headers:{"X-API-Key-Id":this.apiKeyId,"X-API-Key":this.apiKey,"X-Snowtype":j}}).json();return this.accessToken=n,n}fetchResource(e){return this.pLimit(async()=>{try{let n=await this.fetchAccessToken();return await(0,rt.default)(e,{headers:{Authorization:"Bearer "+n,"X-Snowtype":j}}).json()}catch(n){throw zt(n)?new ot(n):n}})}postResource(e,n){return this.pLimit(async()=>{try{let i=await this.fetchAccessToken();return await rt.default.post(e,{headers:{Authorization:"Bearer "+i,"X-Snowtype":j},json:n}).json()}catch(i){throw zt(i)?new ot(i):i}})}getSchemaVersion({schema:e,env:n="DEV"}){return(n==="DEV"?this.schemaVersionsDevCache:this.schemaVersionsProdCache).get(e)??(()=>{throw new Error(`Schema ${e} not found in ${n} environment`)})()}getAllSchemaDraftVersion(){return this.schemaVersionsDraftsCache}async fetchDeployments({schema:e,deploymentEnv:n}){let i=Ae(e,this.organizationId),o=25,r=[],a=!0,s=0,c=p=>`${this.apiUrl}/v1/organizations/${this.organizationId}/data-structures/v1/${i}/deployments?size=${o}&from=${p}${n?`&env=${n}`:""}`;for(;a;){let p=await this.fetchResource(c(s));s+=o,r=r.concat(p),p.length===0&&(a=!1)}return r}getEventSpecificationById(e){let n=this.eventSpecsCache.get(e)??(()=>{throw new Error(`Event specification ${e} not found`)})();return{data:n.data,metadata:n.metadata}}async fetchImageVariant({imageId:e,imageVariant:n}){let i=`${this.apiUrl}/v1/organizations/${this.organizationId}/images/v1/${e}/${n}`,o=await this.fetchAccessToken();return(0,rt.default)(i,{headers:{Authorization:"Bearer "+o,"X-Snowtype":j}})}getDataProductById(e){let n=this.dataProductsCache.get(e)??(()=>{throw new Error(`Data product ${e} not found`)})(),i=(n.sourceApplications||[]).map(o=>this.sourceApplicationsCache.get(o)).filter(Boolean);return{data:[n],includes:{sourceApplications:i}}}async batchFetchEventSpecifications(e){if(e.length===0)return;let n=`${this.apiUrl}/v1/organizations/${this.organizationId}/event-specs/v1/versions`;(await this.postResource(n,{eventSpecifications:e})).data.forEach(o=>{let r=this.eventSpecsCache.get(o.id);this.eventSpecsCache.set(o.id,{data:o,metadata:r?.metadata??{outdatedDsWarnings:[],hiddenDsWarnings:[],metrics:[]}})})}async authenticate(){try{return await this.fetchAccessToken(),!0}catch{return!1}}};var F=require("path"),I=require("fs");var Xt=h(require("util")),Yt=require("tsx/cjs/api");var W=(()=>{let t="json";return{setFormat:i=>t=i,getFormat:()=>t}})();var bt=require("@snowplow/snowtype-core");var xt=require("fs");var Ct=h(require("node:assert"));var Te=require("semver");function Fe(t,e,n){try{let i=(0,xt.readFileSync)(n,{encoding:"utf-8"}),o=JSON.parse(i);return o[t].some(a=>a===e)||o[t].push(e),(0,xt.writeFileSync)(n,Jt(o)),!0}catch(i){return console.error(i),!1}}var Ei=(t,e)=>{let{model:n,revision:i,addition:o}=it(t.version),{model:r,revision:a,addition:s}=it(e.version);return(0,Ct.default)(n!==void 0&&i!==void 0&&o!==void 0&&r!==void 0&&a!==void 0&&s!==void 0,`Invalid version number comparing (${t}, ${e})`),n>r?1:n<r?-1:i>a?1:i<a?-1:o>s?1:o<s?-1:t.patchLevel>e.patchLevel&&t.contentHash!==e.contentHash?1:e.patchLevel>t.patchLevel&&t.contentHash!==e.contentHash||t.env==="DEV"&&e.env==="PROD"?-1:t.env==="PROD"&&e.env==="DEV"?1:0};async function Le(t,e,n,i){return(await Promise.all(e.map(async r=>{let{version:a}=T(r),s=await t.fetchDeployments({schema:r,...i&&{deploymentEnv:"PROD"}}),c=Pi(s,a,n);c.sort(Ei);let p=c.pop();if(!p)return null;let d={previous:r,next:De(r,{version:p.version}),nextEnv:p.env};return p.version!==a?{...d,nextReason:"version"}:p.patchLevel>0&&p.env==="DEV"?{...d,nextReason:"patch"}:null}))).flatMap(r=>r===null?[]:[r])}async function Bt(t,e){return Promise.all(e.map(async n=>{try{t.getSchemaVersion({schema:n,env:"PROD"})}catch(i){if(i.response?.statusCode===404||i.message?.includes("not found in PROD environment"))try{return t.getSchemaVersion({schema:n,env:"DEV"}),n}catch(r){if(!(r.response?.statusCode===404||r.message?.includes("not found in DEV environment")))throw r}}return null})).then(n=>n.flatMap(i=>i!==null?[i]:[]))}async function Re(t,e,n){let{eventSpecifications:i}=n,o={};return await Promise.all(e.map(async r=>{let a=!(r in i),s=i[r]??0,c=t.getEventSpecificationById(r).data;if((0,Ct.default)(!!c,`failed to fetch event spec ${r}`),(0,Ct.default)(c.version!=null,`event spec with no version ${r}`),!c.event?.source)return r;let p=[c.event?.source,...c.entities?.tracked?.map(l=>l.source)||[]].flatMap(l=>typeof l=="string"?[l]:[]),d=await Bt(t,p);return(a||(c.version??0)>s)&&(o[r]={previous:s,next:c.version??0,isNew:a,devOnlySchema:d}),r})),o}function Pi(t,e,n){return t.filter(i=>Ht(e,i.version)!==1).filter(i=>i.version!==e||i.patchLevel).map(i=>({...i,updateType:Oe(i.version,e,i.patchLevel)})).filter(Ci(n))}function Ci(t){return({updateType:e})=>{switch(t){case"major":return!0;case"minor":return e==="patch"||e==="minor";case"patch":return e==="patch"}}}function Ht(t,e){let n=t.replaceAll("-","."),i=e.replaceAll("-",".");return(0,Te.compare)(n,i)}var Ne=require("cli-spinner"),w=h(require("chalk"));function Ve(){let t=new Ne.Spinner;return t.setSpinnerString(18),t}var xi="https://snowplow.io",Ai="https://docs.snowplow.io/docs/collecting-data/code-generation/",at={SUCCESS:"\u2714",LOG:"\u2139",DEBUG:"\u27A4",ERROR:"\u2717",WARN:"\u26A0"},je={LINK:"#9911BB",OPTION:"#9911DD"};function $e(t){return w.default.hex(je.LINK).bold(t)}function M(t){return w.default.hex(je.OPTION).italic(t)}function At(t,e){return t==="h1"?w.default.bold.underline(e):w.default.bold(e)}function We(){return`
${At("h1","CLI Help")}
For more information visit the Snowplow website ${$e(xi)}
For details see the CLI documentation ${$e(Ai)}
${At("h2","How to get started")}
1. Use ${w.default.cyanBright("snowtype init")} to initialize the setup.
2. Use ${w.default.cyanBright("snowtype patch")} to add a Data Structure or Event Specification.
3. Use ${w.default.cyanBright("snowtype generate")} to generate tracking code.
${At("h2","Available commands")}
To learn more about each CLI command, use the ${M("--help")} option, for example, ${M("snowtype init --help")}.
${M("snowtype init")}
Initialize the setup of Snowtype code generation in a project. Creates the \`snowtype.config.json\` file.
${M("snowtype patch")}
Adds new Data Structures and Event Specifications in the \`snowtype.config.json\` file.
${M("snowtype generate")}
Generates tracking code based on configuration on the \`snowtype.config.json\` file.
${M("snowtype update")}
Checks for latest version updates in Data Structures and Event Specifications.
${At("h2","Debug")}
Use the ${M("-v")} to output verbose logs
`}function Me(t){let e=`${at.SUCCESS}: `;return w.default.cyanBright(e)+t}function Dt(t){let e=`${at.WARN} Warning: `;return w.default.hex("#FFA500")(e)+t}function _e(t){let e=`${at.LOG} ${t}`;return w.default.yellowBright(e)}function Ue(t){let e=`${at.DEBUG} Debug: `;return w.default.magenta(e)+t}function Ge(t){let e=`${at.ERROR} Error: `;return w.default.redBright(e)+t}function ze(t,e){let n=`- ${t}`,i=`+ ${e}`;return`
${w.default.magenta(n)}
${w.default.cyanBright(i)}
`}var qe=h(require("mime-types"));var Be=t=>{let e={outdatedDsWarnings:[],hiddenDsWarnings:[],metrics:[]};return t.reduce((n,i)=>Di({currentMetadata:n,eventSpecificationId:i.eventSpecification.id,newMetadata:i.metadata||e}),{})};function Di({currentMetadata:t,eventSpecificationId:e,newMetadata:n}){let i=(o,r)=>o.id>r.id?1:-1;return{...t,[e]:{hiddenDsWarnings:n.hiddenDsWarnings.sort(i).map(o=>({sources:o.sources})),outdatedDsWarnings:n.outdatedDsWarnings.sort(i).map(o=>({sources:o.sources}))}}}var He=t=>(e,n)=>{bi(e,n||"").forEach(t.warn)};function bi(t,e){let n=Oi(t.outdatedDsWarnings,e),i=ki(t.hiddenDsWarnings,e);return n.concat(i)}function Oi(t,e){return t.reduce((n,i)=>{let o=i.sources.map(r=>[`Source: ${r.source}`,`Latest Version: ${r.latestVersion}`].join(`
`));return[...n,`${["Outdated Data Structures detected:",`Data Product Id: ${e}`,`Event Specification Id: ${i.id}`,...o].join(`
`)}`]},[])}function ki(t,e){return t.reduce((n,i)=>{let o=i.sources.map(r=>`Source: ${r.source}`).join(`
`);return[...n,`${["Hidden Data Structures detected:",`Data Product Id: ${e}`,`Event Specification Id: ${i.id}`,o].join(`
`)}`]},[])}async function Je(t,e){let n=Fi(t),i=await Promise.all(n.map(async r=>({schema:r,deployments:await e.fetchDeployments({schema:r,deploymentEnv:"PROD"})}))),o=Ti(i);return Li(t,o)}var Ti=t=>t.flatMap(({schema:e,deployments:n})=>{let{version:i}=T(e);return n.filter(r=>Ht(i,r.version)===-1).length===0?[]:[e]}),Fi=t=>_(Object.entries(t).filter(([,e])=>e.outdatedDsWarnings.length!==0).flatMap(([,e])=>e.outdatedDsWarnings.flatMap(n=>n.sources.map(i=>i.source)))),Li=(t,e)=>Object.keys(t).reduce((n,i)=>{let o=t[i];if(o){let r=o.outdatedDsWarnings.flatMap(({sources:a})=>{let s=a.filter(c=>e.includes(c.source));return s.length>0?[{sources:s}]:[]});n[i]={...o,outdatedDsWarnings:r}}return n},{});function U(t,e){return e.map(i=>t.getDataProductById(i)).flatMap(({data:[i]})=>i?i.eventSpecs:[]).map(i=>i.id)}function Ri(t){let{original:e}=t,[n,i]=e.split("/").reverse();return{imageVariant:n,imageId:i}}async function Xe(t,e){let n=[];if(!(e&&e.length))return[];for(let i of e){let{description:o,appIds:r,url:a,variantUrls:s}=i,c={description:o,appIds:r,url:a};if(s){let{imageVariant:p,imageId:d}=Ri(s),l=await t.fetchImageVariant({imageId:d,imageVariant:p});c.imageBuffer=l.rawBody,c.imageExtension=qe.default.extension(l.headers["content-type"])||""}n.push(c)}return n}function Ye(t,e,n){return{eventSpecificationsWithId:e.map(o=>{let r=t.getEventSpecificationById(o),a=r.data;if(typeof a>"u"||typeof a.event>"u")return[];r.metadata&&He(n)(r.metadata,a.dataProductId);let c=Kt(a.event.source);c&&n.warn("Currently code will not be generated for `Standard` events. Skipping...");let p=a.triggers,d=a.name,l=a.version,S=a.sourceApplications||[],m=a.event.schema,g=c?Ni(a.event.source):Ke(t,a,a.event.source),f=a.entities?.tracked||[],C=f.map(({source:G,schema:v})=>({original:Ke(t,a,G),propertyRule:v}));return{eventSpecification:{name:d||"",id:o,dataProductId:a.dataProductId||"",dataProductName:""},version:l||0,eventSchema:g,entitiesSchemas:C,entities:f,triggers:p,propertyRules:m,sourceApplicationIds:S,metadata:r.metadata}}).flat()}}async function Ze(t){return await Promise.all(t.map(async n=>JSON.parse(await ve({schema:n}))))}async function Qe(t,e){return await Promise.all(e.map(i=>t.getSchemaVersion({schema:i})))}function tn(t,e){return e.flatMap(({eventSpecification:{dataProductId:r}})=>r?[r]:[]).map(r=>t.getDataProductById(r)).map(r=>r.data[0]&&{...r.data[0],sourceApplications:(r.includes.sourceApplications||[]).filter(a=>a!==void 0)}).filter($i)}function en(t,e){let n=t.reduce((o,r)=>(o[r.id]={...r},o),{});return e.map(o=>{let r=n[o.eventSpecification.dataProductId],a=o.sourceApplicationIds.flatMap(s=>r?.sourceApplications.find(c=>c.id===s)||[]);return{...o,eventSpecification:{id:o.eventSpecification.id,name:o.eventSpecification.name,dataProductId:r?.id||"",dataProductName:r?.name||"",...r?.domain?{dataProductDomain:r.domain}:{}},sourceApplications:a}})}function $i(t){return!!t}function Ke(t,e,n){let i=e.event?.schema?.properties?.type?.enum?.[0];return n.match(Ee)?{self:T(n),isEcomTemplateSchema:i}:t.getSchemaVersion({schema:n})}function nn(t){return t.reduce((n,i)=>{let o=i.eventSpecification.id;return i.entities.forEach(({source:r,minCardinality:a,maxCardinality:s})=>{if(typeof a<"u"||typeof s<"u"){let c={minCardinality:a,maxCardinality:s};n[o]=n[o]||{},n[o][r]=c}}),n},{})}function Ni(t){return{self:{...T(t)}}}function on(t,e,n){return t.filter(i=>{let{data:o}=e.getEventSpecificationById(i),r=e.getAllSchemaDraftVersion(),a=o.event?r.has(o.event.source):!1,s=o.entities?.tracked?o.entities.tracked.filter(c=>r.has(c.source)):[];if(a||s.length>0){let c=[];if(a&&o.event&&c.push(`Event DS: ${o.event.source}`),s.length>0){let p=s.map(d=>d.source).join(", ");c.push(`Entity DS: [${p}]`)}return n.warn(`Event specification with ID "${i}" has been excluded because it contains draft data structures - ${c.join(" | ")}`),!1}else return!0})}function rn(t,e,n){return t.filter(i=>{let o=e.getAllSchemaDraftVersion().has(i);return o&&n.warn(`DS ${i} is skipped because it is draft`),!o})}var Vi="SNOWPLOW_CONSOLE_API_KEY_ID",ji="SNOWPLOW_CONSOLE_API_KEY";function cn(t){return t.length!==0}function Jt(t){return JSON.stringify(t,null,2)}function pn(t){let e={organizationId:t.organizationId,tracker:t.tracker,language:t.language,outpath:t.outpath};return Object.assign({igluCentralSchemas:[],dataStructures:[],repositories:[],eventSpecificationIds:[],dataProductIds:[]},e)}function Wi(t){switch(t){case"typescript":return`${et}${wt}`;case"javascript":return`${et}${yt}`;case"json":return`${et}${It}`;default:return""}}var an=t=>(0,I.existsSync)(t)&&!(0,I.lstatSync)(t).isDirectory(),Mi=t=>et+t,_i=t=>({isTS:t.endsWith(wt),isJSON:t.endsWith(It),isJS:t.endsWith(yt)}),qt=t=>({configDir:(0,F.dirname)(t),configPath:t,..._i(t)});function D(t){let e=(0,F.isAbsolute)(t)?t:(0,F.resolve)(process.cwd(),t);if(an(e))return qt(e);if(!(0,I.existsSync)(e))throw new Error(`Can't find a root directory while resolving a config file path.
Provided path to resolve: ${t}
cwd: ${process.cwd()}`);let[n]=ye.map(i=>(0,F.resolve)(e,Mi(i))).filter(an);return qt(typeof n!="string"?e:n)}function Ot(t,e){let n=W.getFormat(),i=Wi(n),o=(0,F.resolve)(e,i),r=`const config = ${Xt.default.inspect(t,!1,null)}
`,a='import { SnowtypeConfig } from "@snowplow/snowtype/types";',s=`const config: SnowtypeConfig = ${Xt.default.inspect(t,!1,null)}
`,c="module.exports = config;",p="export default config;";return n==="json"?(0,I.writeFileSync)(o,Jt(t)):(0,I.writeFileSync)(o,(n==="typescript"?[a,s,p]:[r,c]).join(`
`))}function L(t){let e=(0,I.statSync)(t,{throwIfNoEntry:!1});return e===void 0?!1:e.isFile()}function Zt(t){return(0,I.readFileSync)(t,{encoding:"utf-8"})}var Ui=async t=>(await(0,Yt.require)(t,__filename)).default;async function R(t){let{configPath:e,isJS:n,isJSON:i,isTS:o}=D(t),r;return o?(r=await Ui(e),W.setFormat("typescript")):n?(r=(await import(e)).default,W.setFormat("javascript")):i&&(r=JSON.parse(Zt(e)),W.setFormat("json")),typeof r=="function"&&(r=await r()),r}function q(t){try{return JSON.parse(Zt(t))}catch(e){throw new ft(e instanceof Error?e.message:String(e))}}async function un(t,e){t.debug("Checking for existing configuration.."),await Qt(!0,e),t.success("Valid configuration found")}async function Qt(t,e){let{configPath:n,isJS:i,isJSON:o,isTS:r}=D(e),a=o===!0||r===!0||i===!0,s=r===!1&&i===!1&&o===!1,c;if(r?c=(await(0,Yt.require)(n,__filename)).default:i?c=(await import(n)).default:o&&(c=JSON.parse(Zt(n))),typeof c=="function"&&(c=await c()),t){if(s)throw new dt;K(c)}else if(a)try{throw K(c),new tt}catch(p){if(p instanceof tt)throw p}}function dn(t){return{javascript:".js","javascript-gtm":".js",typescript:".ts",kotlin:".kt",swift:".swift",go:".go",dart:".dart",java:".java"}[t]||""}function ln(t,e){let n={eventSpecifications:{}};t.forEach(i=>{n.eventSpecifications[i.eventSpecification.id]=i.version});try{(0,I.writeFileSync)(e,JSON.stringify(n,null,2))}catch{throw new H}}function gn(t,e){let n=q(e),i={...n,eventSpecifications:{...n.eventSpecifications,...t}};try{(0,I.writeFileSync)(e,JSON.stringify(i,null,2))}catch{throw new H}}function mn(t,e){return t.reduce((n,i)=>(i in e.eventSpecifications?(n.lockedIds.push(i),n.batchSpecs.push({id:i,version:e.eventSpecifications[i]})):n.skippedIds.push(i),n),{lockedIds:[],skippedIds:[],batchSpecs:[]})}function fn(t,e){if(!L(e))return[];let n=q(e),i=new Set(t),o=[];for(let r of Object.keys(n.eventSpecifications))i.has(r)||(o.push(r),delete n.eventSpecifications[r]);if(o.length===0)return[];try{(0,I.writeFileSync)(e,JSON.stringify(n,null,2))}catch{throw new H}return o}function hn(t,e,n){let i=Object.entries(t);i.length>0&&n.success("Available Event Specification Updates"),i.forEach(([o,r])=>{n.diff(r.isNew?`${o}: (new)`:`${o}: version ${r.previous}`,`${o}: version ${r.next}`),r.devOnlySchema.length>0&&(n.warn("This Event Specification uses schema that are not in production."),n.warn(r.devOnlySchema.join(" ")))}),e.length>0&&n.success("Available Data Structures Updates"),e.forEach(o=>{let r=`${o.previous}`,a=`${o.next}`;if(n.diff(r,a),o.nextReason==="patch"&&n.warn("The most recent version of this schema has been patched. Possible update required."),o.nextEnv==="DEV"){let s=o.next.split("/").pop();n.warn(`This data structure version (${s}) is not in production.`)}})}function Sn(t){let e=t.optsWithGlobals();return{...e,apiKeyId:e.apiKeyId||process.env[Vi],apiKey:e.apiKey||process.env[ji]}}function P(t){return!!(Array.isArray(t)&&!t.length)}function _(t){return[...new Set(t)]}function kt(t){let e=_(t);return e.sort(),e}function Gi(t){return t.flatMap(e=>{let n=(0,bt.joinIgluSchemaUrlParts)(e.eventSchema.self),i=e.entities.map(o=>o.source);return[n,...i]})}async function vn(t,e,n,i){let o=t.map(s=>(0,bt.joinIgluSchemaUrlParts)(s.self)),r=Gi(e),a=await Bt(n,_([...o,...r]));if(a.length>0&&(console.log(`
`,Dt(`Generating code using schemas in DEV environment, tracking against those will result in failed events. Schemas in DEV:
`+a.join(`
`)),`
`),i))throw new St}function Kt(t){return Ie.includes(t)}function sn({self:t}){let e=(0,bt.joinIgluSchemaUrlParts)(t);return Kt(e)}function yn(t){return{standardEventSpecs:t.filter(e=>sn(e.eventSchema)),customEventSpecs:t.filter(e=>!sn(e.eventSchema))}}function wn(t,e,n){if(typeof t=="string"&&typeof e=="string"&&t&&e)return{apiKeyId:t,apiKey:e};throw n.error(new vt),new Error}function In(t){let e=!P(t.configDataStructures),n=!P(t.igluCentralSchemas),i=!P(t.repositories),o=!P(t.eventSpecificationIds),r=!P(t.dataProductIds);return(e||n||i)&&(!o&&!r)}var zi=["javascript","json","typescript"];function En(t){return t in nt}function Pn(t,e){let n=nt[t];return Array.isArray(n)?n.map(o=>o.value).includes(e):!1}function Cn(t){return zi.includes(t)}function xn(){return{withVerbosity:e=>({success:i=>{console.log(Me(i))},warn:i=>{console.log(Dt(i))},log:i=>{console.log(_e(i))},diff:(i,o)=>{console.log(ze(i,o))},debug:i=>{e===!0&&console.log(Ue(JSON.stringify(i)))},error:i=>{console.log(Ge(i.message)),e===!0&&console.log(i)}})}}function b(t,e){return async(n,i)=>{let o=Sn(i),r=xn(),a=Ve(),s=r.withVerbosity(o.verbose),{apiKeyId:c,apiKey:p}=wn(o.apiKeyId,o.apiKey,s);if(e!=="init")try{let d=n.config||process.cwd();await un(s,d)}catch(d){An(d,s,a)}return t({apiKeyId:c,apiKey:p},s,a,n).then(()=>Dn(a)).catch(d=>{An(d,s,a)})}}function An(t,e,n){throw Dn(n),e.error(t),t}function Dn(t){t.isSpinning()===!0&&t.stop(!0)}var Bi={type:"password",message:"Enter your Snowplow organization ID:",mask:!0,validate:cn},Hi={type:"select",message:"Select the Snowplow Tracker to use:",choices:[{value:"google-tag-manager",name:"Google Tag Manager"},{value:"@snowplow/javascript-tracker",name:"JavaScript Tracker"},{value:"@snowplow/browser-tracker",name:"Browser Tracker"},{value:"@snowplow/node-tracker",name:"Node Tracker"},{value:"snowplow-android-tracker",name:"Android Tracker"},{value:"snowplow-ios-tracker",name:"iOS Tracker"},{value:"snowplow-golang-tracker",name:"Golang Tracker"},{value:"@snowplow/react-native-tracker",name:"React Native Tracker"},{value:"snowplow-flutter-tracker",name:"Flutter Tracker"},{value:"snowplow-java-tracker",name:"Java Tracker"}]},Ji={type:"select",message:"Select the format to use:",choices:[{value:"javascript",name:"JavaScript"},{value:"typescript",name:"TypeScript"},{value:"json",name:"JSON"}]},Ki={type:"input",message:"Enter the directory for Snowtype output:",default:"./snowtype"},qi=t=>({type:"select",message:"Select the language to use:",choices:t});async function Xi(t,e){e.debug("Checking for existing configuration file.."),await Qt(!1,process.cwd());let{password:n,select:i,input:o}=await import("@inquirer/prompts"),r=t.organizationId||await n(Bi),a=t.tracker||await i(Hi);if(!En(a))throw new B("tracker",a);let s=nt[a],c;if(s.length===1){let l=s[0];if(typeof l>"u")throw new gt("Missing language entry.");c=l.value}else c=t.language||await i(qi(s));if(!Pn(a,c))throw new B("language",c);let p=await i(Ji);if(!Cn(p))throw new B("format",p);W.setFormat(p);let d=t.outpath||await o(Ki);return e.debug("Assembling initialization options.."),{organizationId:r,tracker:a,language:c,format:p,outpath:d}}async function Yi(t,e,n,i){let o=await Xi(i,e);n.setSpinnerTitle("Initialising..."),n.isSpinning()===!1&&n.start(),e.debug("Creating configuration with options: ".concat(JSON.stringify(o)));let r=pn(o);if(K(r),!await A.createLazy({...t,organizationId:r.organizationId}).authenticate())throw new O;e.success("Authentication succeeded"),Ot(r,process.cwd()),e.success("Configuration created")}var te=b(Yi,"init");var Jn=require("path");var Hn=require("@snowplow/snowtype-core");var Tt=require("path"),bn=require("mkdirp"),ne=require("fs"),Ft=require("@snowplow/snowtype-core");var Zi="instructions.md",On="assets";async function kn(t,e,n,i,o){bn.mkdirp.sync((0,Tt.resolve)(i,On));let r=[],a=no(e,n,o),s=[];await Promise.all(e.map(async p=>{let d={triggers:await Xe(t,p.triggers),instructionsHeading:ee(p.eventSpecification.name)};s.push(ee(p.eventSpecification.name));let l=oo(p.propertyRules),S=ro(p.entities);to(p.eventSpecification.id,d,i),r.push(Qi({eventStructure:p.eventSchema.self,entitiesStructures:p.entitiesSchemas?.map(m=>m.original.self)||[],name:p.eventSpecification.name,id:p.eventSpecification.id,dataProductId:p.eventSpecification.dataProductId,version:p.version,triggerInstructions:d.triggers,linkToCode:a[p.eventSpecification.id],formattedPropertyRules:l,formattedCardinalityRules:S,organizationId:t.organizationId,sourceApplications:p.sourceApplications,...p.eventSpecification?.dataProductDomain?{dataProductDomain:p.eventSpecification?.dataProductDomain}:{}}))}));let c=`
# Implementation instructions
_A guide on how to implement tracking for the generated Event Specifications._
**Table of contents:**
${s.map(p=>`- [${p.instructionsTitle}](#${p.instructionsLink})`).join(`
`)}
${r.join(`
`)}
`;(0,ne.writeFileSync)((0,Tt.resolve)(i,Zi),c,"utf-8")}function Qi({eventStructure:t,entitiesStructures:e,name:n,id:i,dataProductId:o,version:r,triggerInstructions:a,linkToCode:s,formattedPropertyRules:c,formattedCardinalityRules:p,organizationId:d,sourceApplications:l,dataProductDomain:S}){let m="_N/A_";return`
## [${ee(n).instructionsTitle}](${eo(d,o,i)})
| | |
| ----------- | ----------- |
| **Id** | ${i} |
| **Version** | ${r} |
| **Data Product Id** | ${o} |
| **Source Application/s** | ${l.length?l.map(g=>g.name).join(", "):"None selected"} |
| **Event Data Structure** | ${t.name}/${t.version} |
| **Entity Data Structures** | ${e.map(g=>`${g.name}/${g.version}`).sort().join(", ")} |
| **Code** | ${s} |
| **Data Product Domain** | ${S&&S.length>0?S:m} |
${c.length>0?`### Implementation Instructions for ${t.name} event properties
#### Property Rules
| Name | Required | Description | Exact value(s) expected |
| ----------- | ----------- | ----------- | ----------- |
${c.map(g=>Object.values(g).join(" | ")).join(`
`)}
`:""}
${p.length>0?`
#### Entity Cardinality Rules
| Name | Required | Number of entities |
| ----------- | ----------- | ----------- |
${p.map(g=>Object.values(g).join(" | ")).join(`
`)}
`:""}
${a.map((g,f,C)=>`
### Trigger ${C.length!==1?f+1:""}
#### Screenshot
${g.imageBuffer?`[<img src="./assets/${i}_${f}.${g.imageExtension}" width="550"/>](./assets/${i}_${f}.${g.imageExtension})`:m}
#### In which application(s) does this trigger apply?
${g.appIds&&g.appIds.length?g.appIds.map(G=>"`"+G+"` "):m}
#### The URL of the page on which this event specification triggers:
${g.url||m}
#### Notes
${g.description||m}
`).join("")}`}function to(t,e,n){e.triggers.forEach((i,o)=>{i.imageBuffer&&(0,ne.writeFileSync)((0,Tt.resolve)(n,On,t+"_"+o+"."+i.imageExtension),i.imageBuffer,"binary")})}function eo(t,e,n){return`https://console.snowplowanalytics.com/${t}/data-products/${e}/event-specifications/${n}`}function no(t,e,n){let i=t.reduce((o,{eventSpecification:{id:r}})=>(o[r]="",o),{});return Object.keys(i).forEach(o=>{let r=e.findIndex(a=>a.match((0,Ft.createEventSpecificationInstructionsIdentifier)(o)));i[o]=r!==-1?`[Link](./${n+"#L"+r})`:"N/A"}),i}function ee(t){let e=t;return{instructionsTitle:e,instructionsLink:io(e)}}function io(t){return t.toLowerCase().replace(/[^a-z\d\s-]/g," ").replace(/\s+/g," ").trim().replace(/-{2,}|\s/g,"-")}function oo(t){return t?Object.entries(t.properties||{}).map(e=>{let[n,i]=e,o=t.required?.includes(n)?"\u2705":"\u274C",r=i.description||"-",a=i.enum?i.enum.map(s=>`\`${s}\``).join(" or "):"-";return{name:n,isRequired:o,description:r,expectedValues:a}}):[]}function ro(t){return t?t.map(({source:e,minCardinality:n,maxCardinality:i})=>{let{name:o}=(0,Ft.splitIgluSchemaUrlParts)(e),r=typeof n<"u"&&n>0?"\u2705":"\u274C",a=ao(n,i);return{name:o,isRequired:r,formattedCardinalityValues:a}}):[]}function ao(t,e){return typeof t>"u"?"`any`":typeof e<"u"?t===e?`Exactly \`${t}\``:`Between \`${t}\` and \`${e}\``:`At least \`${t}\``}var Fn=require("fs"),Ln=require("path"),Rn=h(require("util"));function $n(t,e,n,i){let o=e==="typescript"?"ts":"js";(0,Fn.writeFileSync)((0,Ln.resolve)(t,`validations.${o}`),`${o==="ts"?`
import { AnySchema } from "ajv";
export type CardinalityRule = { minCardinality?: number; maxCardinality?: number };
type IgluUrl = string;
type EventSpecificationId = string;
`:""}
export const entityRules${o==="ts"?": Record<EventSpecificationId, Record<IgluUrl, CardinalityRule>>":""} = ${Tn(i)}
export const schemasObject${o==="ts"?": Record<IgluUrl | EventSpecificationId, AnySchema | Record<IgluUrl, AnySchema>>":""} = ${Tn(n)}`,"utf-8")}function Tn(t){return Rn.default.inspect(t,{showHidden:!1,depth:null,maxArrayLength:null})}function ie(t){return Object.values(t).some(e=>so(e)?co(e):ie(e))}function so(t){return typeof t=="object"&&t!==null&&Object.hasOwn(t,"$schema")}function co(t){return t.properties?Object.values(t.properties).some(e=>Object.hasOwn(e||{},"pattern")):!1}function Nn(t,e){let n=uo(t);po(n,e)}function po(t,e){Object.entries(t).map(([n,i])=>e.warn(`Event Specification ${n} includes entities that are also present in it's application context: ${i.join(", ")}`))}function uo(t){let e={};return t.forEach(n=>{let i=n.entities.map(r=>r.source),o=n.sourceApplications.flatMap(r=>[...r.entities.enriched.map(a=>a.source),...r.entities.tracked.map(a=>a.source)]);i.forEach(r=>{o.includes(r)&&(e[n.eventSpecification.id]?e[n.eventSpecification.id]?.push(r):e[n.eventSpecification.id]=[r])})}),e}var Lt=h(require("fs/promises")),Rt=h(require("path")),Vn=require("yaml");async function jn(t,e=[]){let n=[];for(let i of e){let o=Rt.default.resolve(t,i),r=await Wn(o),a=await lo(r);n.push(...a)}return n}async function lo(t){let e=[];for(let n of t){let{isJson:i}=Mn(n),o=await Lt.default.readFile(n,{encoding:"utf-8"}),r=i?JSON.parse(o):(0,Vn.parse)(o);go(r)&&e.push(r.data)}return e}async function Wn(t,e=[]){let n=await Lt.default.readdir(t);for(let i of n){let o=Rt.default.join(t,i),r=await Lt.default.stat(o),{isJson:a,isYaml:s}=Mn(i);r.isDirectory()?e=await Wn(o,e):(a||s)&&e.push(o)}return e}function go(t){return typeof t=="object"&&t!==null&&"apiVersion"in t&&typeof t.apiVersion=="string"&&"resourceType"in t&&t.resourceType==="data-structure"}function Mn(t){let e=Rt.default.extname(t);return e.match(/\.yml|\.yaml/)?{isYaml:!0,isJson:!1}:e.match(".json")?{isYaml:!1,isJson:!0}:{isYaml:!1,isJson:!1}}var X=require("path"),oe=require("fs"),re=require("mkdirp"),_n=h(require("fs-extra"));function Un({codeLines:t,outFilePath:e,language:n}){if(n==="java"){let i="// SNOWTYPE START: ",o="// SNOWTYPE END: ",r=(0,X.resolve)((0,X.dirname)(e),"com","snowplowanalytics","snowplow","snowtype");re.mkdirp.sync(r);let a="",s=!1,c="";for(let p of t)p===o+a&&((0,oe.writeFileSync)((0,X.resolve)(r,a),c),c="",s=!1),s&&(c+=p+`
`),p.startsWith(i)&&(a=p.slice(i.length),s=!0)}else{let i=t.join(`
`);(0,oe.writeFileSync)(e,i)}}function Gn(t){_n.default.removeSync((0,X.resolve)(t)),re.mkdirp.sync(t)}var Nt=require("path");var zn=require("path"),$t=require("fs-extra"),Y=2e4,mo=({code:t,codeMinified:e})=>t.length>Y&&e.length<=Y?`Warning: The content exceeds the GTM limit of ${Y} characters. Please use the minified version.`:e.length>Y&&e.length>Y?`Warning: The content exceeds the GTM limit of ${Y} characters.`:"";async function Bn({defaultFileName:t,outDir:e,codeLines:n}){let i=(0,zn.resolve)(e,t+".minified.js"),o=n.join(`
`),{minify:r}=await import("terser"),a=await r(o,{mangle:!1,ecma:5});a.code?(console.warn(mo({code:o,codeMinified:a.code})),await(0,$t.remove)(i),await(0,$t.writeFile)(i,a.code)):console.error("Minification failed: Terser did not generate any code.")}async function fo(t){let{config:e,...n}=t,i=await R(e||process.cwd());return k(i),i.options.commands.generate={...i.options.commands.generate,...n},i}async function st(t,e,n,i){let{dataProductIds:o,dataStructures:r,igluCentralSchemas:a,eventSpecificationIds:s,repositories:c,language:p,tracker:d,outpath:l,organizationId:S,namespace:m,options:{commands:{generate:g}}}=await fo(i),{configDir:f}=D(i.config||process.cwd()),C=P(r),G=P(a),v=P(s),x=P(o),N=P(c);C&&G&&v&&x&&N&&(e.warn("Data structures, schemas, and event specifications are empty."),e.warn("Code generation has been interrupted."),process.exit(1)),n.setSpinnerTitle("Generating..."),n.isSpinning()===!1&&n.start();let Zn=In({configDataStructures:r,igluCentralSchemas:a,repositories:c,eventSpecificationIds:s,dataProductIds:o}),E=await A.create({...t,organizationId:S,enableSupportForNonDataProductsTier:Zn});if(!await E.authenticate())throw new O;let Qn=U(E,o),jt=kt([...Qn,...s]),ct=(0,Nt.resolve)(f,J);if(L(ct)){let Q=q(ct),{lockedIds:Mt,skippedIds:me,batchSpecs:fe}=mn(jt,Q);me.length>0&&e.warn(`Skipping ${me.length} event specification(s) not found in lock file. Run 'update --yes' to add new entries.`),fe.length>0&&await E.batchFetchEventSpecifications(fe),jt=Mt}let ti=on(jt,E,e),{eventSpecificationsWithId:z}=Ye(E,ti,e),Wt=Be(z);g.deprecateOnlyOnProdAvailableUpdates&&(Wt=await Je(Wt,E));let ei=tn(E,z),pt=en(ei,z);Nn(pt,e);let{customEventSpecs:ni,standardEventSpecs:ii}=yn(pt),oi=ii.flatMap(Q=>Q.entities.map(Mt=>Mt.source));be(z)&&d==="@snowplow/browser-tracker"&&e.log("You are generating Snowplow Ecommerce events. You would need to install `@snowplow/browser-plugin-snowplow-ecommerce`."),g.validations&&e.log("For validations to work properly you would need to install `ajv@8`, `ajv-formats@2` and `ajv-draft-04@1` on your project.");let ri=await Ze(a),ai=rn(r,E,e),ue=await Qe(E,[...ai,...oi]),si=await jn(f,c),de=!!(d==="@snowplow/browser-tracker"&&p.match(/javascript|typescript/));await vn(ue,pt,E,g.disallowDevSchemas);let ci=[...si,...ri,...ue],le={language:p,tracker:d,schemas:ci,eventSpecifications:ni,validations:de&&g.validations,eventSpecificationsInputMetadata:Wt,namespace:m},V=await(0,Hn.generate)(le);if(n.stop(!0),!V)throw new ut;e.success("Code generated, writing...");let Z=(0,Nt.resolve)(f,l),pi=dn(p),ge=_t+pi,ui=(0,Nt.resolve)(Z,ge);if(Gn(Z),Un({codeLines:V.lines,outFilePath:ui,language:p}),le.language==="javascript-gtm"&&await Bn({defaultFileName:_t,outDir:Z,codeLines:V.lines}),L(ct)||ln(z,ct),de&&g.validations&&V.validationsSchemaObject){let Q=nn(z);$n(Z,p,V.validationsSchemaObject,Q),ie(V.validationsSchemaObject)&&e.warn("Some schemas appear to have attributes that can have inconsistent validations between the pipeline and client-side validation. Read more at https://docs.snowplow.io/docs/collecting-data/code-generation/client-side-validation/#divergence-with-pipeline-validation")}g.instructions&&await kn(E,pt,V.lines,Z,ge)}var ae=b(st,"generate");async function ho(t){let e=await R(t||process.cwd());return k(e),e}async function So(t,e,n,i){let o=await ho(i.config),{options:{commands:{update:{maximumBump:r,showOnlyProdUpdates:a,regenerateOnUpdate:s},generate:c}}}=o;e.debug("Starting update process with options: ".concat(JSON.stringify(i)));let{configDir:p}=D(i.config||process.cwd()),d=(0,Jn.resolve)(p,J),l=await A.create({...t,organizationId:o.organizationId});n.setSpinnerTitle("Checking for updates..."),n.isSpinning()===!1&&n.start();let S=i.dataProducts&&i.dataProducts.length>0||i.eventSpecs&&i.eventSpecs.length>0,m;if(S){let v=i.dataProducts||[],x=i.eventSpecs||[],N=U(l,v);m=_([...N,...x])}else{let v=U(l,o.dataProductIds);m=_([...o.eventSpecificationIds,...v])}let g=L(d)?q(d):{eventSpecifications:{}},f={};if(m.length>0&&(f=await Re(l,m,g),!i.latestDraft)){let v={};for(let[x,N]of Object.entries(f))l.getEventSpecificationById(x)?.data?.status!=="draft"&&(v[x]=N);f=v}let C=await Le(l,o.dataStructures,i.maximumBump||r,a);if((Object.entries(f).length>0||C.length>0)===!0)if(e.success("Available updates found!"),hn(f,C,e),i.yes){if(C.length>0&&(C.forEach(v=>{let x=o.dataStructures.indexOf(v.previous);o.dataStructures[x]=v.next}),Ot(o,i.config||process.cwd())),Object.keys(f).length>0){let v={};for(let[x,N]of Object.entries(f))v[x]=N.next;gn(v,d),e.success("Lock file updated with new event specification versions.")}if(e.debug("Updates applied."),s)return e.debug("Regenerating code after update..."),st(t,e,n,{...c,...i.config&&{config:i.config}})}else e.log("No updates applied"),e.log("To apply the available updates automatically run `update` with the --yes flag"),e.log("(caution: will overwrite the configuration file)");else e.success("No updates found. Everything is up-to-date!");return Promise.resolve(void 0)}var se=b(So,"update");async function vo(t){let{config:e,...n}=t;if(Object.values(n).every(o=>Array.isArray(o)&&o.length===0))throw new mt;let i=await R(e||process.cwd());return k(i),{patchOptions:n,generateOptions:i.options.commands.generate,regenerateOnPatch:i.options.commands.patch.regenerateOnPatch}}async function yo(t,e,n,i){let{isJSON:o,configPath:r}=D(i.config||process.cwd());if(o===!1)throw new ht;let{patchOptions:a,generateOptions:s,regenerateOnPatch:c}=await vo(i);return e.debug("Starting patch process with options: ".concat(JSON.stringify(a))),Object.entries(a).forEach(([d,l])=>{l.forEach(S=>{Fe(d,S,r)})}),e.success("Configuration patched"),c?st(t,e,n,s):(e.log("Code is not generated yet for the patched configuration"),Promise.resolve(void 0))}var ce=b(yo,"patch");var Kn=require("path");async function wo(t,e,n,i){let o=i.config||process.cwd(),r=await R(o);k(r);let{configDir:a}=D(o),s=(0,Kn.resolve)(a,J);if(!L(s)){e.log("No lock file found. Nothing to purge.");return}n.setSpinnerTitle("Resolving valid event specifications..."),n.isSpinning()===!1&&n.start();let c=await A.create({...t,organizationId:r.organizationId});if(!await c.authenticate())throw new O;let d=U(c,r.dataProductIds),l=kt([...r.eventSpecificationIds,...d]);n.stop(!0);let S=fn(l,s);S.length===0?e.success("Lock file is clean. No stale entries found."):(e.success(`Purged ${S.length} stale event specification(s) from lock file:`),S.forEach(m=>e.log(` - ${m}`)))}var pe=b(wo,"purge");var Vt=require("@snowplow/snowtype-core");async function Xn(){await import("dotenv/config");let t=new $.Command;t.exitOverride(),t.version(j,void 0,"Snowtype CLI version number").name("snowtype").description("The Snowtype CLI is a tool which aims to speed up tracking implementations, provide type safety and inline documentation for developers and ultimately reduce the number of erroneous events.").showHelpAfterError().configureHelp({showGlobalOptions:!0}).option("-k, --apiKey <string>","Snowplow Console API key").option("-s, --apiKeyId <string>","Snowplow Console API key ID").option("-v, --verbose","Enable verbose logging"),t.command("init").description("Initialize the setup of Snowtype code generation in a project. Creates the `snowtype.config.json` file.").option("-i, --organizationId <string>","organization ID").addOption(new $.Option("-t, --tracker <availableTrackers>","tracker to use").choices(Vt.trackerTemplates)).addOption(new $.Option("-l, --language <availableLanguages>","language to use").choices(Vt.languageIds)).option("-o, --outpath <string>","output path").action(te),t.command("update").description("Checks for latest version updates in Data Structures and Event Specifications.").option("-c, --config <string>","config file path").option("-y, --yes","updates all to latest without asking (caution: will overwrite the configuration file)").addOption(new $.Option("-m, --maximumBump <'patch' | 'minor' | 'major'>","the maximum SchemaVer update to show an available update notification. Defaults to 'major'").choices(["patch","minor","major"])).option("-d, --latestDraft","update event specifications to the latest version including drafts (default: published only)").option("-p, --dataProducts <dataProductIds...>","only update event specifications belonging to these data products").option("-e, --eventSpecs <eventSpecIds...>","only update these specific event specifications").action(se),t.command("generate").option("-c, --config <string>","config file path").option("--instructions","generate event specification instructions").option("--no-instructions","generate without instructions").option("--validations","add runtime validation using Ajv").option("--no-validations","generate without runtime validations").option("--disallowDevSchemas","disallow generation of code using schemas only deployed on DEV environment").option("--deprecateOnlyOnProdAvailableUpdates","show deprecation warnings only when there are PROD available schema updates").description("Generates tracking code based on configuration on the `snowtype.config.json` file.").action(ae),t.command("patch").option("-c, --config <string>","config file path").description("Adds new Data Structures and Event Specifications in the `snowtype.config.json` file.").option("-p, --dataProductIds <dataProductIds...>","data product ID").option("-e, --eventSpecificationIds <eventSpecificationIds...>","tracking eventSpecification ID").option("-d, --dataStructures <dataStructures...>","data structure URI").option("-i, --igluCentralSchemas <igluCentralSchemas...>","iglu central URI").option("-r, --repositories <repositories...>","repository path").action(ce),t.command("purge").description("Removes stale event specification entries from the lock file that no longer exist in the configuration.").option("-c, --config <string>","config file path").action(pe),t.addHelpText("before",We()).addHelpText("after",`
`),await t.parseAsync(qn.argv).catch(e=>{Io(e)})}function Io(t){if(!(t instanceof $.CommanderError&&["commander.help","commander.version","commander.helpDisplayed"].indexOf(t.code)>-1))throw t}Xn().then(()=>{}).catch(()=>{process.exitCode=1});