import { createTypeSpecLibrary, paramMessage, listServices, getEffectiveModelType, ignoreDiagnostics, getProjectedName, getFriendlyName, resolveEncodedName, getNamespaceFullName, createDiagnosticCollector, getSummary, getDoc, getDeprecationDetails, isNullType, isNeverType, isVoidType, getFormat, getEncode, isErrorModel, getKnownValues, getDiscriminator, getVisibility, getService, SyntaxKind, isService, isTemplateDeclaration, validateDecoratorUniqueOnNode, isTemplateDeclarationOrInstance, projectProgram } from '@typespec/compiler';
import { isMetadata, getHttpOperation, isHeader, Visibility, getAuthentication, isStatusCode, getServers, isPathParam, isQueryParam, isBody, getPathParamName, getQueryParamName, getHeaderFieldName, getQueryParamOptions, getHeaderFieldOptions } from '@typespec/http';
import { getVersions, getAddedOnVersions, getRemovedOnVersions, resolveVersions, buildVersionProjections } from '@typespec/versioning';
import { getUnionAsEnum, getLroMetadata, getPagedResult } from '@azure-tools/typespec-azure-core';

const defaultDecoratorsAllowList = [
    "TypeSpec\\.Xml\\..*",
    "Azure\\.Core\\.@useFinalStateVia",
    "Autorest\\.@example",
];

const $lib = createTypeSpecLibrary({
    name: "@azure-tools/typespec-client-generator-core",
    diagnostics: {
        "client-name": {
            severity: "warning",
            messages: {
                default: paramMessage `Client name "${"name"}" must end with Client. Use @client({name: "...Client"}`,
            },
        },
        "client-service": {
            severity: "warning",
            messages: {
                default: paramMessage `Client "${"name"}" is not inside a service namespace. Use @client({service: MyServiceNS}`,
            },
        },
        "unknown-client-format": {
            severity: "error",
            messages: {
                default: paramMessage `Client format "${"format"}" is unknown. Known values are "${"knownValues"}"`,
            },
        },
        "incorrect-client-format": {
            severity: "error",
            messages: {
                default: paramMessage `Format "${"format"}" can only apply to "${"expectedTargetTypes"}"`,
            },
        },
        "union-null": {
            severity: "error",
            messages: {
                default: "Cannot have a union containing only null types.",
            },
        },
        "union-unsupported": {
            severity: "error",
            messages: {
                default: "Unions cannot be emitted by our language generators unless all options are literals of the same type.",
                null: "Unions containing multiple model types cannot be emitted unless the union is between one model type and 'null'.",
            },
        },
        "use-enum-instead": {
            severity: "warning",
            messages: {
                default: "Use enum instead of union of string or number literals. Falling back to the literal type.",
            },
        },
        access: {
            severity: "error",
            messages: {
                default: `Access decorator value must be "public" or "internal".`,
            },
        },
        "invalid-usage": {
            severity: "error",
            messages: {
                default: `Usage decorator value must be 2 ("input") or 4 ("output").`,
            },
        },
        "invalid-encode": {
            severity: "error",
            messages: {
                default: "Invalid encoding",
                wrongType: paramMessage `Encoding '${"encoding"}' cannot be used on type '${"type"}'`,
            },
        },
        "conflicting-multipart-model-usage": {
            severity: "error",
            messages: {
                default: "Invalid encoding",
                wrongType: paramMessage `Model '${"modelName"}' cannot be used as both multipart/form-data input and regular body input. You can create a separate model with name 'model ${"modelName"}FormData' extends ${"modelName"} {}`,
            },
        },
        "discriminator-not-constant": {
            severity: "error",
            messages: {
                default: paramMessage `Discriminator ${"discriminator"} has to be constant`,
            },
        },
        "discriminator-not-string": {
            severity: "warning",
            messages: {
                default: paramMessage `Value of discriminator ${"discriminator"} has to be a string, not ${"discriminatorValue"}`,
            },
        },
        "wrong-client-decorator": {
            severity: "warning",
            messages: {
                default: "@client or @operationGroup should decorate namespace or interface in client.tsp",
            },
        },
        "encoding-multipart-bytes": {
            severity: "error",
            messages: {
                default: "Encoding should not be applied to bytes content in a multipart request. This is semi-incompatible with how multipart works in HTTP.",
            },
        },
        "unsupported-kind": {
            severity: "warning",
            messages: {
                default: paramMessage `Unsupported kind ${"kind"}`,
            },
        },
        "multiple-services": {
            severity: "warning",
            messages: {
                default: paramMessage `Multiple services found in definition. Only one service is supported, so we will choose the first one ${"service"}`,
            },
        },
        "server-param-not-path": {
            severity: "error",
            messages: {
                default: paramMessage `Template argument ${"templateArgumentName"} is not a path parameter, it is a ${"templateArgumentType"}. It has to be a path.`,
            },
        },
        "unexpected-http-param-type": {
            severity: "error",
            messages: {
                default: paramMessage `Expected parameter "${"paramName"}" to be of type "${"expectedType"}", but instead it is of type "${"actualType"}"`,
            },
        },
        "multiple-response-types": {
            severity: "warning",
            messages: {
                default: paramMessage `Multiple response types found in operation ${"operation"}. Only one response type is supported, so we will choose the first one ${"response"}`,
            },
        },
        "no-corresponding-method-param": {
            severity: "error",
            messages: {
                default: paramMessage `Missing "${"paramName"}" method parameter in method "${"methodName"}", when "${"paramName"}" must be sent to the service. Add a parameter named "${"paramName"}" to the method.`,
            },
        },
        "unsupported-protocol": {
            severity: "error",
            messages: {
                default: "Currently we only support HTTP and HTTPS protocols",
            },
        },
        "no-emitter-name": {
            severity: "warning",
            messages: {
                default: "Can not find name for your emitter, please check your emitter name.",
            },
        },
        "unsupported-generic-decorator-arg-type": {
            severity: "warning",
            messages: {
                default: paramMessage `Can not parse the arg type for decorator "${"decoratorName"}".`,
            },
        },
        "empty-client-name": {
            severity: "warning",
            messages: {
                default: `Cannot pass an empty value to the @clientName decorator`,
            },
        },
    },
});
const { reportDiagnostic, createDiagnostic, createStateSymbol } = $lib;

// Regexps involved with splitting words in various case formats.
const SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu;
const SPLIT_UPPER_UPPER_RE = /(\p{Lu})([\p{Lu}][\p{Ll}])/gu;
// Used to iterate over the initial split result and separate numbers.
const SPLIT_SEPARATE_NUMBER_RE = /(\d)\p{Ll}|(\p{L})\d/u;
// Regexp involved with stripping non-word characters from the result.
const DEFAULT_STRIP_REGEXP = /[^\p{L}\d]+/giu;
// The replacement value for splits.
const SPLIT_REPLACE_VALUE = "$1\0$2";
// The default characters to keep after transforming case.
const DEFAULT_PREFIX_SUFFIX_CHARACTERS = "";
/**
 * Split any cased input strings into an array of words.
 */
function split(value) {
    let result = value.trim();
    result = result
        .replace(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE)
        .replace(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE);
    result = result.replace(DEFAULT_STRIP_REGEXP, "\0");
    let start = 0;
    let end = result.length;
    // Trim the delimiter from around the output string.
    while (result.charAt(start) === "\0")
        start++;
    if (start === end)
        return [];
    while (result.charAt(end - 1) === "\0")
        end--;
    return result.slice(start, end).split(/\0/g);
}
/**
 * Split the input string into an array of words, separating numbers.
 */
function splitSeparateNumbers(value) {
    const words = split(value);
    for (let i = 0; i < words.length; i++) {
        const word = words[i];
        const match = SPLIT_SEPARATE_NUMBER_RE.exec(word);
        if (match) {
            const offset = match.index + (match[1] ?? match[2]).length;
            words.splice(i, 1, word.slice(0, offset), word.slice(offset));
        }
    }
    return words;
}
/**
 * Convert a string to camel case (`fooBar`).
 */
function camelCase(input, options) {
    const [prefix, words, suffix] = splitPrefixSuffix(input, options);
    const lower = lowerFactory(options?.locale);
    const upper = upperFactory(options?.locale);
    const transform = pascalCaseTransformFactory(lower, upper);
    return (prefix +
        words
            .map((word, index) => {
            if (index === 0)
                return lower(word);
            return transform(word, index);
        })
            .join("") +
        suffix);
}
/**
 * Convert a string to pascal case (`FooBar`).
 */
function pascalCase(input, options) {
    const [prefix, words, suffix] = splitPrefixSuffix(input, options);
    const lower = lowerFactory(options?.locale);
    const upper = upperFactory(options?.locale);
    const transform = pascalCaseTransformFactory(lower, upper);
    return prefix + words.map(transform).join("") + suffix;
}
function lowerFactory(locale) {
    return (input) => input.toLocaleLowerCase(locale);
}
function upperFactory(locale) {
    return (input) => input.toLocaleUpperCase(locale);
}
function pascalCaseTransformFactory(lower, upper) {
    return (word, index) => {
        const char0 = word[0];
        const initial = index > 0 && char0 >= "0" && char0 <= "9" ? "_" + char0 : upper(char0);
        return initial + lower(word.slice(1));
    };
}
function splitPrefixSuffix(input, options = {}) {
    const splitFn = options.split ?? (options.separateNumbers ? splitSeparateNumbers : split);
    const prefixCharacters = options.prefixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
    const suffixCharacters = options.suffixCharacters ?? DEFAULT_PREFIX_SUFFIX_CHARACTERS;
    let prefixIndex = 0;
    let suffixIndex = input.length;
    while (prefixIndex < input.length) {
        const char = input.charAt(prefixIndex);
        if (!prefixCharacters.includes(char))
            break;
        prefixIndex++;
    }
    while (suffixIndex > prefixIndex) {
        const index = suffixIndex - 1;
        const char = input.charAt(index);
        if (!suffixCharacters.includes(char))
            break;
        suffixIndex = index;
    }
    return [
        input.slice(0, prefixIndex),
        splitFn(input.slice(prefixIndex, suffixIndex)),
        input.slice(suffixIndex),
    ];
}

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function getDefaultExportFromCjs (x) {
	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}

function commonjsRequire(path) {
	throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}

var pluralize$1 = {exports: {}};

/* global define */

