Skip to content

πŸš€ API Maker v2 to v3 repository migration prompt

⭐ Jun 2026 ⭐

Project Directory : /Volumes/Data/code/Git/sava_ecom_be Below is secret value and you can use that as auth provider name :

authTokenInfo_SAVA_ECom: <T.IAuthTokenInfo[]>[{
    "authTokenType": "AM_DB",
    "authTokenAMDB": {
        "instance": "mongodb",
        "database": "sava_ecom",
        "collection": "users",
        "usernameColumn": "username",
        "passwordColumn": "password",
        "expiresInSeconds": 259200
    }
}]

βœ… Migration checklist (summary)

Done # Step In one line
☐ M Manual β€” deploy to v3 first Deploy the repo to v3 and commit the regenerated src/assets/schema-types/types.ts.
☐ 0 Discover every occurrence Grep the whole repo for authTokenInfo, IAuthTokenInfo, EAuthTokenType.
☐ 1 authTokenInfo β†’ authProviders Rename the field, change the cast to <string[]>, drop unused imports.
☐ 2 Create the Auth Providers Extract every inline auth object into a named provider under Auth Providers, de-duplicated.
☐ 3 Get Token + headers + WebSocket Get Token now takes a provider name; each provider type has its own request header.
☐ 4 Short folder names β€” give a name 7 folder types are now named by their name property instead of ins -- db -- col -- api.
☐ 4a Know which items have a name Only those 7. Do not invent a name for third party / system / utility items.
☐ 4b Put name in the right place Schemas + Instance API settings β†’ inside the .config.ts code. Everything else β†’ the .yaml.
☐ 4c Rename folder + .yaml + .config.ts together A mismatch makes git pull silently skip the item.
☐ 4d Set authProvider on every WebSocket event v3-only field; leaving it empty falls back to the first provider alphabetically.
☐ 5 Verify Providers resolve, no authTokenInfo left, no -- left in the 7 renamed folders.

  • API Maker is a framework and it has it's own standard way of organizing backend code.
  • In project directory which uses API Maker v2 and we want to migrate that repository to API Maker V3.
  • Do NOT change any business logic or code other than what is described below.
  • Once you assign a name to a newly-created auth provider, use that exact same name everywhere it is referenced (in every authProviders array) so the references stay consistent.
  • You need to make below changes.

πŸ”§ Manual task (do this first, yourself)

This step is manual β€” do it yourself before handing the rest of this prompt to an AI agent.

  • Deploy the repository to API Maker v3 first. The types.ts in a v2 repo is the old v2 file β€” it does not yet contain the v3 auth-provider interfaces or the authProviders field.
  • After deploying to v3, commit only the regenerated src/assets/schema-types/types.ts (the type interfaces referenced below live in that file).
  • Do this before any of the migration steps below, otherwise the new code will not reference the right symbols or typecheck.

πŸ€– Automated migration steps (for the AI agent)

0. Discover every occurrence first

  • Before editing anything, grep the entire repository for all v2 auth-field forms and enumerate every occurrence: authTokenInfo, IAuthTokenInfo, EAuthTokenType.
  • The settings categories in step 1 are a guide, not an exhaustive file list β€” migrate every occurrence you find.
  • Note that third party API settings exist at TWO levels β€” version-level (T.ITPApiSettingsTypes) and per-API level (T.ITPApiSettingsTypesAPILevel) β€” and both carry the auth field, so both must be migrated.
  • The type interfaces referenced below live in src/assets/schema-types/types.ts.