(function (module, exports) {
	(function (root, pluralize) {
	  /* istanbul ignore else */
	  if (typeof commonjsRequire === 'function' && 'object' === 'object' && 'object' === 'object') {
	    // Node.
	    module.exports = pluralize();
	  } else {
	    // Browser global.
	    root.pluralize = pluralize();
	  }
	})(commonjsGlobal, function () {
	  // Rule storage - pluralize and singularize need to be run sequentially,
	  // while other rules can be optimized using an object for instant lookups.
	  var pluralRules = [];
	  var singularRules = [];
	  var uncountables = {};
	  var irregularPlurals = {};
	  var irregularSingles = {};

	  /**
	   * Sanitize a pluralization rule to a usable regular expression.
	   *
	   * @param  {(RegExp|string)} rule
	   * @return {RegExp}
	   */
	  function sanitizeRule (rule) {
	    if (typeof rule === 'string') {
	      return new RegExp('^' + rule + '$', 'i');
	    }

	    return rule;
	  }

	  /**
	   * Pass in a word token to produce a function that can replicate the case on
	   * another word.
	   *
	   * @param  {string}   word
	   * @param  {string}   token
	   * @return {Function}
	   */
	  function restoreCase (word, token) {
	    // Tokens are an exact match.
	    if (word === token) return token;

	    // Lower cased words. E.g. "hello".
	    if (word === word.toLowerCase()) return token.toLowerCase();

	    // Upper cased words. E.g. "WHISKY".
	    if (word === word.toUpperCase()) return token.toUpperCase();

	    // Title cased words. E.g. "Title".
	    if (word[0] === word[0].toUpperCase()) {
	      return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
	    }

	    // Lower cased words. E.g. "test".
	    return token.toLowerCase();
	  }

	  /**
	   * Interpolate a regexp string.
	   *
	   * @param  {string} str
	   * @param  {Array}  args
	   * @return {string}
	   */
	  function interpolate (str, args) {
	    return str.replace(/\$(\d{1,2})/g, function (match, index) {
	      return args[index] || '';
	    });
	  }

	  /**
	   * Replace a word using a rule.
	   *
	   * @param  {string} word
	   * @param  {Array}  rule
	   * @return {string}
	   */
	  function replace (word, rule) {
	    return word.replace(rule[0], function (match, index) {
	      var result = interpolate(rule[1], arguments);

	      if (match === '') {
	        return restoreCase(word[index - 1], result);
	      }

	      return restoreCase(match, result);
	    });
	  }

	  /**
	   * Sanitize a word by passing in the word and sanitization rules.
	   *
	   * @param  {string}   token
	   * @param  {string}   word
	   * @param  {Array}    rules
	   * @return {string}
	   */
	  function sanitizeWord (token, word, rules) {
	    // Empty string or doesn't need fixing.
	    if (!token.length || uncountables.hasOwnProperty(token)) {
	      return word;
	    }

	    var len = rules.length;

	    // Iterate over the sanitization rules and use the first one to match.
	    while (len--) {
	      var rule = rules[len];

	      if (rule[0].test(word)) return replace(word, rule);
	    }

	    return word;
	  }

	  /**
	   * Replace a word with the updated word.
	   *
	   * @param  {Object}   replaceMap
	   * @param  {Object}   keepMap
	   * @param  {Array}    rules
	   * @return {Function}
	   */
	  function replaceWord (replaceMap, keepMap, rules) {
	    return function (word) {
	      // Get the correct token and case restoration functions.
	      var token = word.toLowerCase();

	      // Check against the keep object map.
	      if (keepMap.hasOwnProperty(token)) {
	        return restoreCase(word, token);
	      }

	      // Check against the replacement map for a direct word replacement.
	      if (replaceMap.hasOwnProperty(token)) {
	        return restoreCase(word, replaceMap[token]);
	      }

	      // Run all the rules against the word.
	      return sanitizeWord(token, word, rules);
	    };
	  }

	  /**
	   * Check if a word is part of the map.
	   */
	  function checkWord (replaceMap, keepMap, rules, bool) {
	    return function (word) {
	      var token = word.toLowerCase();

	      if (keepMap.hasOwnProperty(token)) return true;
	      if (replaceMap.hasOwnProperty(token)) return false;

	      return sanitizeWord(token, token, rules) === token;
	    };
	  }

	  /**
	   * Pluralize or singularize a word based on the passed in count.
	   *
	   * @param  {string}  word      The word to pluralize
	   * @param  {number}  count     How many of the word exist
	   * @param  {boolean} inclusive Whether to prefix with the number (e.g. 3 ducks)
	   * @return {string}
	   */
	  function pluralize (word, count, inclusive) {
	    var pluralized = count === 1
	      ? pluralize.singular(word) : pluralize.plural(word);

	    return (inclusive ? count + ' ' : '') + pluralized;
	  }

	  /**
	   * Pluralize a word.
	   *
	   * @type {Function}
	   */
	  pluralize.plural = replaceWord(
	    irregularSingles, irregularPlurals, pluralRules
	  );

	  /**
	   * Check if a word is plural.
	   *
	   * @type {Function}
	   */
	  pluralize.isPlural = checkWord(
	    irregularSingles, irregularPlurals, pluralRules
	  );

	  /**
	   * Singularize a word.
	   *
	   * @type {Function}
	   */
	  pluralize.singular = replaceWord(
	    irregularPlurals, irregularSingles, singularRules
	  );

	  /**
	   * Check if a word is singular.
	   *
	   * @type {Function}
	   */
	  pluralize.isSingular = checkWord(
	    irregularPlurals, irregularSingles, singularRules
	  );

	  /**
	   * Add a pluralization rule to the collection.
	   *
	   * @param {(string|RegExp)} rule
	   * @param {string}          replacement
	   */
	  pluralize.addPluralRule = function (rule, replacement) {
	    pluralRules.push([sanitizeRule(rule), replacement]);
	  };

	  /**
	   * Add a singularization rule to the collection.
	   *
	   * @param {(string|RegExp)} rule
	   * @param {string}          replacement
	   */
	  pluralize.addSingularRule = function (rule, replacement) {
	    singularRules.push([sanitizeRule(rule), replacement]);
	  };

	  /**
	   * Add an uncountable word rule.
	   *
	   * @param {(string|RegExp)} word
	   */
	  pluralize.addUncountableRule = function (word) {
	    if (typeof word === 'string') {
	      uncountables[word.toLowerCase()] = true;
	      return;
	    }

	    // Set singular and plural references for the word.
	    pluralize.addPluralRule(word, '$0');
	    pluralize.addSingularRule(word, '$0');
	  };

	  /**
	   * Add an irregular word definition.
	   *
	   * @param {string} single
	   * @param {string} plural
	   */
	  pluralize.addIrregularRule = function (single, plural) {
	    plural = plural.toLowerCase();
	    single = single.toLowerCase();

	    irregularSingles[single] = plural;
	    irregularPlurals[plural] = single;
	  };

	  /**
	   * Irregular rules.
	   */
	  [
	    // Pronouns.
	    ['I', 'we'],
	    ['me', 'us'],
	    ['he', 'they'],
	    ['she', 'they'],
	    ['them', 'them'],
	    ['myself', 'ourselves'],
	    ['yourself', 'yourselves'],
	    ['itself', 'themselves'],
	    ['herself', 'themselves'],
	    ['himself', 'themselves'],
	    ['themself', 'themselves'],
	    ['is', 'are'],
	    ['was', 'were'],
	    ['has', 'have'],
	    ['this', 'these'],
	    ['that', 'those'],
	    // Words ending in with a consonant and `o`.
	    ['echo', 'echoes'],
	    ['dingo', 'dingoes'],
	    ['volcano', 'volcanoes'],
	    ['tornado', 'tornadoes'],
	    ['torpedo', 'torpedoes'],
	    // Ends with `us`.
	    ['genus', 'genera'],
	    ['viscus', 'viscera'],
	    // Ends with `ma`.
	    ['stigma', 'stigmata'],
	    ['stoma', 'stomata'],
	    ['dogma', 'dogmata'],
	    ['lemma', 'lemmata'],
	    ['schema', 'schemata'],
	    ['anathema', 'anathemata'],
	    // Other irregular rules.
	    ['ox', 'oxen'],
	    ['axe', 'axes'],
	    ['die', 'dice'],
	    ['yes', 'yeses'],
	    ['foot', 'feet'],
	    ['eave', 'eaves'],
	    ['goose', 'geese'],
	    ['tooth', 'teeth'],
	    ['quiz', 'quizzes'],
	    ['human', 'humans'],
	    ['proof', 'proofs'],
	    ['carve', 'carves'],
	    ['valve', 'valves'],
	    ['looey', 'looies'],
	    ['thief', 'thieves'],
	    ['groove', 'grooves'],
	    ['pickaxe', 'pickaxes'],
	    ['passerby', 'passersby']
	  ].forEach(function (rule) {
	    return pluralize.addIrregularRule(rule[0], rule[1]);
	  });

	  /**
	   * Pluralization rules.
	   */
	  [
	    [/s?$/i, 's'],
	    [/[^\u0000-\u007F]$/i, '$0'],
	    [/([^aeiou]ese)$/i, '$1'],
	    [/(ax|test)is$/i, '$1es'],
	    [/(alias|[^aou]us|t[lm]as|gas|ris)$/i, '$1es'],
	    [/(e[mn]u)s?$/i, '$1s'],
	    [/([^l]ias|[aeiou]las|[ejzr]as|[iu]am)$/i, '$1'],
	    [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'],
	    [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
	    [/(seraph|cherub)(?:im)?$/i, '$1im'],
	    [/(her|at|gr)o$/i, '$1oes'],
	    [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'],
	    [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'],
	    [/sis$/i, 'ses'],
	    [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'],
	    [/([^aeiouy]|qu)y$/i, '$1ies'],
	    [/([^ch][ieo][ln])ey$/i, '$1ies'],
	    [/(x|ch|ss|sh|zz)$/i, '$1es'],
	    [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
	    [/\b((?:tit)?m|l)(?:ice|ouse)$/i, '$1ice'],
	    [/(pe)(?:rson|ople)$/i, '$1ople'],
	    [/(child)(?:ren)?$/i, '$1ren'],
	    [/eaux$/i, '$0'],
	    [/m[ae]n$/i, 'men'],
	    ['thou', 'you']
	  ].forEach(function (rule) {
	    return pluralize.addPluralRule(rule[0], rule[1]);
	  });

	  /**
	   * Singularization rules.
	   */
	  [
	    [/s$/i, ''],
	    [/(ss)$/i, '$1'],
	    [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'],
	    [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
	    [/ies$/i, 'y'],
	    [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'],
	    [/\b(mon|smil)ies$/i, '$1ey'],
	    [/\b((?:tit)?m|l)ice$/i, '$1ouse'],
	    [/(seraph|cherub)im$/i, '$1'],
	    [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|t[lm]as|gas|(?:her|at|gr)o|[aeiou]ris)(?:es)?$/i, '$1'],
	    [/(analy|diagno|parenthe|progno|synop|the|empha|cri|ne)(?:sis|ses)$/i, '$1sis'],
	    [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
	    [/(test)(?:is|es)$/i, '$1is'],
	    [/(alumn|syllab|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'],
	    [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'],
	    [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'],
	    [/(alumn|alg|vertebr)ae$/i, '$1a'],
	    [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
	    [/(matr|append)ices$/i, '$1ix'],
	    [/(pe)(rson|ople)$/i, '$1rson'],
	    [/(child)ren$/i, '$1'],
	    [/(eau)x?$/i, '$1'],
	    [/men$/i, 'man']
	  ].forEach(function (rule) {
	    return pluralize.addSingularRule(rule[0], rule[1]);
	  });

	  /**
	   * Uncountable rules.
	   */
	  [
	    // Singular words with no plurals.
	    'adulthood',
	    'advice',
	    'agenda',
	    'aid',
	    'aircraft',
	    'alcohol',
	    'ammo',
	    'analytics',
	    'anime',
	    'athletics',
	    'audio',
	    'bison',
	    'blood',
	    'bream',
	    'buffalo',
	    'butter',
	    'carp',
	    'cash',
	    'chassis',
	    'chess',
	    'clothing',
	    'cod',
	    'commerce',
	    'cooperation',
	    'corps',
	    'debris',
	    'diabetes',
	    'digestion',
	    'elk',
	    'energy',
	    'equipment',
	    'excretion',
	    'expertise',
	    'firmware',
	    'flounder',
	    'fun',
	    'gallows',
	    'garbage',
	    'graffiti',
	    'hardware',
	    'headquarters',
	    'health',
	    'herpes',
	    'highjinks',
	    'homework',
	    'housework',
	    'information',
	    'jeans',
	    'justice',
	    'kudos',
	    'labour',
	    'literature',
	    'machinery',
	    'mackerel',
	    'mail',
	    'media',
	    'mews',
	    'moose',
	    'music',
	    'mud',
	    'manga',
	    'news',
	    'only',
	    'personnel',
	    'pike',
	    'plankton',
	    'pliers',
	    'police',
	    'pollution',
	    'premises',
	    'rain',
	    'research',
	    'rice',
	    'salmon',
	    'scissors',
	    'series',
	    'sewage',
	    'shambles',
	    'shrimp',
	    'software',
	    'species',
	    'staff',
	    'swine',
	    'tennis',
	    'traffic',
	    'transportation',
	    'trout',
	    'tuna',
	    'wealth',
	    'welfare',
	    'whiting',
	    'wildebeest',
	    'wildlife',
	    'you',
	    /pok[eé]mon$/i,
	    // Regexes.
	    /[^aeiou]ese$/i, // "chinese", "japanese"
	    /deer$/i, // "deer", "reindeer"
	    /fish$/i, // "fish", "blowfish", "angelfish"
	    /measles$/i,
	    /o[iu]s$/i, // "carnivorous"
	    /pox$/i, // "chickpox", "smallpox"
	    /sheep$/i
	  ].forEach(pluralize.addUncountableRule);

	  return pluralize;
	}); 
} (pluralize$1));

var pluralizeExports = pluralize$1.exports;
var pluralize = /*@__PURE__*/getDefaultExportFromCjs(pluralizeExports);

/**
 * Return the default api version for a versioned service. Will return undefined if one does not exist
 * @param program
 * @param serviceNamespace
 * @returns
 */
function getDefaultApiVersion(context, serviceNamespace) {
    try {
        const versions = getVersions(context.program, serviceNamespace)[1].getVersions();
        removeVersionsLargerThanExplicitlySpecified(context, versions);
        // follow versioning principals of the versioning library and return last in list
        return versions[versions.length - 1];
    }
    catch (e) {
        return undefined;
    }
}
/**
 * Return whether a parameter is the Api Version parameter of a client
 * @param program
 * @param parameter
 * @returns
 */
function isApiVersion(context, type) {
    return (type.name.toLowerCase().includes("apiversion") ||
        type.name.toLowerCase().includes("api-version"));
}
/**
 * Get the client's namespace for generation. If package-name is passed in config, we return
 * that value as our namespace. Otherwise, we default to the TypeSpec service namespace.
 * @param program
 * @param context
 * @returns
 */
function getClientNamespaceString(context) {
    return getClientNamespaceStringHelper(context, listServices(context.program)[0]?.type);
}
/**
 * If the given type is an anonymous model and all of its properties excluding
 * header/query/path/status-code are sourced from a named model, returns that original named model.
 * Otherwise the given type is returned unchanged.
 *
 * @param context
 * @param type
 * @returns
 */
function getEffectivePayloadType(context, type) {
    const program = context.program;
    // if a type has name, we should resolve the name
    // this logic is for template cases, for e.g.,
    // model Catalog is TrackedResource<CatalogProperties>{}
    // model Deployment is TrackedResource<DeploymentProperties>{}
    // when pass them to getEffectiveModelType, we will get two different types
    // with the same name "TrackedResource" which will loose original infomation
    if (type.name) {
        return type;
    }
    const effective = getEffectiveModelType(program, type, (t) => !isMetadata(context.program, t));
    if (effective.name) {
        return effective;
    }
    return type;
}
/**
 *
 * @deprecated This function is deprecated. Please pass in your emitter name as a parameter name to createSdkContext
 */
function getEmitterTargetName(context) {
    return ignoreDiagnostics(parseEmitterName(context.program, context.program.emitters[0]?.metadata?.name)); // eslint-disable-line deprecation/deprecation
}
/**
 * Get the library and wire name of a model property. Takes @clientName and @encodedName into account
 * @param context
 * @param property
 * @returns a tuple of the library and wire name for a model property
 */
function getPropertyNames(context, property) {
    return [getLibraryName(context, property), getWireName(context, property)];
}
/**
 * Get the library name of a property / parameter / operation / model / enum. Takes projections into account
 *
 * Returns name in the following order of priority
 * 1. language emitter name, i.e. @clientName("csharpSpecificName", "csharp") => "csharpSpecificName"
 * 2. client name, i.e. @clientName(""clientName") => "clientName"
 * 3. deprecated projected name
 * 4. friendly name, i.e. @friendlyName("friendlyName") => "friendlyName"
 * 5. name in typespec
 *
 * @param context
 * @param type
 * @returns the library name for a typespec type
 */
function getLibraryName(context, type) {
    // 1. check if there's a client name
    let emitterSpecificName = getClientNameOverride(context, type);
    if (emitterSpecificName && emitterSpecificName !== type.name)
        return emitterSpecificName;
    // 2. check if there's a specific name for our language with deprecated @projectedName
    emitterSpecificName = getProjectedName(context.program, type, context.emitterName);
    if (emitterSpecificName && emitterSpecificName !== type.name)
        return emitterSpecificName;
    // 3. check if there's a client name with deprecated @projectedName
    const clientSpecificName = getProjectedName(context.program, type, "client");
    if (clientSpecificName && emitterSpecificName !== type.name)
        return clientSpecificName;
    // 4. check if there's a friendly name, if so return friendly name
    const friendlyName = getFriendlyName(context.program, type);
    if (friendlyName)
        return friendlyName;
    // 5. if type is derived from template and name is the same as template, add template parameters' name as suffix
    if (typeof type.name === "string" && type.kind === "Model" && type.templateMapper?.args) {
        return (type.name +
            type.templateMapper.args
                .filter((arg) => "kind" in arg &&
                (arg.kind === "Model" || arg.kind === "Enum" || arg.kind === "Union") &&
                arg.name !== undefined &&
                arg.name.length > 0)
                .map((arg) => pascalCase(arg.name))
                .join(""));
    }
    return typeof type.name === "string" ? type.name : "";
}
/**
 * Get the serialized name of a type.
 * @param context
 * @param type
 * @returns
 */
function getWireName(context, type) {
    // 1. Check if there's an encoded name
    const encodedName = resolveEncodedName(context.program, type, "application/json");
    if (encodedName !== type.name)
        return encodedName;
    // 2. Check if there's deprecated language projection
    return getProjectedName(context.program, type, "json") ?? type.name;
}
/**
 * Helper function to return cross language definition id for a type
 * @param type
 * @returns
 */
function getCrossLanguageDefinitionId(context, type, operation, appendNamespace = true) {
    let retval = type.name || "anonymous";
    const namespace = type.kind === "ModelProperty" ? type.model?.namespace : type.namespace;
    switch (type.kind) {
        case "Union":
        case "Model":
            // Enum and Scalar will always have a name
            if (type.name) {
                break;
            }
            const contextPath = operation
                ? getContextPath(context, operation, type)
                : findContextPath(context, type);
            retval =
                contextPath
                    .slice(findLastNonAnonymousModelNode(contextPath))
                    .map((x) => x.type?.kind === "Model" || x.type?.kind === "Union"
                    ? x.type.name || x.name
                    : x.name || "anonymous")
                    .join(".") +
                    "." +
                    retval;
            break;
        case "ModelProperty":
            if (type.model) {
                retval = `${getCrossLanguageDefinitionId(context, type.model, undefined, false)}.${retval}`;
            }
            break;
        case "Operation":
            if (type.interface) {
                retval = `${getCrossLanguageDefinitionId(context, type.interface, undefined, false)}.${retval}`;
            }
            break;
    }
    if (appendNamespace && namespace && getNamespaceFullName(namespace)) {
        retval = `${getNamespaceFullName(namespace)}.${retval}`;
    }
    return retval;
}
/**
 * Helper function return the cross langauge package id for a package
 */
function getCrossLanguagePackageId(context) {
    const diagnostics = createDiagnosticCollector();
    const services = listServices(context.program);
    if (services.length === 0)
        return diagnostics.wrap("");
    const serviceNamespace = getNamespaceFullName(services[0].type);
    if (services.length > 1) {
        diagnostics.add(createDiagnostic({
            code: "multiple-services",
            target: services[0].type,
            format: {
                service: serviceNamespace,
            },
        }));
    }
    return diagnostics.wrap(serviceNamespace);
}
/**
 * Create a name for anonymous model
 * @param context
 * @param type
 */
function getGeneratedName(context, type, operation) {
    if (!context.generatedNames) {
        context.generatedNames = new Map();
    }
    const generatedName = context.generatedNames.get(type);
    if (generatedName)
        return generatedName;
    const contextPath = operation
        ? getContextPath(context, operation, type)
        : findContextPath(context, type);
    const createdName = buildNameFromContextPaths(context, type, contextPath);
    return createdName;
}
/**
 * Traverse each operation and model to find one possible context path for the given type.
 * @param context
 * @param type
 * @returns
 */
function findContextPath(context, type) {
    for (const client of listClients(context)) {
        // orphan models
        if (client.service) {
            for (const model of client.service.models.values()) {
                if ([...model.properties.values()].filter((p) => !isMetadata(context.program, p)).length === 0)
                    continue;
                const result = getContextPath(context, model, type);
                if (result.length > 0) {
                    return result;
                }
            }
        }
        for (const operation of listOperationsInOperationGroup(context, client)) {
            const result = getContextPath(context, operation, type);
            if (result.length > 0) {
                return result;
            }
        }
        const ogs = listOperationGroups(context, client);
        while (ogs.length) {
            const operationGroup = ogs.pop();
            for (const operation of listOperationsInOperationGroup(context, operationGroup)) {
                const result = getContextPath(context, operation, type);
                if (result.length > 0) {
                    return result;
                }
            }
            if (operationGroup?.subOperationGroups) {
                ogs.push(...operationGroup.subOperationGroups);
            }
        }
    }
    return [];
}
/**
 * Find one possible context path for the given type in the given operation or model.
 * @param context
 * @param root
 * @param typeToFind
 * @returns
 */
function getContextPath(context, root, typeToFind) {
    // use visited set to avoid cycle model reference
    const visited = new Set();
    let result;
    if (root.kind === "Operation") {
        const httpOperation = getHttpOperationWithCache(context, root);
        if (httpOperation.parameters.body) {
            visited.clear();
            result = [{ name: root.name }];
            if (dfsModelProperties(typeToFind, httpOperation.parameters.body.type, "Request")) {
                return result;
            }
        }
        for (const parameter of Object.values(httpOperation.parameters.parameters)) {
            visited.clear();
            result = [{ name: root.name }];
            if (dfsModelProperties(typeToFind, parameter.param.type, `Request${pascalCase(parameter.name)}`)) {
                return result;
            }
        }
        for (const response of httpOperation.responses) {
            for (const innerResponse of response.responses) {
                if (innerResponse.body?.type) {
                    const body = innerResponse.body.type.kind === "Model"
                        ? getEffectivePayloadType(context, innerResponse.body.type)
                        : innerResponse.body.type;
                    visited.clear();
                    result = [{ name: root.name }];
                    if (dfsModelProperties(typeToFind, body, "Response")) {
                        return result;
                    }
                }
                const headers = getHttpOperationResponseHeaders(innerResponse);
                if (headers) {
                    for (const header of Object.values(headers)) {
                        visited.clear();
                        result = [{ name: root.name }];
                        if (dfsModelProperties(typeToFind, header.type, `Response${pascalCase(header.name)}`)) {
                            return result;
                        }
                    }
                }
            }
        }
    }
    else {
        visited.clear();
        result = [];
        if (dfsModelProperties(typeToFind, root, root.name)) {
            return result;
        }
    }
    return [];
    /**
     * Traverse each node, if it is not model or union, no need to traverse anymore.
     * If it is the expected type just return.
     * If it is array or dict, traverse the array/dict item node. e.g. {name: string}[] case.
     * If it is model, add the current node to the path and traverse each property node.
     * If it is model, traverse the base and derived model node if existed.
     * @param expectedType
     * @param currentType
     * @param displayName
     * @param currentContextPath
     * @param contextPaths
     * @param visited
     * @returns
     */
    function dfsModelProperties(expectedType, currentType, displayName) {
        if (currentType == null || visited.has(currentType)) {
            // cycle reference detected
            return false;
        }
        if (!["Model", "Union", "String", "Number", "Boolean"].includes(currentType.kind)) {
            return false;
        }
        visited.add(currentType);
        if (currentType === expectedType) {
            result.push({ name: displayName, type: currentType });
            return true;
        }
        else if (currentType.kind === "Model" &&
            currentType.indexer &&
            currentType.properties.size === 0 &&
            ((currentType.indexer.key.name === "string" && currentType.name === "Record") ||
                currentType.indexer.key.name === "integer")) {
            // handle array or dict
            const dictOrArrayItemType = currentType.indexer.value;
            return dfsModelProperties(expectedType, dictOrArrayItemType, pluralize.singular(displayName));
        }
        else if (currentType.kind === "Model") {
            // handle model
            result.push({ name: displayName, type: currentType });
            for (const property of currentType.properties.values()) {
                // traverse model property
                // use property.name as displayName
                const result = dfsModelProperties(expectedType, property.type, property.name);
                if (result)
                    return true;
            }
            // handle additional properties type: model MyModel is Record<> {}
            if (currentType.sourceModel?.kind === "Model" && currentType.sourceModel?.name === "Record") {
                const result = dfsModelProperties(expectedType, currentType.sourceModel.indexer.value, "AdditionalProperty");
                if (result)
                    return true;
            }
            // handle additional properties type: model MyModel { ...Record<>}
            if (currentType.indexer) {
                const result = dfsModelProperties(expectedType, currentType.indexer.value, "AdditionalProperty");
                if (result)
                    return true;
            }
            // handle additional properties type: model MyModel extends Record<> {}
            if (currentType.baseModel) {
                if (currentType.baseModel.name === "Record") {
                    const result = dfsModelProperties(expectedType, currentType.baseModel.indexer.value, "AdditionalProperty");
                    if (result)
                        return true;
                }
            }
            result.pop();
            if (currentType.baseModel) {
                const result = dfsModelProperties(expectedType, currentType.baseModel, currentType.baseModel.name);
                if (result)
                    return true;
            }
            for (const derivedModel of currentType.derivedModels) {
                const result = dfsModelProperties(expectedType, derivedModel, derivedModel.name);
                if (result)
                    return true;
            }
            return false;
        }
        else if (currentType.kind === "Union") {
            // handle union
            for (const unionType of currentType.variants.values()) {
                // traverse union type
                // use unionType.name as displayName
                const result = dfsModelProperties(expectedType, unionType.type, displayName);
                if (result)
                    return true;
            }
            return false;
        }
        else {
            return false;
        }
    }
}
function findLastNonAnonymousModelNode(contextPath) {
    let lastNonAnonymousModelNodeIndex = contextPath.length - 1;
    while (lastNonAnonymousModelNodeIndex >= 0) {
        const currType = contextPath[lastNonAnonymousModelNodeIndex].type;
        if (!contextPath[lastNonAnonymousModelNodeIndex].type ||
            (currType?.kind === "Model" && currType.name)) {
            // it's nonanonymous model node (if no type defined, it's the operation node)
            break;
        }
        else {
            --lastNonAnonymousModelNodeIndex;
        }
    }
    return lastNonAnonymousModelNodeIndex;
}
/**
 * The logic is basically three steps:
 * 1. find the last nonanonymous model node, this node can be operation node or model node which is not anonymous
 * 2. build the name from the last nonanonymous model node to the end of the path
 * 3. simplely handle duplication with adding number suffix
 * @param contextPaths
 * @returns
 */
function buildNameFromContextPaths(context, type, contextPath) {
    // fallback to empty name for corner case
    if (contextPath.length === 0) {
        return "";
    }
    // 1. find the last nonanonymous model node
    const lastNonAnonymousModelNodeIndex = findLastNonAnonymousModelNode(contextPath);
    // 2. build name
    let createName = "";
    for (let j = lastNonAnonymousModelNodeIndex; j < contextPath.length; j++) {
        const currContextPathType = contextPath[j]?.type;
        if (currContextPathType?.kind === "String" ||
            currContextPathType?.kind === "Number" ||
            currContextPathType?.kind === "Boolean") {
            // constant type
            createName = `${createName}${pascalCase(contextPath[j].name)}`;
        }
        else if (!currContextPathType?.name) {
            // is anonymous model node
            createName = `${createName}${pascalCase(contextPath[j].name)}`;
        }
        else {
            // is non-anonymous model, use type name
            createName = `${createName}${currContextPathType.name}`;
        }
    }
    // 3. simplely handle duplication
    let duplicateCount = 1;
    const rawCreateName = createName;
    const generatedNames = [...(context.generatedNames?.values() ?? [])];
    while (generatedNames.includes(createName)) {
        createName = `${rawCreateName}${duplicateCount++}`;
    }
    if (context.generatedNames) {
        context.generatedNames.set(type, createName);
    }
    else {
        context.generatedNames = new Map([[type, createName]]);
    }
    return createName;
}
function getHttpOperationWithCache(context, operation) {
    if (context.httpOperationCache === undefined) {
        context.httpOperationCache = new Map();
    }
    if (context.httpOperationCache.has(operation)) {
        return context.httpOperationCache.get(operation);
    }
    const httpOperation = ignoreDiagnostics(getHttpOperation(context.program, operation));
    context.httpOperationCache.set(operation, httpOperation);
    return httpOperation;
}

/**
 *
 * @param emitterName Full emitter name
 * @returns The language of the emitter. I.e. "@azure-tools/typespec-csharp" will return "csharp"
 */
function parseEmitterName(program, emitterName) {
    const diagnostics = createDiagnosticCollector();
    if (!emitterName) {
        diagnostics.add(createDiagnostic({
            code: "no-emitter-name",
            format: {},
            target: program.getGlobalNamespaceType(),
        }));
        return diagnostics.wrap("none");
    }
    const regex = /(?:cadl|typespec|client|server)-([^\\/-]*)/;
    const match = emitterName.match(regex);
    if (!match || match.length < 2)
        return diagnostics.wrap("none");
    const language = match[1];
    if (["typescript", "ts"].includes(language))
        return diagnostics.wrap("javascript");
    return diagnostics.wrap(language);
}
/**
 *
 * @param context
 * @param namespace If we know explicitly the namespace of the client, pass this in
 * @returns The name of the namespace
 */
function getClientNamespaceStringHelper(context, namespace) {
    let packageName = context.packageName;
    if (packageName) {
        packageName = packageName
            .replace(/-/g, ".")
            .replace(/\.([a-z])?/g, (match) => match.toUpperCase());
        return packageName.charAt(0).toUpperCase() + packageName.slice(1);
    }
    if (namespace) {
        return getNamespaceFullName(namespace);
    }
    return undefined;
}
/**
 *
 * @param context
 * @param type The type that we are adding api version information onto
 * @returns Whether the type is the api version parameter and the default value for the client
 */
function updateWithApiVersionInformation(context, type, namespace) {
    const isApiVersionParam = isApiVersion(context, type);
    return {
        isApiVersionParam,
        clientDefaultValue: isApiVersionParam && namespace
            ? context.__namespaceToApiVersionClientDefaultValue.get(namespace)
            : undefined,
        onClient: onClient(context, type),
    };
}
function filterApiVersionsWithDecorators(context, type, apiVersions) {
    const addedOnVersions = getAddedOnVersions(context.program, type)?.map((x) => x.value) ?? [];
    const removedOnVersions = getRemovedOnVersions(context.program, type)?.map((x) => x.value) ?? [];
    let added = addedOnVersions.length ? false : true;
    let addedCounter = 0;
    let removeCounter = 0;
    const retval = [];
    for (let i = 0; i < apiVersions.length; i++) {
        const version = apiVersions[i];
        if (addedCounter < addedOnVersions.length && version === addedOnVersions[addedCounter]) {
            added = true;
            addedCounter++;
        }
        if (removeCounter < removedOnVersions.length && version === removedOnVersions[removeCounter]) {
            added = false;
            removeCounter++;
        }
        if (added) {
            // only add version smaller than config
            if (context.apiVersion === undefined ||
                context.apiVersion === "latest" ||
                context.apiVersion === "all" ||
                apiVersions.indexOf(context.apiVersion) >= i) {
                retval.push(version);
            }
        }
    }
    return retval;
}
function sortAndRemoveDuplicates(a, b, apiVersions) {
    const union = Array.from(new Set([...a, ...b]));
    return apiVersions.filter((item) => union.includes(item));
}
/**
 *
 * @param context
 * @param type
 * @param client If it's associated with a client, meaning it's a param etc, we can see if it's available on that client
 * @returns All api versions the type is available on
 */
function getAvailableApiVersions(context, type, wrapper) {
    let wrapperApiVersions = [];
    if (wrapper) {
        wrapperApiVersions = context.__tspTypeToApiVersions.get(wrapper) || [];
    }
    const allApiVersions = getVersions(context.program, type)[1]
        ?.getVersions()
        .map((x) => x.value) || [];
    const apiVersions = wrapperApiVersions.length ? wrapperApiVersions : allApiVersions;
    if (!apiVersions)
        return [];
    const explicitlyDecorated = filterApiVersionsWithDecorators(context, type, apiVersions);
    if (explicitlyDecorated.length) {
        context.__tspTypeToApiVersions.set(type, explicitlyDecorated);
        return explicitlyDecorated;
    }
    // we take the union of all of the api versions that the type is available on
    // if it's called multiple times with diff wrappers, we want to make sure we have
    // all of the possible api versions listed
    const existing = context.__tspTypeToApiVersions.get(type) || [];
    const retval = sortAndRemoveDuplicates(wrapperApiVersions, existing, allApiVersions);
    context.__tspTypeToApiVersions.set(type, retval);
    return retval;
}
/**
 *
 * @param context
 * @param type
 * @returns Returns the description and details of a type
 */
function getDocHelper(context, type) {
    const program = context.program;
    if (getSummary(program, type)) {
        return {
            description: getSummary(program, type),
            details: getDoc(program, type),
        };
    }
    return {
        description: getDoc(program, type),
    };
}
/**
 *
 * @param type
 * @returns A unique id for each type so we can do set comparisons
 */
function getHashForType(type) {
    if (type.kind === "array" || type.kind === "dict") {
        return `${type.kind}[${getHashForType(type.valueType)}]`;
    }
    if (type.kind === "enum" || type.kind === "model" || type.kind === "enumvalue")
        return type.name;
    if (type.kind === "union") {
        return type.values.map((x) => getHashForType(x)).join("|");
    }
    return type.kind;
}
/**
 * Helper function to return default values for encode etc
 * @param type
 */
function getSdkTypeBaseHelper(context, type, kind) {
    const diagnostics = createDiagnosticCollector();
    return diagnostics.wrap({
        __raw: type,
        deprecation: getDeprecationDetails(context.program, type)?.message,
        kind,
        decorators: diagnostics.pipe(getTypeDecorators(context, type)),
    });
}
function getNamespacePrefix(namespace) {
    return namespace ? getNamespaceFullName(namespace) + "." : "";
}
function getTypeDecorators(context, type) {
    const diagnostics = createDiagnosticCollector();
    const retval = [];
    if ("decorators" in type) {
        for (const decorator of type.decorators) {
            // only process explicitly defined decorators
            if (decorator.definition) {
                const decoratorName = `${getNamespacePrefix(decorator.definition?.namespace)}${decorator.definition?.name}`;
                // white list filtering
                if (!context.decoratorsAllowList ||
                    !context.decoratorsAllowList.some((x) => new RegExp(x).test(decoratorName))) {
                    continue;
                }
                const decoratorInfo = {
                    name: decoratorName,
                    arguments: {},
                };
                for (let i = 0; i < decorator.args.length; i++) {
                    decoratorInfo.arguments[decorator.definition.parameters[i].name] = diagnostics.pipe(getDecoratorArgValue(decorator.args[i].jsValue, type, decoratorName));
                }
                retval.push(decoratorInfo);
            }
        }
    }
    return diagnostics.wrap(retval);
}
function getDecoratorArgValue(arg, type, decoratorName) {
    const diagnostics = createDiagnosticCollector();
    if (typeof arg === "object" && arg !== null && "kind" in arg) {
        if (arg.kind === "EnumMember") {
            return diagnostics.wrap(arg.value ?? arg.name);
        }
        if (arg.kind === "String" || arg.kind === "Number" || arg.kind === "Boolean") {
            return diagnostics.wrap(arg.value);
        }
        diagnostics.add(createDiagnostic({
            code: "unsupported-generic-decorator-arg-type",
            target: type,
            format: { decoratorName },
        }));
        return diagnostics.wrap(undefined);
    }
    return diagnostics.wrap(arg);
}
function intOrFloat(value) {
    return value.toString().indexOf(".") === -1 ? "int32" : "float32";
}
/**
 * Whether a model or enum or union as enum is in Azure.Core[.Foundations] namespace
 * @param t
 * @returns
 */
function isAzureCoreModel(t) {
    return ((t.kind === "Model" || t.kind === "Enum" || t.kind === "Union") &&
        t.namespace !== undefined &&
        ["Azure.Core", "Azure.Core.Foundations"].includes(getNamespaceFullName(t.namespace)));
}
function isAcceptHeader(param) {
    return param.kind === "header" && param.serializedName.toLowerCase() === "accept";
}
function isContentTypeHeader(param) {
    return param.kind === "header" && param.serializedName.toLowerCase() === "content-type";
}
function isMultipartOperation(context, operation) {
    if (!operation)
        return false;
    const httpOperation = getHttpOperationWithCache(context, operation);
    const httpBody = httpOperation.parameters.body;
    if (httpBody && httpBody.type.kind === "Model") {
        return httpBody.contentTypes.some((x) => x.startsWith("multipart/"));
    }
    return false;
}
function isHttpOperation(context, obj) {
    return obj?.kind === "Operation" && getHttpOperationWithCache(context, obj) !== undefined;
}
function getNonNullOptions(type) {
    return [...type.variants.values()].map((x) => x.type).filter((t) => !isNullType(t));
}
function getNullOption(type) {
    return [...type.variants.values()].map((x) => x.type).filter((t) => isNullType(t))[0];
}
function getAllResponseBodiesAndNonBodyExists(responses) {
    const allResponseBodies = [];
    let nonBodyExists = false;
    for (const response of responses.values()) {
        if (response.type) {
            if (response.type.kind === "nullable") {
                nonBodyExists = true;
            }
            allResponseBodies.push(response.type);
        }
        else {
            nonBodyExists = true;
        }
    }
    return { allResponseBodies, nonBodyExists };
}
/**
 * Use this if you are trying to create a generated name for something without an original TypeSpec type.
 *
 * Otherwise, you should use the `getGeneratedName` function.
 * @param context
 */
function createGeneratedName(context, type, suffix) {
    return `${getCrossLanguageDefinitionId(context, type).split(".").at(-1)}${suffix}`;
}
function isOperationBodyType(context, type, operation) {
    if (type.kind !== "Model")
        return false;
    if (!isHttpOperation(context, operation))
        return false;
    const httpBody = operation
        ? getHttpOperationWithCache(context, operation).parameters.body
        : undefined;
    return Boolean(httpBody &&
        httpBody.type.kind === "Model" &&
        getEffectivePayloadType(context, httpBody.type) === getEffectivePayloadType(context, type));
}
function isMultipartFormData(context, type, operation) {
    return isMultipartOperation(context, operation) && isOperationBodyType(context, type, operation);
}
function isSubscriptionId(context, parameter) {
    return Boolean(context.arm) && parameter.name === "subscriptionId";
}
function onClient(context, parameter) {
    return isSubscriptionId(context, parameter) || isApiVersion(context, parameter);
}
function getLocationOfOperation(operation) {
    // have to check interface first, because interfaces are more granular than namespaces
    return (operation.interface || operation.namespace);
}
function isNeverOrVoidType(type) {
    return isNeverType(type) || isVoidType(type);
}
function getAnyType(context, type) {
    const diagnostics = createDiagnosticCollector();
    return diagnostics.wrap({
        kind: "any",
        encode: "string",
        decorators: diagnostics.pipe(getTypeDecorators(context, type)),
    });
}
function getHttpOperationResponseHeaders(response) {
    const headers = response.headers ? Object.values(response.headers) : [];
    if (response.body?.contentTypeProperty) {
        headers.push(response.body.contentTypeProperty);
    }
    return headers;
}
function removeVersionsLargerThanExplicitlySpecified(context, versions) {
    // filter with specific api version
    if (context.apiVersion !== undefined &&
        context.apiVersion !== "latest" &&
        context.apiVersion !== "all") {
        const index = versions.findIndex((version) => version.value === context.apiVersion);
        if (index >= 0) {
            versions.splice(index + 1, versions.length - index - 1);
        }
    }
}
function filterApiVersionsInEnum(context, client, sdkVersionsEnum) {
    // if they explicitly set an api version, remove larger versions
    removeVersionsLargerThanExplicitlySpecified(context, sdkVersionsEnum.values);
    const defaultApiVersion = getDefaultApiVersion(context, client.service);
    if (!context.previewStringRegex.test(defaultApiVersion?.value || "")) {
        sdkVersionsEnum.values = sdkVersionsEnum.values.filter((v) => typeof v.value === "string" && !context.previewStringRegex.test(v.value));
    }
}
function isJsonContentType(contentType) {
    const regex = new RegExp(/^(application|text)\/(.+\+)?json$/);
    return regex.test(contentType);
}

var SdkIntKindsEnum;
(function (SdkIntKindsEnum) {
    SdkIntKindsEnum["numeric"] = "numeric";
    SdkIntKindsEnum["integer"] = "integer";
    SdkIntKindsEnum["safeint"] = "safeint";
    SdkIntKindsEnum["int8"] = "int8";
    SdkIntKindsEnum["int16"] = "int16";
    SdkIntKindsEnum["int32"] = "int32";
    SdkIntKindsEnum["int64"] = "int64";
    SdkIntKindsEnum["uint8"] = "uint8";
    SdkIntKindsEnum["uint16"] = "uint16";
    SdkIntKindsEnum["uint32"] = "uint32";
    SdkIntKindsEnum["uint64"] = "uint64";
})(SdkIntKindsEnum || (SdkIntKindsEnum = {}));
var SdkFloatKindsEnum;
(function (SdkFloatKindsEnum) {
    SdkFloatKindsEnum["float"] = "float";
    SdkFloatKindsEnum["float32"] = "float32";
    SdkFloatKindsEnum["float64"] = "float64";
    SdkFloatKindsEnum["decimal"] = "decimal";
    SdkFloatKindsEnum["decimal128"] = "decimal128";
})(SdkFloatKindsEnum || (SdkFloatKindsEnum = {}));
const SdkAzureBuiltInStringKindsMapping = {
    uuid: "uuid",
    ipV4Address: "ipV4Address",
    ipV6Address: "ipV6Address",
    eTag: "eTag",
    armId: "armResourceIdentifier",
    azureLocation: "azureLocation",
};
var SdkGenericBuiltInStringKindsEnum;
(function (SdkGenericBuiltInStringKindsEnum) {
    SdkGenericBuiltInStringKindsEnum["string"] = "string";
    SdkGenericBuiltInStringKindsEnum["password"] = "password";
    SdkGenericBuiltInStringKindsEnum["guid"] = "guid";
    SdkGenericBuiltInStringKindsEnum["url"] = "url";
    SdkGenericBuiltInStringKindsEnum["uri"] = "uri";
    SdkGenericBuiltInStringKindsEnum["ipAddress"] = "ipAddress";
})(SdkGenericBuiltInStringKindsEnum || (SdkGenericBuiltInStringKindsEnum = {}));
var SdkBuiltInKindsMiscellaneousEnum;
(function (SdkBuiltInKindsMiscellaneousEnum) {
    SdkBuiltInKindsMiscellaneousEnum["bytes"] = "bytes";
    SdkBuiltInKindsMiscellaneousEnum["boolean"] = "boolean";
    SdkBuiltInKindsMiscellaneousEnum["plainDate"] = "plainDate";
    SdkBuiltInKindsMiscellaneousEnum["plainTime"] = "plainTime";
    SdkBuiltInKindsMiscellaneousEnum["any"] = "any";
})(SdkBuiltInKindsMiscellaneousEnum || (SdkBuiltInKindsMiscellaneousEnum = {}));
function getKnownScalars() {
    const retval = {};
    const typespecNamespace = Object.keys(SdkBuiltInKindsMiscellaneousEnum)
        .concat(Object.keys(SdkIntKindsEnum))
        .concat(Object.keys(SdkFloatKindsEnum))
        .concat(Object.keys(SdkGenericBuiltInStringKindsEnum));
    for (const kind of typespecNamespace) {
        if (!isSdkBuiltInKind(kind))
            continue; // it will always be true
        retval[`TypeSpec.${kind}`] = kind;
    }
    for (const kind in SdkAzureBuiltInStringKindsMapping) {
        if (!isSdkBuiltInKind(kind))
            continue; // it will always be true
        const kindMappedName = SdkAzureBuiltInStringKindsMapping[kind];
        retval[`Azure.Core.${kindMappedName}`] = kind;
    }
    return retval;
}
function isSdkBuiltInKind(kind) {
    return (kind in SdkBuiltInKindsMiscellaneousEnum ||
        isSdkIntKind(kind) ||
        isSdkFloatKind(kind) ||
        kind in SdkGenericBuiltInStringKindsEnum ||
        kind in SdkAzureBuiltInStringKindsMapping);
}
function isSdkIntKind(kind) {
    return kind in SdkIntKindsEnum;
}
function isSdkFloatKind(kind) {
    return kind in SdkFloatKindsEnum;
}
const SdkDateTimeEncodingsConst = ["rfc3339", "rfc7231", "unixTimestamp"];
function isSdkDateTimeEncodings(encoding) {
    return SdkDateTimeEncodingsConst.includes(encoding);
}
/**
 * This enum represents the different ways a model can be used in a method.
 */
var UsageFlags;
(function (UsageFlags) {
    UsageFlags[UsageFlags["None"] = 0] = "None";
    UsageFlags[UsageFlags["Input"] = 2] = "Input";
    UsageFlags[UsageFlags["Output"] = 4] = "Output";
    UsageFlags[UsageFlags["ApiVersionEnum"] = 8] = "ApiVersionEnum";
    // Input and Json will also be set when JsonMergePatch is set.
    UsageFlags[UsageFlags["JsonMergePatch"] = 16] = "JsonMergePatch";
    // Input will also be set when MultipartFormData is set.
    UsageFlags[UsageFlags["MultipartFormData"] = 32] = "MultipartFormData";
    // Used in spread.
    UsageFlags[UsageFlags["Spread"] = 64] = "Spread";
    // Output will also be set when Error is set.
    UsageFlags[UsageFlags["Error"] = 128] = "Error";
    // Set when model is used in conjunction with an application/json content type.
    UsageFlags[UsageFlags["Json"] = 256] = "Json";
})(UsageFlags || (UsageFlags = {}));

function getEncodeHelper(context, type, kind) {
    if (type.kind === "ModelProperty" || type.kind === "Scalar") {
        return getEncode(context.program, type)?.encoding || kind;
    }
    return kind;
}
/**
 * Add format info onto an sdk type. Since the format decorator
 * decorates the ModelProperty, we add the format info onto the property's internal
 * type.
 * @param context sdk context
 * @param type the original typespec type. Used to grab the format decorator off of
 * @param propertyType the type of the property, i.e. the internal type that we add the format info onto
 */
function addFormatInfo(context, type, propertyType) {
    const innerType = propertyType.kind === "nullable" ? propertyType.type : propertyType;
    const format = getFormat(context.program, type) ?? "";
    if (isSdkBuiltInKind(format))
        innerType.kind = format;
}
/**
 * Add encoding info onto an sdk type. Since the encoding decorator
 * decorates the ModelProperty, we add the encoding info onto the property's internal
 * type.
 * @param context sdk context
 * @param type the original typespec type. Used to grab the encoding decorator off of
 * @param propertyType the type of the property, i.e. the internal type that we add the encoding info onto
 */
function addEncodeInfo(context, type, propertyType, defaultContentType) {
    const diagnostics = createDiagnosticCollector();
    const innerType = propertyType.kind === "nullable" ? propertyType.type : propertyType;
    const encodeData = getEncode(context.program, type);
    if (innerType.kind === "duration") {
        if (!encodeData)
            return diagnostics.wrap(undefined);
        innerType.encode = encodeData.encoding;
        innerType.wireType = diagnostics.pipe(getClientTypeWithDiagnostics(context, encodeData.type));
    }
    if (innerType.kind === "utcDateTime" || innerType.kind === "offsetDateTime") {
        if (encodeData) {
            innerType.encode = encodeData.encoding;
            innerType.wireType = diagnostics.pipe(getClientTypeWithDiagnostics(context, encodeData.type));
        }
        else if (type.kind === "ModelProperty" && isHeader(context.program, type)) {
            innerType.encode = "rfc7231";
        }
    }
    if (innerType.kind === "bytes") {
        if (encodeData) {
            innerType.encode = encodeData.encoding;
        }
        else if (!defaultContentType || defaultContentType === "application/json") {
            innerType.encode = "base64";
        }
        else {
            innerType.encode = "bytes";
        }
    }
    return diagnostics.wrap(undefined);
}
/**
 * Mapping of typespec scalar kinds to the built in kinds exposed in the SDK
 * @param scalar the original typespec scalar
 * @returns the corresponding sdk built in kind
 */
function getScalarKind(scalar) {
    if (isSdkBuiltInKind(scalar.name)) {
        return scalar.name;
    }
    throw Error(`Unknown scalar kind ${scalar.name}`);
}
/**
 * Get the sdk built in type for a given typespec type
 * @param context the sdk context
 * @param type the typespec type
 * @returns the corresponding sdk type
 */
function getSdkBuiltInTypeWithDiagnostics(context, type) {
    const diagnostics = createDiagnosticCollector();
    if (context.program.checker.isStdType(type) || type.kind === "Intrinsic") {
        let kind = "any";
        if (type.kind === "Scalar") {
            if (isSdkBuiltInKind(type.name)) {
                kind = getScalarKind(type);
            }
        }
        const docWrapper = getDocHelper(context, type);
        return diagnostics.wrap({
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, kind)),
            encode: getEncodeHelper(context, type, kind),
            description: docWrapper.description,
            details: docWrapper.details,
        });
    }
    else if (type.kind === "String" || type.kind === "Boolean" || type.kind === "Number") {
        let kind;
        if (type.kind === "String") {
            kind = "string";
        }
        else if (type.kind === "Boolean") {
            kind = "boolean";
        }
        else {
            kind = intOrFloat(type.value);
        }
        return diagnostics.wrap({
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, kind)),
            encode: getEncodeHelper(context, type, kind),
        });
    }
    diagnostics.add(createDiagnostic({ code: "unsupported-kind", target: type, format: { kind: type.kind } }));
    return diagnostics.wrap(diagnostics.pipe(getAnyType(context, type)));
}
function getSdkBuiltInType(context, type) {
    return ignoreDiagnostics(getSdkBuiltInTypeWithDiagnostics(context, type));
}
function getSdkDurationType(context, type) {
    return ignoreDiagnostics(getSdkDurationTypeWithDiagnostics(context, type));
}
function getSdkDurationTypeWithDiagnostics(context, type) {
    const diagnostics = createDiagnosticCollector();
    // we don't get encode info until we get to the property / parameter level
    // so we insert the default. Later in properties, we will check
    // for encoding info and override accordingly
    return diagnostics.wrap({
        ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "duration")),
        encode: "ISO8601",
        wireType: {
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "string")),
            encode: "string",
        },
    });
}
function getSdkArrayOrDict(context, type, operation) {
    return ignoreDiagnostics(getSdkArrayOrDictWithDiagnostics(context, type, operation));
}
function getSdkArrayOrDictWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    // if model with both indexer and properties or name should be a model with additional properties
    if (type.indexer !== undefined && type.properties.size === 0) {
        if (!isNeverType(type.indexer.key)) {
            const valueType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.indexer.value, operation));
            const name = type.indexer.key.name;
            if (name === "string" && type.name === "Record") {
                // model MyModel is Record<> {} should be model with additional properties
                if (type.sourceModel?.kind === "Model" && type.sourceModel?.name === "Record") {
                    return diagnostics.wrap(undefined);
                }
                // other cases are dict
                return diagnostics.wrap({
                    ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "dict")),
                    keyType: diagnostics.pipe(getClientTypeWithDiagnostics(context, type.indexer.key, operation)),
                    valueType: valueType,
                });
            }
            else if (name === "integer") {
                // only array's index key name is integer
                return diagnostics.wrap({
                    ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "array")),
                    name: getLibraryName(context, type),
                    valueType: valueType,
                    crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, type, operation),
                });
            }
        }
    }
    return diagnostics.wrap(undefined);
}
function getSdkTuple(context, type, operation) {
    return ignoreDiagnostics(getSdkTupleWithDiagnostics(context, type, operation));
}
function getSdkTupleWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    return diagnostics.wrap({
        ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "tuple")),
        values: type.values.map((x) => diagnostics.pipe(getClientTypeWithDiagnostics(context, x, operation))),
    });
}
function getSdkUnion(context, type, operation) {
    return ignoreDiagnostics(getSdkUnionWithDiagnostics(context, type, operation));
}
function getSdkUnionWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    const nonNullOptions = getNonNullOptions(type);
    const nullOption = getNullOption(type);
    let retval = undefined;
    if (nonNullOptions.length === 0) {
        diagnostics.add(createDiagnostic({ code: "union-null", target: type }));
        return diagnostics.wrap(diagnostics.pipe(getAnyType(context, type)));
    }
    // if a union is `type | null`, then we will return a nullable wrapper type of the type
    if (nonNullOptions.length === 1 && nullOption !== undefined) {
        retval = diagnostics.pipe(getClientTypeWithDiagnostics(context, nonNullOptions[0], operation));
    }
    else if (
    // judge if the union can be converted to enum
    // if language does not need flatten union as enum
    // filter the case that union is composed of union or enum
    context.flattenUnionAsEnum ||
        ![...type.variants.values()].some((variant) => {
            return variant.type.kind === "Union" || variant.type.kind === "Enum";
        })) {
        const unionAsEnum = diagnostics.pipe(getUnionAsEnum(type));
        if (unionAsEnum) {
            retval = diagnostics.pipe(getSdkUnionEnumWithDiagnostics(context, unionAsEnum, operation));
        }
    }
    // other cases
    if (retval === undefined) {
        retval = {
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "union")),
            name: getLibraryName(context, type) || getGeneratedName(context, type, operation),
            isGeneratedName: !type.name,
            values: nonNullOptions.map((x) => diagnostics.pipe(getClientTypeWithDiagnostics(context, x, operation))),
            crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, type, operation),
        };
    }
    if (nullOption !== undefined) {
        retval = {
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "nullable")),
            type: retval,
        };
    }
    return diagnostics.wrap(retval);
}
function getSdkConstantWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    switch (type.kind) {
        case "Number":
        case "String":
        case "Boolean":
            const valueType = diagnostics.pipe(getSdkBuiltInTypeWithDiagnostics(context, type));
            return diagnostics.wrap({
                ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "constant")),
                value: type.value,
                valueType,
                name: getGeneratedName(context, type, operation),
                isGeneratedName: true,
            });
    }
}
function getSdkConstant(context, type, operation) {
    return ignoreDiagnostics(getSdkConstantWithDiagnostics(context, type, operation));
}
function addDiscriminatorToModelType(context, type, model) {
    const discriminator = getDiscriminator(context.program, type);
    const diagnostics = createDiagnosticCollector();
    if (discriminator) {
        let discriminatorType = undefined;
        for (let i = 0; i < model.properties.length; i++) {
            const property = model.properties[i];
            if (property.kind === "property" && property.__raw?.name === discriminator.propertyName) {
                discriminatorType = property.type;
            }
        }
        let discriminatorProperty;
        for (const childModel of type.derivedModels) {
            const childModelSdkType = diagnostics.pipe(getSdkModelWithDiagnostics(context, childModel));
            for (const property of childModelSdkType.properties) {
                if (property.kind === "property") {
                    if (property.__raw?.name === discriminator?.propertyName) {
                        if (property.type.kind !== "constant" && property.type.kind !== "enumvalue") {
                            diagnostics.add(createDiagnostic({
                                code: "discriminator-not-constant",
                                target: type,
                                format: { discriminator: property.name },
                            }));
                        }
                        else if (typeof property.type.value !== "string") {
                            diagnostics.add(createDiagnostic({
                                code: "discriminator-not-string",
                                target: type,
                                format: {
                                    discriminator: property.name,
                                    discriminatorValue: String(property.type.value),
                                },
                            }));
                        }
                        else {
                            // map string value type to enum value type
                            if (property.type.kind === "constant" && discriminatorType?.kind === "enum") {
                                for (const value of discriminatorType.values) {
                                    if (value.value === property.type.value) {
                                        property.type = value;
                                    }
                                }
                            }
                            childModelSdkType.discriminatorValue = property.type.value;
                            property.discriminator = true;
                            if (model.discriminatedSubtypes === undefined) {
                                model.discriminatedSubtypes = {};
                            }
                            model.discriminatedSubtypes[property.type.value] = childModelSdkType;
                            discriminatorProperty = property;
                        }
                    }
                }
            }
        }
        for (let i = 0; i < model.properties.length; i++) {
            const property = model.properties[i];
            if (property.kind === "property" && property.__raw?.name === discriminator.propertyName) {
                property.discriminator = true;
                model.discriminatorProperty = property;
                return diagnostics.wrap(undefined);
            }
        }
        if (discriminatorProperty) {
            if (discriminatorProperty.type.kind === "constant") {
                discriminatorType = { ...discriminatorProperty.type.valueType };
            }
            else if (discriminatorProperty.type.kind === "enumvalue") {
                discriminatorType = discriminatorProperty.type.enumType;
            }
        }
        else {
            discriminatorType = {
                kind: "string",
                encode: "string",
                decorators: [],
            };
        }
        const name = discriminatorProperty ? discriminatorProperty.name : discriminator.propertyName;
        model.properties.splice(0, 0, {
            kind: "property",
            description: `Discriminator property for ${model.name}.`,
            optional: false,
            discriminator: true,
            serializedName: discriminatorProperty
                ? discriminatorProperty.serializedName
                : discriminator.propertyName,
            type: discriminatorType,
            name,
            isGeneratedName: false,
            onClient: false,
            apiVersions: discriminatorProperty
                ? getAvailableApiVersions(context, discriminatorProperty.__raw, type)
                : getAvailableApiVersions(context, type, type),
            isApiVersionParam: false,
            isMultipartFileInput: false, // discriminator property cannot be a file
            flatten: false, // discriminator properties can not be flattened
            crossLanguageDefinitionId: `${model.crossLanguageDefinitionId}.${name}`,
            decorators: [],
        });
        model.discriminatorProperty = model.properties[0];
    }
    return diagnostics.wrap(undefined);
}
function getSdkModel(context, type, operation) {
    return ignoreDiagnostics(getSdkModelWithDiagnostics(context, type, operation));
}
function getSdkModelWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    let sdkType = context.modelsMap?.get(type);
    if (sdkType) {
        updateModelsMap(context, type, sdkType, operation);
    }
    else {
        const docWrapper = getDocHelper(context, type);
        const name = getLibraryName(context, type) || getGeneratedName(context, type, operation);
        const usage = isErrorModel(context.program, type) ? UsageFlags.Error : UsageFlags.None; // initial usage we can tell just by looking at the model
        sdkType = {
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "model")),
            name: name,
            isGeneratedName: !type.name,
            description: docWrapper.description,
            details: docWrapper.details,
            properties: [],
            additionalProperties: undefined, // going to set additional properties in the next few lines when we look at base model
            access: "public",
            usage,
            crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, type, operation),
            apiVersions: getAvailableApiVersions(context, type, type.namespace),
            isFormDataType: isMultipartFormData(context, type, operation),
        };
        updateModelsMap(context, type, sdkType);
        // model MyModel is Record<> {} should be model with additional properties
        if (type.sourceModel?.kind === "Model" && type.sourceModel?.name === "Record") {
            sdkType.additionalProperties = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.sourceModel.indexer.value, operation));
        }
        // model MyModel { ...Record<>} should be model with additional properties
        if (type.indexer) {
            sdkType.additionalProperties = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.indexer.value, operation));
        }
        // propreties should be generated first since base model'sdiscriminator handling is depend on derived model's properties
        diagnostics.pipe(addPropertiesToModelType(context, type, sdkType, operation));
        if (type.baseModel) {
            sdkType.baseModel = context.modelsMap?.get(type.baseModel);
            if (sdkType.baseModel === undefined) {
                const baseModel = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.baseModel, operation));
                if (baseModel.kind === "dict") {
                    // model MyModel extends Record<> {} should be model with additional properties
                    sdkType.additionalProperties = baseModel.valueType;
                }
                else {
                    sdkType.baseModel = baseModel;
                }
            }
        }
        diagnostics.pipe(addDiscriminatorToModelType(context, type, sdkType));
        updateModelsMap(context, type, sdkType, operation);
    }
    return diagnostics.wrap(sdkType);
}
function getSdkEnumValueType(context, values) {
    const diagnostics = createDiagnosticCollector();
    let kind = "string";
    let type;
    for (const value of values) {
        if (value.kind) {
            type = value;
        }
        else {
            type = value.type;
        }
        if (typeof value.value === "number") {
            kind = intOrFloat(value.value);
            if (kind === "float32") {
                break;
            }
        }
        else if (typeof value.value === "string") {
            kind = "string";
            break;
        }
    }
    return diagnostics.wrap({
        ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, kind)),
        encode: kind,
    });
}
function getUnionAsEnumValueType(context, union) {
    const diagnostics = createDiagnosticCollector();
    const nonNullOptions = getNonNullOptions(union);
    for (const option of nonNullOptions) {
        if (option.kind === "Union") {
            const ret = diagnostics.pipe(getUnionAsEnumValueType(context, option));
            if (ret)
                return diagnostics.wrap(ret);
        }
        else if (option.kind === "Scalar") {
            const ret = diagnostics.pipe(getClientTypeWithDiagnostics(context, option));
            return diagnostics.wrap(ret);
        }
    }
    return diagnostics.wrap(undefined);
}
function getSdkEnumValue(context, enumType, type) {
    return ignoreDiagnostics(getSdkEnumValueWithDiagnostics(context, enumType, type));
}
function getSdkEnumValueWithDiagnostics(context, enumType, type) {
    const diagnostics = createDiagnosticCollector();
    const docWrapper = getDocHelper(context, type);
    return diagnostics.wrap({
        ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "enumvalue")),
        name: getLibraryName(context, type),
        value: type.value ?? type.name,
        description: docWrapper.description,
        details: docWrapper.details,
        enumType,
        valueType: enumType.valueType,
    });
}
function getSdkEnum(context, type, operation) {
    return ignoreDiagnostics(getSdkEnumWithDiagnostics(context, type, operation));
}
function getSdkEnumWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    let sdkType = context.modelsMap?.get(type);
    if (!sdkType) {
        const docWrapper = getDocHelper(context, type);
        sdkType = {
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "enum")),
            name: getLibraryName(context, type),
            isGeneratedName: false,
            description: docWrapper.description,
            details: docWrapper.details,
            valueType: diagnostics.pipe(getSdkEnumValueType(context, type.members.values())),
            values: [],
            isFixed: true, // enums are always fixed after we switch to use union to represent extensible enum
            isFlags: false,
            usage: UsageFlags.None, // We will add usage as we loop through the operations
            access: "public", // Dummy value until we update models map
            crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, type, operation),
            apiVersions: getAvailableApiVersions(context, type, type.namespace),
            isUnionAsEnum: false,
        };
        for (const member of type.members.values()) {
            sdkType.values.push(diagnostics.pipe(getSdkEnumValueWithDiagnostics(context, sdkType, member)));
        }
    }
    updateModelsMap(context, type, sdkType, operation);
    return diagnostics.wrap(sdkType);
}
function getSdkUnionEnumValues(context, type, enumType) {
    const diagnostics = createDiagnosticCollector();
    const values = [];
    for (const member of type.flattenedMembers.values()) {
        const docWrapper = getDocHelper(context, member.type);
        const name = getLibraryName(context, member.type);
        values.push({
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, member.type, "enumvalue")),
            name: name ? name : `${member.value}`,
            description: docWrapper.description,
            details: docWrapper.details,
            value: member.value,
            valueType: enumType.valueType,
            enumType,
        });
    }
    return diagnostics.wrap(values);
}
function getSdkUnionEnum(context, type, operation) {
    return ignoreDiagnostics(getSdkUnionEnumWithDiagnostics(context, type, operation));
}
function getSdkUnionEnumWithDiagnostics(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    const union = type.union;
    let sdkType = context.modelsMap?.get(union);
    if (!sdkType) {
        const docWrapper = getDocHelper(context, union);
        const name = getLibraryName(context, type.union) || getGeneratedName(context, union, operation);
        sdkType = {
            ...diagnostics.pipe(getSdkTypeBaseHelper(context, type.union, "enum")),
            name,
            isGeneratedName: !type.union.name,
            description: docWrapper.description,
            details: docWrapper.details,
            valueType: diagnostics.pipe(getUnionAsEnumValueType(context, type.union)) ??
                diagnostics.pipe(getSdkEnumValueType(context, type.flattenedMembers.values())),
            values: [],
            isFixed: !type.open,
            isFlags: false,
            usage: UsageFlags.None, // We will add usage as we loop through the operations
            access: "public", // Dummy value until we update models map
            crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, union, operation),
            apiVersions: getAvailableApiVersions(context, type.union, type.union.namespace),
            isUnionAsEnum: true,
        };
        sdkType.values = diagnostics.pipe(getSdkUnionEnumValues(context, type, sdkType));
    }
    updateModelsMap(context, type.union, sdkType, operation);
    return diagnostics.wrap(sdkType);
}
function getKnownValuesEnum(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    const knownValues = getKnownValues(context.program, type);
    if (!knownValues) {
        return diagnostics.wrap(undefined);
    }
    if (type.kind === "ModelProperty") {
        const sdkType = diagnostics.pipe(getSdkEnumWithDiagnostics(context, knownValues, operation));
        return diagnostics.wrap(sdkType);
    }
    else {
        let sdkType = context.modelsMap?.get(type);
        if (!sdkType) {
            const docWrapper = getDocHelper(context, type);
            sdkType = {
                ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "enum")),
                name: getLibraryName(context, type),
                isGeneratedName: false,
                description: docWrapper.description,
                details: docWrapper.details,
                valueType: diagnostics.pipe(getSdkEnumValueType(context, knownValues.members.values())),
                values: [],
                isFixed: false,
                isFlags: false,
                usage: UsageFlags.None, // We will add usage as we loop through the operations
                access: "public", // Dummy value until we update models map
                crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, type, operation),
                apiVersions: getAvailableApiVersions(context, type, type.namespace),
                isUnionAsEnum: false,
            };
            for (const member of knownValues.members.values()) {
                sdkType.values.push(diagnostics.pipe(getSdkEnumValueWithDiagnostics(context, sdkType, member)));
            }
        }
        updateModelsMap(context, type, sdkType, operation);
        return diagnostics.wrap(sdkType);
    }
}
function getClientTypeWithDiagnostics(context, type, operation) {
    if (!context.knownScalars) {
        context.knownScalars = getKnownScalars();
    }
    const diagnostics = createDiagnosticCollector();
    let retval = undefined;
    switch (type.kind) {
        case "String":
        case "Number":
        case "Boolean":
            retval = diagnostics.pipe(getSdkConstantWithDiagnostics(context, type));
            break;
        case "Tuple":
            retval = diagnostics.pipe(getSdkTupleWithDiagnostics(context, type, operation));
            break;
        case "Model":
            retval = diagnostics.pipe(getSdkArrayOrDictWithDiagnostics(context, type, operation));
            if (retval === undefined) {
                retval = diagnostics.pipe(getSdkModelWithDiagnostics(context, type, operation));
            }
            break;
        case "Intrinsic":
            retval = diagnostics.pipe(getSdkBuiltInTypeWithDiagnostics(context, type));
            break;
        case "Scalar":
            if (!context.program.checker.isStdType(type) && type.kind === "Scalar" && type.baseScalar) {
                const baseType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.baseScalar, operation));
                addEncodeInfo(context, type, baseType);
                addFormatInfo(context, type, baseType);
                retval = diagnostics.pipe(getKnownValuesEnum(context, type, operation)) ?? baseType;
                const namespace = type.namespace ? getNamespaceFullName(type.namespace) : "";
                retval.kind = context.knownScalars[`${namespace}.${type.name}`] ?? retval.kind;
                const docWrapper = getDocHelper(context, type);
                retval.description = docWrapper.description;
                retval.details = docWrapper.details;
                break;
            }
            if (type.name === "utcDateTime" || type.name === "offsetDateTime") {
                retval = {
                    ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, type.name)),
                    encode: "rfc3339",
                    wireType: {
                        ...diagnostics.pipe(getSdkTypeBaseHelper(context, type, "string")),
                        encode: "string",
                    },
                };
                break;
            }
            if (type.name === "duration") {
                retval = diagnostics.pipe(getSdkDurationTypeWithDiagnostics(context, type));
                break;
            }
            const scalarType = diagnostics.pipe(getSdkBuiltInTypeWithDiagnostics(context, type));
            // just add default encode, normally encode is on extended scalar and model property
            addEncodeInfo(context, type, scalarType);
            retval = scalarType;
            break;
        case "Enum":
            retval = diagnostics.pipe(getSdkEnumWithDiagnostics(context, type, operation));
            break;
        case "Union":
            retval = diagnostics.pipe(getSdkUnionWithDiagnostics(context, type, operation));
            break;
        case "ModelProperty":
            const innerType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.type, operation));
            diagnostics.pipe(addEncodeInfo(context, type, innerType));
            addFormatInfo(context, type, innerType);
            retval = diagnostics.pipe(getKnownValuesEnum(context, type, operation)) ?? innerType;
            break;
        case "UnionVariant":
            const unionType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.union, operation));
            if (unionType.kind === "enum") {
                retval = unionType.values.find((x) => x.name === getLibraryName(context, type));
            }
            else {
                retval = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.type, operation));
            }
            break;
        case "EnumMember":
            const enumType = diagnostics.pipe(getSdkEnumWithDiagnostics(context, type.enum, operation));
            retval = diagnostics.pipe(getSdkEnumValueWithDiagnostics(context, enumType, type));
            break;
        default:
            retval = diagnostics.pipe(getAnyType(context, type));
            diagnostics.add(createDiagnostic({ code: "unsupported-kind", target: type, format: { kind: type.kind } }));
    }
    return diagnostics.wrap(retval);
}
function getClientType(context, type, operation) {
    return ignoreDiagnostics(getClientTypeWithDiagnostics(context, type, operation));
}
function isReadOnly(property) {
    if (property.visibility &&
        property.visibility.includes(Visibility.Read) &&
        property.visibility.length === 1) {
        return true;
    }
    return false;
}
function getSdkVisibility(context, type) {
    const visibility = getVisibility(context.program, type);
    if (visibility) {
        const result = [];
        if (visibility.includes("read")) {
            result.push(Visibility.Read);
        }
        if (visibility.includes("create")) {
            result.push(Visibility.Create);
        }
        if (visibility.includes("update")) {
            result.push(Visibility.Update);
        }
        if (visibility.includes("delete")) {
            result.push(Visibility.Delete);
        }
        if (visibility.includes("query")) {
            result.push(Visibility.Query);
        }
        return result;
    }
    return undefined;
}
function getSdkCredentialType(context, client, authentication) {
    const credentialTypes = [];
    for (const option of authentication.options) {
        for (const scheme of option.schemes) {
            credentialTypes.push({
                __raw: client.service,
                kind: "credential",
                scheme: scheme,
                decorators: [],
            });
        }
    }
    if (credentialTypes.length > 1) {
        return {
            __raw: client.service,
            kind: "union",
            values: credentialTypes,
            name: createGeneratedName(context, client.service, "CredentialUnion"),
            isGeneratedName: true,
            crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, client.service),
            decorators: [],
        };
    }
    return credentialTypes[0];
}
function getSdkCredentialParameter(context, client) {
    const auth = getAuthentication(context.program, client.service);
    if (!auth)
        return undefined;
    const name = "credential";
    return {
        type: getSdkCredentialType(context, client, auth),
        kind: "credential",
        name,
        isGeneratedName: true,
        description: "Credential used to authenticate requests to the service.",
        apiVersions: getAvailableApiVersions(context, client.service, client.type),
        onClient: true,
        optional: false,
        isApiVersionParam: false,
        crossLanguageDefinitionId: `${getCrossLanguageDefinitionId(context, client.service)}.credential`,
        decorators: [],
    };
}
function getSdkModelPropertyTypeBase(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    // get api version info so we can cache info about its api versions before we get to property type level
    const apiVersions = getAvailableApiVersions(context, type, operation || type.model);
    let propertyType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type.type, operation));
    diagnostics.pipe(addEncodeInfo(context, type, propertyType));
    addFormatInfo(context, type, propertyType);
    const knownValues = getKnownValues(context.program, type);
    if (knownValues) {
        propertyType = diagnostics.pipe(getSdkEnumWithDiagnostics(context, knownValues, operation));
    }
    const docWrapper = getDocHelper(context, type);
    const name = getPropertyNames(context, type)[0];
    return diagnostics.wrap({
        __raw: type,
        description: docWrapper.description,
        details: docWrapper.details,
        apiVersions,
        type: propertyType,
        name,
        isGeneratedName: false,
        optional: type.optional,
        ...updateWithApiVersionInformation(context, type, operation ? getLocationOfOperation(operation) : undefined),
        crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, type, operation),
        decorators: diagnostics.pipe(getTypeDecorators(context, type)),
    });
}
function getSdkModelPropertyType(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type, operation));
    if (isSdkHttpParameter(context, type))
        return getSdkHttpParameter(context, type, operation);
    // I'm a body model property
    let operationIsMultipart = false;
    if (operation) {
        const httpOperation = getHttpOperationWithCache(context, operation);
        operationIsMultipart = Boolean(httpOperation && httpOperation.parameters.body?.contentTypes.includes("multipart/form-data"));
    }
    // Currently we only recognize bytes and list of bytes as potential file inputs
    const isBytesInput = base.type.kind === "bytes" ||
        (base.type.kind === "array" && base.type.valueType.kind === "bytes");
    if (isBytesInput && operationIsMultipart && getEncode(context.program, type)) {
        diagnostics.add(createDiagnostic({
            code: "encoding-multipart-bytes",
            target: type,
        }));
    }
    return diagnostics.wrap({
        ...base,
        kind: "property",
        optional: type.optional,
        visibility: getSdkVisibility(context, type),
        discriminator: false,
        serializedName: getPropertyNames(context, type)[1],
        isMultipartFileInput: isBytesInput && operationIsMultipart,
        flatten: shouldFlattenProperty(context, type),
    });
}
function addPropertiesToModelType(context, type, sdkType, operation) {
    const diagnostics = createDiagnosticCollector();
    for (const property of type.properties.values()) {
        if (isStatusCode(context.program, property) ||
            isNeverOrVoidType(property.type) ||
            sdkType.kind !== "model") {
            continue;
        }
        const clientProperty = diagnostics.pipe(getSdkModelPropertyType(context, property, operation));
        if (sdkType.properties) {
            sdkType.properties.push(clientProperty);
        }
        else {
            sdkType.properties = [clientProperty];
        }
    }
    return diagnostics.wrap(undefined);
}
function updateModelsMap(context, type, sdkType, operation) {
    if (sdkType.kind !== "model" && sdkType.kind !== "enum") {
        return;
    }
    if (context.modelsMap === undefined) {
        context.modelsMap = new Map();
    }
    if (context.operationModelsMap === undefined) {
        context.operationModelsMap = new Map();
    }
    const value = context.modelsMap.get(type);
    if (value) {
        sdkType = value;
    }
    else {
        context.modelsMap.set(type, sdkType);
    }
    if (operation) {
        if (context.operationModelsMap.has(operation)) {
            if (context.operationModelsMap.get(operation)?.has(type)) {
                return;
            }
            context.operationModelsMap.get(operation)?.set(type, sdkType);
        }
        else {
            context.operationModelsMap.set(operation, new Map([[type, sdkType]]));
        }
        // TODO: it seems duplicate calculation, need to optimize later
        if (sdkType.kind === "model") {
            for (const prop of sdkType.properties) {
                if (prop.type.kind === "model" || prop.type.kind === "enum") {
                    updateModelsMap(context, prop.type.__raw, prop.type, operation);
                }
                if (prop.type.kind === "array" || prop.type.kind === "dict") {
                    updateModelsMap(context, prop.type.valueType.__raw, prop.type.valueType, operation);
                }
                if (prop.type.kind === "union") {
                    for (const unionType of prop.type.values) {
                        updateModelsMap(context, unionType.__raw, unionType, operation);
                    }
                }
            }
            if (sdkType.baseModel) {
                updateModelsMap(context, sdkType.baseModel.__raw, sdkType.baseModel, operation);
            }
            if (sdkType.additionalProperties) {
                updateModelsMap(context, sdkType.additionalProperties.__raw, sdkType.additionalProperties, operation);
            }
            if (sdkType.discriminatedSubtypes) {
                for (const subtype of Object.values(sdkType.discriminatedSubtypes)) {
                    updateModelsMap(context, subtype.__raw, subtype, operation);
                }
            }
        }
    }
}
function updateUsageOfModel(context, usage, type, options) {
    options = options ?? {};
    options.propagation = options?.propagation ?? true;
    options.ignoreSubTypeStack = options.ignoreSubTypeStack ?? [];
    // if (!type || !["model", "enum", "array", "dict", "union", "enumvalue"].includes(type.kind))
    //   return;
    if (!type)
        return;
    if (options?.seenModelNames === undefined) {
        options.seenModelNames = new Set();
    }
    if (type.kind === "model" && options.seenModelNames.has(type))
        return; // avoid circular references
    if (type.kind === "array" || type.kind === "dict") {
        return updateUsageOfModel(context, usage, type.valueType, options);
    }
    if (type.kind === "union") {
        for (const unionType of type.values) {
            updateUsageOfModel(context, usage, unionType, options);
        }
        return;
    }
    if (type.kind === "enumvalue") {
        updateUsageOfModel(context, usage, type.enumType, options);
        return;
    }
    if (type.kind === "nullable") {
        updateUsageOfModel(context, usage, type.type, options);
        return;
    }
    if (type.kind !== "model" && type.kind !== "enum")
        return;
    options.seenModelNames.add(type);
    const usageOverride = getUsageOverride(context, type.__raw);
    if (usageOverride) {
        type.usage |= usageOverride | usage;
    }
    else {
        type.usage |= usage;
    }
    if (type.kind === "enum")
        return;
    if (!options.propagation)
        return;
    if (type.baseModel) {
        options.ignoreSubTypeStack.push(true);
        updateUsageOfModel(context, usage, type.baseModel, options);
        options.ignoreSubTypeStack.pop();
    }
    if (type.discriminatedSubtypes &&
        (options.ignoreSubTypeStack.length === 0 || !options.ignoreSubTypeStack.at(-1))) {
        for (const discriminatedSubtype of Object.values(type.discriminatedSubtypes)) {
            options.ignoreSubTypeStack.push(false);
            updateUsageOfModel(context, usage, discriminatedSubtype, options);
            options.ignoreSubTypeStack.pop();
        }
    }
    if (type.additionalProperties) {
        options.ignoreSubTypeStack.push(false);
        updateUsageOfModel(context, usage, type.additionalProperties, options);
        options.ignoreSubTypeStack.pop();
    }
    for (const property of type.properties) {
        options.ignoreSubTypeStack.push(false);
        if (property.kind === "property" && isReadOnly(property) && usage === UsageFlags.Input) {
            continue;
        }
        updateUsageOfModel(context, usage, property.type, options);
        options.ignoreSubTypeStack.pop();
    }
}
function updateTypesFromOperation(context, operation) {
    const diagnostics = createDiagnosticCollector();
    const program = context.program;
    const httpOperation = getHttpOperationWithCache(context, operation);
    const generateConvenient = shouldGenerateConvenient(context, operation);
    for (const param of operation.parameters.properties.values()) {
        if (isNeverOrVoidType(param.type))
            continue;
        const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, param.type, operation));
        if (generateConvenient) {
            updateUsageOfModel(context, UsageFlags.Input, sdkType);
        }
    }
    for (const param of httpOperation.parameters.parameters) {
        if (isNeverOrVoidType(param.param.type))
            continue;
        const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, param.param.type, operation));
        if (generateConvenient) {
            updateUsageOfModel(context, UsageFlags.Input, sdkType);
        }
    }
    const httpBody = httpOperation.parameters.body;
    if (httpBody && !isNeverOrVoidType(httpBody.type)) {
        const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, httpBody.type, operation));
        if (generateConvenient) {
            // Special logic for spread body model:
            // If body is from spread, then it should be an anonymous model.
            // Also all model properties should be
            // either equal to one of operation parameters (for case spread from model without property with metadata decorator)
            // or its source property equal to one of operation parameters (for case spread from model with property with metadata decorator)
            if (httpBody.type.kind === "Model" &&
                httpBody.type.name === "" &&
                [...httpBody.type.properties.keys()].every((k) => operation.parameters.properties.has(k) &&
                    (operation.parameters.properties.get(k) ===
                        httpBody.type.properties.get(k) ||
                        operation.parameters.properties.get(k) ===
                            httpBody.type.properties.get(k)?.sourceProperty)) &&
                !context.spreadModels?.has(httpBody.type)) {
                context.spreadModels?.set(httpBody.type, sdkType);
            }
            else {
                updateUsageOfModel(context, UsageFlags.Input, sdkType);
            }
            if (httpBody.contentTypes.some((x) => isJsonContentType(x))) {
                updateUsageOfModel(context, UsageFlags.Json, sdkType);
            }
            if (httpBody.contentTypes.includes("application/merge-patch+json")) {
                // will also have Json type
                updateUsageOfModel(context, UsageFlags.JsonMergePatch, sdkType);
            }
        }
        if (isMultipartFormData(context, httpBody.type, operation)) {
            updateUsageOfModel(context, UsageFlags.MultipartFormData, sdkType, {
                propagation: false,
            });
        }
    }
    for (const response of httpOperation.responses) {
        for (const innerResponse of response.responses) {
            if (innerResponse.body?.type && !isNeverOrVoidType(innerResponse.body.type)) {
                const body = innerResponse.body.type.kind === "Model"
                    ? getEffectivePayloadType(context, innerResponse.body.type)
                    : innerResponse.body.type;
                const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, body, operation));
                if (generateConvenient) {
                    updateUsageOfModel(context, UsageFlags.Output, sdkType);
                }
                if (innerResponse.body.contentTypes.some((x) => isJsonContentType(x))) {
                    updateUsageOfModel(context, UsageFlags.Json, sdkType);
                }
            }
            const headers = getHttpOperationResponseHeaders(innerResponse);
            if (headers) {
                for (const header of Object.values(headers)) {
                    if (isNeverOrVoidType(header.type))
                        continue;
                    const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, header.type, operation));
                    if (generateConvenient) {
                        updateUsageOfModel(context, UsageFlags.Output, sdkType);
                    }
                }
            }
        }
    }
    const lroMetaData = getLroMetadata(program, operation);
    if (lroMetaData && generateConvenient) {
        if (lroMetaData.finalResult !== undefined && lroMetaData.finalResult !== "void") {
            const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, lroMetaData.finalResult, operation));
            updateUsageOfModel(context, UsageFlags.Output, sdkType);
            if (!context.arm) {
                // TODO: currently skipping adding of envelopeResult due to arm error
                // https://github.com/Azure/typespec-azure/issues/311
                const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, lroMetaData.envelopeResult, operation));
                updateUsageOfModel(context, UsageFlags.Output, sdkType);
            }
        }
    }
    return diagnostics.wrap(undefined);
}
function updateAccessOfModel(context) {
    for (const [type, sdkType] of context.modelsMap?.entries() ?? []) {
        const internal = isInternal(context, type); // eslint-disable-line deprecation/deprecation
        if (internal) {
            sdkType.access = "internal";
            continue;
        }
        const accessOverride = getAccessOverride(context, sdkType.__raw);
        if (accessOverride) {
            sdkType.access = accessOverride;
            continue;
        }
        let referredByInternal = false;
        let referredByPublic = false;
        let referredByUndefined = false;
        for (const [operation, modelMap] of context.operationModelsMap) {
            const access = getAccessOverride(context, operation);
            if (access === "internal" && modelMap.get(type)) {
                referredByInternal = true;
            }
            else if (access === "public" && modelMap.get(type)) {
                referredByPublic = true;
                break;
            }
            else if (access === undefined && modelMap.get(type)) {
                referredByUndefined = true;
            }
        }
        if (referredByPublic) {
            sdkType.access = "public";
        }
        else if (referredByInternal && !referredByUndefined) {
            sdkType.access = "internal";
        }
    }
}
function updateSpreadModelUsageAndAccess(context) {
    for (const sdkType of context.spreadModels?.values() ?? []) {
        updateUsageOfModel(context, UsageFlags.Spread, sdkType);
    }
    for (const sdkType of context.modelsMap?.values() ?? []) {
        // if a type only has spread usage, then it could be internal
        if ((sdkType.usage & UsageFlags.Spread) > 0) {
            sdkType.access = "internal";
        }
    }
}
function handleServiceOrphanType(context, type) {
    const diagnostics = createDiagnosticCollector();
    // eslint-disable-next-line deprecation/deprecation
    if (type.kind === "Model" && isInclude(context, type)) {
        const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type));
        updateUsageOfModel(context, UsageFlags.Input | UsageFlags.Output, sdkType);
    }
    if (getAccessOverride(context, type) !== undefined) {
        const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type));
        updateUsageOfModel(context, UsageFlags.None, sdkType);
    }
}
function verifyNoConflictingMultipartModelUsage(context) {
    const diagnostics = createDiagnosticCollector();
    for (const [operation, modelMap] of context.operationModelsMap) {
        for (const [type, sdkType] of modelMap.entries()) {
            const isMultipartFormData = (sdkType.usage & UsageFlags.MultipartFormData) > 0;
            if (sdkType.kind === "model" &&
                isMultipartFormData !== isMultipartOperation(context, operation)) {
                // This means we have a model that is used both for formdata input and for regular body input
                diagnostics.add(createDiagnostic({
                    code: "conflicting-multipart-model-usage",
                    target: type,
                    format: {
                        modelName: sdkType.name,
                    },
                }));
            }
        }
    }
    return diagnostics.wrap(undefined);
}
function modelChecks(context) {
    return verifyNoConflictingMultipartModelUsage(context);
}
function filterOutModels(context) {
    for (const [type, sdkType] of context.modelsMap?.entries() ?? []) {
        if (type.kind === "Model") {
            if (isExclude(context, type))
                sdkType.usage = UsageFlags.None; // eslint-disable-line deprecation/deprecation
        }
        if (type.kind === "Enum" || type.kind === "Model" || type.kind === "Union") {
            if (context.filterOutCoreModels && isAzureCoreModel(type)) {
                sdkType.usage = UsageFlags.None;
            }
        }
    }
}
function getAllModelsWithDiagnostics(context, options = {}) {
    const diagnostics = createDiagnosticCollector();
    const defaultOptions = {
        input: true,
        output: true,
    };
    options = { ...defaultOptions, ...options };
    if (context.modelsMap === undefined) {
        context.modelsMap = new Map();
    }
    if (context.unionsMap === undefined) {
        context.unionsMap = new Map();
    }
    if (context.operationModelsMap === undefined) {
        context.operationModelsMap = new Map();
    }
    if (context.spreadModels === undefined) {
        context.spreadModels = new Map();
    }
    for (const client of listClients(context)) {
        for (const operation of listOperationsInOperationGroup(context, client)) {
            // operations on a client
            diagnostics.pipe(updateTypesFromOperation(context, operation));
        }
        const ogs = listOperationGroups(context, client);
        while (ogs.length) {
            const operationGroup = ogs.pop();
            for (const operation of listOperationsInOperationGroup(context, operationGroup)) {
                // operations on operation groups
                diagnostics.pipe(updateTypesFromOperation(context, operation));
            }
            if (operationGroup?.subOperationGroups) {
                ogs.push(...operationGroup.subOperationGroups);
            }
        }
        // orphan models
        for (const model of client.service.models.values()) {
            handleServiceOrphanType(context, model);
        }
        // orphan enums
        for (const enumType of client.service.enums.values()) {
            handleServiceOrphanType(context, enumType);
        }
        // orphan unions
        for (const unionType of client.service.unions.values()) {
            handleServiceOrphanType(context, unionType);
        }
        // server parameters
        const servers = getServers(context.program, client.service);
        if (servers !== undefined && servers[0].parameters !== undefined) {
            for (const param of servers[0].parameters.values()) {
                const sdkType = diagnostics.pipe(getClientTypeWithDiagnostics(context, param));
                updateUsageOfModel(context, UsageFlags.Input, sdkType);
            }
        }
        // versioned enums
        const [_, versionMap] = getVersions(context.program, client.service);
        if (versionMap && versionMap.getVersions()[0]) {
            // create sdk enum for versions enum
            const sdkVersionsEnum = diagnostics.pipe(getSdkEnumWithDiagnostics(context, versionMap.getVersions()[0].enumMember.enum));
            filterApiVersionsInEnum(context, client, sdkVersionsEnum);
            updateUsageOfModel(context, UsageFlags.ApiVersionEnum, sdkVersionsEnum);
        }
    }
    // update access
    updateAccessOfModel(context);
    // update spread model
    updateSpreadModelUsageAndAccess(context);
    // filter out models
    filterOutModels(context);
    let filter = 0;
    if (options.input && options.output) {
        filter = Number.MAX_SAFE_INTEGER;
    }
    else if (options.input) {
        filter += UsageFlags.Input;
    }
    else if (options.output) {
        filter += UsageFlags.Output;
    }
    diagnostics.pipe(modelChecks(context));
    return diagnostics.wrap([...new Set(context.modelsMap.values())].filter((t) => (t.usage & filter) > 0));
}
function getAllModels(context, options = {}) {
    // we currently don't return diagnostics even though we keep track of them
    // when we move to the new sdk type ecosystem completely, we'll expose
    // diagnostics as a separate property on the TCGCContext
    return ignoreDiagnostics(getAllModelsWithDiagnostics(context, options));
}

function getSdkHttpOperation(context, httpOperation, methodParameters) {
    const diagnostics = createDiagnosticCollector();
    const { responses, exceptions } = diagnostics.pipe(getSdkHttpResponseAndExceptions(context, httpOperation));
    const responsesWithBodies = [...responses.values()]
        .concat([...exceptions.values()])
        .filter((r) => r.type);
    const parameters = diagnostics.pipe(getSdkHttpParameters(context, httpOperation, methodParameters, responsesWithBodies[0]));
    return diagnostics.wrap({
        __raw: httpOperation,
        kind: "http",
        path: httpOperation.path,
        verb: httpOperation.verb,
        ...parameters,
        responses,
        exceptions,
    });
}
function isSdkHttpParameter(context, type) {
    const program = context.program;
    return (isPathParam(program, type) ||
        isQueryParam(program, type) ||
        isHeader(program, type) ||
        isBody(program, type));
}
function getSdkHttpParameters(context, httpOperation, methodParameters, responseBody) {
    const diagnostics = createDiagnosticCollector();
    const retval = {
        parameters: [],
        bodyParam: undefined,
    };
    retval.parameters = httpOperation.parameters.parameters
        .filter((x) => !isNeverOrVoidType(x.param.type))
        .map((x) => diagnostics.pipe(getSdkHttpParameter(context, x.param, httpOperation.operation, x.type)))
        .filter((x) => x.kind === "header" || x.kind === "query" || x.kind === "path");
    const headerParams = retval.parameters.filter((x) => x.kind === "header");
    // add operation info onto body param
    const tspBody = httpOperation.parameters.body;
    // we add correspondingMethodParams after we create the type, since we need the info on the type
    const correspondingMethodParams = [];
    if (tspBody && tspBody?.bodyKind !== "multipart") {
        // if there's a param on the body, we can just rely on getSdkHttpParameter
        if (tspBody.property && !isNeverOrVoidType(tspBody.property.type)) {
            const getParamResponse = diagnostics.pipe(getSdkHttpParameter(context, tspBody.property, httpOperation.operation, "body"));
            if (getParamResponse.kind !== "body") {
                diagnostics.add(createDiagnostic({
                    code: "unexpected-http-param-type",
                    target: tspBody.property,
                    format: {
                        paramName: tspBody.property.name,
                        expectedType: "body",
                        actualType: getParamResponse.kind,
                    },
                }));
                return diagnostics.wrap(retval);
            }
            retval.bodyParam = getParamResponse;
        }
        else if (!isNeverOrVoidType(tspBody.type)) {
            const type = diagnostics.pipe(getClientTypeWithDiagnostics(context, tspBody.type, httpOperation.operation));
            const name = camelCase(type.name ?? "body");
            retval.bodyParam = {
                kind: "body",
                name,
                isGeneratedName: true,
                description: getDocHelper(context, tspBody.type).description,
                details: getDocHelper(context, tspBody.type).details,
                onClient: false,
                contentTypes: [],
                defaultContentType: "application/json", // actual content type info is added later
                isApiVersionParam: false,
                apiVersions: getAvailableApiVersions(context, tspBody.type, httpOperation.operation),
                type,
                optional: false,
                correspondingMethodParams,
                crossLanguageDefinitionId: `${getCrossLanguageDefinitionId(context, httpOperation.operation)}.body`,
                decorators: diagnostics.pipe(getTypeDecorators(context, tspBody.type)),
            };
        }
        if (retval.bodyParam) {
            addContentTypeInfoToBodyParam(context, httpOperation, retval.bodyParam);
            retval.bodyParam.correspondingMethodParams = diagnostics.pipe(getCorrespondingMethodParams(context, httpOperation.operation, methodParameters, retval.bodyParam));
        }
    }
    if (retval.bodyParam && !headerParams.some((h) => isContentTypeHeader(h))) {
        // if we have a body param and no content type header, we add one
        const contentTypeBase = {
            ...createContentTypeOrAcceptHeader(context, httpOperation, retval.bodyParam),
            description: `Body parameter's content type. Known values are ${retval.bodyParam.contentTypes}`,
        };
        if (!methodParameters.some((m) => m.name === "contentType")) {
            methodParameters.push({
                ...contentTypeBase,
                kind: "method",
            });
        }
        retval.parameters.push({
            ...contentTypeBase,
            kind: "header",
            serializedName: "Content-Type",
            correspondingMethodParams,
        });
    }
    if (responseBody && !headerParams.some((h) => isAcceptHeader(h))) {
        // If our operation returns a body, we add an accept header if none exist
        const acceptBase = {
            ...createContentTypeOrAcceptHeader(context, httpOperation, responseBody),
        };
        if (!methodParameters.some((m) => m.name === "accept")) {
            methodParameters.push({
                ...acceptBase,
                kind: "method",
            });
        }
        retval.parameters.push({
            ...acceptBase,
            kind: "header",
            serializedName: "Accept",
            correspondingMethodParams,
        });
    }
    for (const param of retval.parameters) {
        param.correspondingMethodParams = diagnostics.pipe(getCorrespondingMethodParams(context, httpOperation.operation, methodParameters, param));
    }
    return diagnostics.wrap(retval);
}
function createContentTypeOrAcceptHeader(context, httpOperation, bodyObject) {
    const name = bodyObject.kind === "body" ? "contentType" : "accept";
    let type = {
        kind: "string",
        encode: "string",
        decorators: [],
    };
    // for contentType, we treat it as a constant IFF there's one value and it's application/json.
    // this is to prevent a breaking change when a service adds more content types in the future.
    // e.g. the service accepting image/png then later image/jpeg should _not_ be a breaking change.
    //
    // for accept, we treat it as a constant IFF there's a single value. adding more content types
    // for this case is considered a breaking change for SDKs so we want to surface it as such.
    // e.g. the service returns image/png then later provides the option to return image/jpeg.
    if (bodyObject.contentTypes &&
        bodyObject.contentTypes.length === 1 &&
        (/json/.test(bodyObject.contentTypes[0]) || name === "accept")) {
        // in this case, we just want a content type of application/json
        type = {
            kind: "constant",
            value: bodyObject.contentTypes[0],
            valueType: type,
            name: `${httpOperation.operation.name}ContentType`,
            isGeneratedName: true,
            decorators: [],
        };
    }
    // No need for clientDefaultValue because it's a constant, it only has one value
    return {
        type,
        name,
        isGeneratedName: true,
        apiVersions: bodyObject.apiVersions,
        isApiVersionParam: false,
        onClient: false,
        optional: false,
        crossLanguageDefinitionId: `${getCrossLanguageDefinitionId(context, httpOperation.operation)}.${name}`,
        decorators: [],
    };
}
function addContentTypeInfoToBodyParam(context, httpOperation, bodyParam) {
    const diagnostics = createDiagnosticCollector();
    const tspBody = httpOperation.parameters.body;
    if (!tspBody)
        return diagnostics.diagnostics;
    let contentTypes = tspBody.contentTypes;
    if (contentTypes.length === 0) {
        contentTypes = ["application/json"];
    }
    const defaultContentType = contentTypes.includes("application/json")
        ? "application/json"
        : contentTypes[0];
    bodyParam.contentTypes = contentTypes;
    bodyParam.defaultContentType = defaultContentType;
    diagnostics.pipe(addEncodeInfo(context, bodyParam.__raw, bodyParam.type, defaultContentType));
    return diagnostics.diagnostics;
}
function getSdkHttpParameter(context, type, operation, location) {
    const diagnostics = createDiagnosticCollector();
    const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type, operation));
    const program = context.program;
    const correspondingMethodParams = []; // we set it later in the operation
    if (isPathParam(context.program, type) || location === "path") {
        // we don't url encode if the type can be assigned to url
        const urlEncode = !ignoreDiagnostics(program.checker.isTypeAssignableTo(type.type.projectionBase ?? type.type, program.checker.getStdType("url"), type.type));
        return diagnostics.wrap({
            ...base,
            kind: "path",
            urlEncode,
            serializedName: getPathParamName(program, type) ?? base.name,
            correspondingMethodParams,
            optional: false,
        });
    }
    if (isBody(context.program, type) || location === "body") {
        return diagnostics.wrap({
            ...base,
            kind: "body",
            contentTypes: ["application/json"], // will update when we get to the operation level
            defaultContentType: "application/json", // will update when we get to the operation level
            optional: type.optional,
            correspondingMethodParams,
        });
    }
    const headerQueryBase = {
        ...base,
        optional: type.optional,
        collectionFormat: getCollectionFormat(context, type),
        correspondingMethodParams,
    };
    if (isQueryParam(context.program, type) || location === "query") {
        return diagnostics.wrap({
            ...headerQueryBase,
            kind: "query",
            serializedName: getQueryParamName(program, type) ?? base.name,
        });
    }
    if (!(isHeader(context.program, type) || location === "header")) {
        diagnostics.add(createDiagnostic({
            code: "unexpected-http-param-type",
            target: type,
            format: {
                paramName: type.name,
                expectedType: "path, query, header, or body",
                actualType: type.kind,
            },
        }));
    }
    return diagnostics.wrap({
        ...headerQueryBase,
        kind: "header",
        serializedName: getHeaderFieldName(program, type) ?? base.name,
    });
}
function getSdkHttpResponseAndExceptions(context, httpOperation) {
    const diagnostics = createDiagnosticCollector();
    const responses = new Map();
    const exceptions = new Map();
    for (const response of httpOperation.responses) {
        const headers = [];
        let body;
        let contentTypes = [];
        for (const innerResponse of response.responses) {
            for (const header of getHttpOperationResponseHeaders(innerResponse)) {
                if (isNeverOrVoidType(header.type))
                    continue;
                const clientType = diagnostics.pipe(getClientTypeWithDiagnostics(context, header.type));
                const defaultContentType = innerResponse.body?.contentTypes.includes("application/json")
                    ? "application/json"
                    : innerResponse.body?.contentTypes[0];
                addEncodeInfo(context, header, clientType, defaultContentType);
                addFormatInfo(context, header, clientType);
                headers.push({
                    __raw: header,
                    description: getDocHelper(context, header).description,
                    details: getDocHelper(context, header).details,
                    serializedName: getHeaderFieldName(context.program, header),
                    type: clientType,
                });
            }
            if (innerResponse.body && !isNeverOrVoidType(innerResponse.body.type)) {
                if (body && body !== innerResponse.body.type) {
                    diagnostics.add(createDiagnostic({
                        code: "multiple-response-types",
                        target: innerResponse.body.type,
                        format: {
                            operation: httpOperation.operation.name,
                            response: innerResponse.body.type.kind === "Model"
                                ? innerResponse.body.type.name
                                : innerResponse.body.type.kind,
                        },
                    }));
                }
                contentTypes = contentTypes.concat(innerResponse.body.contentTypes);
                body =
                    innerResponse.body.type.kind === "Model"
                        ? getEffectivePayloadType(context, innerResponse.body.type)
                        : innerResponse.body.type;
            }
        }
        const sdkResponse = {
            __raw: response,
            kind: "http",
            type: body ? diagnostics.pipe(getClientTypeWithDiagnostics(context, body)) : undefined,
            headers,
            contentTypes: contentTypes.length > 0 ? contentTypes : undefined,
            defaultContentType: contentTypes.includes("application/json")
                ? "application/json"
                : contentTypes[0],
            apiVersions: getAvailableApiVersions(context, httpOperation.operation, httpOperation.operation),
            description: response.description,
        };
        if (response.statusCodes === "*" || (body && isErrorModel(context.program, body))) {
            exceptions.set(response.statusCodes, sdkResponse);
        }
        else {
            responses.set(response.statusCodes, sdkResponse);
        }
    }
    return diagnostics.wrap({ responses, exceptions });
}
function getCorrespondingMethodParams(context, operation, methodParameters, serviceParam) {
    const diagnostics = createDiagnosticCollector();
    const operationLocation = getLocationOfOperation(operation);
    if (serviceParam.isApiVersionParam) {
        const existingApiVersion = context.__namespaceToApiVersionParameter.get(operationLocation);
        if (!existingApiVersion) {
            const apiVersionParam = methodParameters.find((x) => x.name.includes("apiVersion"));
            if (!apiVersionParam) {
                diagnostics.add(createDiagnostic({
                    code: "no-corresponding-method-param",
                    target: serviceParam.__raw,
                    format: {
                        paramName: "apiVersion",
                        methodName: operation.name,
                    },
                }));
                return diagnostics.wrap([]);
            }
            const apiVersionParamUpdated = {
                ...apiVersionParam,
                name: "apiVersion",
                isGeneratedName: apiVersionParam.name !== "apiVersion",
                optional: false,
                clientDefaultValue: context.__namespaceToApiVersionClientDefaultValue.get(operationLocation),
            };
            context.__namespaceToApiVersionParameter.set(operationLocation, apiVersionParamUpdated);
        }
        return diagnostics.wrap([context.__namespaceToApiVersionParameter.get(operationLocation)]);
    }
    if (isSubscriptionId(context, serviceParam)) {
        if (!context.__subscriptionIdParameter) {
            const subscriptionIdParam = methodParameters.find((x) => isSubscriptionId(context, x));
            if (!subscriptionIdParam) {
                diagnostics.add(createDiagnostic({
                    code: "no-corresponding-method-param",
                    target: serviceParam.__raw,
                    format: {
                        paramName: "subscriptionId",
                        methodName: operation.name,
                    },
                }));
                return diagnostics.wrap([]);
            }
            context.__subscriptionIdParameter = subscriptionIdParam;
        }
        return diagnostics.wrap([context.__subscriptionIdParameter]);
    }
    // to see if the service parameter is a method parameter or a property of a method parameter
    const directMapping = findMapping(methodParameters, serviceParam);
    if (directMapping) {
        return diagnostics.wrap([directMapping]);
    }
    // to see if all the property of service parameter could be mapped to a method parameter or a property of a method parameter
    if (serviceParam.kind === "body" && serviceParam.type.kind === "model") {
        const retVal = [];
        for (const serviceParamProp of serviceParam.type.properties) {
            const propertyMapping = findMapping(methodParameters, serviceParamProp);
            if (propertyMapping) {
                retVal.push(propertyMapping);
            }
        }
        if (retVal.length === serviceParam.type.properties.length) {
            return diagnostics.wrap(retVal);
        }
    }
    diagnostics.add(createDiagnostic({
        code: "no-corresponding-method-param",
        target: serviceParam.__raw,
        format: {
            paramName: serviceParam.name,
            methodName: operation.name,
        },
    }));
    return diagnostics.wrap([]);
}
function findMapping(methodParameters, serviceParam) {
    const queue = [...methodParameters];
    const visited = new Set();
    while (queue.length > 0) {
        const methodParam = queue.shift();
        // http operation parameter/body parameter/property of body parameter could either from an operation parameter directly or from a property of an operation parameter
        if (methodParam.__raw &&
            serviceParam.__raw &&
            (methodParam.__raw === serviceParam.__raw ||
                methodParam.__raw === serviceParam.__raw.sourceProperty)) {
            return methodParam;
        }
        // this following two hard code mapping is for the case that TCGC help to add content type and accept header is not exist
        if (serviceParam.kind === "header" &&
            serviceParam.serializedName === "Content-Type" &&
            methodParam.name === "contentType") {
            return methodParam;
        }
        if (serviceParam.kind === "header" &&
            serviceParam.serializedName === "Accept" &&
            methodParam.name === "accept") {
            return methodParam;
        }
        if (methodParam.type.kind === "model" && !visited.has(methodParam.type)) {
            visited.add(methodParam.type);
            let current = methodParam.type;
            while (current) {
                for (const prop of methodParam.type.properties) {
                    queue.push(prop);
                }
                current = current.baseModel;
            }
        }
    }
    return undefined;
}
function getCollectionFormat(context, type) {
    const program = context.program;
    const tspCollectionFormat = (isQueryParam(program, type)
        ? getQueryParamOptions(program, type)
        : isHeader(program, type)
            ? getHeaderFieldOptions(program, type)
            : undefined)?.format;
    if (tspCollectionFormat === "form" || tspCollectionFormat === "simple") {
        return undefined;
    }
    return tspCollectionFormat;
}