1. authTokenInfo β†’ authProviders

  • authTokenInfo is now authProviders and it takes an array of strings (the names of the auth providers to use).
  • Make this change in instance, database, collection, API settings files, system API settings, third party API settings (both version-level and per-API level), custom API settings, and in secrets (the default secret also holds authProviders).
  • In v2 the auth config was written inline as an array of objects (there was no auth master). In v3 those objects move out into named auth providers (step 2) and the settings file only keeps the list of names.
  • In v2 the field looked like this (array of objects):
    authTokenInfo: <T.IAuthTokenInfo[]>[
        {
            authTokenType: T.EAuthTokenType.AM_DB,
            authTokenAMDB: { instance: "...", database: "...", collection: "...", usernameColumn: "...", passwordColumn: "..." }
        }
    ]
    
  • In v3 it becomes just the list of provider names. Change the cast from <T.IAuthTokenInfo[]> to <string[]>, and remove any now-unused imports of T.IAuthTokenInfo / T.EAuthTokenType so the code still compiles:
    authProviders: <string[]>["my_db_login", "my_google_login"]
    
  • An empty array (authProviders: <string[]>[]) keeps its v2 meaning: it overrides the default secret so only API Maker's API user token is accepted in x-am-authorization. Create no providers for an empty array.
  • If authTokenInfo is omitted, omit authProviders too (make zero edits to that file) β€” it will inherit from the default secret.
  • Leave apiAccessType exactly where it is. In v2 apiAccessType (NO_ACCESS | IS_PUBLIC | TOKEN_ACCESS) is a sibling api-level field next to authTokenInfo, not part of any token object β€” it is unrelated to the authProviders rename and must not be touched.

Idempotency / guardrails: If a settings file already uses authProviders (the v2 authTokenInfo key is not present), leave it untouched and create no duplicate providers. If a file contains neither key, make no edits to it. Always preserve existing formatting, comments, key order, and all unrelated fields. Re-running this prompt must be a no-op.

2. Create the Auth Providers from each object

  • In v2 there was no auth master β€” the auth config was defined inline as the array of objects inside each settings file, and those objects had no name.
  • In v3 auth is a master: every object must be extracted into one separate auth provider (a named master record) inside the new Auth Providers folder, and settings reference it by name.
  • De-duplicate across files: if the same inline auth object (same type and same data values) appears in more than one settings file, create only ONE shared provider and reference it by the same name from every file that used it. Two objects that differ in any value are distinct and each gets its own provider.
  • Since v2 objects have no name, assign each provider a unique, descriptive name derived from its purpose (e.g. customers_token, google_login). Use that exact name, referenced verbatim, in every authProviders array of step 1. If two distinct providers would end up with the same name, append a numeric suffix (_2, _3). Only @ and / are stripped from a provider name when it is written to disk, so avoid those two characters in names.
  • Map the v2 authTokenType and its data object to the v3 provider type as follows:
v2 authTokenType v2 data object v3 provider type property reference in types.ts
AM authTokenAM ({ u, p } or { refresh_token }) no provider β€” this is the API Maker user token; referenced by sending x-am-authorization. Do not create a provider for it. IAuthTokenAM / IRefreshTokenAM
AM_DB authTokenAMDB DB_TOKEN_GENERATOR IAuthTokenAMDB
GOOGLE authTokenGoogle GOOGLE IAuthTokenGoogle
AWS authTokenAWS AWS IAuthTokenAWS
AZURE authTokenAzureAD AZURE IAuthTokenAzureAD