function getSdkServiceOperation(context, operation, methodParameters) {
    const diagnostics = createDiagnosticCollector();
    const httpOperation = getHttpOperationWithCache(context, operation);
    if (httpOperation) {
        const sdkHttpOperation = diagnostics.pipe(getSdkHttpOperation(context, httpOperation, methodParameters));
        return diagnostics.wrap(sdkHttpOperation);
    }
    diagnostics.add(createDiagnostic({
        code: "unsupported-protocol",
        target: operation,
        format: {},
    }));
    return diagnostics.wrap(undefined);
}
function getSdkLroPagingServiceMethod(context, operation) {
    const diagnostics = createDiagnosticCollector();
    return diagnostics.wrap({
        ...diagnostics.pipe(getSdkLroServiceMethod(context, operation)),
        ...diagnostics.pipe(getSdkPagingServiceMethod(context, operation)),
        kind: "lropaging",
    });
}
function getSdkPagingServiceMethod(context, operation) {
    const diagnostics = createDiagnosticCollector();
    const pagedMetadata = getPagedResult(context.program, operation);
    const basic = diagnostics.pipe(getSdkBasicServiceMethod(context, operation));
    if (pagedMetadata.itemsProperty) {
        basic.response.type = diagnostics.pipe(getClientTypeWithDiagnostics(context, pagedMetadata.itemsProperty.type));
    }
    basic.response.resultPath = pagedMetadata.itemsSegments?.join(".");
    return diagnostics.wrap({
        ...basic,
        __raw_paged_metadata: pagedMetadata,
        kind: "paging",
        nextLinkPath: pagedMetadata?.nextLinkSegments?.join("."),
        nextLinkOperation: pagedMetadata?.nextLinkOperation
            ? diagnostics.pipe(getSdkServiceOperation(context, pagedMetadata.nextLinkOperation, basic.parameters))
            : undefined,
        getResponseMapping() {
            return basic.response.resultPath;
        },
    });
}
function getSdkLroServiceMethod(context, operation) {
    const diagnostics = createDiagnosticCollector();
    const metadata = getLroMetadata(context.program, operation);
    const basicServiceMethod = diagnostics.pipe(getSdkBasicServiceMethod(context, operation));
    if (metadata.finalResult === undefined || metadata.finalResult === "void") {
        basicServiceMethod.response.type = undefined;
    }
    else {
        basicServiceMethod.response.type = diagnostics.pipe(getClientTypeWithDiagnostics(context, metadata.finalResult));
    }
    basicServiceMethod.response.resultPath = metadata.finalResultPath;
    return diagnostics.wrap({
        ...basicServiceMethod,
        kind: "lro",
        __raw_lro_metadata: metadata,
        operation: diagnostics.pipe(getSdkServiceOperation(context, metadata.operation, basicServiceMethod.parameters)),
        getResponseMapping() {
            return this.response.resultPath;
        },
    });
}
function getSdkMethodResponse(context, operation, sdkOperation) {
    const responses = sdkOperation.responses;
    // TODO: put head as bool here
    const { allResponseBodies, nonBodyExists } = getAllResponseBodiesAndNonBodyExists(responses);
    const responseTypes = new Set(allResponseBodies.map((x) => getHashForType(x)));
    let type = undefined;
    if (responseTypes.size > 1) {
        // return union of all the different types
        type = {
            __raw: operation,
            kind: "union",
            values: allResponseBodies,
            name: createGeneratedName(context, operation, "UnionResponse"),
            isGeneratedName: true,
            crossLanguageDefinitionId: getCrossLanguageDefinitionId(context, operation),
            decorators: [],
        };
    }
    else if (responseTypes.size === 1) {
        type = allResponseBodies[0];
    }
    if (nonBodyExists && type) {
        type = {
            kind: "nullable",
            type: type,
            decorators: [],
        };
    }
    return {
        kind: "method",
        type,
    };
}
function getSdkBasicServiceMethod(context, operation) {
    const diagnostics = createDiagnosticCollector();
    const methodParameters = [];
    // we have to calculate apiVersions first, so that the information is put
    // in __tspTypeToApiVersions before we call parameters since method wraps parameter
    const apiVersions = getAvailableApiVersions(context, operation, getLocationOfOperation(operation));
    for (const param of operation.parameters.properties.values()) {
        if (isNeverOrVoidType(param.type))
            continue;
        methodParameters.push(diagnostics.pipe(getSdkMethodParameter(context, param, operation)));
    }
    const serviceOperation = diagnostics.pipe(getSdkServiceOperation(context, operation, methodParameters));
    const response = getSdkMethodResponse(context, operation, serviceOperation);
    const name = getLibraryName(context, operation);
    return diagnostics.wrap({
        __raw: operation,
        kind: "basic",
        name,
        access: getAccess(context, operation),
        parameters: methodParameters,
        description: getDocHelper(context, operation).description,
        details: getDocHelper(context, operation).details,
        operation: serviceOperation,
        response,
        apiVersions,
        getParameterMapping: function getParameterMapping(serviceParam) {
            return ignoreDiagnostics(getCorrespondingMethodParams(context, operation, methodParameters, serviceParam));
        },
        getResponseMapping: function getResponseMapping() {
            return undefined; // currently we only return a value for paging or lro
        },
        crossLanguageDefintionId: getCrossLanguageDefinitionId(context, operation),
        decorators: diagnostics.pipe(getTypeDecorators(context, operation)),
        generateConvenient: shouldGenerateConvenient(context, operation),
        generateProtocol: shouldGenerateProtocol(context, operation),
    });
}
function getSdkServiceMethod(context, operation) {
    const lro = getLroMetadata(context.program, operation);
    const paging = getPagedResult(context.program, operation);
    if (lro && paging) {
        return getSdkLroPagingServiceMethod(context, operation);
    }
    else if (paging) {
        return getSdkPagingServiceMethod(context, operation);
    }
    else if (lro) {
        return getSdkLroServiceMethod(context, operation);
    }
    return getSdkBasicServiceMethod(context, operation);
}
function getClientDefaultApiVersion(context, client) {
    if (context.apiVersion && !["latest", "all"].includes(context.apiVersion)) {
        return context.apiVersion;
    }
    let defaultVersion = getDefaultApiVersion(context, client.service)?.value;
    if (!defaultVersion) {
        // eslint-disable-next-line deprecation/deprecation
        defaultVersion = getService(context.program, client.service)?.version;
    }
    return defaultVersion;
}
function getSdkInitializationType(context, client) {
    const diagnostics = createDiagnosticCollector();
    const credentialParam = getSdkCredentialParameter(context, client);
    const properties = [
        diagnostics.pipe(getSdkEndpointParameter(context, client)), // there will always be an endpoint parameter
    ];
    if (credentialParam) {
        properties.push(credentialParam);
    }
    let apiVersionParam = context.__namespaceToApiVersionParameter.get(client.type);
    if (!apiVersionParam) {
        for (const operationGroup of listOperationGroups(context, client)) {
            // if any sub operation groups have an api version param, the top level needs
            // the api version param as well
            apiVersionParam = context.__namespaceToApiVersionParameter.get(operationGroup.type);
            if (apiVersionParam)
                break;
        }
    }
    if (apiVersionParam) {
        properties.push(apiVersionParam);
    }
    if (context.__subscriptionIdParameter) {
        properties.push(context.__subscriptionIdParameter);
    }
    const namePrefix = client.kind === "SdkClient" ? client.name : client.groupPath;
    const name = `${namePrefix.split(".").at(-1)}Options`;
    return diagnostics.wrap({
        __raw: client.service,
        description: "Initialization class for the client",
        kind: "model",
        properties,
        name,
        isGeneratedName: true,
        access: client.kind === "SdkClient" ? "public" : "internal",
        usage: UsageFlags.Input,
        crossLanguageDefinitionId: `${getNamespaceFullName(client.service.namespace)}.${name}`,
        apiVersions: context.__tspTypeToApiVersions.get(client.type),
        isFormDataType: false,
        isError: false,
        decorators: [],
    });
}
function getSdkMethodParameter(context, type, operation) {
    const diagnostics = createDiagnosticCollector();
    if (type.kind !== "ModelProperty") {
        const libraryName = getLibraryName(context, type);
        const name = camelCase(libraryName ?? "body");
        // call before creating property type, so we can pass apiVersions of param onto its type
        const apiVersions = getAvailableApiVersions(context, type, operation);
        const propertyType = diagnostics.pipe(getClientTypeWithDiagnostics(context, type, operation));
        return diagnostics.wrap({
            kind: "method",
            description: getDocHelper(context, type).description,
            details: getDocHelper(context, type).details,
            apiVersions,
            type: propertyType,
            name,
            isGeneratedName: Boolean(libraryName),
            optional: false,
            discriminator: false,
            serializedName: name,
            isApiVersionParam: false,
            onClient: false,
            crossLanguageDefinitionId: "anonymous",
            decorators: diagnostics.pipe(getTypeDecorators(context, type)),
        });
    }
    return diagnostics.wrap({
        ...diagnostics.pipe(getSdkModelPropertyType(context, type, operation)),
        kind: "method",
    });
}
function getSdkMethods(context, client) {
    const diagnostics = createDiagnosticCollector();
    const retval = [];
    for (const operation of listOperationsInOperationGroup(context, client)) {
        retval.push(diagnostics.pipe(getSdkServiceMethod(context, operation)));
    }
    for (const operationGroup of listOperationGroups(context, client)) {
        // We create a client accessor for each operation group
        const operationGroupClient = diagnostics.pipe(createSdkClientType(context, operationGroup));
        const name = `get${operationGroup.type.name}`;
        retval.push({
            kind: "clientaccessor",
            parameters: [],
            name,
            description: getDocHelper(context, operationGroup.type).description,
            details: getDocHelper(context, operationGroup.type).details,
            access: "internal",
            response: operationGroupClient,
            apiVersions: getAvailableApiVersions(context, operationGroup.type, client.type),
            crossLanguageDefintionId: getCrossLanguageDefinitionId(context, operationGroup.type),
            decorators: [],
        });
    }
    return diagnostics.wrap(retval);
}
function getSdkEndpointParameter(context, client) {
    const diagnostics = createDiagnosticCollector();
    const servers = getServers(context.program, client.service);
    let type;
    let optional = false;
    if (servers === undefined || servers.length > 1) {
        // if there is no defined server url, or if there are more than one
        // we will return a mandatory endpoint parameter in initialization
        const name = "endpoint";
        type = {
            kind: "endpoint",
            serverUrl: "{endpoint}",
            templateArguments: [
                {
                    name,
                    isGeneratedName: true,
                    description: "Service host",
                    kind: "path",
                    onClient: true,
                    urlEncode: false,
                    optional: false,
                    serializedName: "endpoint",
                    correspondingMethodParams: [],
                    type: {
                        kind: "string",
                        encode: "string",
                        decorators: [],
                    },
                    isApiVersionParam: false,
                    apiVersions: context.__tspTypeToApiVersions.get(client.type),
                    crossLanguageDefinitionId: `${getCrossLanguageDefinitionId(context, client.service)}.endpoint`,
                    decorators: [],
                },
            ],
            decorators: [],
        };
    }
    else {
        // this means we have one server
        const templateArguments = [];
        type = {
            kind: "endpoint",
            serverUrl: servers[0].url,
            templateArguments,
            decorators: [],
        };
        for (const param of servers[0].parameters.values()) {
            const sdkParam = diagnostics.pipe(getSdkHttpParameter(context, param, undefined, "path"));
            if (sdkParam.kind === "path") {
                templateArguments.push(sdkParam);
                sdkParam.description = sdkParam.description ?? servers[0].description;
                sdkParam.onClient = true;
                const apiVersionInfo = updateWithApiVersionInformation(context, param, client.type);
                sdkParam.clientDefaultValue = apiVersionInfo.clientDefaultValue;
                sdkParam.isApiVersionParam = apiVersionInfo.isApiVersionParam;
                sdkParam.apiVersions = getAvailableApiVersions(context, param, client.type);
            }
            else {
                diagnostics.add(createDiagnostic({
                    code: "server-param-not-path",
                    target: param,
                    format: {
                        templateArgumentName: sdkParam.name,
                        templateArgumentType: sdkParam.kind,
                    },
                }));
            }
        }
        optional = Boolean(servers[0].url.length && templateArguments.every((param) => param.optional));
    }
    return diagnostics.wrap({
        kind: "endpoint",
        type,
        name: "endpoint",
        isGeneratedName: true,
        description: "Service host",
        onClient: true,
        urlEncode: false,
        apiVersions: context.__tspTypeToApiVersions.get(client.type),
        optional,
        isApiVersionParam: false,
        crossLanguageDefinitionId: `${getCrossLanguageDefinitionId(context, client.service)}.endpoint`,
        decorators: [],
    });
}
function createSdkClientType(context, client) {
    const diagnostics = createDiagnosticCollector();
    const isClient = client.kind === "SdkClient";
    const clientName = isClient ? client.name : client.type.name;
    // NOTE: getSdkMethods recursively calls createSdkClientType
    const methods = diagnostics.pipe(getSdkMethods(context, client));
    const docWrapper = getDocHelper(context, client.type);
    const sdkClientType = {
        kind: "client",
        name: clientName,
        description: docWrapper.description,
        details: docWrapper.details,
        methods: methods,
        apiVersions: context.__tspTypeToApiVersions.get(client.type),
        nameSpace: getClientNamespaceStringHelper(context, client.service),
        initialization: diagnostics.pipe(getSdkInitializationType(context, client)), // MUST call this after getSdkMethods has been called
        // eslint-disable-next-line deprecation/deprecation
        arm: client.kind === "SdkClient" ? client.arm : false,
        decorators: diagnostics.pipe(getTypeDecorators(context, client.type)),
    };
    return diagnostics.wrap(sdkClientType);
}
function populateApiVersionInformation(context) {
    for (const client of listClients(context)) {
        let clientApiVersions = resolveVersions(context.program, client.service)
            .filter((x) => x.rootVersion)
            .map((x) => x.rootVersion.value);
        context.__tspTypeToApiVersions.set(client.type, filterApiVersionsWithDecorators(context, client.type, clientApiVersions));
        context.__namespaceToApiVersionClientDefaultValue.set(client.type, getClientDefaultApiVersion(context, client));
        for (const og of listOperationGroups(context, client)) {
            clientApiVersions = resolveVersions(context.program, og.service)
                .filter((x) => x.rootVersion)
                .map((x) => x.rootVersion.value);
            context.__tspTypeToApiVersions.set(og.type, filterApiVersionsWithDecorators(context, og.type, clientApiVersions));
            context.__namespaceToApiVersionClientDefaultValue.set(og.type, getClientDefaultApiVersion(context, og));
        }
    }
}
function getSdkPackage(context) {
    const diagnostics = createDiagnosticCollector();
    populateApiVersionInformation(context);
    const modelsAndEnums = diagnostics.pipe(getAllModelsWithDiagnostics(context));
    const crossLanguagePackageId = diagnostics.pipe(getCrossLanguagePackageId(context));
    return {
        name: getClientNamespaceString(context),
        rootNamespace: getClientNamespaceString(context),
        clients: listClients(context).map((c) => diagnostics.pipe(createSdkClientType(context, c))),
        models: modelsAndEnums.filter((x) => x.kind === "model"),
        enums: modelsAndEnums.filter((x) => x.kind === "enum"),
        diagnostics: diagnostics.diagnostics,
        crossLanguagePackageId,
    };
}

const namespace = "Azure.ClientGenerator.Core";
const AllScopes = Symbol.for("@azure-core/typespec-client-generator-core/all-scopes");
function getScopedDecoratorData(context, key, target) {
    const retval = context.program.stateMap(key).get(target);
    if (retval === undefined)
        return retval;
    if (Object.keys(retval).includes(context.emitterName))
        return retval[context.emitterName];
    return retval[AllScopes]; // in this case it applies to all languages
}
function listScopedDecoratorData(context, key) {
    const retval = [...context.program.stateMap(key).values()];
    return retval
        .filter((targetEntry) => {
        return targetEntry[context.emitterName] || targetEntry[AllScopes];
    })
        .flatMap((targetEntry) => targetEntry[context.emitterName] ?? targetEntry[AllScopes]);
}
function setScopedDecoratorData(context, decorator, key, target, value, scope, transitivity = false) {
    const targetEntry = context.program.stateMap(key).get(target);
    const splitScopes = scope?.split(",").map((s) => s.trim()) || [AllScopes];
    // If target doesn't exist in decorator map, create a new entry
    if (!targetEntry) {
        const newObject = Object.fromEntries(splitScopes.map((scope) => [scope, value]));
        context.program.stateMap(key).set(target, newObject);
        return true;
    }
    // If target exists, but there's a specified scope and it doesn't exist in the target entry, add mapping of scope and value to target entry
    const scopes = Reflect.ownKeys(targetEntry);
    if (!scopes.includes(AllScopes) && scope && !splitScopes.some((s) => scopes.includes(s))) {
        const newObject = Object.fromEntries(splitScopes.map((scope) => [scope, value]));
        context.program.stateMap(key).set(target, { ...targetEntry, ...newObject });
        return true;
    }
    // we only want to allow multiple decorators if they each specify a different scope
    if (!transitivity) {
        validateDecoratorUniqueOnNode(context, target, decorator);
        return false;
    }
    // for transitivity situation, we could allow scope extension
    if (!scopes.includes(AllScopes) && !scope) {
        const newObject = Object.fromEntries(splitScopes.map((scope) => [scope, value]));
        context.program.stateMap(key).set(target, { ...targetEntry, ...newObject });
    }
    return false;
}
const clientKey = createStateSymbol("client");
function isArm(service) {
    return service.decorators.some((decorator) => decorator.decorator.name === "$armProviderNamespace");
}
function $client(context, target, options, scope) {
    if (context.decoratorTarget.kind === SyntaxKind.AugmentDecoratorStatement) {
        reportDiagnostic(context.program, {
            code: "wrong-client-decorator",
            target: context.decoratorTarget,
        });
        return;
    }
    const explicitName = options?.properties.get("name")?.type;
    const name = explicitName?.kind === "String" ? explicitName.value : target.name;
    const explicitService = options?.properties.get("service")?.type;
    const service = explicitService?.kind === "Namespace"
        ? explicitService
        : findClientService(context.program, target) ?? target;
    if (!name.endsWith("Client")) {
        reportDiagnostic(context.program, {
            code: "client-name",
            format: { name },
            target: context.decoratorTarget,
        });
    }
    if (!isService(context.program, service)) {
        reportDiagnostic(context.program, {
            code: "client-service",
            format: { name },
            target: context.decoratorTarget,
        });
    }
    const client = {
        kind: "SdkClient",
        name,
        service,
        type: target,
        arm: isArm(service),
        crossLanguageDefinitionId: `${getNamespaceFullName(service)}.${name}`,
    };
    setScopedDecoratorData(context, $client, clientKey, target, client, scope);
}
function findClientService(program, client) {
    let current = client;
    while (current) {
        if (isService(program, current)) {
            // we don't check scoped clients here, because we want to find the service for the client
            return current;
        }
        const client = program.stateMap(clientKey).get(current);
        if (client && client[AllScopes]) {
            return client[AllScopes].service;
        }
        current = current.namespace;
    }
    return undefined;
}
/**
 * Return the client object for the given namespace or interface, or undefined if the given namespace or interface is not a client.
 *
 * @param context TCGCContext
 * @param type Type to check
 * @returns Client or undefined
 */