v2 EAuthTokenType has exactly these five members: AM, AM_DB, GOOGLE, AWS, AZURE. There is no CUSTOM member and no authTokenCustom object in v2 β€” do not look for them. CUSTOM_TOKEN_GENERATOR is a v3-only provider type with no v2 source to migrate.

  • You can check the property details in the types.ts file for IAuthTokenAMDB, IAuthTokenGoogle, IAuthTokenAWS, IAuthTokenAzureAD.

  • Per-type fields to carry over (verify against src/assets/schema-types/types.ts and src/ajv/mongoose/MongooseAuthProviders_Vali.ts):

    • AM_DB β†’ DB_TOKEN_GENERATOR: carry instance, database, collection (MongoDB) or table (SQL), usernameColumn, passwordColumn, and also the two load-bearing columns passwordChangedAtColumn and groupsColumn. groupsColumn drives group/role access; passwordChangedAtColumn changes the JWT contents (when set, the password field is not stored in the JWT β€” this timestamp is stored instead so password changes can be detected).
    • AWS: cognitoUserPoolId, region, tokenUse ('access' | 'id'), tokenExpiration (in milliseconds).
    • AZURE: the field is appId (documented as the OAuth client_id), NOT clientId. Carry appId, tenant, audience, issuer, maxRetries.
    • GOOGLE: clientId.
  • Groups / roles config (AWS, Azure, Google only): these three providers each also carry the shared IAuthTokenGroupsProperties config β€” sourceFieldOfUniqueId (the token field holding the user's unique id) and groupsDataSource ({ instance, database, collection? / table?, targetFieldForUniqueId, groupsColumn, select? }). Carry these over for any AWS/Azure/Google object that defines them, or group/role access for federated tokens will be lost. (For AM_DB the equivalent is the inline groupsColumn field β€” there is no groupsDataSource.)
  • expiresInSeconds is v3-only. v2 has no per-token expiresInSeconds (the AM token lifetime was global, default 3600s). Do not try to migrate it from v2 β€” set it fresh in v3 if desired, respecting the v3 minimum of 600.

  • Inside the Auth Providers folder, each provider named <name> uses these files:

    • <name>.yaml β€” the config file that stores generatorType (DB_TOKEN_GENERATOR / CUSTOM_TOKEN_GENERATOR / AWS / GOOGLE / AZURE) and the materialized config fields. This is the source of truth for the provider type, and generatorType is required. AWS, Azure, Google and DB providers all present on disk as just <name>.ts (plus a possibly-empty <name>.fg.ts) and are indistinguishable by file presence β€” so you must write the correct generatorType into <name>.yaml; never try to reconstruct the type from which .ts/.tg.ts/.tv.ts/.fg.ts files exist.
    • <name>.ts β€” basic info / DB token generator code.
    • <name>.tg.ts β€” custom token generator code (only for CUSTOM_TOKEN_GENERATOR).
    • <name>.tv.ts β€” custom token validator code (only for CUSTOM_TOKEN_GENERATOR).
    • <name>.fg.ts β€” fields generator code. This is a NEW, optional v3 concept β€” v2 had no fields generator (which DB columns became token claims was implicit in the AM_DB column config). Generate it only if you want to inject specific fields into the token; there is no v2 source to copy from. (On write, .fg.ts is always emitted for DB_TOKEN_GENERATOR even when empty, and only when a fields-generator function is set for CUSTOM_TOKEN_GENERATOR.)

3. Get Token

  • The Get Token API and the call from code is now changed. It just needs the provider name and all other information will be picked up automatically from the auth providers master. Please check the example below.
  • The request body accepts: name? (optional), u, p, refresh_token? (optional β€” re-issues a token without u/p), and expiresInSeconds? (optional). Routing is by name:
    • When name is omitted, the request hits the API Maker user path, where the request body's expiresInSeconds is honored directly.
    • When a name is supplied, it resolves a DB/Custom auth provider and the token expiry comes from that provider's configured expiresInSeconds (the request-body value is ignored on that path).
      [
          {
              "name": "token_generator_name",
              "u": "[email protected]",
              "p": "student1"
          },
          {
              // When name is not provided, system will generate API Maker User's token
              "u": "default",
              "p": "12345",
              "expiresInSeconds": 259200
          }
      ]
      
  • Get Token only mints tokens for DB_TOKEN_GENERATOR and CUSTOM_TOKEN_GENERATOR providers. For AWS (Cognito), Google, and Azure providers, API Maker does NOT issue tokens β€” the client obtains its own provider-issued token from the external identity provider and sends it to API Maker, which only validates it. There is no Get Token login flow for AWS/Google/Azure.
  • Each provider type's token goes in its own request header β€” update client call sites accordingly:
Provider Request header
API Maker user/admin token (name-less Get Token result) x-am-authorization
DB_TOKEN_GENERATOR x-am-user-authorization
CUSTOM_TOKEN_GENERATOR x-custom-authorization
AWS x-aws-authorization
GOOGLE x-google-authorization
AZURE x-azure-authorization
  • WebSocket note: a v3 WebSocket connection does not need to name its auth provider at all. The client sends its token in the query-string key of that provider's type (the same keys as the header table above β€” x-am-user-authorization, x-aws-authorization, x-google-authorization, x-azure-authorization, x-custom-authorization) plus x-am-authorization, and API Maker works out which provider the token belongs to: a DB-user token carries its provider's name inside it, and AWS/Google/Azure/custom tokens are matched against the providers of their own type.
    • Preferred migration: drop the authTokenInfo parameter from WS connection URLs and keep only the token keys.
    • If you keep it, it still works and is now only a filter that narrows the connection to the named providers. Both authTokenInfo and authProviders are accepted as the key, so a rename is safe here too β€” but a provider you list without sending its token closes the connection, and a token whose provider you left out of the list is not validated.
    • The two internal literals authTokenInfo=ws-local-client-sync and authTokenInfo=ws-browser-client-sync are unrelated to provider names and must be left exactly as they are.

4. Short folder names β€” give a name to instance-keyed items

  • In v2 the folder name of these items encoded their identity, with -- as the level separator β€” e.g. Instance API settings/mongodb -- test -- default -- GEN_GET_ALL/. Those paths got very long and hit path-length limits on Windows.
  • In v3 the folder name is simply the item's name property. It no longer encodes instance / database / collection / api β€” those values live only inside the .yaml file, which is now the single source of truth for identity.

4.1 Which items have a name, and which do not

A. Newly named in v3 β€” folder is {name}, falling back to {guid}. These are the only seven folders affected by this step:

Folder v2 folder name v3 folder name name is stored in
Schemas {instance} -- {database} -- {collection} {name} or {guid} the code β€” <name>.config.ts
Instance API settings {instance} -- {database} -- {collection} -- {apiId} {name} or {guid} the code β€” <name>.config.ts
Instance hooks {instance} {name} or {guid} the .yaml
Database hooks {instance} -- {database} {name} or {guid} the .yaml
Collection hooks {instance} -- {database} -- {collection} {name} or {guid} the .yaml
Instance API hooks {instance} -- {database} -- {collection} -- {apiId} {name} or {guid} the .yaml
WebSocket events {Category} -- {identifier} {name} or {guid} the .yaml

⚠️ Instance API settings covers three levels of settings, not one. Database settings and collection settings are not stored in the Database hooks / Collection hooks folders β€” those two folders only hold pre-hooks and post-hooks. Database, collection and API settings are all rows of the same Instance API settings item type, told apart by their apiId / collectionName:

Settings level Lives in folder Marked by Settings code type
Database settings Instance API settings collectionName = apiId = __DATABASE_SETTINGS__ T.IInstanceApiSettingsTypes
Collection settings Instance API settings apiId = __COLLECTION_SETTINGS__ T.IInstanceApiSettingsTypes
API settings Instance API settings a real apiId, e.g. GEN_GET_ALL T.IInstanceApiSettingsTypesForAPI

So all three get their name inside the .config.ts code, not in the .yaml. Instance-level settings are the exception: they live in Instance hooks, have no settings code, and take name as a plain .yaml key.

B. NOT named β€” leave these completely alone. They have no name property at all; adding one to the settings code will not typecheck and renaming their folder will break the repository:

Folder v3 folder name (unchanged) Why there is no name
Third party API settings {bundleName} -- {apiVersion} -- {apiName} Neither T.ITPApiSettingsTypes nor T.ITPApiSettingsTypesAPILevel has a name property.
Third party APIs {apiBundleName} -- {storeApiVersion} Identity is the bundle + version. (The installed APIs inside it, under apis/, are foldered by their own long-standing name β€” that is not new and needs no change.)
System API settings {apiId} T.ISystemApiSettingsTypes has no name; the apiId is already short.
System API hooks {apiId} Same as above.
Utility classes {folderPath} -- {ClassName} It does have a name, but the folder is name plus folderPath, so -- here is correct and must stay. / inside folderPath is written as -.

C. Already named since v2 β€” nothing to do. These masters always required a name and were always foldered by it: Custom APIs, Auth Providers, Schedulers, Events, Instances, Groups, API users, Secrets, i18ns, Log profiles, Database migrations, Process initializers, Test cases, DB masters, DB master utils, UI maker styles. Do not rename or re-generate their names.

Do NOT touch Third party APIs, Third party API settings, System API settings, System API hooks or Utility classes. They still compose their folder names with -- (or with apiId) in v3 β€” that is not a leftover, it is correct.

4.2 Rules for a name value

  • name is optional for all seven folders in group A. An item with no name keeps working and uses its guid as the folder name. So doing nothing is a valid, non-breaking outcome β€” only rename an item when you are also giving it a name.
  • It must be unique per user across items of the same type. A partial unique index on { name, user } enforces it, so a duplicate is rejected on save. Items without a name are excluded from that index, which is why old unnamed items still coexist.
  • Allowed characters are letters, numbers, space, underscore and dash only β€” [a-zA-Z0-9 _-]. Any other character fails validation. Leading/trailing whitespace is trimmed on save, so do not rely on it.
    • WebSocket events are the one exception: they additionally allow /, for tree-style custom events (see 4.5).
  • Keep it short β€” shorter paths are the whole point of this change.
  • Default names generated by API Maker follow this recipe, and matching it keeps things predictable (any valid unique name works, though):
    • take the parts instance, database, collection, apiId β€” skipping the ones that do not apply to the item type;
    • keep the first 6 characters of each part, except collection, which keeps up to 22 characters (the collection name identifies the item the most);
    • strip any disallowed character, then join with _;
    • on a collision, append _2, then _3, and so on.
    • e.g. mongodb + test + default β†’ mongod_test_default; mongodb + test + default + GEN_GET_ALL β†’ mongod_test_default_GEN_GE.

4.3 Where the name value lives, per item type

This is the part that is easy to get wrong.

  • Schemas β€” name goes inside the code of <name>.config.ts, as a top-level let name: string = '...' that is exported alongside the schema. The export line must include it:
    import { ISchemaType, EType, ISchemaProperty, IPropertyValidation } from 'types';
    import * as T from 'types';
    
    let name: string = 'mongod_test_default'; // Folder name of this schema in git. It has to be unique.
    
    let schema: ISchemaType = {
        // ... unchanged
    };
    
    module.exports = { name, schema };
    
  • Instance API settings β€” for all three levels (database / collection / API settings), name goes inside the code of <name>.config.ts, as a property of the exported settings object. Both T.IInstanceApiSettingsTypes (database & collection level) and T.IInstanceApiSettingsTypesForAPI (API level) accept it:
    let instanceColSetting: T.IInstanceApiSettingsTypes = {
        name: 'mongod_test_default', // Folder name of this item in git. It has to be unique.
        enableCaching: false,
        // ... unchanged
    };
    module.exports = instanceColSetting;
    
  • All hooks (Instance hooks, Database hooks, Collection hooks, Instance API hooks) and WebSocket events β€” these have no settings code, so name is a plain key in the item's <name>.yaml file.
  • The .yaml also carries a name key for Schemas and Instance API settings. Keep the two in sync β€” write the same value in the .yaml and in the .config.ts. On save the value from the code wins, and it is only applied when the code actually sets it: deleting name from the code does not clear the stored name (that is deliberate, so old unnamed items keep their guid folder), it just leaves a stale name behind. Never let the two disagree.
  • Do not change the __DATABASE_SETTINGS__ / __COLLECTION_SETTINGS__ values. They remain exactly as-is in collectionName / apiId inside the .yaml. Only the folder gets shorter, via name.

4.4 Renaming a folder: three names must change together

Git pull reads the .yaml and .config.ts by the folder name, so a mismatch silently fails to load the item:

  • the folder: <name>/
  • the config file inside it: <name>.yaml
  • the code file inside it (Schemas and Instance API settings only): <name>.config.ts
  • …and the name value written inside that .yaml / .config.ts must equal the folder name too.

Hook code files (pre-hooks/*.ts, post-hooks/*.ts) are named after the hook, not the item β€” do not rename them.

4.5 WebSocket events β€” extra rules

  • Every WS event should have a name. In v2 only custom WS events had one; instance / custom-API / system / third-party events had none. In v3 name is the git folder name for every category and must be unique across all categories together (not just within one category).
    • If you leave it empty, the save does not fail β€” the event's guid is written into name automatically, and the folder becomes that guid. That works, but you get a long unreadable folder, so set a real name.
  • For tree-style custom events the name is a path like level1/level2/name β€” / is allowed only for these, and it is stripped when the folder is written. Leading and trailing / are removed on save.
  • For custom (tree) WS events there is an additional constraint: one event's name may not contain another event's name as a substring β€” it would break tree generation. So orders and orders/new cannot both exist.
  • Set the new authProvider key. This is a v3-only field with no v2 source: it names the one auth provider whose token a client must hold to subscribe to that event, and a client connecting with any other provider's token is refused at REGISTER time. Like name, it is a plain key in the event's <name>.yaml β€” e.g. authProvider: customers_token.
    • Use one of the exact provider names created in step 2. An event whose authProvider names a provider that does not exist (or is inactive) is refused at REGISTER time, so a typo here silently breaks subscriptions.
    • Leaving it empty is the risky outcome, not the safe one. An event with no authProvider falls back to the account's first auth provider by name ascending β€” fine while a repo has exactly one provider, wrong as soon as it has two. Set it explicitly on every WS event whose subscribers log in through a specific provider.
    • Pick the provider the event's clients actually authenticate with. If the v2 client connected with authTokenInfo=<something> in its WebSocket URL, the provider you created from that entry in step 2 is the one to use here.

Idempotency / guardrails: If an item's folder name contains no -- it is already migrated (or is a guid) β€” leave it alone. If you rename a folder, rename its inner .yaml/.config.ts in the same step and never leave a half-renamed item. Do not invent a name for Third party APIs, Third party API settings, System API settings, System API hooks or Utility classes. Changing nothing is always safe: those items keep using their guid.

5. After migration β€” verify

  • Make sure every name listed in any authProviders array has a matching auth provider in the Auth Providers folder.
  • Confirm the number of distinct auth providers you created equals the number of distinct auth objects in the original v2 authTokenInfo arrays.
  • Make sure no authTokenInfo field (or IAuthTokenInfo / EAuthTokenType references / imports) remains anywhere in the migrated repository β€” except any WebSocket connection URL you deliberately kept it in as a filter, and the two ws-local-client-sync / ws-browser-client-sync literals, both noted in step 3.
  • Confirm every WebSocket connection URL still carries the token keys themselves (x-am-authorization plus the provider-type key) β€” dropping authTokenInfo is only safe because the token is what identifies the provider.
  • Confirm every WebSocket events item has an authProvider naming one of the providers created in step 2, and that no event was left to the first-provider fallback by accident.
  • For every folder you renamed in step 4, confirm the folder, its .yaml and its .config.ts (where present) all share the exact same name, and that the name inside the code/yaml matches that folder name too.
  • For Schemas and Instance API settings, confirm the name in the .config.ts code and the name in the .yaml are identical β€” the code value wins on save, so a disagreement is a silent rename.
  • Confirm every name you assigned is unique per item type, that it matches [a-zA-Z0-9 _-] (plus / for WebSocket events only), and that every WebSocket events item has one.
  • Confirm no folder under Schemas, Collection hooks, Database hooks, Instance hooks, Instance API hooks, Instance API settings or WebSocket events still contains --, and that folders under Third party APIs, Third party API settings and Utility classes still do.
  • Confirm you did not add a name property to any T.ITPApiSettingsTypes, T.ITPApiSettingsTypesAPILevel or T.ISystemApiSettingsTypes settings object β€” those interfaces have no name and it will not typecheck.
  • Confirm the Instance API settings items whose apiId is __DATABASE_SETTINGS__ or __COLLECTION_SETTINGS__ were renamed too β€” they are easy to miss because they are "database/collection settings" but live in the Instance API settings folder.
  • If the target repo is a buildable TypeScript project, run its build/lint and confirm it compiles after the cast and import changes.