function getClient(context, type) {
    for (const client of listClients(context)) {
        if (client.type === type) {
            return client;
        }
    }
    return undefined;
}
function hasExplicitClientOrOperationGroup(context) {
    return (listScopedDecoratorData(context, clientKey).length > 0 ||
        listScopedDecoratorData(context, operationGroupKey).length > 0);
}
function serviceVersioningProjection(context, client) {
    if (!context.__service_projection) {
        context.__service_projection = new Map();
    }
    let projectedService;
    let projectedProgram;
    if (context.__service_projection.has(client.service)) {
        [projectedService, projectedProgram] = context.__service_projection.get(client.service);
    }
    else {
        const allApiVersions = getVersions(context.program, client.service)[1]
            ?.getVersions()
            .map((x) => x.value);
        if (!allApiVersions)
            return;
        let apiVersion = context.apiVersion;
        if (apiVersion === "latest" ||
            apiVersion === undefined ||
            !allApiVersions.includes(apiVersion)) {
            apiVersion = allApiVersions[allApiVersions.length - 1];
        }
        if (apiVersion === undefined)
            return;
        const versionProjections = buildVersionProjections(context.program, client.service).filter((v) => apiVersion === v.version);
        if (versionProjections.length !== 1)
            throw new Error("Version projects should only contain one element");
        const projectedVersion = versionProjections[0];
        if (projectedVersion.projections.length > 0) {
            projectedProgram = context.program = projectProgram(context.originalProgram, projectedVersion.projections);
        }
        projectedService = projectedProgram
            ? projectedProgram.projector.projectedTypes.get(client.service)
            : client.service;
        context.__service_projection.set(client.service, [projectedService, projectedProgram]);
    }
    if (client.service !== client.type) {
        client.type = projectedProgram
            ? projectedProgram.projector.projectedTypes.get(client.type)
            : client.type;
    }
    else {
        client.type = projectedService;
    }
    client.service = projectedService;
}
function getClientsWithVersioning(context, clients) {
    if (context.apiVersion !== "all") {
        const projectedClients = [];
        for (const client of clients) {
            const projectedClient = { ...client };
            serviceVersioningProjection(context, projectedClient);
            // filter client not existed in the current version
            if (projectedClient.type.kind !== "Intrinsic") {
                projectedClients.push(projectedClient);
            }
        }
        return projectedClients;
    }
    return clients;
}
/**
 * List all the clients.
 *
 * @param context TCGCContext
 * @returns Array of clients
 */
function listClients(context) {
    if (context.__rawClients)
        return context.__rawClients;
    const explicitClients = [...listScopedDecoratorData(context, clientKey)];
    if (explicitClients.length > 0) {
        context.__rawClients = getClientsWithVersioning(context, explicitClients);
        if (context.__rawClients.some((client) => isArm(client.service))) {
            context.arm = true;
        }
        return context.__rawClients;
    }
    // if there is no explicit client, we will treat namespaces with service decorator as clients
    const services = listServices(context.program);
    const clients = services.map((service) => {
        let originalName = service.type.name;
        const clientNameOverride = getClientNameOverride(context, service.type);
        if (clientNameOverride) {
            originalName = clientNameOverride;
        }
        else {
            originalName = getProjectedName(context.program, service.type, "client") ?? service.type.name;
        }
        const clientName = originalName.endsWith("Client") ? originalName : `${originalName}Client`;
        context.arm = isArm(service.type);
        return {
            kind: "SdkClient",
            name: clientName,
            service: service.type,
            type: service.type,
            arm: isArm(service.type),
            crossLanguageDefinitionId: `${getNamespaceFullName(service.type)}.${clientName}`,
        };
    });
    context.__rawClients = getClientsWithVersioning(context, clients);
    return context.__rawClients;
}
const operationGroupKey = createStateSymbol("operationGroup");
function $operationGroup(context, target, scope) {
    if (context.decoratorTarget.kind === SyntaxKind.AugmentDecoratorStatement) {
        reportDiagnostic(context.program, {
            code: "wrong-client-decorator",
            target: context.decoratorTarget,
        });
        return;
    }
    const service = findClientService(context.program, target) ?? target;
    if (!isService(context.program, service)) {
        reportDiagnostic(context.program, {
            code: "client-service",
            format: { name: target.name },
            target: context.decoratorTarget,
        });
    }
    setScopedDecoratorData(context, $operationGroup, operationGroupKey, target, {
        kind: "SdkOperationGroup",
        type: target,
        service,
    }, scope);
}
/**
 * Check a namespace or interface is an operation group.
 * @param context TCGCContext
 * @param type Type to check
 * @returns boolean
 */
function isOperationGroup(context, type) {
    if (hasExplicitClientOrOperationGroup(context)) {
        return getScopedDecoratorData(context, operationGroupKey, type) !== undefined;
    }
    // if there is no explicit client, we will treat non-client namespaces and all interfaces as operation group
    if (type.kind === "Interface" && !isTemplateDeclaration(type)) {
        return true;
    }
    if (type.kind === "Namespace" && !type.decorators.some((t) => t.decorator.name === "$service")) {
        return true;
    }
    return false;
}
/**
 * Check an operation is in an operation group.
 * @param context TCGCContext
 * @param type Type to check
 * @returns boolean
 */
function isInOperationGroup(context, type) {
    switch (type.kind) {
        case "Operation":
            return type.interface
                ? isInOperationGroup(context, type.interface)
                : type.namespace
                    ? isInOperationGroup(context, type.namespace)
                    : false;
        case "Interface":
        case "Namespace":
            return (isOperationGroup(context, type) ||
                (type.namespace ? isInOperationGroup(context, type.namespace) : false));
    }
}
function buildOperationGroupPath(context, type) {
    const path = [];
    while (true) {
        const client = getClient(context, type);
        if (client) {
            path.push(client.name);
            break;
        }
        if (isOperationGroup(context, type)) {
            path.push(getLibraryName(context, type));
        }
        if (type.namespace) {
            type = type.namespace;
        }
        else {
            break;
        }
    }
    return path.reverse().join(".");
}
/**
 * Return the operation group object for the given namespace or interface or undefined is not an operation group.
 * @param context TCGCContext
 * @param type Type to check
 * @returns Operation group or undefined.
 */
function getOperationGroup(context, type) {
    let operationGroup;
    const service = findClientService(context.program, type) ?? type;
    if (!isService(context.program, service)) {
        reportDiagnostic(context.program, {
            code: "client-service",
            format: { name: type.name },
            target: type,
        });
    }
    if (hasExplicitClientOrOperationGroup(context)) {
        operationGroup = getScopedDecoratorData(context, operationGroupKey, type);
        if (operationGroup) {
            operationGroup.groupPath = buildOperationGroupPath(context, type);
        }
    }
    else {
        // if there is no explicit client, we will treat non-client namespaces and all interfaces as operation group
        if (type.kind === "Interface" && !isTemplateDeclaration(type)) {
            operationGroup = {
                kind: "SdkOperationGroup",
                type,
                groupPath: buildOperationGroupPath(context, type),
                service,
            };
        }
        if (type.kind === "Namespace" &&
            !type.decorators.some((t) => t.decorator.name === "$service")) {
            operationGroup = {
                kind: "SdkOperationGroup",
                type,
                groupPath: buildOperationGroupPath(context, type),
                service,
            };
        }
    }
    // build hierarchy of operation group
    if (operationGroup && type.kind === "Namespace") {
        const subOperationGroups = [];
        type.namespaces.forEach((ns) => {
            const subOperationGroup = getOperationGroup(context, ns);
            if (subOperationGroup) {
                subOperationGroups.push(subOperationGroup);
            }
        });
        type.interfaces.forEach((i) => {
            const subOperationGroup = getOperationGroup(context, i);
            if (subOperationGroup) {
                subOperationGroups.push(subOperationGroup);
            }
        });
        if (subOperationGroups.length > 0) {
            operationGroup.subOperationGroups = subOperationGroups;
        }
    }
    return operationGroup;
}
/**
 * List all the operation groups inside a client or an operation group. If ignoreHierarchy is true, the result will include all nested operation groups.
 *
 * @param context TCGCContext
 * @param group Client or operation group to list operation groups
 * @param ignoreHierarchy Whether to get all nested operation groups
 * @returns
 */
function listOperationGroups(context, group, ignoreHierarchy = false) {
    const groups = [];
    if (group.type.kind === "Interface") {
        return groups;
    }
    for (const subItem of group.type.namespaces.values()) {
        track(getOperationGroup(context, subItem));
    }
    for (const subItem of group.type.interfaces.values()) {
        track(getOperationGroup(context, subItem));
    }
    function track(item) {
        if (!item) {
            return;
        }
        groups.push(item);
        if (ignoreHierarchy) {
            for (const subItem of item.subOperationGroups ?? []) {
                track(subItem);
            }
        }
    }
    return groups;
}
/**
 * List operations inside a client or an operation group. If ignoreHierarchy is true, the result will include all nested operations.
 * @param program TCGCContext
 * @param group Client or operation group to list operations
 * @param ignoreHierarchy Whether to get all nested operations
 * @returns
 */
function listOperationsInOperationGroup(context, group, ignoreHierarchy = false) {
    const operations = [];
    function addOperations(current) {
        if (current !== group.type &&
            !ignoreHierarchy &&
            (getClient(context, current) || isOperationGroup(context, current))) {
            return;
        }
        if (current.kind === "Interface" && isTemplateDeclaration(current)) {
            // Skip template interface operations
            return;
        }
        for (const op of current.operations.values()) {
            // Skip templated operations
            if (!isTemplateDeclarationOrInstance(op)) {
                operations.push(op);
            }
        }
        if (current.kind === "Namespace") {
            for (const subItem of current.namespaces.values()) {
                addOperations(subItem);
            }
            for (const subItem of current.interfaces.values()) {
                addOperations(subItem);
            }
        }
    }
    addOperations(group.type);
    return operations;
}
function createSdkContext(context, emitterName, options) {
    const diagnostics = createDiagnosticCollector();
    const protocolOptions = true; // context.program.getLibraryOptions("generate-protocol-methods");
    const convenienceOptions = true; // context.program.getLibraryOptions("generate-convenience-methods");
    const generateProtocolMethods = context.options["generate-protocol-methods"] ?? protocolOptions;
    const generateConvenienceMethods = context.options["generate-convenience-methods"] ?? convenienceOptions;
    const sdkContext = {
        program: context.program,
        emitContext: context,
        sdkPackage: undefined,
        emitterName: diagnostics.pipe(parseEmitterName(context.program, emitterName ?? context.program.emitters[0]?.metadata?.name)), // eslint-disable-line deprecation/deprecation
        generateProtocolMethods: generateProtocolMethods,
        generateConvenienceMethods: generateConvenienceMethods,
        filterOutCoreModels: context.options["filter-out-core-models"] ?? true,
        packageName: context.options["package-name"],
        flattenUnionAsEnum: context.options["flatten-union-as-enum"] ?? true,
        diagnostics: diagnostics.diagnostics,
        apiVersion: options?.versioning?.strategy === "ignore" ? "all" : context.options["api-version"],
        originalProgram: context.program,
        __namespaceToApiVersionParameter: new Map(),
        __tspTypeToApiVersions: new Map(),
        __namespaceToApiVersionClientDefaultValue: new Map(),
        decoratorsAllowList: [...defaultDecoratorsAllowList, ...(options?.additionalDecorators ?? [])],
        previewStringRegex: options?.versioning?.previewStringRegex || /-preview$/,
    };
    sdkContext.sdkPackage = getSdkPackage(sdkContext);
    if (sdkContext.diagnostics) {
        sdkContext.diagnostics = sdkContext.diagnostics.concat(sdkContext.sdkPackage.diagnostics // eslint-disable-line deprecation/deprecation
        );
    }
    return sdkContext;
}
const protocolAPIKey = createStateSymbol("protocolAPI");
function $protocolAPI(context, entity, value, scope) {
    setScopedDecoratorData(context, $protocolAPI, protocolAPIKey, entity, value, scope);
}
const convenientAPIKey = createStateSymbol("convenientAPI");
function $convenientAPI(context, entity, value, scope) {
    setScopedDecoratorData(context, $convenientAPI, convenientAPIKey, entity, value, scope);
}
function shouldGenerateProtocol(context, entity) {
    const value = getScopedDecoratorData(context, protocolAPIKey, entity);
    return value ?? Boolean(context.generateProtocolMethods);
}
function shouldGenerateConvenient(context, entity) {
    const value = getScopedDecoratorData(context, convenientAPIKey, entity);
    return value ?? Boolean(context.generateConvenienceMethods);
}
const excludeKey = createStateSymbol("exclude");
/**
 * @deprecated Use `usage` and `access` decorator instead.
 */
function $exclude(context, entity, scope) {
    setScopedDecoratorData(context, $exclude, excludeKey, entity, true, scope); // eslint-disable-line deprecation/deprecation
}
const includeKey = createStateSymbol("include");
/**
 * @deprecated Use `usage` and `access` decorator instead.
 */
function $include(context, entity, scope) {
    modelTransitiveSet(context, $include, includeKey, entity, true, scope); // eslint-disable-line deprecation/deprecation
}
/**
 * @deprecated This function is unused and will be removed in a future release.
 */
function isExclude(context, entity) {
    return getScopedDecoratorData(context, excludeKey, entity) ?? false;
}
/**
 * @deprecated This function is unused and will be removed in a future release.
 */
function isInclude(context, entity) {
    return getScopedDecoratorData(context, includeKey, entity) ?? false;
}
function modelTransitiveSet(context, decorator, key, entity, value, scope, transitivity = false) {
    if (!setScopedDecoratorData(context, decorator, key, entity, value, scope, transitivity)) {
        return;
    }
    if (entity.baseModel) {
        modelTransitiveSet(context, decorator, key, entity.baseModel, value, scope, true);
    }
    entity.properties.forEach((p) => {
        if (p.kind === "ModelProperty" && p.type.kind === "Model") {
            modelTransitiveSet(context, decorator, key, p.type, value, scope, true);
        }
    });
}
const clientFormatKey = createStateSymbol("clientFormat");
const allowedClientFormatToTargetTypeMap = {
    unixtime: ["int32", "int64"],
    iso8601: ["utcDateTime", "offsetDateTime", "duration"],
    rfc1123: ["utcDateTime", "offsetDateTime"],
    seconds: ["duration"],
};
/**
 * @deprecated Use `encode` decorator in `@typespec/core` instead.
 */
function $clientFormat(context, target, format, scope) {
    const expectedTargetTypes = allowedClientFormatToTargetTypeMap[format];
    if (context.program.checker.isStdType(target.type) &&
        expectedTargetTypes.includes(target.type.name)) {
        setScopedDecoratorData(context, $clientFormat, clientFormatKey, target, format, scope); // eslint-disable-line deprecation/deprecation
    }
    else {
        reportDiagnostic(context.program, {
            code: "incorrect-client-format",
            format: { format, expectedTargetTypes: expectedTargetTypes.join('", "') },
            target: context.decoratorTarget,
        });
    }
}
/**
 * Gets additional information on how to serialize / deserialize TYPESPEC standard types depending
 * on whether additional serialization information is provided or needed
 *
 * @param context the Sdk Context
 * @param entity the entity whose client format we are going to get
 * @returns the format in which to serialize the typespec type or undefined
 * @deprecated This function is unused and will be removed in a future release.
 */
function getClientFormat(context, entity) {
    let retval = getScopedDecoratorData(context, clientFormatKey, entity);
    if (retval === undefined && context.program.checker.isStdType(entity.type)) {
        if (entity.type.name === "utcDateTime" || entity.type.name === "offsetDateTime") {
            // if it's a date-time we have the following defaults
            retval = isHeader(context.program, entity) ? "rfc1123" : "iso8601";
            context.program.stateMap(clientFormatKey).set(entity, retval);
        }
        else if (entity.type.name === "duration") {
            retval = "iso8601";
        }
    }
    return retval;
}
const internalKey = createStateSymbol("internal");
/**
 * Whether a operation is internal and should not be exposed
 * to end customers
 *
 * @param context DecoratorContext
 * @param target Operation to mark as internal
 * @param scope Names of the projection (e.g. "python", "csharp", "java", "javascript")
 * @deprecated Use `access` decorator instead.
 */
function $internal(context, target, scope) {
    setScopedDecoratorData(context, $internal, internalKey, target, true, scope); // eslint-disable-line deprecation/deprecation
}
/**
 * Whether a model / operation is internal or not. If it's internal, emitters
 * should not expose them to users
 *
 * @param context TCGCContext
 * @param entity model / operation that we want to check is internal or not
 * @returns whether the entity is internal
 * @deprecated This function is unused and will be removed in a future release.
 */
function isInternal(context, entity) {
    const found = getScopedDecoratorData(context, internalKey, entity) ?? false;
    if (entity.kind === "Operation" || found) {
        return found;
    }
    const operationModels = context.operationModelsMap;
    let referredByInternal = false;
    for (const [operation, modelMap] of operationModels) {
        // eslint-disable-next-line deprecation/deprecation
        if (isInternal(context, operation) && modelMap.get(entity)) {
            referredByInternal = true;
            // eslint-disable-next-line deprecation/deprecation
        }
        else if (!isInternal(context, operation) && modelMap.get(entity)) {
            return false;
        }
    }
    return referredByInternal;
}
const usageKey = createStateSymbol("usage");
function $usage(context, entity, value, scope) {
    const isValidValue = (value) => value === 2 || value === 4;
    if (value.kind === "EnumMember") {
        if (typeof value.value === "number" && isValidValue(value.value)) {
            setScopedDecoratorData(context, $usage, usageKey, entity, value.value, scope);
            return;
        }
    }
    else {
        let usage = 0;
        for (const variant of value.variants.values()) {
            if (variant.type.kind === "EnumMember" && typeof variant.type.value === "number") {
                if (isValidValue(variant.type.value)) {
                    usage |= variant.type.value;
                }
            }
            else {
                break;
            }
        }
        if (usage !== 0) {
            setScopedDecoratorData(context, $usage, usageKey, entity, usage, scope);
            return;
        }
    }
    reportDiagnostic(context.program, {
        code: "invalid-usage",
        format: {},
        target: entity,
    });
}
function getUsageOverride(context, entity) {
    return getScopedDecoratorData(context, usageKey, entity);
}
function getUsage(context, entity) {
    return entity.kind === "Model"
        ? getSdkModel(context, entity).usage
        : getSdkEnum(context, entity).usage;
}
const accessKey = createStateSymbol("access");
function $access(context, entity, value, scope) {
    if (typeof value.value !== "string" || (value.value !== "public" && value.value !== "internal")) {
        reportDiagnostic(context.program, {
            code: "access",
            format: {},
            target: entity,
        });
    }
    setScopedDecoratorData(context, $access, accessKey, entity, value.value, scope);
}
function getAccessOverride(context, entity) {
    return getScopedDecoratorData(context, accessKey, entity);
}
function getAccess(context, entity) {
    const override = getScopedDecoratorData(context, accessKey, entity);
    if (override || entity.kind === "Operation") {
        return override || "public";
    }
    switch (entity.kind) {
        case "Model":
            return getSdkModel(context, entity).access;
        case "Enum":
            return getSdkEnum(context, entity).access;
        case "Union":
            const type = getSdkUnion(context, entity);
            if (type.kind === "enum" || type.kind === "model") {
                return type.access;
            }
            return "public";
    }
}
const flattenPropertyKey = createStateSymbol("flattenPropertyKey");
/**
 * Whether a model property should be flattened.
 *
 * @param context DecoratorContext
 * @param target ModelProperty to mark as flattened
 * @param scope Names of the projection (e.g. "python", "csharp", "java", "javascript")
 * @deprecated This decorator is not recommended to use.
 */
function $flattenProperty(context, target, scope) {
    setScopedDecoratorData(context, $flattenProperty, flattenPropertyKey, target, true, scope); // eslint-disable-line deprecation/deprecation
}
/**
 * Whether a model property should be flattened or not.
 *
 * @param context TCGCContext
 * @param target ModelProperty that we want to check whether it should be flattened or not
 * @returns whether the model property should be flattened or not
 */
function shouldFlattenProperty(context, target) {
    return getScopedDecoratorData(context, flattenPropertyKey, target) ?? false;
}
const clientNameKey = createStateSymbol("clientName");
function $clientName(context, entity, value, scope) {
    // workaround for current lack of functionality in compiler
    // https://github.com/microsoft/typespec/issues/2717
    if (entity.kind === "Model" || entity.kind === "Operation") {
        if (context.decoratorTarget.kind === SyntaxKind.AugmentDecoratorStatement) {
            if (ignoreDiagnostics(context.program.checker.resolveTypeReference(context.decoratorTarget.targetType))?.node !== entity.node) {
                return;
            }
        }
        if (context.decoratorTarget.kind === SyntaxKind.DecoratorExpression) {
            if (context.decoratorTarget.parent !== entity.node) {
                return;
            }
        }
    }
    if (value.trim() === "") {
        reportDiagnostic(context.program, {
            code: "empty-client-name",
            format: {},
            target: entity,
        });
    }
    setScopedDecoratorData(context, $clientName, clientNameKey, entity, value, scope);
}
function getClientNameOverride(context, entity) {
    return getScopedDecoratorData(context, clientNameKey, entity);
}

var f0 = /*#__PURE__*/Object.freeze({
    __proto__: null,
    $access: $access,
    $client: $client,
    $clientFormat: $clientFormat,
    $clientName: $clientName,
    $convenientAPI: $convenientAPI,
    $exclude: $exclude,
    $flattenProperty: $flattenProperty,
    $include: $include,
    $internal: $internal,
    $lib: $lib,
    $operationGroup: $operationGroup,
    $protocolAPI: $protocolAPI,
    $usage: $usage,
    get UsageFlags () { return UsageFlags; },
    addEncodeInfo: addEncodeInfo,
    addFormatInfo: addFormatInfo,
    createDiagnostic: createDiagnostic,
    createSdkContext: createSdkContext,
    createStateSymbol: createStateSymbol,
    getAccess: getAccess,
    getAccessOverride: getAccessOverride,
    getAllModels: getAllModels,
    getAllModelsWithDiagnostics: getAllModelsWithDiagnostics,
    getClient: getClient,
    getClientFormat: getClientFormat,
    getClientNameOverride: getClientNameOverride,
    getClientNamespaceString: getClientNamespaceString,
    getClientType: getClientType,
    getClientTypeWithDiagnostics: getClientTypeWithDiagnostics,
    getCrossLanguageDefinitionId: getCrossLanguageDefinitionId,
    getCrossLanguagePackageId: getCrossLanguagePackageId,
    getDefaultApiVersion: getDefaultApiVersion,
    getEffectivePayloadType: getEffectivePayloadType,
    getEmitterTargetName: getEmitterTargetName,
    getGeneratedName: getGeneratedName,
    getHttpOperationWithCache: getHttpOperationWithCache,
    getKnownScalars: getKnownScalars,
    getLibraryName: getLibraryName,
    getOperationGroup: getOperationGroup,
    getPropertyNames: getPropertyNames,
    getSdkArrayOrDict: getSdkArrayOrDict,
    getSdkArrayOrDictWithDiagnostics: getSdkArrayOrDictWithDiagnostics,
    getSdkBuiltInType: getSdkBuiltInType,
    getSdkConstant: getSdkConstant,
    getSdkCredentialParameter: getSdkCredentialParameter,
    getSdkDurationType: getSdkDurationType,
    getSdkEnum: getSdkEnum,
    getSdkEnumValue: getSdkEnumValue,
    getSdkModel: getSdkModel,
    getSdkModelPropertyType: getSdkModelPropertyType,
    getSdkModelPropertyTypeBase: getSdkModelPropertyTypeBase,
    getSdkModelWithDiagnostics: getSdkModelWithDiagnostics,
    getSdkTuple: getSdkTuple,
    getSdkTupleWithDiagnostics: getSdkTupleWithDiagnostics,
    getSdkUnion: getSdkUnion,
    getSdkUnionEnum: getSdkUnionEnum,
    getSdkUnionWithDiagnostics: getSdkUnionWithDiagnostics,
    getUsage: getUsage,
    getUsageOverride: getUsageOverride,
    getWireName: getWireName,
    isApiVersion: isApiVersion,
    isExclude: isExclude,
    isInOperationGroup: isInOperationGroup,
    isInclude: isInclude,
    isInternal: isInternal,
    isOperationGroup: isOperationGroup,
    isReadOnly: isReadOnly,
    isSdkBuiltInKind: isSdkBuiltInKind,
    isSdkDateTimeEncodings: isSdkDateTimeEncodings,
    isSdkFloatKind: isSdkFloatKind,
    isSdkIntKind: isSdkIntKind,
    listClients: listClients,
    listOperationGroups: listOperationGroups,
    listOperationsInOperationGroup: listOperationsInOperationGroup,
    namespace: namespace,
    reportDiagnostic: reportDiagnostic,
    shouldFlattenProperty: shouldFlattenProperty,
    shouldGenerateConvenient: shouldGenerateConvenient,
    shouldGenerateProtocol: shouldGenerateProtocol
});

const TypeSpecJSSources = {
"dist/src/index.js": f0,
};
const TypeSpecSources = {
  "package.json": "{\"name\":\"@azure-tools/typespec-client-generator-core\",\"version\":\"0.44.0\",\"author\":\"Microsoft Corporation\",\"description\":\"TypeSpec Data Plane Generation library\",\"homepage\":\"https://azure.github.io/typespec-azure\",\"readme\":\"https://github.com/Microsoft/typespec/blob/main/README.md\",\"license\":\"MIT\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/Azure/typespec-azure.git\"},\"bugs\":{\"url\":\"https://github.com/Azure/typespec-azure/issues\"},\"keywords\":[\"typespec\",\"sdk\",\"ClientGenerator\"],\"main\":\"dist/src/index.js\",\"tspMain\":\"./lib/main.tsp\",\"exports\":{\".\":{\"types\":\"./dist/src/index.d.ts\",\"default\":\"./dist/src/index.js\"},\"./testing\":{\"types\":\"./dist/src/testing/index.d.ts\",\"default\":\"./dist/src/testing/index.js\"}},\"type\":\"module\",\"engines\":{\"node\":\">=18.0.0\"},\"scripts\":{\"clean\":\"rimraf ./dist ./temp\",\"build\":\"tsc -p . && npm run lint-typespec-library\",\"watch\":\"tsc -p . --watch\",\"lint-typespec-library\":\"tsp compile . --warn-as-error --import @typespec/library-linter --no-emit\",\"test\":\"vitest run\",\"test:watch\":\"vitest -w\",\"test:ui\":\"vitest --ui\",\"test:ci\":\"vitest run --coverage  --reporter=junit --reporter=default\",\"test:e2e\":\"vitest run --config ./vitest.config.e2e.ts\",\"lint\":\"eslint .  --max-warnings=0\",\"lint:fix\":\"eslint . --fix \",\"regen-docs\":\"tspd doc .  --enable-experimental  --output-dir ../../docs/libraries/typespec-client-generator-core/reference\"},\"files\":[\"lib/*.tsp\",\"dist/**\",\"!dist/test/**\"],\"dependencies\":{\"change-case\":\"~5.4.4\",\"pluralize\":\"^8.0.0\"},\"peerDependencies\":{\"@azure-tools/typespec-azure-core\":\"workspace:~\",\"@typespec/compiler\":\"workspace:~\",\"@typespec/http\":\"workspace:~\",\"@typespec/rest\":\"workspace:~\",\"@typespec/versioning\":\"workspace:~\"},\"devDependencies\":{\"@azure-tools/typespec-azure-core\":\"workspace:~\",\"@types/node\":\"~18.11.19\",\"@types/pluralize\":\"^0.0.33\",\"@typespec/compiler\":\"workspace:~\",\"@typespec/http\":\"workspace:~\",\"@typespec/library-linter\":\"workspace:~\",\"@typespec/prettier-plugin-typespec\":\"workspace:~\",\"@typespec/rest\":\"workspace:~\",\"@typespec/tspd\":\"workspace:~\",\"@typespec/versioning\":\"workspace:~\",\"@typespec/xml\":\"workspace:~\",\"@vitest/coverage-v8\":\"^1.6.0\",\"@vitest/ui\":\"^1.6.0\",\"c8\":\"^10.1.2\",\"rimraf\":\"~5.0.7\",\"typescript\":\"~5.5.3\",\"vitest\":\"^1.6.0\"}}",
  "../../core/packages/compiler/lib/intrinsics.tsp": "import \"../dist/src/lib/intrinsic-decorators.js\";\n\n// This file contains all the intrinsic types of typespec. Everything here will always be loaded\nnamespace TypeSpec;\n\n/**\n * Represent a byte array\n */\nscalar bytes;\n\n/**\n * A numeric type\n */\nscalar numeric;\n\n/**\n * A whole number. This represent any `integer` value possible.\n * It is commonly represented as `BigInteger` in some languages.\n */\nscalar integer extends numeric;\n\n/**\n * A number with decimal value\n */\nscalar float extends numeric;\n\n/**\n * A 64-bit integer. (`-9,223,372,036,854,775,808` to `9,223,372,036,854,775,807`)\n */\nscalar int64 extends integer;\n\n/**\n * A 32-bit integer. (`-2,147,483,648` to `2,147,483,647`)\n */\nscalar int32 extends int64;\n\n/**\n * A 16-bit integer. (`-32,768` to `32,767`)\n */\nscalar int16 extends int32;\n\n/**\n * A 8-bit integer. (`-128` to `127`)\n */\nscalar int8 extends int16;\n\n/**\n * A 64-bit unsigned integer (`0` to `18,446,744,073,709,551,615`)\n */\nscalar uint64 extends integer;\n\n/**\n * A 32-bit unsigned integer (`0` to `4,294,967,295`)\n */\nscalar uint32 extends uint64;\n\n/**\n * A 16-bit unsigned integer (`0` to `65,535`)\n */\nscalar uint16 extends uint32;\n\n/**\n * A 8-bit unsigned integer (`0` to `255`)\n */\nscalar uint8 extends uint16;\n\n/**\n * An integer that can be serialized to JSON (`−9007199254740991 (−(2^53 − 1))` to `9007199254740991 (2^53 − 1)` )\n */\nscalar safeint extends int64;\n\n/**\n * A 32 bit floating point number. (`±1.5 x 10^−45` to `±3.4 x 10^38`)\n */\nscalar float64 extends float;\n\n/**\n * A 32 bit floating point number. (`±5.0 × 10^−324` to `±1.7 × 10^308`)\n */\nscalar float32 extends float64;\n\n/**\n * A decimal number with any length and precision. This represent any `decimal` value possible.\n * It is commonly represented as `BigDecimal` in some languages.\n */\nscalar decimal extends numeric;\n\n/**\n * A 128-bit decimal number.\n */\nscalar decimal128 extends decimal;\n\n/**\n * A sequence of textual characters.\n */\nscalar string;\n\n/**\n * A date on a calendar without a time zone, e.g. \"April 10th\"\n */\nscalar plainDate {\n  /**\n   * Create a plain date from an ISO 8601 string.\n   * @example\n   *\n   * ```tsp\n   * const time = plainTime.fromISO(\"2024-05-06\");\n   * ```\n   */\n  init fromISO(value: string);\n}\n\n/**\n * A time on a clock without a time zone, e.g. \"3:00 am\"\n */\nscalar plainTime {\n  /**\n   * Create a plain time from an ISO 8601 string.\n   * @example\n   *\n   * ```tsp\n   * const time = plainTime.fromISO(\"12:34\");\n   * ```\n   */\n  init fromISO(value: string);\n}\n\n/**\n * An instant in coordinated universal time (UTC)\"\n */\nscalar utcDateTime {\n  /**\n   * Create a date from an ISO 8601 string.\n   * @example\n   *\n   * ```tsp\n   * const time = utcDateTime.fromISO(\"2024-05-06T12:20-12Z\");\n   * ```\n   */\n  init fromISO(value: string);\n}\n\n/**\n * A date and time in a particular time zone, e.g. \"April 10th at 3:00am in PST\"\n */\nscalar offsetDateTime {\n  /**\n   * Create a date from an ISO 8601 string.\n   * @example\n   *\n   * ```tsp\n   * const time = offsetDateTime.fromISO(\"2024-05-06T12:20-12-0700\");\n   * ```\n   */\n  init fromISO(value: string);\n}\n\n/**\n * A duration/time period. e.g 5s, 10h\n */\nscalar duration {\n  /**\n   * Create a duration from an ISO 8601 string.\n   * @example\n   *\n   * ```tsp\n   * const time = duration.fromISO(\"P1Y1D\");\n   * ```\n   */\n  init fromISO(value: string);\n}\n\n/**\n * Boolean with `true` and `false` values.\n */\nscalar boolean;\n\n/**\n * @dev Array model type, equivalent to `Element[]`\n * @template Element The type of the array elements\n */\n@indexer(integer, Element)\nmodel Array<Element> {}\n\n/**\n * @dev Model with string properties where all the properties have type `Property`\n * @template Element The type of the properties\n */\n@indexer(string, Element)\nmodel Record<Element> {}\n",
  "../../core/packages/compiler/lib/std/main.tsp": "// TypeSpec standard library. Everything in here can be omitted by using `--nostdlib` cli flag or `nostdlib` in the config.\nimport \"./types.tsp\";\nimport \"./decorators.tsp\";\nimport \"./reflection.tsp\";\nimport \"./projected-names.tsp\";\n",
  "../../core/packages/compiler/lib/std/types.tsp": "namespace TypeSpec;\n\n/**\n * Represent a 32-bit unix timestamp datetime with 1s of granularity.\n * It measures time by the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970.\n */\n@encode(\"unixTimestamp\", int32)\nscalar unixTimestamp32 extends utcDateTime;\n\n/**\n * Represent a model\n */\n// Deprecated June 2023 sprint\n#deprecated \"object is deprecated. Please use {} for an empty model, `Record<unknown>` for a record with unknown property types, `unknown[]` for an array.\"\nmodel object {}\n\n/**\n * Represent a URL string as described by https://url.spec.whatwg.org/\n */\nscalar url extends string;\n\n/**\n * Represents a collection of optional properties.\n *\n * @template Source An object whose spread properties are all optional.\n */\n@doc(\"The template for adding optional properties.\")\n@withOptionalProperties\nmodel OptionalProperties<Source> {\n  ...Source;\n}\n\n/**\n * Represents a collection of updateable properties.\n *\n * @template Source An object whose spread properties are all updateable.\n */\n@doc(\"The template for adding updateable properties.\")\n@withUpdateableProperties\nmodel UpdateableProperties<Source> {\n  ...Source;\n}\n\n/**\n * Represents a collection of omitted properties.\n *\n * @template Source An object whose properties are spread.\n * @template Keys The property keys to omit.\n */\n@doc(\"The template for omitting properties.\")\n@withoutOmittedProperties(Keys)\nmodel OmitProperties<Source, Keys extends string> {\n  ...Source;\n}\n\n/**\n * Represents a collection of properties with only the specified keys included.\n *\n * @template Source An object whose properties are spread.\n * @template Keys The property keys to include.\n */\n@doc(\"The template for picking properties.\")\n@withPickedProperties(Keys)\nmodel PickProperties<Source, Keys extends string> {\n  ...Source;\n}\n\n/**\n * Represents a collection of properties with default values omitted.\n *\n * @template Source An object whose spread property defaults are all omitted.\n */\n@withoutDefaultValues\nmodel OmitDefaults<Source> {\n  ...Source;\n}\n\n/**\n * Applies a visibility setting to a collection of properties.\n *\n * @template Source An object whose properties are spread.\n * @template Visibility The visibility to apply to all properties.\n */\n@doc(\"The template for setting the default visibility of key properties.\")\n@withDefaultKeyVisibility(Visibility)\nmodel DefaultKeyVisibility<Source, Visibility extends valueof string> {\n  ...Source;\n}\n",
  "../../core/packages/compiler/lib/std/decorators.tsp": "import \"../../dist/src/lib/decorators.js\";\n\nusing TypeSpec.Reflection;\n\nnamespace TypeSpec;\n\n/**\n * Typically a short, single-line description.\n * @param summary Summary string.\n *\n * @example\n * ```typespec\n * @summary(\"This is a pet\")\n * model Pet {}\n * ```\n */\nextern dec summary(target: unknown, summary: valueof string);\n\n/**\n * Attach a documentation string.\n * @param doc Documentation string\n * @param formatArgs Record with key value pair that can be interpolated in the doc.\n *\n * @example\n * ```typespec\n * @doc(\"Represent a Pet available in the PetStore\")\n * model Pet {}\n * ```\n */\nextern dec doc(target: unknown, doc: valueof string, formatArgs?: {});\n\n/**\n * Attach a documentation string to describe the successful return types of an operation.\n * If an operation returns a union of success and errors it only describes the success. See `@errorsDoc` for error documentation.\n * @param doc Documentation string\n *\n * @example\n * ```typespec\n * @returnsDoc(\"Returns doc\")\n * op get(): Pet | NotFound;\n * ```\n */\nextern dec returnsDoc(target: Operation, doc: valueof string);\n\n/**\n * Attach a documentation string to describe the error return types of an operation.\n * If an operation returns a union of success and errors it only describes the errors. See `@returnsDoc` for success documentation.\n * @param doc Documentation string\n *\n * @example\n * ```typespec\n * @errorsDoc(\"Errors doc\")\n * op get(): Pet | NotFound;\n * ```\n */\nextern dec errorsDoc(target: Operation, doc: valueof string);\n\n/**\n * Mark this type as deprecated.\n *\n * NOTE: This decorator **should not** be used, use the `#deprecated` directive instead.\n *\n * @deprecated Use the `#deprecated` directive instead.\n * @param message Deprecation message.\n *\n * @example\n *\n * Use the `#deprecated` directive instead:\n *\n * ```typespec\n * #deprecated \"Use ActionV2\"\n * op Action<Result>(): Result;\n * ```\n */\n#deprecated \"@deprecated decorator is deprecated. Use the `#deprecated` directive instead.\"\nextern dec deprecated(target: unknown, message: valueof string);\n\n/**\n * Service options.\n */\nmodel ServiceOptions {\n  /**\n   * Title of the service.\n   */\n  title?: string;\n\n  /**\n   * Version of the service.\n   */\n  version?: string;\n}\n\n/**\n * Mark this namespace as describing a service and configure service properties.\n * @param options Optional configuration for the service.\n *\n * @example\n * ```typespec\n * @service\n * namespace PetStore;\n * ```\n *\n * @example Setting service title\n * ```typespec\n * @service({title: \"Pet store\"})\n * namespace PetStore;\n * ```\n *\n * @example Setting service version\n * ```typespec\n * @service({version: \"1.0\"})\n * namespace PetStore;\n * ```\n */\nextern dec service(target: Namespace, options?: ServiceOptions);\n\n/**\n * Specify that this model is an error type. Operations return error types when the operation has failed.\n *\n * @example\n * ```typespec\n * @error\n * model PetStoreError {\n *   code: string;\n *   message: string;\n * }\n * ```\n */\nextern dec error(target: Model);\n\n/**\n * Specify a known data format hint for this string type. For example `uuid`, `uri`, etc.\n * This differs from the `@pattern` decorator which is meant to specify a regular expression while `@format` accepts a known format name.\n * The format names are open ended and are left to emitter to interpret.\n *\n * @param format format name.\n *\n * @example\n * ```typespec\n * @format(\"uuid\")\n * scalar uuid extends string;\n * ```\n */\nextern dec format(target: string | bytes | ModelProperty, format: valueof string);\n\n/**\n * Specify the the pattern this string should respect using simple regular expression syntax.\n * The following syntax is allowed: alternations (`|`), quantifiers (`?`, `*`, `+`, and `{ }`), wildcard (`.`), and grouping parentheses.\n * Advanced features like look-around, capture groups, and references are not supported.\n *\n * This decorator may optionally provide a custom validation _message_. Emitters may choose to use the message to provide\n * context when pattern validation fails. For the sake of consistency, the message should be a phrase that describes in\n * plain language what sort of content the pattern attempts to validate. For example, a complex regular expression that\n * validates a GUID string might have a message like \"Must be a valid GUID.\"\n *\n * @param pattern Regular expression.\n * @param validationMessage Optional validation message that may provide context when validation fails.\n *\n * @example\n * ```typespec\n * @pattern(\"[a-z]+\", \"Must be a string consisting of only lower case letters and of at least one character.\")\n * scalar LowerAlpha extends string;\n * ```\n */\nextern dec pattern(\n  target: string | bytes | ModelProperty,\n  pattern: valueof string,\n  validationMessage?: valueof string\n);\n\n/**\n * Specify the minimum length this string type should be.\n * @param value Minimum length\n *\n * @example\n * ```typespec\n * @minLength(2)\n * scalar Username extends string;\n * ```\n */\nextern dec minLength(target: string | ModelProperty, value: valueof integer);\n\n/**\n * Specify the maximum length this string type should be.\n * @param value Maximum length\n *\n * @example\n * ```typespec\n * @maxLength(20)\n * scalar Username extends string;\n * ```\n */\nextern dec maxLength(target: string | ModelProperty, value: valueof integer);\n\n/**\n * Specify the minimum number of items this array should have.\n * @param value Minimum number\n *\n * @example\n * ```typespec\n * @minItems(1)\n * model Endpoints is string[];\n * ```\n */\nextern dec minItems(target: unknown[] | ModelProperty, value: valueof integer);\n\n/**\n * Specify the maximum number of items this array should have.\n * @param value Maximum number\n *\n * @example\n * ```typespec\n * @maxItems(5)\n * model Endpoints is string[];\n * ```\n */\nextern dec maxItems(target: unknown[] | ModelProperty, value: valueof integer);\n\n/**\n * Specify the minimum value this numeric type should be.\n * @param value Minimum value\n *\n * @example\n * ```typespec\n * @minValue(18)\n * scalar Age is int32;\n * ```\n */\nextern dec minValue(target: numeric | ModelProperty, value: valueof numeric);\n\n/**\n * Specify the maximum value this numeric type should be.\n * @param value Maximum value\n *\n * @example\n * ```typespec\n * @maxValue(200)\n * scalar Age is int32;\n * ```\n */\nextern dec maxValue(target: numeric | ModelProperty, value: valueof numeric);\n\n/**\n * Specify the minimum value this numeric type should be, exclusive of the given\n * value.\n * @param value Minimum value\n *\n * @example\n * ```typespec\n * @minValueExclusive(0)\n * scalar distance is float64;\n * ```\n */\nextern dec minValueExclusive(target: numeric | ModelProperty, value: valueof numeric);\n\n/**\n * Specify the maximum value this numeric type should be, exclusive of the given\n * value.\n * @param value Maximum value\n *\n * @example\n * ```typespec\n * @maxValueExclusive(50)\n * scalar distance is float64;\n * ```\n */\nextern dec maxValueExclusive(target: numeric | ModelProperty, value: valueof numeric);\n\n/**\n * Mark this string as a secret value that should be treated carefully to avoid exposure\n *\n * @example\n * ```typespec\n * @secret\n * scalar Password is string;\n * ```\n */\nextern dec secret(target: string | ModelProperty);\n\n/**\n * Mark this operation as a `list` operation for resource types.\n * @deprecated Use the `listsResource` decorator in `@typespec/rest` instead.\n * @param listedType Optional type of the items in the list.\n */\nextern dec list(target: Operation, listedType?: Model);\n\n/**\n * Attaches a tag to an operation, interface, or namespace. Multiple `@tag` decorators can be specified to attach multiple tags to a TypeSpec element.\n * @param tag Tag value\n */\nextern dec tag(target: Namespace | Interface | Operation, tag: valueof string);\n\n/**\n * Specifies how a templated type should name their instances.\n * @param name name the template instance should take\n * @param formatArgs Model with key value used to interpolate the name\n *\n * @example\n * ```typespec\n * @friendlyName(\"{name}List\", T)\n * model List<Item> {\n *   value: Item[];\n *   nextLink: string;\n * }\n * ```\n */\nextern dec friendlyName(target: unknown, name: valueof string, formatArgs?: unknown);\n\n/**\n * Provide a set of known values to a string type.\n * @param values Known values enum.\n *\n * @example\n * ```typespec\n * @knownValues(KnownErrorCode)\n * scalar ErrorCode extends string;\n *\n * enum KnownErrorCode {\n *   NotFound,\n *   Invalid,\n * }\n * ```\n */\n#deprecated \"This decorator has been deprecated. Use a named union of string literals with a string variant to achieve the same result without a decorator.\"\nextern dec knownValues(target: string | numeric | ModelProperty, values: Enum);\n\n/**\n * Mark a model property as the key to identify instances of that type\n * @param altName Name of the property. If not specified, the decorated property name is used.\n *\n * @example\n * ```typespec\n * model Pet {\n *   @key id: string;\n * }\n * ```\n */\nextern dec key(target: ModelProperty, altName?: valueof string);\n\n/**\n * Specify this operation is an overload of the given operation.\n * @param overloadbase Base operation that should be a union of all overloads\n *\n * @example\n * ```typespec\n * op upload(data: string | bytes, @header contentType: \"text/plain\" | \"application/octet-stream\"): void;\n * @overload(upload)\n * op uploadString(data: string, @header contentType: \"text/plain\" ): void;\n * @overload(upload)\n * op uploadBytes(data: bytes, @header contentType: \"application/octet-stream\"): void;\n * ```\n */\nextern dec overload(target: Operation, overloadbase: Operation);\n\n/**\n * DEPRECATED: Use `@encodedName` instead.\n *\n * Provide an alternative name for this type.\n * @param targetName Projection target\n * @param projectedName Alternative name\n *\n * @example\n * ```typespec\n * model Certificate {\n *   @projectedName(\"json\", \"exp\")\n *   expireAt: int32;\n * }\n * ```\n */\n#deprecated \"Use `@encodedName` instead for changing the name over the wire.\"\nextern dec projectedName(\n  target: unknown,\n  targetName: valueof string,\n  projectedName: valueof string\n);\n\n/**\n * Provide an alternative name for this type when serialized to the given mime type.\n * @param mimeType Mime type this should apply to. The mime type should be a known mime type as described here https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types without any suffix (e.g. `+json`)\n * @param name Alternative name\n *\n * @example\n *\n * ```typespec\n * model Certificate {\n *   @encodedName(\"application/json\", \"exp\")\n *   @encodedName(\"application/xml\", \"expiry\")\n *   expireAt: int32;\n * }\n * ```\n *\n * @example Invalid values\n *\n * ```typespec\n * @encodedName(\"application/merge-patch+json\", \"exp\")\n *              ^ error cannot use subtype\n * ```\n */\nextern dec encodedName(target: unknown, mimeType: valueof string, name: valueof string);\n\n/**\n * Specify the property to be used to discriminate this type.\n * @param propertyName The property name to use for discrimination\n *\n * @example\n *\n * ```typespec\n * @discriminator(\"kind\")\n * union Pet{ cat: Cat, dog: Dog }\n *\n * model Cat {kind: \"cat\", meow: boolean}\n * model Dog {kind: \"dog\", bark: boolean}\n * ```\n *\n * ```typespec\n * @discriminator(\"kind\")\n * model Pet{ kind: string }\n *\n * model Cat extends Pet {kind: \"cat\", meow: boolean}\n * model Dog extends Pet  {kind: \"dog\", bark: boolean}\n * ```\n */\nextern dec discriminator(target: Model | Union, propertyName: valueof string);\n\n/**\n * Known encoding to use on utcDateTime or offsetDateTime\n */\nenum DateTimeKnownEncoding {\n  /**\n   * RFC 3339 standard. https://www.ietf.org/rfc/rfc3339.txt\n   * Encode to string.\n   */\n  rfc3339: \"rfc3339\",\n\n  /**\n   * RFC 7231 standard. https://www.ietf.org/rfc/rfc7231.txt\n   * Encode to string.\n   */\n  rfc7231: \"rfc7231\",\n\n  /**\n   * Encode a datetime to a unix timestamp.\n   * Unix timestamps are represented as an integer number of seconds since the Unix epoch and usually encoded as an int32.\n   */\n  unixTimestamp: \"unixTimestamp\",\n}\n\n/**\n * Known encoding to use on duration\n */\nenum DurationKnownEncoding {\n  /**\n   * ISO8601 duration\n   */\n  ISO8601: \"ISO8601\",\n\n  /**\n   * Encode to integer or float\n   */\n  seconds: \"seconds\",\n}\n\n/**\n * Known encoding to use on bytes\n */\nenum BytesKnownEncoding {\n  /**\n   * Encode to Base64\n   */\n  base64: \"base64\",\n\n  /**\n   * Encode to Base64 Url\n   */\n  base64url: \"base64url\",\n}\n\n/**\n * Specify how to encode the target type.\n * @param encoding Known name of an encoding.\n * @param encodedAs What target type is this being encoded as. Default to string.\n *\n * @example offsetDateTime encoded with rfc7231\n *\n * ```tsp\n * @encode(\"rfc7231\")\n * scalar myDateTime extends offsetDateTime;\n * ```\n *\n * @example utcDateTime encoded with unixTimestamp\n *\n * ```tsp\n * @encode(\"unixTimestamp\", int32)\n * scalar myDateTime extends unixTimestamp;\n * ```\n */\nextern dec encode(\n  target: Scalar | ModelProperty,\n  encoding: string | EnumMember,\n  encodedAs?: Scalar\n);\n\n/** Options for example decorators */\nmodel ExampleOptions {\n  /** The title of the example */\n  title?: string;\n\n  /** Description of the example */\n  description?: string;\n}\n\n/**\n * Provide an example value for a data type.\n *\n * @param example Example value.\n * @param options Optional metadata for the example.\n *\n * @example\n *\n * ```tsp\n * @example(#{name: \"Fluffy\", age: 2})\n * model Pet {\n *  name: string;\n *  age: int32;\n * }\n * ```\n */\nextern dec example(\n  target: Model | Enum | Scalar | Union | ModelProperty | UnionVariant,\n  example: valueof unknown,\n  options?: valueof ExampleOptions\n);\n\n/**\n * Operation example configuration.\n */\nmodel OperationExample {\n  /** Example request body. */\n  parameters?: unknown;\n\n  /** Example response body. */\n  returnType?: unknown;\n}\n\n/**\n * Provide example values for an operation's parameters and corresponding return type.\n *\n * @param example Example value.\n * @param options Optional metadata for the example.\n *\n * @example\n *\n * ```tsp\n * @example(#{parameters: #{name: \"Fluffy\", age: 2}, returnType: #{name: \"Fluffy\", age: 2, id: \"abc\"})\n * op createPet(pet: Pet): Pet;\n * ```\n */\nextern dec opExample(\n  target: Operation,\n  example: valueof OperationExample,\n  options?: valueof ExampleOptions\n);\n/**\n * Indicates that a property is only considered to be present or applicable (\"visible\") with\n * the in the given named contexts (\"visibilities\"). When a property has no visibilities applied\n * to it, it is implicitly visible always.\n *\n * As far as the TypeSpec core library is concerned, visibilities are open-ended and can be arbitrary\n * strings, but  the following visibilities are well-known to standard libraries and should be used\n * with standard emitters that interpret them as follows:\n *\n * - \"read\": output of any operation.\n * - \"create\": input to operations that create an entity..\n * - \"query\": input to operations that read data.\n * - \"update\": input to operations that update data.\n * - \"delete\": input to operations that delete data.\n *\n * See also: [Automatic visibility](https://typespec.io/docs/libraries/http/operations#automatic-visibility)\n *\n * @param visibilities List of visibilities which apply to this property.\n *\n * @example\n *\n * ```typespec\n * model Dog {\n *   // the service will generate an ID, so you don't need to send it.\n *   @visibility(\"read\") id: int32;\n *   // the service will store this secret name, but won't ever return it\n *   @visibility(\"create\", \"update\") secretName: string;\n *   // the regular name is always present\n *   name: string;\n * }\n * ```\n */\nextern dec visibility(target: ModelProperty, ...visibilities: valueof string[]);\n\n/**\n * Removes properties that are not considered to be present or applicable\n * (\"visible\") in the given named contexts (\"visibilities\"). Can be used\n * together with spread to effectively spread only visible properties into\n * a new model.\n *\n * See also: [Automatic visibility](https://typespec.io/docs/libraries/http/operations#automatic-visibility)\n *\n * When using an emitter that applies visibility automatically, it is generally\n * not necessary to use this decorator.\n *\n * @param visibilities List of visibilities which apply to this property.\n *\n * @example\n * ```typespec\n * model Dog {\n *   @visibility(\"read\") id: int32;\n *   @visibility(\"create\", \"update\") secretName: string;\n *   name: string;\n * }\n *\n * // The spread operator will copy all the properties of Dog into DogRead,\n * // and @withVisibility will then remove those that are not visible with\n * // create or update visibility.\n * //\n * // In this case, the id property is removed, and the name and secretName\n * // properties are kept.\n * @withVisibility(\"create\", \"update\")\n * model DogCreateOrUpdate {\n *   ...Dog;\n * }\n *\n * // In this case the id and name properties are kept and the secretName property\n * // is removed.\n * @withVisibility(\"read\")\n * model DogRead {\n *   ...Dog;\n * }\n * ```\n */\nextern dec withVisibility(target: Model, ...visibilities: valueof string[]);\n\n/**\n * Set the visibility of key properties in a model if not already set.\n *\n * @param visibility The desired default visibility value. If a key property already has a `visibility` decorator then the default visibility is not applied.\n */\nextern dec withDefaultKeyVisibility(target: Model, visibility: valueof string);\n\n/**\n * Returns the model with non-updateable properties removed.\n */\nextern dec withUpdateableProperties(target: Model);\n\n/**\n * Returns the model with required properties removed.\n */\nextern dec withOptionalProperties(target: Model);\n\n/**\n * Returns the model with any default values removed.\n */\nextern dec withoutDefaultValues(target: Model);\n\n/**\n * Returns the model with the given properties omitted.\n * @param omit List of properties to omit\n */\nextern dec withoutOmittedProperties(target: Model, omit: string | Union);\n\n/**\n * Returns the model with only the given properties included.\n * @param pick List of properties to include\n */\nextern dec withPickedProperties(target: Model, pick: string | Union);\n\n//---------------------------------------------------------------------------\n// Debugging\n//---------------------------------------------------------------------------\n\n/**\n * A debugging decorator used to inspect a type.\n * @param text Custom text to log\n */\nextern dec inspectType(target: unknown, text: valueof string);\n\n/**\n * A debugging decorator used to inspect a type name.\n * @param text Custom text to log\n */\nextern dec inspectTypeName(target: unknown, text: valueof string);\n\n/**\n * Sets which visibilities apply to parameters for the given operation.\n * @param visibilities List of visibility strings which apply to this operation.\n */\nextern dec parameterVisibility(target: Operation, ...visibilities: valueof string[]);\n\n/**\n * Sets which visibilities apply to the return type for the given operation.\n * @param visibilities List of visibility strings which apply to this operation.\n */\nextern dec returnTypeVisibility(target: Operation, ...visibilities: valueof string[]);\n",
  "../../core/packages/compiler/lib/std/reflection.tsp": "namespace TypeSpec.Reflection;\n\nmodel Enum {}\nmodel EnumMember {}\nmodel Interface {}\nmodel Model {}\nmodel ModelProperty {}\nmodel Namespace {}\nmodel Operation {}\nmodel Scalar {}\nmodel Union {}\nmodel UnionVariant {}\nmodel StringTemplate {}\n",
  "../../core/packages/compiler/lib/std/projected-names.tsp": "// Set of projections consuming the @projectedName decorator\n#suppress \"projections-are-experimental\"\nprojection op#target {\n  to(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(getProjectedName(self, targetName));\n    };\n  }\n  from(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(self::projectionBase::name);\n    };\n  }\n}\n\n#suppress \"projections-are-experimental\"\nprojection interface#target {\n  to(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(getProjectedName(self, targetName));\n    };\n  }\n  from(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(self::projectionBase::name);\n    };\n  }\n}\n\n#suppress \"projections-are-experimental\"\nprojection model#target {\n  to(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(getProjectedName(self, targetName));\n    };\n\n    self::properties::forEach((p) => {\n      if hasProjectedName(p, targetName) {\n        self::renameProperty(p::name, getProjectedName(p, targetName));\n      };\n    });\n  }\n  from(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(self::projectionBase::name);\n    };\n\n    self::projectionBase::properties::forEach((p) => {\n      if hasProjectedName(p, targetName) {\n        self::renameProperty(getProjectedName(p, targetName), p::name);\n      };\n    });\n  }\n}\n\n#suppress \"projections-are-experimental\"\nprojection enum#target {\n  to(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(getProjectedName(self, targetName));\n    };\n\n    self::members::forEach((p) => {\n      if hasProjectedName(p, targetName) {\n        self::renameMember(p::name, getProjectedName(p, targetName));\n      };\n    });\n  }\n  from(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(self::projectionBase::name);\n    };\n\n    self::projectionBase::members::forEach((p) => {\n      if hasProjectedName(p, targetName) {\n        self::renameMember(getProjectedName(p, targetName), p::name);\n      };\n    });\n  }\n}\n\n#suppress \"projections-are-experimental\"\nprojection union#target {\n  to(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(getProjectedName(self, targetName));\n    };\n  }\n  from(targetName) {\n    if hasProjectedName(self, targetName) {\n      self::rename(self::projectionBase::name);\n    };\n  }\n}\n",
  "lib/main.tsp": "import \"./decorators.tsp\";\nimport \"./augmentCore.tsp\";\nimport \"../dist/src/index.js\";\n",
  "lib/decorators.tsp": "using TypeSpec.Reflection;\n\nnamespace Azure.ClientGenerator.Core;\n\n/**\n * Changes the name of a method, parameter, property, or model generated in the client SDK\n * @param rename The rename you want applied to the object\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @clientName(\"nameInClient\")\n * op nameInService: void;\n * ```\n *\n * @example\n * ```typespec\n * @clientName(\"nameForJava\", \"java\")\n * @clientName(\"name_for_python\", \"python\")\n * @clientName(\"nameForCsharp\", \"csharp\")\n * @clientName(\"nameForJavascript\", \"javascript\")\n * op nameInService: void;\n * ```\n */\nextern dec clientName(target: unknown, rename: valueof string, scope?: valueof string);\n\n/**\n * Whether you want to generate an operation as a convenient operation.\n * @param value Whether to generate the operation as convenience method or not.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @convenientAPI(false)\n * op test: void;\n * ```\n */\nextern dec convenientAPI(target: Operation, value?: valueof boolean, scope?: valueof string);\n\n/**\n * Whether you want to generate an operation as a protocol operation.\n * @param value Whether to generate the operation as protocol or not.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @protocolAPI(false)\n * op test: void;\n * ```\n */\nextern dec protocolAPI(target: Operation, value?: valueof boolean, scope?: valueof string);\n\n/**\n * Create a ClientGenerator.Core client out of a namespace or interface\n * @param value Optional configuration for the service.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example Basic client setting\n * ```typespec\n * @client\n * namespace MyService {}\n * ```\n *\n * @example Setting with other service\n * ```typespec\n * namespace MyService {}\n *\n * @client({service: MyService})\n * interface MyInterface {}\n * ```\n *\n * @example Changing client name if you don't want <Interface/Namespace>Client\n * ```typespec\n * @client({client: MySpecialClient})\n * interface MyInterface {}\n * ```\n *\n * @example\n */\nextern dec client(target: Namespace | Interface, value?: {}, scope?: valueof string);\n\n/**\n * Create a ClientGenerator.Core operation group out of a namespace or interface\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @operationGroup\n * interface MyInterface{}\n * ```\n */\nextern dec operationGroup(target: Namespace | Interface, scope?: valueof string);\n\n/**\n * DEPRECATED: Use `@usage` and `@access` decorator instead.\n *\n * Whether to exclude a model from generation for specific languages. By default we generate\n * all models that are included in operations.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @exclude(\"python\")\n * model ModelToExclude {\n *   prop: string;\n * }\n * ```\n */\n#deprecated \"@exclude decorator is deprecated. Use `@usage` and `@access` decorator instead.\"\nextern dec exclude(target: Model, scope?: valueof string);\n\n/**\n * DEPRECATED: Use `@usage` and `@access` decorator instead.\n *\n * Whether to include a model in generation for specific languages. By default we generate\n * all models that are included in operations.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @include(\"python\")\n * model ModelToInclude {\n *   prop: string;\n * }\n * ```\n */\n#deprecated \"@include decorator is deprecated. Use `@usage` and `@access` decorator instead.\"\nextern dec include(target: Model, scope?: valueof string);\n\nalias ClientFormat = \"unixtime\" | \"iso8601\" | \"rfc1123\" | \"seconds\";\n\n/**\n * DEPRECATED: Use `@encode` decorator in `@typespec/compiler` instead.\n *\n * Can be used to explain the client type that the current TYPESPEC\n * type should map to.\n * @param value The client format to apply.\n * @example\n * ```typespec\n * model MyModel {\n *   @clientFormat(\"unixtime\")\n *   created_at?: int64\n * }\n * ```\n */\n#deprecated \"@clientFormat decorator is deprecated. Use `@encode` decorator in `@typespec/compiler` instead.\"\nextern dec clientFormat(target: ModelProperty, value: valueof ClientFormat);\n\n/**\n * DEPRECATED: Use `@access` decorator instead.\n *\n * Whether to mark an operation as internal for specific languages,\n * meaning it should not be exposed to end SDK users\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * @internal(\"python\")\n * op test: void;\n * ```\n */\n#deprecated \"@internal decorator is deprecated. Use `@access` decorator instead.\"\nextern dec internal(target: Operation, scope?: valueof string);\n\n/**\n * Usage value.\n */\nenum Usage {\n  /**\n   * Used in request\n   */\n  input: 2,\n\n  /**\n   * Used in response\n   */\n  output: 4,\n}\n\n/**\n * Expand usage for models/enums.\n * A model/enum's default usage info is always calculated by the operations that use it.\n * You could use this decorator to expand the default usage info.\n * For example, with operation definition `op test(): OutputModel`,\n * the model `OutputModel` has default usage `Usage.output`.\n * After adding decorator `@@usage(OutputModel, Usage.input)`,\n * the final usage result for `OutputModel` is `Usage.input | Usage.output`.\n * The calculation of default usage info for models will be propagated to models' properties,\n * parent models, discriminated sub models.\n * But the expanded usage from `@usage` decorator will not be propagated.\n * If you want to do any customization for the usage of a model,\n * you need to take care of all related models/enums.\n * @param value The usage info you want to set for this model.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example Expand usage for model\n * ```typespec\n * op test(): OutputModel;\n *\n * // usage result for `OutputModel` is `Usage.input | Usage.output`\n * @usage(Usage.input)\n * model OutputModel {\n *   prop: string\n * }\n * ```\n *\n * @example Propagation of usage\n * ```typespec\n * // Usage.output\n * @discriminator(\"kind\")\n * model Fish {\n *   age: int32;\n * }\n *\n * // Usage.input | Usage.output\n * @discriminator(\"sharktype\")\n * @usage(Usage.input)\n * model Shark extends Fish {\n *   kind: \"shark\";\n *   origin: Origin;\n * }\n *\n * // Usage.output\n * model Salmon extends Fish {\n *   kind: \"salmon\";\n * }\n *\n * // Usage.output\n * model SawShark extends Shark {\n *   sharktype: \"saw\";\n * }\n *\n * // Usage.output\n * model Origin {\n *   country: string;\n *   city: string;\n *   manufacture: string;\n * }\n *\n * @get\n * op getModel(): Fish;\n * ```\n */\nextern dec usage(target: Model | Enum | Union, value: EnumMember | Union, scope?: valueof string);\n\n/**\n * Access value.\n */\nenum Access {\n  /**\n   * Open to user\n   */\n  public: \"public\",\n\n  /**\n   * Hide from user\n   */\n  internal: \"internal\",\n}\n\n/**\n * Set explicit access for operations, models and enums.\n * When setting access for models,\n * the access info wll not be propagated to models' properties, base models or sub models.\n * When setting access for an operation,\n * it will influence the access info for models/enums that are used by this operation.\n * Models/enums that are used in any operations with `@access(Access.public)` will be implicitly set to access \"public\"\n * Models/enums that are only used in operations with `@access(Access.internal)` will be implicitly set to access \"internal\".\n * This influence will be propagated to models' properties, parent models, discriminated sub models.\n * But this influence will be override by `@usage` decorator on models/enums directly.\n * If an operation/model/enum has no `@access` decorator and is not influenced by any operation with `@access` decorator,\n * the access result is undefined.\n * @param value The access info you want to set for this model or operation.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example Set access\n * ```typespec\n * // Access.internal\n * @access(Access.internal)\n * model ModelToHide {\n *   prop: string;\n * }\n * // Access.internal\n * @access(Access.internal)\n * op test: void;\n * ```\n * @example Access propagation\n * ```typespec\n * // Access.internal\n * @discriminator(\"kind\")\n * model Fish {\n *   age: int32;\n * }\n *\n * // Access.internal\n * @discriminator(\"sharktype\")\n * model Shark extends Fish {\n *   kind: \"shark\";\n *   origin: Origin;\n * }\n *\n * // Access.internal\n * model Salmon extends Fish {\n *   kind: \"salmon\";\n * }\n *\n * // Access.internal\n * model SawShark extends Shark {\n *   sharktype: \"saw\";\n * }\n *\n * // Access.internal\n * model Origin {\n *   country: string;\n *   city: string;\n *   manufacture: string;\n * }\n *\n * // Access.internal\n * @get\n * @access(Access.internal)\n * op getModel(): Fish;\n * ```\n * @example Access influence from operation\n * ```typespec\n * // Access.internal\n * model Test1 {\n * }\n *\n * // Access.internal\n * @access(Access.internal)\n * @route(\"/func1\")\n * op func1(\n *   @body body: Test1\n * ): void;\n *\n * // undefined\n * model Test2 {\n * }\n *\n * // undefined\n * @route(\"/func2\")\n * op func2(\n *   @body body: Test2\n * ): void;\n *\n * // Access.public\n * model Test3 {\n * }\n *\n * // Access.public\n * @access(Access.public)\n * @route(\"/func3\")\n * op func3(\n *   @body body: Test3\n * ): void;\n *\n * // undefined\n * model Test4 {\n * }\n *\n * // Access.internal\n * @access(Access.internal)\n * @route(\"/func4\")\n * op func4(\n *   @body body: Test4\n * ): void;\n *\n * // undefined\n * @route(\"/func5\")\n * op func5(\n *   @body body: Test4\n * ): void;\n *\n * // Access.public\n * model Test5 {\n * }\n *\n * // Access.internal\n * @access(Access.internal)\n * @route(\"/func6\")\n * op func6(\n *   @body body: Test5\n * ): void;\n *\n * // undefined\n * @route(\"/func7\")\n * op func7(\n *   @body body: Test5\n * ): void;\n *\n * // Access.public\n * @access(Access.public)\n * @route(\"/func8\")\n * op func8(\n *   @body body: Test5\n * ): void;\n * ```\n */\nextern dec access(\n  target: Model | Operation | Enum | Union,\n  value: EnumMember,\n  scope?: valueof string\n);\n\n/**\n * Set whether a model property should be flattened or not.\n * @param scope The language scope you want this decorator to apply to. If not specified, will apply to all language emitters\n *\n * @example\n * ```typespec\n * model Foo {\n *    @flattenProperty\n *    prop: Bar;\n * }\n * model Bar {\n * }\n * ```\n */\n#deprecated \"@flattenProperty decorator is not recommended to use.\"\nextern dec flattenProperty(target: ModelProperty, scope?: valueof string);\n",
  "lib/augmentCore.tsp": ""
};
const _TypeSpecLibrary_ = {
  jsSourceFiles: TypeSpecJSSources,
  typespecSourceFiles: TypeSpecSources,
};

export { $access, $client, $clientFormat, $clientName, $convenientAPI, $exclude, $flattenProperty, $include, $internal, $lib, $operationGroup, $protocolAPI, $usage, UsageFlags, _TypeSpecLibrary_, addEncodeInfo, addFormatInfo, createDiagnostic, createSdkContext, createStateSymbol, getAccess, getAccessOverride, getAllModels, getAllModelsWithDiagnostics, getClient, getClientFormat, getClientNameOverride, getClientNamespaceString, getClientType, getClientTypeWithDiagnostics, getCrossLanguageDefinitionId, getCrossLanguagePackageId, getDefaultApiVersion, getEffectivePayloadType, getEmitterTargetName, getGeneratedName, getHttpOperationWithCache, getKnownScalars, getLibraryName, getOperationGroup, getPropertyNames, getSdkArrayOrDict, getSdkArrayOrDictWithDiagnostics, getSdkBuiltInType, getSdkConstant, getSdkCredentialParameter, getSdkDurationType, getSdkEnum, getSdkEnumValue, getSdkModel, getSdkModelPropertyType, getSdkModelPropertyTypeBase, getSdkModelWithDiagnostics, getSdkTuple, getSdkTupleWithDiagnostics, getSdkUnion, getSdkUnionEnum, getSdkUnionWithDiagnostics, getUsage, getUsageOverride, getWireName, isApiVersion, isExclude, isInOperationGroup, isInclude, isInternal, isOperationGroup, isReadOnly, isSdkBuiltInKind, isSdkDateTimeEncodings, isSdkFloatKind, isSdkIntKind, listClients, listOperationGroups, listOperationsInOperationGroup, namespace, reportDiagnostic, shouldFlattenProperty, shouldGenerateConvenient, shouldGenerateProtocol };
