/** * Mock of the makedata service for the browser-hosted and CI estates. * * Answers the same three actions as the SAS service (action is required): * * DIRLIST the folders below PARENT, for the deploy screen's picker * WRITECHECK is PATH a folder this deployment can write to * MAKEDATA seed the control library, then remove this program * * DIRLIST and WRITECHECK are what the deploy screen asks before the control * library exists. They must not seed anything: a browse that fell through to * the seeding path would build the site, delete this program and close the * deploy screen the visitor is standing on. */ const nodePath = require('path') // Fixed libref for the mock environment const dcLibref = 'DC_JSLIB' // Read URL params (provided as module-scope consts by the JS runtime) let adminGroup = 'AllUsers' if (typeof admin !== 'undefined') adminGroup = admin // Derive the SASjs Drive root from weboutPath // weboutPath is /sessions//webout.txt // Drive is at /drive const sasjsRoot = nodePath.resolve(weboutPath, '..', '..', '..') const driveRoot = nodePath.resolve(sasjsRoot, 'drive') const appLoc = nodePath.join(..._program.split('services')[0].split('/')) // DC data lives under /files//data// - one JSON file per table // This is browsable in SASjs Studio and persists across service redeployes const dataDir = nodePath.resolve(driveRoot, 'files', appLoc, 'data', dcLibref) // ─── Actions ──────────────────────────────────────────────────────────────── /* ACTION arrives the way the SAS service reads it - as a column of the fromjs input table, or as a macro variable (a URL parameter) on the platforms that deliver one. It is required: a default here is what lets a browse seed the site and delete the program the deploy screen is using. */ eval( fs.readFileSync( nodePath.resolve(driveRoot, 'files', appLoc, 'services', 'dcMockUtils.js'), 'utf8' ) ) const brPlatform = process.platform === 'win32' ? 'WIN' : 'UNIX' const brSep = brPlatform === 'WIN' ? '\\' : '/' /** Case-insensitive column read - the header carries the caller's casing. */ function brValue(row, name) { if (!row) return '' if (row[name] !== undefined) return row[name] const key = Object.keys(row).find(function (k) { return k.toUpperCase() === name }) return key ? row[key] : '' } /** * The input table, whatever the caller called it - %webout(FETCH) takes the * first table that arrived, and the deploy screen ("fromjs") and a CLI seed * ("SASControlTable") are the same request to the SAS service. */ function brFirstInputTable() { for (let i = 1; i <= 10; i++) { let name try { name = eval('_WEBIN_NAME' + i) } catch (err) { continue } if (name) return fetchRaw(name) } return '' } const brRows = parseCsv(brFirstInputTable()) let brAction = brValue(brRows[0], 'ACTION') if (!brAction && typeof action !== 'undefined') brAction = action const ACTION = String(brAction || '').trim().toUpperCase() try { if (!ACTION) { mpAbort('ACTION is required: MAKEDATA, DIRLIST or WRITECHECK', _program) } if (['MAKEDATA', 'DIRLIST', 'WRITECHECK'].indexOf(ACTION) < 0) { mpAbort('ACTION must be MAKEDATA, DIRLIST or WRITECHECK', _program) } /** The deploy window closes once the settings file exists (see browse_gate). */ function brBrowseGate() { const settings = [ nodePath.resolve(driveRoot, 'files', appLoc, 'services', 'settings.js'), nodePath.resolve( driveRoot, 'files', appLoc, 'services', 'public', 'settings.sas' ) ] for (const file of settings) { if (fs.existsSync(file)) { throw new Error( 'DIRLIST and WRITECHECK are only available until DC is configured' ) } } } /* The same refusals as mpe_dirlist / mpe_writecheck: the value comes from the request, so a macro trigger, a quote or a statement separator is refused before it is used, and what is left has to be an absolute path. */ function brCheckPath(value, message) { if (value.length > 1000) throw new Error(message) if (/[\u0000-\u001f]/.test(value)) throw new Error(message) if (/[%&"';,()]/.test(value)) throw new Error(message) const absolute = brPlatform === 'WIN' ? /^[A-Za-z]:[\\/]/.test(value) || /^\\\\/.test(value) : value.charAt(0) === '/' if (!absolute) throw new Error(message) } function brRoots() { if (brPlatform !== 'WIN') return ['/'] const roots = [] for (let i = 65; i <= 90; i++) { const drive = String.fromCharCode(i) + ':\\' if (fs.existsSync(drive)) roots.push(drive) } return roots } function brFolderRow(filepath, level, type, msg) { return { FILEPATH: filepath, FILENAME: nodePath.basename(filepath) || filepath, FILE_OR_FOLDER: type, LEVEL: level, MSG: msg || '' } } /* One level at a time, as the real picker is: a parent with tens of thousands of subfolders is not transferred in full, and MAXOBS caps the rows with the TRUNCATED flag the screen shows a note about. */ function brDirList(parent, depth, maxobs) { const rows = [] if (!parent) { for (const root of brRoots()) rows.push(brFolderRow(root, 0, 'folder', '')) } else { rows.push(brFolderRow(parent, 0, 'folder', '')) let frontier = [parent] for (let level = 1; level <= depth; level++) { const next = [] for (const folder of frontier) { let names try { names = fs.readdirSync(folder).slice().sort() } catch (err) { continue } for (const name of names) { const child = nodePath.join(folder, name) let isFolder = false try { isFolder = fs.statSync(child).isDirectory() } catch (err) { rows.push(brFolderRow(child, level, 'locked', err.message)) continue } if (!isFolder) continue rows.push(brFolderRow(child, level, 'folder', '')) next.push(child) } } frontier = next if (!frontier.length) break } } rows.sort(function (a, b) { return a.FILEPATH < b.FILEPATH ? -1 : a.FILEPATH > b.FILEPATH ? 1 : 0 }) const truncated = rows.length > maxobs return { rows: truncated ? rows.slice(0, maxobs) : rows, truncated: truncated } } /** Creates and removes a probe file - what the deployment itself will do. */ function brWriteCheck(path) { if (!path) throw new Error('Missing path') brCheckPath(path, 'Invalid path') let target = path while (target.length > 1 && /[\\/]$/.test(target)) { if (target.length === 3 && target.charAt(1) === ':') break target = target.slice(0, -1) } const row = { PATH: target, PATH_EXISTS: 'N', IS_FOLDER: 'N', WRITEABLE: 'N', MSG: '' } if (!fs.existsSync(target)) { row.MSG = 'Path does not exist' return row } row.PATH_EXISTS = 'Y' let isFolder = false try { isFolder = fs.statSync(target).isDirectory() } catch (err) { /* exists but cannot be opened: reported as not a folder, as the SAS does */ } if (!isFolder) { row.MSG = 'Path exists but is not a folder' return row } row.IS_FOLDER = 'Y' const probe = nodePath.join( target, '.dcprobe_' + (typeof process !== 'undefined' && process.pid ? process.pid : 0) + '_' + Math.floor(Math.random() * 1e9) ) try { fs.writeFileSync(probe, '') fs.unlinkSync(probe) row.WRITEABLE = 'Y' } catch (err) { row.MSG = err.message } return row } try { switch (ACTION) { case 'DIRLIST': { brBrowseGate() const parent = String(brValue(brRows[0], 'PARENT') || '').trim() const depth = Math.min( Math.max(parseInt(brValue(brRows[0], 'DEPTH'), 10) || 1, 1), 3 ) const maxobs = Math.min( Math.max(parseInt(brValue(brRows[0], 'MAXOBS'), 10) || 2000, 1), 10000 ) /* a blank parent is the platform root; only a supplied one is checked */ if (parent) brCheckPath(parent, 'Invalid parent') const listing = brDirList(parent, depth, maxobs) _webout = JSON.stringify({ dirinfo: [ { PARENT: parent, SEP: brSep, DEPTH: depth, TRUNCATED: listing.truncated ? 'Y' : 'N', PLATFORM: brPlatform } ], dirlist: listing.rows }) break } case 'WRITECHECK': { brBrowseGate() const path = String(brValue(brRows[0], 'PATH') || '').trim() _webout = JSON.stringify({ checkwrite: [brWriteCheck(path)] }) break } case 'MAKEDATA': // The seeding path below is the service body as it was, left at file-scope // indentation so this change is the dispatch rather than a reformat of // every seed table. It is the only action that writes to the drive. // Ensure the data directory exists (create parent dirs as needed) if (!fs.existsSync(dataDir)) { fs.mkdirSync(dataDir, { recursive: true }) } // Build the DC database - all MPE tables with seed data // Column definitions follow mpe_makedatamodel.sas structure const tables = { MPE_ALERTS: [], MPE_AUDIT: [], MPE_COLUMN_LEVEL_SECURITY: [ { tx_from: 0, tx_to: 253717919999, CLS_SCOPE: 'EDIT', CLS_GROUP: 'AllUsers', CLS_LIBREF: dcLibref, CLS_TABLE: 'MPE_LOCKANYTABLE', CLS_VARIABLE_NM: 'LOCK_STATUS_CD', CLS_ACTIVE: 1, CLS_HIDE: 0 } ], MPE_CONFIG: [ { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_EMAIL_ALERTS', var_value: 'NO', var_active: 1, var_desc: 'YES or NO to enable email alerts.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_VIEWLIB_CHECK', var_value: 'NO', var_active: 1, var_desc: 'Set to YES to enable library validity checking in viewLibs service.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_MACROS', var_value: dataDir + '/dc_macros', var_active: 1, var_desc: 'Location of underlying macros - EUC feature.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_MAXOBS_WEBEDIT', var_value: '250', var_active: 1, var_desc: 'Maximum observations for editing in the EDIT screen. The ' + 'DC_MAXCELLS_WEBEDIT limit applies at the same time, whichever is ' + 'reached first.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_MAXCELLS_WEBEDIT', var_value: '200000', var_active: 1, var_desc: 'Maximum CELLS (rows x columns) for editing in the EDIT screen - a ' + 'wide table is expensive long before it is tall.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_MAXOBS_WEBVIEW', var_value: '2000', var_active: 1, var_desc: 'Maximum observations for the VIEW screen.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_REQUEST_LOGS', var_value: 'YES', var_active: 1, var_desc: 'Setting to NO will prevent each request being logged to MPE_REQUESTS.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_RESTRICT_VIEWER', var_value: 'NO', var_active: 1, var_desc: 'YES will restrict the viewer to tables in MPE_SECURITY.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_RESTRICT_EDITRECORD', var_value: 'NO', var_active: 1, var_desc: 'YES will prevent the EDIT RECORD dialog.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC_CATALOG', var_name: 'DC_IGNORELIBS', var_value: '|MAPSSAS|MAPS|', var_active: 1, var_desc: 'Pipe separated list of librefs to ignore in Data Catalog.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_LOCALE', var_value: 'SYSTEM', var_active: 1, var_desc: 'Set to a locale to override the system value.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC_REVIEW', var_name: 'HISTORY_ROWS', var_value: '100', var_active: 1, var_desc: 'Number of rows to return in the HISTORY page.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_LICENCE_KEY', var_value: ' ', var_active: 1, var_desc: 'Licence Key' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC', var_name: 'DC_ACTIVATION_KEY', var_value: ' ', var_active: 1, var_desc: 'Activation Key' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC_EMAIL', var_name: 'SUBMITTED_TEMPLATE', var_value: 'Dear user, a change has been submitted.', var_active: 1, var_desc: 'Template email sent after submitting a change.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC_EMAIL', var_name: 'APPROVED_TEMPLATE', var_value: 'Dear user, a change has been approved.', var_active: 1, var_desc: 'Template email sent after approving a change.' }, { tx_from: 0, tx_to: 253717919999, var_scope: 'DC_EMAIL', var_name: 'REJECTED_TEMPLATE', var_value: 'Dear user, a change has been rejected.', var_active: 1, var_desc: 'Template email sent after rejecting a change.' } ], MPE_DATACATALOG_CATS: [], MPE_DATACATALOG_LIBS: [], MPE_DATACATALOG_OBJS: [], MPE_DATACATALOG_TABS: [], MPE_DATACATALOG_VARS: [], MPE_DATASTATUS_CATS: [], MPE_DATASTATUS_LIBS: [], MPE_DATASTATUS_OBJS: [], MPE_DATASTATUS_TABS: [], MPE_DATADICTIONARY: [ { tx_from: 0, tx_to: 127490111999, DD_TYPE: 'LIBRARY', DD_SOURCE: dcLibref, DD_SHORTDESC: 'Data Controller Control Tables', DD_LONGDESC: '# The Data Controller Library', DD_OWNER: 'sasdemo', DD_RESPONSIBLE: 'sasdemo', DD_SENSITIVITY: 'Low' }, { tx_from: 0, tx_to: 127490111999, DD_TYPE: 'TABLE', DD_SOURCE: dcLibref + '.MPE_TABLES', DD_SHORTDESC: 'Configuration of new tables for Data Controller', DD_LONGDESC: '# MPE_TABLES', DD_OWNER: 'sasdemo', DD_RESPONSIBLE: 'sasdemo', DD_SENSITIVITY: 'Low' }, { tx_from: 0, tx_to: 127490111999, DD_TYPE: 'COLUMN', DD_SOURCE: dcLibref + '.MPE_TABLES.DSN', DD_SHORTDESC: 'Dataset Name to be edited', DD_LONGDESC: '_DSN_ - must be UPCASE', DD_OWNER: 'sasdemo', DD_RESPONSIBLE: 'sasdemo', DD_SENSITIVITY: 'Low' }, { tx_from: 0, tx_to: 127490111999, DD_TYPE: 'DIRECTORY', DD_SOURCE: '/some/directory', DD_SHORTDESC: 'Directory for some purpose', DD_LONGDESC: 'This directory is great.', DD_OWNER: 'sasdemo', DD_RESPONSIBLE: 'sasdemo', DD_SENSITIVITY: 'Low' }, { tx_from: 0, tx_to: 127490111999, DD_TYPE: 'TABLE', DD_SOURCE: dcLibref, DD_SHORTDESC: 'Transaction table for capturing Data Controller users', DD_LONGDESC: 'After a user accepts the EULA they are registered here.', DD_OWNER: 'sasdemo', DD_RESPONSIBLE: 'sasdemo', DD_SENSITIVITY: 'Low' }, { tx_from: 0, tx_to: 127490111999, DD_TYPE: 'COLUMN', DD_SOURCE: dcLibref + '.MPE_CONFIG.VAR_ACTIVE', DD_SHORTDESC: 'Set to 1 to make an option active', DD_LONGDESC: 'Used as a filter when querying for option settings.', DD_OWNER: 'sasdemo', DD_RESPONSIBLE: 'sasdemo', DD_SENSITIVITY: 'Low' } ], // Derived (computed) variables. Values are display-time only - the logic is // applied by mpe_derived in the mock's getdata/getcolvals, and must use the // expression subset that compileSasExpression supports (the real evaluation // is done by SAS). MPE_DERIVED: [ { tx_from: 0, tx_to: 253717919999, libref: 'TESTDATA', dsn: 'DERIVED_DEMO', var_nm: 'REGION', var_deps: 'STATE', var_type: 'C', var_len: 8, var_fmt: '', var_logic: "ifc(STATE in ('CA','OR','WA'),'West','East')", active: 1 }, { tx_from: 0, tx_to: 253717919999, libref: 'TESTDATA', dsn: 'DERIVED_DEMO', var_nm: 'LINE_VALUE', var_deps: 'QTY PRICE', var_type: 'N', var_len: 8, var_fmt: 'dollar12.2', var_logic: 'QTY * PRICE', active: 1 }, { // built on REGION, so it proves the dependency order is applied tx_from: 0, tx_to: 253717919999, libref: 'TESTDATA', dsn: 'DERIVED_DEMO', var_nm: 'REGION_LABEL', var_deps: 'REGION STATE', var_type: 'C', var_len: 14, var_fmt: '', var_label: 'Region and state', var_logic: "cats(REGION,'-',STATE)", active: 1 } ], MPE_DATALOADS: [], MPE_EMAILS: [], MPE_EXCEL_CONFIG: [], MPE_FILTERANYTABLE: [], MPE_FILTERSOURCE: [], MPE_GROUPS: [ { tx_from: 0, tx_to: 127490111999, group_name: 'dc-admin', group_desc: 'Custom Group for Data Controller Purposes', user_name: 'allbow' }, { tx_from: 0, tx_to: 127490111999, group_name: 'dc-admin', group_desc: 'Custom Group for Data Controller Purposes', user_name: 'dctestuser1' }, { tx_from: 0, tx_to: 127490111999, group_name: 'dc-admin', group_desc: 'Custom Group for Data Controller Purposes', user_name: 'mihmed' } ], MPE_LINEAGE_COLS: [], MPE_LINEAGE_TABS: [], MPE_LOADS: [], MPE_LOCKANYTABLE: [], MPE_REVIEW: [], MPE_REQUESTS: [], MPE_ROW_LEVEL_SECURITY: [ { tx_from: 0, tx_to: 127490111999, RLS_RK: 1, RLS_SCOPE: 'ALL', RLS_GROUP: 'dc-admin', RLS_LIBREF: dcLibref, RLS_TABLE: 'MPE_GROUPS', RLS_GROUP_LOGIC: 'AND', RLS_SUBGROUP_LOGIC: 'OR', RLS_SUBGROUP_ID: 0, RLS_VARIABLE_NM: 'GROUP_NAME', RLS_OPERATOR_NM: 'NE', RLS_RAW_VALUE: "'-1'", RLS_ACTIVE: 1 }, { tx_from: 0, tx_to: 127490111999, RLS_RK: 2, RLS_SCOPE: 'ALL', RLS_GROUP: 'dc-admin', RLS_LIBREF: dcLibref, RLS_TABLE: 'MPE_ROW_LEVEL_SECURITY', RLS_GROUP_LOGIC: 'AND', RLS_SUBGROUP_LOGIC: 'OR', RLS_SUBGROUP_ID: 0, RLS_VARIABLE_NM: 'RLS_RK', RLS_OPERATOR_NM: '>', RLS_RAW_VALUE: '0', RLS_ACTIVE: 1 }, { tx_from: 0, tx_to: 127490111999, RLS_RK: 3, RLS_SCOPE: 'ALL', RLS_GROUP: 'DC Demo Group', RLS_LIBREF: dcLibref, RLS_TABLE: 'MPE_SECURITY', RLS_GROUP_LOGIC: 'AND', RLS_SUBGROUP_LOGIC: 'OR', RLS_SUBGROUP_ID: 0, RLS_VARIABLE_NM: 'ACCESS_LEVEL', RLS_OPERATOR_NM: 'NE', RLS_RAW_VALUE: "'N/A'", RLS_ACTIVE: 1 } ], MPE_SECURITY: [ { tx_from: 0, tx_to: 127490111999, libref: '*ALL*', dsn: '*ALL*', access_level: 'APPROVE', sas_group: 'dc-admin' }, { tx_from: 0, tx_to: 127490111999, libref: '*ALL*', dsn: '*ALL*', access_level: 'EDIT', sas_group: 'dc-admin' }, { tx_from: 0, tx_to: 127490111999, libref: '*ALL*', dsn: '*ALL*', access_level: 'VIEW', sas_group: 'AllUsers' } ], MPE_SELECTBOX: [ { selectbox_rk: 1, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_LOCKANYTABLE', base_column: 'LOCK_STATUS_CD', selectbox_value: 'LOCKED', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 2, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_LOCKANYTABLE', base_column: 'LOCK_STATUS_CD', selectbox_value: 'UNLOCKED', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 3, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'ACCESS_LEVEL', selectbox_value: 'EDIT', selectbox_order: 0, ver_to_dttm: 127490111999 }, { selectbox_rk: 4, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'ACCESS_LEVEL', selectbox_value: 'APPROVE', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 5, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'ACCESS_LEVEL', selectbox_value: 'VIEW', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 6, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'ACCESS_LEVEL', selectbox_value: 'SIGNOFF', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 7, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'ACCESS_LEVEL', selectbox_value: 'AUDIT', selectbox_order: 4, ver_to_dttm: 127490111999 }, { selectbox_rk: 8, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_TABLES', base_column: 'LOADTYPE', selectbox_value: 'UPDATE', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 9, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_TABLES', base_column: 'LOADTYPE', selectbox_value: 'REPLACE', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 10, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_TABLES', base_column: 'LOADTYPE', selectbox_value: 'TXTEMPORAL', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 11, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_TABLES', base_column: 'LOADTYPE', selectbox_value: 'BITEMPORAL', selectbox_order: 4, ver_to_dttm: 127490111999 }, { selectbox_rk: 12, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_TABLES', base_column: 'LOADTYPE', selectbox_value: 'FORMAT_CAT', selectbox_order: 5, ver_to_dttm: 127490111999 }, { selectbox_rk: 13, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ALERTS', base_column: 'ALERT_EVENT', selectbox_value: '*ALL*', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 14, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ALERTS', base_column: 'ALERT_EVENT', selectbox_value: 'SUBMITTED', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 15, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ALERTS', base_column: 'ALERT_EVENT', selectbox_value: 'APPROVED', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 16, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ALERTS', base_column: 'ALERT_EVENT', selectbox_value: 'REJECTED', selectbox_order: 4, ver_to_dttm: 127490111999 }, { selectbox_rk: 17, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_X_TEST', base_column: 'SOME_DROPDOWN', selectbox_value: 'Option 1', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 18, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_X_TEST', base_column: 'SOME_DROPDOWN', selectbox_value: 'Option 2', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 19, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_X_TEST', base_column: 'SOME_DROPDOWN', selectbox_value: 'Option 3', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 20, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_X_TEST', base_column: 'SOME_DROPDOWN', selectbox_value: 'This is a long option. This option is very long. It is optional, though.', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 21, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'CASE', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 22, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'HARDSELECT', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 23, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'HARDSELECT_HOOK', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 24, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'HIDDEN', selectbox_order: 4, ver_to_dttm: 127490111999 }, { selectbox_rk: 25, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'MAXVAL', selectbox_order: 5, ver_to_dttm: 127490111999 }, { selectbox_rk: 26, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'MINVAL', selectbox_order: 6, ver_to_dttm: 127490111999 }, { selectbox_rk: 27, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'NOTNULL', selectbox_order: 7, ver_to_dttm: 127490111999 }, { selectbox_rk: 28, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'NUMBER_FORMAT', selectbox_order: 8, ver_to_dttm: 127490111999 }, { selectbox_rk: 29, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'READONLY', selectbox_order: 9, ver_to_dttm: 127490111999 }, { selectbox_rk: 30, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'ROUND', selectbox_order: 10, ver_to_dttm: 127490111999 }, { selectbox_rk: 31, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'SOFTSELECT', selectbox_order: 11, ver_to_dttm: 127490111999 }, { selectbox_rk: 32, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'SOFTSELECT_HOOK', selectbox_order: 12, ver_to_dttm: 127490111999 }, { selectbox_rk: 33, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'HARDREGEX', selectbox_order: 13, ver_to_dttm: 127490111999 }, { selectbox_rk: 34, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'SOFTREGEX', selectbox_order: 14, ver_to_dttm: 127490111999 }, { selectbox_rk: 35, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'HARDFORMULA', selectbox_order: 15, ver_to_dttm: 127490111999 }, { selectbox_rk: 36, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_TYPE', selectbox_value: 'SOFTFORMULA', selectbox_order: 16, ver_to_dttm: 127490111999 }, { selectbox_rk: 37, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_ACTIVE', selectbox_value: '1', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 38, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_VALIDATIONS', base_column: 'RULE_ACTIVE', selectbox_value: '0', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 39, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'DSN', selectbox_value: '*ALL*', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 40, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_SECURITY', base_column: 'LIBREF', selectbox_value: '*ALL*', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 41, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DATADICTIONARY', base_column: 'DD_TYPE', selectbox_value: 'COLUMN', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 42, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DATADICTIONARY', base_column: 'DD_TYPE', selectbox_value: 'TABLE', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 43, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DATADICTIONARY', base_column: 'DD_TYPE', selectbox_value: 'LIBRARY', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 44, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DATADICTIONARY', base_column: 'DD_TYPE', selectbox_value: 'CATALOG', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 45, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DATADICTIONARY', base_column: 'DD_TYPE', selectbox_value: 'FORMAT', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 46, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_SCOPE', selectbox_value: 'ALL', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 47, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_SCOPE', selectbox_value: 'EDIT', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 48, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_SCOPE', selectbox_value: 'VIEW', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 49, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_GROUP_LOGIC', selectbox_value: 'AND', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 50, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_GROUP_LOGIC', selectbox_value: 'OR', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 51, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_SUBGROUP_LOGIC', selectbox_value: 'AND', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 52, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_SUBGROUP_LOGIC', selectbox_value: 'OR', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 53, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: '=', selectbox_order: 0, ver_to_dttm: 127490111999 }, { selectbox_rk: 54, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: '>', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 55, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: '<', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 56, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: '<=', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 57, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: '>=', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 58, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: 'BETWEEN', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 59, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: 'IN', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 60, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: 'NOT IN', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 61, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: 'NE', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 62, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_OPERATOR_NM', selectbox_value: 'CONTAINS', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 63, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_ACTIVE', selectbox_value: '1', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 64, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_ROW_LEVEL_SECURITY', base_column: 'RLS_ACTIVE', selectbox_value: '0', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 65, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_ACTIVE', selectbox_value: '1', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 66, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_ACTIVE', selectbox_value: '0', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 67, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_SCOPE', selectbox_value: 'EDIT', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 68, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_SCOPE', selectbox_value: 'VIEW', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 69, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_SCOPE', selectbox_value: 'ALL', selectbox_order: 3, ver_to_dttm: 127490111999 }, { selectbox_rk: 70, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_HIDE', selectbox_value: '0', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 71, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_column: 'CLS_HIDE', selectbox_value: '1', selectbox_order: 2, ver_to_dttm: 127490111999 }, { selectbox_rk: 72, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_EXCEL_CONFIG', base_column: 'XL_RULE', selectbox_value: 'FORMULA', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 73, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DERIVED', base_column: 'VAR_TYPE', selectbox_value: 'C', selectbox_order: 1, ver_to_dttm: 127490111999 }, { selectbox_rk: 74, ver_from_dttm: 0, select_lib: dcLibref, select_ds: 'MPE_DERIVED', base_column: 'VAR_TYPE', selectbox_value: 'N', selectbox_order: 2, ver_to_dttm: 127490111999 } ], MPE_SUBMIT: [], MPE_TABLES: [ { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_COLUMN_LEVEL_SECURITY', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', buskey: 'CLS_SCOPE CLS_GROUP CLS_LIBREF CLS_TABLE CLS_VARIABLE_NM', notes: 'Column Level Security config', post_edit_hook: 'services/hooks/mpe_column_level_security_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_XLMAP_INFO', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', buskey: 'XLMAP_ID', notes: 'Excel Map Info', post_edit_hook: 'services/hooks/mpe_xlmap_info_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_XLMAP_RULES', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', buskey: 'XLMAP_ID XLMAP_RANGE_ID', notes: 'Excel Map Rules', post_edit_hook: 'services/hooks/mpe_xlmap_rules_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_XLMAP_DATA', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'LOAD_REF XLMAP_ID XLMAP_RANGE_ID ROW_NO COL_NO', notes: 'Excel Map Data' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_LOCKANYTABLE', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'LOCK_LIB LOCK_DS', notes: 'Table lock management' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_TABLES', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'LIBREF DSN', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', notes: 'MPE Editor self-edit', post_edit_hook: 'services/hooks/mpe_tables_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_SECURITY', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'LIBREF DSN ACCESS_LEVEL SAS_GROUP', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', notes: 'Group access control', post_edit_hook: 'services/hooks/mpe_security_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_SELECTBOX', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'SELECTBOX_RK', var_txfrom: 'VER_FROM_DTTM', var_txto: 'VER_TO_DTTM', notes: 'Dropdown configuration', rk_underlying: 'SELECT_LIB SELECT_DS BASE_COLUMN SELECTBOX_VALUE' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_X_TEST', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'PRIMARY_KEY_FIELD', notes: 'Test table for controller' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_EMAILS', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'USER_NAME', notes: 'Primary Emails Table', var_txfrom: 'TX_FROM', var_txto: 'TX_TO' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_CONFIG', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'VAR_SCOPE VAR_NAME', notes: 'Configuration variables', var_txfrom: 'TX_FROM', var_txto: 'TX_TO' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_ALERTS', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'ALERT_EVENT ALERT_LIB ALERT_DS ALERT_USER', notes: 'Alert email events', var_txfrom: 'TX_FROM', var_txto: 'TX_TO' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_GROUPS', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'GROUP_NAME USER_NAME', notes: 'Additional DC groups', var_txfrom: 'TX_FROM', var_txto: 'TX_TO' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_VALIDATIONS', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'BASE_LIB BASE_DS BASE_COL RULE_TYPE', notes: 'Data quality rules', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', post_edit_hook: 'services/hooks/mpe_validations_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_DATADICTIONARY', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'DD_TYPE DD_SOURCE', notes: 'Data dictionary', var_txfrom: 'TX_FROM', var_txto: 'TX_TO' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_EXCEL_CONFIG', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'XL_LIBREF XL_TABLE XL_COLUMN', notes: 'Excel import rules', var_txfrom: 'TX_FROM', var_txto: 'TX_TO' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_ROW_LEVEL_SECURITY', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'RLS_RK', notes: 'Row Level Security', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', rk_underlying: 'RLS_SCOPE RLS_GROUP RLS_LIBREF RLS_TABLE RLS_GROUP_LOGIC RLS_SUBGROUP_LOGIC RLS_SUBGROUP_ID RLS_VARIABLE_NM RLS_OPERATOR_NM RLS_RAW_VALUE', post_edit_hook: 'services/hooks/mpe_row_level_security_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_DERIVED', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'LIBREF DSN VAR_NM', notes: 'Derived (computed) variables for the EDIT screen', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', post_edit_hook: 'services/hooks/mpe_derived_postedit' }, { tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_X_CATALOG-FC', num_of_approvals_required: 1, loadtype: 'FORMAT_CAT', buskey: 'TYPE FMTNAME FMTROW', notes: 'Sample Format Catalog' } ], MPE_VALIDATIONS: [ { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_SCOPE', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_LIBREF', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_LIBREF', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/libraries_all', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_TABLE', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_TABLE', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/tables_all', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_VARIABLE_NM', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_VARIABLE_NM', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_ACTIVE', rule_type: 'MAXVAL', rule_value: '1', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_HIDE', rule_type: 'MAXVAL', rule_value: '1', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_COLUMN_LEVEL_SECURITY', base_col: 'CLS_GROUP', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/sas_groups', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'LIBREF', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'DSN', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'LIBREF', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'DSN', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'NUM_OF_APPROVALS_REQUIRED', rule_type: 'MINVAL', rule_value: '1', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'BUSKEY', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'BUSKEY', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_TXFROM', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_TXTO', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_BUSFROM', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_BUSTO', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_PROCESSED', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'LIBREF', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/libraries_all', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'DSN', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/mpe_tables.dsn', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_TXFROM', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_TXTO', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_BUSFROM', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_BUSTO', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_TABLES', base_col: 'VAR_PROCESSED', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SECURITY', base_col: 'LIBREF', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SECURITY', base_col: 'LIBREF', rule_type: 'HARDSELECT', rule_value: dcLibref + '.MPE_TABLES.LIBREF', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SECURITY', base_col: 'DSN', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SECURITY', base_col: 'DSN', rule_type: 'SOFTSELECT', rule_value: dcLibref + '.MPE_TABLES.DSN', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SECURITY', base_col: 'SAS_GROUP', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/sas_groups', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_VALIDATIONS', base_col: 'BASE_LIB', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/libraries_editable', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_VALIDATIONS', base_col: 'BASE_DS', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/tables_editable', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_VALIDATIONS', base_col: 'BASE_COL', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_VALIDATIONS', base_col: 'RULE_ACTIVE', rule_type: 'MINVAL', rule_value: '0', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_VALIDATIONS', base_col: 'RULE_ACTIVE', rule_type: 'MAXVAL', rule_value: '1', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_EXCEL_CONFIG', base_col: 'XL_LIBREF', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/libraries_editable', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_EXCEL_CONFIG', base_col: 'XL_TABLE', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/tables_editable', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_EXCEL_CONFIG', base_col: 'XL_COLUMN', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_EXCEL_CONFIG', base_col: 'XL_ACTIVE', rule_type: 'MINVAL', rule_value: '0', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_EXCEL_CONFIG', base_col: 'XL_ACTIVE', rule_type: 'MAXVAL', rule_value: '1', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_XLMAP_INFO', base_col: 'XLMAP_ID', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_XLMAP_INFO', base_col: 'XLMAP_ID', rule_type: 'SOFTSELECT', rule_value: dcLibref + '.MPE_XLMAP_RULES.XLMAP_ID', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_XLMAP_RULES', base_col: 'XLMAP_ID', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SELECTBOX', base_col: 'SELECT_LIB', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/libraries_editable', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SELECTBOX', base_col: 'SELECT_DS', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/tables_editable', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_SELECTBOX', base_col: 'BASE_COLUMN', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ROW_LEVEL_SECURITY', base_col: 'RLS_GROUP', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/sas_groups', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ROW_LEVEL_SECURITY', base_col: 'RLS_LIBREF', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/libraries_all', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ROW_LEVEL_SECURITY', base_col: 'RLS_TABLE', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/tables_all', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ROW_LEVEL_SECURITY', base_col: 'RLS_SUBGROUP_ID', rule_type: 'MINVAL', rule_value: '0', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ROW_LEVEL_SECURITY', base_col: 'RLS_SUBGROUP_ID', rule_type: 'NOTNULL', rule_value: '0', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ROW_LEVEL_SECURITY', base_col: 'RLS_VARIABLE_NM', rule_type: 'SOFTSELECT_HOOK', rule_value: 'services/validations/columns_in_libds', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_ALERTS', base_col: 'ALERT_LIB', rule_type: 'HARDSELECT_HOOK', rule_value: 'services/validations/mpe_alerts.alert_lib', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_X_TEST', base_col: 'SOME_BESTNUM', rule_type: 'SOFTSELECT', rule_value: dcLibref + '.MPE_X_TEST.SOME_BESTNUM', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_X_TEST', base_col: 'SOME_CHAR', rule_type: 'HARDREGEX', rule_value: '/the|data/i', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_X_TEST', base_col: 'SOME_CHAR', rule_type: 'SOFTREGEX', rule_value: '/t/', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_X_TEST', base_col: 'PRIMARY_KEY_FIELD', rule_type: 'SOFTREGEX', rule_value: '/^\\d+$/', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_X_TEST', base_col: 'SOME_NUM', rule_type: 'HARDSELECT_HOOK', rule_value: 'services/validations/mpe_x_test.some_num', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'LIBREF', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'LIBREF', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'DSN', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'DSN', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_NM', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_NM', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_NM', rule_type: 'HARDREGEX', rule_value: '^[A-Za-z_][A-Za-z0-9_]*$', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_DEPS', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_DEPS', rule_type: 'HARDREGEX', rule_value: '^[A-Za-z0-9_ ]*$', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_TYPE', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_TYPE', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_TYPE', rule_type: 'HARDSELECT', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_LEN', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_LEN', rule_type: 'MINVAL', rule_value: '1', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_LEN', rule_type: 'MAXVAL', rule_value: '32767', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_FMT', rule_type: 'CASE', rule_value: 'UPCASE', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_FMT', rule_type: 'HARDREGEX', rule_value: '^(\$?[A-Za-z][A-Za-z0-9_]*(\.[0-9]+)?\.?|\$?[0-9]+(\.[0-9]+)?\.?)?$', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_LOGIC', rule_type: 'NOTNULL', rule_value: ' ', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_LABEL', rule_type: 'HARDREGEX', rule_value: '^[^\\x00-\\x1F\\x7F]*$', rule_active: 1, tx_to: 127490111999 }, { tx_from: 0, base_lib: dcLibref, base_ds: 'MPE_DERIVED', base_col: 'VAR_LOGIC', rule_type: 'HARDREGEX', rule_value: '^(?!.*(/\\*|\\*/))[^;&%]*$', rule_active: 1, tx_to: 127490111999 } ], MPE_X_TEST: [ { PRIMARY_KEY_FIELD: 0, SOME_CHAR: 'this is dummy data', SOME_DROPDOWN: 'Option 1', SOME_NUM: 42, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 42, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 }, { PRIMARY_KEY_FIELD: 1, SOME_CHAR: 'more dummy data', SOME_DROPDOWN: 'Option 2', SOME_NUM: 42, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 422, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 }, { PRIMARY_KEY_FIELD: 2, SOME_CHAR: 'even more dummy data', SOME_DROPDOWN: 'Option 3', SOME_NUM: 42, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 142, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 }, { PRIMARY_KEY_FIELD: 3, SOME_CHAR: 'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:', SOME_DROPDOWN: 'Option 2', SOME_NUM: 1613.001, SOME_DATE: 423, SOME_DATETIME: 423, SOME_TIME: 44, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 }, { PRIMARY_KEY_FIELD: 4, SOME_CHAR: 'if you can fill the unforgiving minute', SOME_DROPDOWN: 'Option 1', SOME_NUM: 1613.001123456, SOME_DATE: 4231, SOME_DATETIME: 423123123, SOME_TIME: 412, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 }, { PRIMARY_KEY_FIELD: 5, SOME_CHAR: '= testing the formula situation', SOME_DROPDOWN: 'Option 1', SOME_NUM: 42, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 42, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 }, { PRIMARY_KEY_FIELD: 6, SOME_CHAR: "'=the formula with leading apostrophe", SOME_DROPDOWN: 'Option 1', SOME_NUM: 42, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 42, SOME_SHORTNUM: 8, SOME_BESTNUM: 44 } ], MPE_XLMAP_DATA: [], MPE_XLMAP_INFO: [ { tx_from: 0, tx_to: 127490111999, XLMAP_ID: 'BASEL-KM1', XLMAP_DESCRIPTION: 'Basel 3 Key Metrics report', XLMAP_TARGETLIBDS: dcLibref + '.MPE_XLMAP_DATA' } ], MPE_XLMAP_RULES: [ { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-KM1', xlmap_range_id: 'KM1:a', xlmap_sheet: 'KM1', xlmap_start: 'MATCH 4 R[2]C[0]:a' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-KM1', xlmap_range_id: 'KM1:b', xlmap_sheet: 'KM1', xlmap_start: 'MATCH 4 R[2]C[0]:b' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-KM1', xlmap_range_id: 'KM1:c', xlmap_sheet: 'KM1', xlmap_start: 'MATCH 4 R[2]C[0]:c' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-KM1', xlmap_range_id: 'KM1:d', xlmap_sheet: 'KM1', xlmap_start: 'MATCH 4 R[2]C[0]:d' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-KM1', xlmap_range_id: 'KM1:e', xlmap_sheet: 'KM1', xlmap_start: 'MATCH 4 R[2]C[0]:e' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-KM1', xlmap_range_id: 'KM1:f', xlmap_sheet: 'KM1', xlmap_start: 'MATCH 4 R[2]C[0]:f' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-CR2', xlmap_range_id: 'CR2-sec1', xlmap_sheet: 'CR2', xlmap_start: 'ABSOLUTE D8', xlmap_finish: 'BLANKROW' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'BASEL-CR2', xlmap_range_id: 'CR2-sec2', xlmap_sheet: 'CR2', xlmap_start: 'ABSOLUTE D18', xlmap_finish: 'LASTDOWN' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'SAMPLE', xlmap_range_id: 'header', xlmap_sheet: '/1', xlmap_start: 'ABSOLUTE B3', xlmap_finish: 'ABSOLUTE B8' }, { tx_from: 0, tx_to: 127490111999, xlmap_id: 'SAMPLE', xlmap_range_id: 'data', xlmap_sheet: '/1', xlmap_start: 'ABSOLUTE B13', xlmap_finish: 'ABSOLUTE E16' } ], MPE_X_CATALOG: [], MPE_X_SEARCH: [], MPE_USERS: [] } // ─── MPE_X_SEARCH: viewer full-table-search demo table ─────────────────────── // Deterministic, obviously fictional deep-sea survey data (no real sites, // vessels or people). Laid out site-major / vessel-minor so every count in // the full-table-search Cypress spec can be derived by hand: // n = rep * 50 + siteIdx * 5 + vesselIdx (0-based, 1000 rows) // -> 20 rows per site, 100 rows per site block, 200 rows per vessel const searchSites = [ 'Nereid Trench', 'Calypso Trench', 'Halcyon Trench', 'Amphitrite Basin', 'Kraken Hollow', 'Erebus Deep', 'Thalassa Shelf', 'Oceanus Rise', 'Selkie Bank', 'Vostok Deep' ] const searchVessels = [ 'RV Pelagia', 'RV Aurora', 'RV Selkie', 'RV Cormorant', 'RV Halcyon' ] const searchSpecies = [ 'Vampire squid', 'Barreleye fish', 'Dumbo octopus', 'Yeti crab', 'Giant isopod', 'Ghost shark', 'Comb jelly', 'Sea pig', 'Glass sponge', 'Anglerfish' ] // Rows carrying the mid-field marker in NOTES (searched as a partial string) const siphonophoreRows = [137, 500, 862] // Rows sharing the repeated exact SAMPLE_COUNT (searched as a number) const sampleCountRows = [220, 780] tables.MPE_X_SEARCH = [] for (let n = 0; n < 1000; n++) { const rep = Math.floor(n / 50) const siteIdx = Math.floor((n % 50) / 5) const vesselIdx = n % 5 const site = searchSites[siteIdx] const depth = 1000 + (n % 90) * 37 tables.MPE_X_SEARCH.push({ PRIMARY_KEY_FIELD: n + 1001, SITE_NAME: site, VESSEL: searchVessels[vesselIdx], SAMPLE_COUNT: sampleCountRows.includes(n) ? 4210 : 1 + (n % 6), DEPTH_M: depth, SPECIES: searchSpecies[(siteIdx + vesselIdx) % searchSpecies.length], CRUISE_DATE: 20000 + (n % 3650), EXPEDITION_ID: 'EXP-' + String(n + 1).padStart(4, '0'), NOTES: 'Leg ' + (rep + 1) + ' of the ' + site + ' survey. ' + (siphonophoreRows.includes(n) ? 'A bioluminescent siphonophore was filmed here.' : 'No anomalies recorded.') + ' Depth soundings logged at ' + depth + 'm.' }) } // Register the demo table like any other editable table (buskey drives the // viewer's PK detection). tables.MPE_TABLES.push({ tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_X_SEARCH', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'PRIMARY_KEY_FIELD', notes: 'Full table search demo table' }) // ─── MPE_X_WIDE: wide table for the EDIT cell limit ───────────────────────── // 200 rows x 1001 columns (ROW_ID + 500 single-character + 500 numeric) is // 200,200 cells - over DC_MAXCELLS_WEBEDIT (200000) while staying under // DC_MAXOBS_WEBEDIT (250), so it exercises the CELL limit on its own and the // row limit spec can use MPE_X_SEARCH (1000 rows) instead. Values are one // character / one digit on purpose: the point is width, and small values keep // the seeded JSON near 1MB rather than the 25MB the real WIDEBOY fixture (20 // character fields) would take. tables.MPE_X_WIDE = [] for (let n = 0; n < 200; n++) { const wideRow = { ROW_ID: n + 1 } for (let c = 1; c <= 500; c++) { wideRow['CHAR' + c] = String.fromCharCode(65 + ((n + c) % 26)) } for (let c = 1; c <= 500; c++) { wideRow['NUM' + c] = (n + c) % 10 } tables.MPE_X_WIDE.push(wideRow) } tables.MPE_TABLES.push({ tx_from: 0, tx_to: 127490111999, libref: dcLibref, dsn: 'MPE_X_WIDE', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'ROW_ID CHAR1 NUM1', notes: 'Wide table fixture for the EDIT cell limit' }) // Column metadata for each table, extracted from mpe_makedatamodel.sas // Each entry: { name, type (N/C), length, format, label, notnull (bool) } const schema = { MPE_ALERTS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: false }, { name: 'ALERT_EVENT', type: 'C', length: 20, format: '', label: '', notnull: false }, { name: 'ALERT_LIB', type: 'C', length: 8, format: '', label: '', notnull: false }, { name: 'ALERT_DS', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'ALERT_USER', type: 'C', length: 100, format: '', label: '', notnull: false }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true } ], MPE_AUDIT: [ { name: 'LOAD_REF', type: 'C', length: 36, format: '', label: 'unique load reference', notnull: false }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Reference (8 chars)', notnull: false }, { name: 'DSN', type: 'C', length: 32, format: '', label: 'Dataset Name (32 chars)', notnull: false }, { name: 'KEY_HASH', type: 'C', length: 32, format: '', label: 'MD5 Hash of primary key values (pipe seperated)', notnull: false }, { name: 'TGTVAR_NM', type: 'C', length: 32, format: '', label: 'Target variable name (32 chars)', notnull: false }, { name: 'MOVE_TYPE', type: 'C', length: 1, format: '', label: 'Either (A)ppended, (D)eleted or (M)odified', notnull: false }, { name: 'PROCESSED_DTTM', type: 'N', length: 8, format: 'E8601DT26.6', label: 'Processed at timestamp', notnull: false }, { name: 'IS_PK', type: 'N', length: 8, format: '', label: 'Is Primary Key Field? (1/0)', notnull: false }, { name: 'IS_DIFF', type: 'N', length: 8, format: '', label: 'Did value change? (1/0/-1)', notnull: false }, { name: 'TGTVAR_TYPE', type: 'C', length: 1, format: '', label: 'Either (C)haracter or (N)umeric', notnull: false }, { name: 'OLDVAL_NUM', type: 'N', length: 8, format: 'best32.', label: 'Old (numeric) value', notnull: false }, { name: 'NEWVAL_NUM', type: 'N', length: 8, format: 'best32.', label: 'New (numeric) value', notnull: false }, { name: 'OLDVAL_CHAR', type: 'C', length: 32765, format: '', label: 'Old (character) value', notnull: false }, { name: 'NEWVAL_CHAR', type: 'C', length: 32765, format: '', label: 'New (character) value', notnull: false } ], MPE_COLUMN_LEVEL_SECURITY: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'CLS_SCOPE', type: 'C', length: 4, format: '', label: '', notnull: true }, { name: 'CLS_GROUP', type: 'C', length: 64, format: '', label: '', notnull: true }, { name: 'CLS_LIBREF', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'CLS_TABLE', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'CLS_VARIABLE_NM', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'CLS_ACTIVE', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'CLS_HIDE', type: 'N', length: 8, format: '', label: '', notnull: false } ], MPE_CONFIG: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'VAR_SCOPE', type: 'C', length: 10, format: '', label: '', notnull: true }, { name: 'VAR_NAME', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'VAR_VALUE', type: 'C', length: 5000, format: '', label: '', notnull: false }, { name: 'VAR_ACTIVE', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'VAR_DESC', type: 'C', length: 300, format: '', label: '', notnull: false } ], MPE_DATACATALOG_CATS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: false }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'MEMNAME', type: 'C', length: 64, format: '', label: 'Member Name', notnull: false } ], MPE_DATACATALOG_LIBS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Ref', notnull: false }, { name: 'ENGINE', type: 'C', length: 32, format: '', label: 'Library Engine', notnull: false }, { name: 'LIBNAME', type: 'C', length: 256, format: '$256.', label: 'Library Name', notnull: false }, { name: 'PATHS', type: 'C', length: 8192, format: '', label: 'Library Paths', notnull: false }, { name: 'PERMS', type: 'C', length: 500, format: '', label: 'Library Permissions (if BASE)', notnull: false }, { name: 'OWNERS', type: 'C', length: 500, format: '', label: 'Library Owners (if BASE)', notnull: false }, { name: 'SCHEMAS', type: 'C', length: 500, format: '', label: 'Library Schemas (if DB)', notnull: false }, { name: 'LIBID', type: 'C', length: 17, format: '', label: 'LibraryId', notnull: false } ], MPE_DATACATALOG_OBJS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: false }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: true }, { name: 'MEMNAME', type: 'C', length: 64, format: '', label: 'Member Name', notnull: true }, { name: 'OBJNAME', type: 'C', length: 32, format: '', label: 'Object Name', notnull: true }, { name: 'OBJTYPE', type: 'C', length: 8, format: '', label: 'Object Type', notnull: true }, { name: 'OBJDESC', type: 'C', length: 256, format: '', label: 'Object Description', notnull: false }, { name: 'ALIAS', type: 'C', length: 32, format: '', label: 'Object Alias', notnull: false } ], MPE_DATACATALOG_TABS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'DSN', type: 'C', length: 64, format: '', label: 'Member Name', notnull: false }, { name: 'MEMTYPE', type: 'C', length: 8, format: '', label: 'Member Type', notnull: false }, { name: 'DBMS_MEMTYPE', type: 'C', length: 32, format: '', label: 'DBMS Member Type', notnull: false }, { name: 'MEMLABEL', type: 'C', length: 512, format: '', label: 'Data Set Label', notnull: false }, { name: 'TYPEMEM', type: 'C', length: 8, format: '', label: 'Data Set Type', notnull: false }, { name: 'NVAR', type: 'N', length: 8, format: '', label: 'Number of Variables', notnull: false }, { name: 'COMPRESS', type: 'C', length: 8, format: '', label: 'Compression Routine', notnull: false }, { name: 'PK_FIELDS', type: 'C', length: 512, format: '', label: 'Primary Key Fields', notnull: false } ], MPE_DATACATALOG_VARS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'DSN', type: 'C', length: 64, format: '', label: 'Table Name', notnull: false }, { name: 'NAME', type: 'C', length: 64, format: '', label: 'Column Name', notnull: false }, { name: 'MEMTYPE', type: 'C', length: 8, format: '', label: 'Member Type', notnull: false }, { name: 'TYPE', type: 'C', length: 16, format: '', label: 'Column Type', notnull: false }, { name: 'LENGTH', type: 'N', length: 8, format: '', label: 'Column Length', notnull: false }, { name: 'VARNUM', type: 'N', length: 8, format: '', label: 'Column Number in Table', notnull: false }, { name: 'LABEL', type: 'C', length: 512, format: '', label: 'Column Label', notnull: false }, { name: 'FORMAT', type: 'C', length: 49, format: '', label: 'Column Format', notnull: false }, { name: 'IDXUSAGE', type: 'C', length: 9, format: '', label: 'Column Index Type', notnull: false }, { name: 'NOTNULL', type: 'C', length: 3, format: '', label: 'Not NULL?', notnull: false }, { name: 'PK_IND', type: 'N', length: 8, format: '', label: 'Primary Key Indicator (1=Primary Key field)', notnull: false } ], MPE_DATASTATUS_CATS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: false }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: false }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'MEMNAME', type: 'C', length: 64, format: '', label: 'Member Name', notnull: false }, { name: 'NOBJS', type: 'N', length: 8, format: '', label: 'Number of objects', notnull: true }, { name: 'CREATED', type: 'N', length: 8, format: 'DATETIME.', label: 'Date Created', notnull: true }, { name: 'MODIFIED', type: 'N', length: 8, format: 'DATETIME.', label: 'Date Modified', notnull: false } ], MPE_DATASTATUS_LIBS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'LIBSIZE', type: 'N', length: 8, format: 'SIZEKMG.', label: 'Size of library', notnull: false }, { name: 'TABLE_CNT', type: 'N', length: 8, format: '', label: 'Number of Tables', notnull: false }, { name: 'CATALOG_CNT', type: 'N', length: 8, format: '', label: 'Number of Catalogs', notnull: false } ], MPE_DATASTATUS_OBJS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: false }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'MEMNAME', type: 'C', length: 64, format: '', label: 'Member Name', notnull: false }, { name: 'OBJNAME', type: 'C', length: 32, format: '', label: 'Object Name', notnull: false }, { name: 'OBJTYPE', type: 'C', length: 8, format: '', label: 'Object Type', notnull: false }, { name: 'CREATED', type: 'N', length: 8, format: 'DATETIME.', label: 'Date Created', notnull: true }, { name: 'MODIFIED', type: 'N', length: 8, format: 'DATETIME.', label: 'Date Modified', notnull: false }, { name: 'LEVEL', type: 'N', length: 8, format: '', label: 'Library Concatenation Level', notnull: false } ], MPE_DATASTATUS_TABS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: 'Library Name', notnull: false }, { name: 'DSN', type: 'C', length: 64, format: '', label: 'Member Name', notnull: false }, { name: 'FILESIZE', type: 'N', length: 8, format: 'SIZEKMG.', label: 'Size of file', notnull: false }, { name: 'CRDATE', type: 'N', length: 8, format: 'DATETIME.', label: 'Date Created', notnull: false }, { name: 'MODATE', type: 'N', length: 8, format: 'DATETIME.', label: 'Date Modified', notnull: false }, { name: 'NOBS', type: 'N', length: 8, format: '', label: 'Number of Physical Observations', notnull: false } ], MPE_DATADICTIONARY: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'DD_TYPE', type: 'C', length: 16, format: '', label: '', notnull: false }, { name: 'DD_SOURCE', type: 'C', length: 1024, format: '', label: '', notnull: false }, { name: 'DD_SHORTDESC', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'DD_LONGDESC', type: 'C', length: 32767, format: '', label: '', notnull: false }, { name: 'DD_OWNER', type: 'C', length: 128, format: '', label: '', notnull: false }, { name: 'DD_RESPONSIBLE', type: 'C', length: 128, format: '', label: '', notnull: false }, { name: 'DD_SENSITIVITY', type: 'C', length: 64, format: '', label: '', notnull: false } ], MPE_DERIVED: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: '', notnull: false }, { name: 'DSN', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_NM', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_DEPS', type: 'C', length: 4000, format: '', label: '', notnull: false }, { name: 'VAR_TYPE', type: 'C', length: 1, format: '', label: '', notnull: false }, { name: 'VAR_LEN', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'VAR_FMT', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_LABEL', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'VAR_LOGIC', type: 'C', length: 4000, format: '', label: '', notnull: false }, { name: 'ACTIVE', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true } ], MPE_DATALOADS: [ { name: 'LIBREF', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'DSN', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'ETLSOURCE', type: 'C', length: 100, format: '', label: '', notnull: true }, { name: 'LOADTYPE', type: 'C', length: 20, format: '', label: '', notnull: true }, { name: 'CHANGED_RECORDS', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'NEW_RECORDS', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'DELETED_RECORDS', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'DURATION', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'USER_NM', type: 'C', length: 50, format: '', label: '', notnull: true }, { name: 'PROCESSED_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: false }, { name: 'MAC_VER', type: 'C', length: 5, format: '', label: '', notnull: false } ], MPE_EMAILS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'USER_NAME', type: 'C', length: 50, format: '', label: '', notnull: true }, { name: 'USER_DISPLAYNAME', type: 'C', length: 100, format: '', label: '', notnull: false }, { name: 'USER_EMAIL', type: 'C', length: 100, format: '', label: '', notnull: true } ], MPE_EXCEL_CONFIG: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'XL_LIBREF', type: 'C', length: 8, format: '', label: '', notnull: false }, { name: 'XL_TABLE', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'XL_COLUMN', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'XL_RULE', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'XL_ACTIVE', type: 'N', length: 8, format: '', label: '', notnull: false } ], MPE_FILTERANYTABLE: [ { name: 'FILTER_RK', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'FILTER_HASH', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'FILTER_TABLE', type: 'C', length: 41, format: '', label: '', notnull: true }, { name: 'PROCESSED_DTTM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: true } ], MPE_FILTERSOURCE: [ { name: 'FILTER_HASH', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'FILTER_LINE', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'GROUP_LOGIC', type: 'C', length: 3, format: '', label: '', notnull: true }, { name: 'SUBGROUP_LOGIC', type: 'C', length: 3, format: '', label: '', notnull: true }, { name: 'SUBGROUP_ID', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'VARIABLE_NM', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'OPERATOR_NM', type: 'C', length: 12, format: '', label: '', notnull: true }, { name: 'RAW_VALUE', type: 'C', length: 4000, format: '', label: '', notnull: true }, { name: 'PROCESSED_DTTM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: true } ], MPE_GROUPS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'GROUP_NAME', type: 'C', length: 100, format: '', label: '', notnull: true }, { name: 'USER_NAME', type: 'C', length: 50, format: '', label: '', notnull: true }, { name: 'GROUP_DESC', type: 'C', length: 256, format: '', label: '', notnull: false } ], MPE_LINEAGE_COLS: [ { name: 'COL_ID', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'DIRECTION', type: 'C', length: 1, format: '', label: '', notnull: false }, { name: 'SOURCECOLURI', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'MAP_TYPE', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'MAP_TRANSFORM', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'JOBNAME', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'SOURCETABLENAME', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'SOURCECOLNAME', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'TARGETTABLENAME', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'TARGETCOLNAME', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'TARGETCOLURI', type: 'C', length: 256, format: '', label: '', notnull: false }, { name: 'DERIVED_RULE', type: 'C', length: 500, format: '', label: '', notnull: false }, { name: 'LEVEL', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'MODIFIED_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: false }, { name: 'MODIFIED_BY', type: 'C', length: 64, format: '', label: '', notnull: false } ], MPE_LINEAGE_TABS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'JOBID', type: 'C', length: 17, format: '', label: '', notnull: false }, { name: 'SRCTABLEID', type: 'C', length: 17, format: '', label: '', notnull: false }, { name: 'TGTTABLEID', type: 'C', length: 17, format: '', label: '', notnull: false }, { name: 'JOBNAME', type: 'C', length: 128, format: '', label: '', notnull: false }, { name: 'SRCTABLETYPE', type: 'C', length: 16, format: '', label: '', notnull: false }, { name: 'SRCTABLENAME', type: 'C', length: 64, format: '', label: '', notnull: false }, { name: 'SRCLIBREF', type: 'C', length: 8, format: '', label: '', notnull: false }, { name: 'TGTTABLETYPE', type: 'C', length: 16, format: '', label: '', notnull: false }, { name: 'TGTTABLENAME', type: 'C', length: 64, format: '', label: '', notnull: false }, { name: 'TGTLIBREF', type: 'C', length: 8, format: '', label: '', notnull: false }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true } ], MPE_LOADS: [ { name: 'CSV_DIR', type: 'C', length: 255, format: '', label: '', notnull: false }, { name: 'USER_NM', type: 'C', length: 50, format: '', label: '', notnull: false }, { name: 'STATUS', type: 'C', length: 15, format: '', label: '', notnull: false }, { name: 'DURATION', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'PROCESSED_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: false }, { name: 'REASON_TXT', type: 'C', length: 2048, format: '', label: '', notnull: false }, { name: 'APPROVALS', type: 'C', length: 64, format: '', label: '', notnull: false } ], MPE_LOCKANYTABLE: [ { name: 'LOCK_LIB', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'LOCK_DS', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'LOCK_STATUS_CD', type: 'C', length: 10, format: '', label: '', notnull: true }, { name: 'LOCK_USER_NM', type: 'C', length: 100, format: '', label: '', notnull: true }, { name: 'LOCK_REF', type: 'C', length: 200, format: '', label: '', notnull: false }, { name: 'LOCK_PID', type: 'C', length: 10, format: '', label: '', notnull: false }, { name: 'LOCK_START_DTTM', type: 'N', length: 8, format: 'E8601DT26.6', label: '', notnull: false }, { name: 'LOCK_END_DTTM', type: 'N', length: 8, format: 'E8601DT26.6', label: '', notnull: false } ], MPE_MAXKEYVALUES: [ { name: 'KEYTABLE', type: 'C', length: 41, format: '', label: 'Base table in libref.dataset format', notnull: false }, { name: 'KEYCOLUMN', type: 'C', length: 32, format: '$32.', label: 'The Surrogate / Retained key field', notnull: false }, { name: 'MAX_KEY', type: 'N', length: 8, format: '', label: 'Integer value representing current max RK or SK value', notnull: false }, { name: 'PROCESSED_DTTM', type: 'N', length: 8, format: 'E8601DT26.6', label: 'Datetime this value was last updated', notnull: false } ], MPE_REQUESTS: [ { name: 'REQUEST_DTTM', type: 'N', length: 8, format: 'datetime19.', label: '', notnull: true }, { name: 'REQUEST_USER', type: 'C', length: 64, format: '', label: '', notnull: true }, { name: 'REQUEST_SERVICE', type: 'C', length: 64, format: '', label: '', notnull: true }, { name: 'REQUEST_PARAMS', type: 'C', length: 128, format: '', label: '', notnull: false } ], MPE_REVIEW: [ { name: 'TABLE_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'REVIEWED_BY_NM', type: 'C', length: 100, format: '', label: '', notnull: true }, { name: 'BASE_TABLE', type: 'C', length: 41, format: '', label: '', notnull: true }, { name: 'REVIEW_STATUS_ID', type: 'C', length: 10, format: '', label: '', notnull: true }, { name: 'REVIEWED_ON_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'REVIEW_REASON_TXT', type: 'C', length: 400, format: '', label: '', notnull: false } ], MPE_ROW_LEVEL_SECURITY: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'RLS_RK', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'RLS_SCOPE', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'RLS_GROUP', type: 'C', length: 128, format: '', label: '', notnull: true }, { name: 'RLS_LIBREF', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'RLS_TABLE', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'RLS_GROUP_LOGIC', type: 'C', length: 3, format: '', label: '', notnull: true }, { name: 'RLS_SUBGROUP_LOGIC', type: 'C', length: 3, format: '', label: '', notnull: true }, { name: 'RLS_SUBGROUP_ID', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'RLS_VARIABLE_NM', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'RLS_OPERATOR_NM', type: 'C', length: 12, format: '', label: '', notnull: true }, { name: 'RLS_RAW_VALUE', type: 'C', length: 4000, format: '', label: '', notnull: true }, { name: 'RLS_ACTIVE', type: 'N', length: 8, format: '', label: '', notnull: true } ], MPE_SECURITY: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'DSN', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'ACCESS_LEVEL', type: 'C', length: 10, format: '', label: '', notnull: true }, { name: 'SAS_GROUP', type: 'C', length: 100, format: '', label: '', notnull: true } ], MPE_SELECTBOX: [ { name: 'VER_FROM_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'VER_TO_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'SELECTBOX_RK', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'SELECT_LIB', type: 'C', length: 17, format: '', label: '', notnull: true }, { name: 'SELECT_DS', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'BASE_COLUMN', type: 'C', length: 36, format: '', label: '', notnull: true }, { name: 'SELECTBOX_VALUE', type: 'C', length: 500, format: '', label: '', notnull: true }, { name: 'SELECTBOX_ORDER', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'SELECTBOX_TYPE', type: 'C', length: 32, format: '', label: '', notnull: false } ], MPE_SIGNOFFS: [ { name: 'TECH_FROM_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TECH_TO_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'SIGNOFF_TABLE', type: 'C', length: 50, format: '', label: '', notnull: true }, { name: 'SIGNOFF_SECTION_RK', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'SIGNOFF_VERSION_RK', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'SIGNOFF_NAME', type: 'C', length: 100, format: '', label: '', notnull: true } ], MPE_SUBMIT: [ { name: 'TABLE_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'SUBMIT_STATUS_CD', type: 'C', length: 10, format: '', label: '', notnull: true }, { name: 'BASE_LIB', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'BASE_DS', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'SUBMITTED_BY_NM', type: 'C', length: 100, format: '', label: '', notnull: true }, { name: 'SUBMITTED_ON_DTTM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'SUBMITTED_REASON_TXT', type: 'C', length: 400, format: '', label: '', notnull: false }, { name: 'INPUT_OBS', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'INPUT_VARS', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'NUM_OF_APPROVALS_REQUIRED', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'NUM_OF_APPROVALS_REMAINING', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'REVIEWED_BY_NM', type: 'C', length: 100, format: '', label: '', notnull: false }, { name: 'REVIEWED_ON_DTTM', type: 'N', length: 8, format: '', label: '', notnull: false } ], MPE_TABLES: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'LIBREF', type: 'C', length: 8, format: '', label: '', notnull: true }, { name: 'DSN', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'NUM_OF_APPROVALS_REQUIRED', type: 'N', length: 4, format: '', label: '', notnull: false }, { name: 'LOADTYPE', type: 'C', length: 12, format: '', label: '', notnull: false }, { name: 'BUSKEY', type: 'C', length: 1000, format: '', label: '', notnull: false }, { name: 'VAR_TXFROM', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_TXTO', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_BUSFROM', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_BUSTO', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'VAR_PROCESSED', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'CLOSE_VARS', type: 'C', length: 500, format: '', label: '', notnull: false }, { name: 'PRE_EDIT_HOOK', type: 'C', length: 200, format: '', label: '', notnull: false }, { name: 'POST_EDIT_HOOK', type: 'C', length: 200, format: '', label: '', notnull: false }, { name: 'PRE_APPROVE_HOOK', type: 'C', length: 200, format: '', label: '', notnull: false }, { name: 'POST_APPROVE_HOOK', type: 'C', length: 200, format: '', label: '', notnull: false }, { name: 'SIGNOFF_COLS', type: 'C', length: 500, format: '', label: '', notnull: false }, { name: 'SIGNOFF_HOOK', type: 'C', length: 200, format: '', label: '', notnull: false }, { name: 'NOTES', type: 'C', length: 1000, format: '', label: '', notnull: false }, { name: 'RK_UNDERLYING', type: 'C', length: 1000, format: '', label: '', notnull: false }, { name: 'AUDIT_LIBDS', type: 'C', length: 41, format: '', label: '', notnull: false } ], MPE_USERS: [ { name: 'USER_ID', type: 'C', length: 50, format: '', label: '', notnull: true }, { name: 'LAST_SEEN_DT', type: 'N', length: 8, format: 'date9.', label: '', notnull: true }, { name: 'REGISTERED_DT', type: 'N', length: 8, format: 'date9.', label: '', notnull: true } ], MPE_VALIDATIONS: [ { name: 'TX_FROM', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true }, { name: 'BASE_LIB', type: 'C', length: 8, format: '', label: '', notnull: false }, { name: 'BASE_DS', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'BASE_COL', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'RULE_TYPE', type: 'C', length: 32, format: '', label: '', notnull: false }, { name: 'RULE_VALUE', type: 'C', length: 128, format: '', label: '', notnull: false }, { name: 'RULE_ACTIVE', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'TX_TO', type: 'N', length: 8, format: 'datetime19.3', label: '', notnull: true } ], MPE_X_TEST: [ { name: 'PRIMARY_KEY_FIELD', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'SOME_CHAR', type: 'C', length: 32767, format: '', label: 'Some Character Column', notnull: false }, { name: 'SOME_DROPDOWN', type: 'C', length: 128, format: '', label: '', notnull: false }, { name: 'SOME_NUM', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'SOME_DATE', type: 'N', length: 8, format: 'date9.', label: 'Some Date', notnull: false }, { name: 'SOME_DATETIME', type: 'N', length: 8, format: 'datetime19.', label: 'Some Datetime', notnull: false }, { name: 'SOME_TIME', type: 'N', length: 8, format: 'time8.', label: 'Some Time', notnull: false }, { name: 'SOME_SHORTNUM', type: 'N', length: 4, format: '', label: '', notnull: false }, { name: 'SOME_BESTNUM', type: 'N', length: 8, format: 'best.', label: '', notnull: false } ], MPE_X_SEARCH: [ { name: 'PRIMARY_KEY_FIELD', type: 'N', length: 8, format: '', label: 'Primary Key', notnull: true }, { name: 'SITE_NAME', type: 'C', length: 32, format: '', label: 'Survey Site', notnull: false }, { name: 'VESSEL', type: 'C', length: 32, format: '', label: 'Survey Vessel', notnull: false }, { name: 'SAMPLE_COUNT', type: 'N', length: 8, format: '', label: 'Samples Collected', notnull: false }, { name: 'DEPTH_M', type: 'N', length: 8, format: '', label: 'Depth (metres)', notnull: false }, { name: 'SPECIES', type: 'C', length: 32, format: '', label: 'Species Observed', notnull: false }, { name: 'CRUISE_DATE', type: 'N', length: 8, format: 'date9.', label: 'Cruise Date', notnull: false }, { name: 'EXPEDITION_ID', type: 'C', length: 12, format: '', label: 'Expedition', notnull: false }, { name: 'NOTES', type: 'C', length: 512, format: '', label: 'Survey Notes', notnull: false } ], MPE_XLMAP_DATA: [ { name: 'LOAD_REF', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'XLMAP_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'XLMAP_RANGE_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'ROW_NO', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'COL_NO', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'VALUE_TXT', type: 'C', length: 4000, format: '', label: '', notnull: false } ], MPE_XLMAP_INFO: [ { name: 'TX_FROM', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'XLMAP_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'XLMAP_DESCRIPTION', type: 'C', length: 1000, format: '', label: '', notnull: true }, { name: 'XLMAP_TARGETLIBDS', type: 'C', length: 41, format: '', label: '', notnull: true } ], MPE_XLMAP_RULES: [ { name: 'TX_FROM', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'TX_TO', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'XLMAP_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'XLMAP_RANGE_ID', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'XLMAP_SHEET', type: 'C', length: 32, format: '', label: '', notnull: true }, { name: 'XLMAP_START', type: 'C', length: 1000, format: '', label: '', notnull: true }, { name: 'XLMAP_FINISH', type: 'C', length: 1000, format: '', label: '', notnull: false } ], MPE_X_CATALOG: [], MPE_MAXKEYVALUES: [] } // Columns for MPE_X_WIDE - built rather than spelled out, there are 1001. schema.MPE_X_WIDE = [ { name: 'ROW_ID', type: 'N', length: 8, format: '', label: '', notnull: true } ] for (let c = 1; c <= 500; c++) { schema.MPE_X_WIDE.push({ name: 'CHAR' + c, type: 'C', length: 1, format: '', label: '', notnull: false }) } for (let c = 1; c <= 500; c++) { schema.MPE_X_WIDE.push({ name: 'NUM' + c, type: 'N', length: 8, format: '', label: '', notnull: false }) } // ─── TESTDATA library: demo user tables for the Cypress E2E suite ─────────── // These tables hold the DQ-rule demo columns (HARDSELECT, READONLY, HIDDEN, // ROUND, NUMBER_FORMAT, HARDREGEX, SOFTREGEX) and the formula demo columns // (HARDFORMULA, SOFTFORMULA, DC.* references) that the editor specs assert // against. They live in a separate library so DC_JSLIB.MPE_X_TEST keeps // matching the excel upload fixtures (which predate these columns), and so // the editor/openTableFromTree flow exercises a real two-library nav tree // (DC_JSLIB + TESTDATA), the same way a real SAS site is laid out. const testDataLibref = 'TESTDATA' const testDataDir = nodePath.resolve( driveRoot, 'files', appLoc, 'data', testDataLibref ) if (!fs.existsSync(testDataDir)) { fs.mkdirSync(testDataDir, { recursive: true }) } const testTables = { MPE_X_NEW: [ { PRIMARY_KEY_FIELD: 0, SOME_CHAR: 'this is dummy data', SOME_DROPDOWN: 'Option 1', SOME_HARDSELECT: 'Alpha', SOME_NUM: 0.00105564761956, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 42, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 1.142857, NUMFMT_COL: 1000, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' }, { PRIMARY_KEY_FIELD: 1, SOME_CHAR: 'more dummy data', SOME_DROPDOWN: 'Option 2', SOME_HARDSELECT: 'Bravo', SOME_NUM: 0.00521895988156, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 422, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 2.285714, NUMFMT_COL: 1012.5, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' }, { PRIMARY_KEY_FIELD: 2, SOME_CHAR: 'even more dummy data', SOME_DROPDOWN: 'Option 3', SOME_HARDSELECT: 'Charlie', SOME_NUM: 0.0058409725343, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 142, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 3.428571, NUMFMT_COL: 1025, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' }, { PRIMARY_KEY_FIELD: 3, SOME_CHAR: 'It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told: It was a dark and stormy night. The wind was blowing a gale! The captain said to his mate - mate, tell us a tale. And this, is the tale he told:', SOME_DROPDOWN: 'Option 2', SOME_HARDSELECT: 'Alpha', SOME_NUM: 0.00613050395908, SOME_DATE: 423, SOME_DATETIME: 423, SOME_TIME: 44, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 4.571428, NUMFMT_COL: 1037.5, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' }, { PRIMARY_KEY_FIELD: 4, SOME_CHAR: 'if you can fill the unforgiving minute', SOME_DROPDOWN: 'Option 1', SOME_HARDSELECT: 'Bravo', SOME_NUM: 0.01305025071513, SOME_DATE: 4231, SOME_DATETIME: 423123123, SOME_TIME: 412, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 5.714285, NUMFMT_COL: 1050, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' }, { PRIMARY_KEY_FIELD: 5, SOME_CHAR: '= testing the formula situation', SOME_DROPDOWN: 'Option 1', SOME_HARDSELECT: 'Charlie', SOME_NUM: 0.01442142483518, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 42, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 6.857142, NUMFMT_COL: 1062.5, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' }, { PRIMARY_KEY_FIELD: 6, SOME_CHAR: "'=the formula with leading apostrophe", SOME_DROPDOWN: 'Option 1', SOME_HARDSELECT: 'Alpha', SOME_NUM: 0.02422838845487, SOME_DATE: 42, SOME_DATETIME: 42, SOME_TIME: 42, SOME_SHORTNUM: 8, SOME_BESTNUM: 44, READONLY_COL: 'Readonly default', HIDDEN_COL: 'Hidden default', ROUND_COL: 8, NUMFMT_COL: 1075, REGEX_HARD_COL: 'user@example.com', REGEX_SOFT_COL: 'SW1A 1AA', REGEX_BOTH_COL: 'ABC-123' } ], MPE_X_FORMULA_TEST: Array.from({ length: 10 }, (_, i) => ({ _____DELETE__THIS__RECORD_____: 'No', PRIMARY_KEY_FIELD: i + 1, A_COL: i + 1, B_COL: 10, FORMULA_HARD_COL: i === 6 ? '7771' : i === 8 ? '9991' : i === 9 ? '1111' : '', FORMULA_SOFT_COL: i === 7 ? '8882' : i === 8 ? '9992' : i === 9 ? '2222' : '', ROW_STATUS_COL: '', USER_NAME_COL: '', ORIG_VALUE_COL: 'orig-' + (i + 1), CHANGE_SUMMARY_COL: 'orig-' + (i + 1), PLAIN_TEXT_COL: i === 4 ? '=100 + B_COL' : i === 5 ? '=100 + 200' : i === 6 ? "'=genuine literal" : 'note-' + (i + 1) })), MPE_X_FORMULA_PK_TEST: [ { _____DELETE__THIS__RECORD_____: 'No', PK_HARDFORMULA_COL: '', PK_SOFTFORMULA_COL: '', A_COL: 2, B_COL: 3 }, { _____DELETE__THIS__RECORD_____: 'No', PK_HARDFORMULA_COL: '', PK_SOFTFORMULA_COL: '', A_COL: 5, B_COL: 4 } ], // DEMO_01 - compact rule-bearing table, eight columns so it fits a narrow // viewport without horizontal scrolling. Used for demos and clips that need // the rule behaviours visible on one screen. DEMO_01: [ { ID: 1, AMOUNT: 120, SCORE: 82, GRADE: '.a', REF: 1001, RATING: 4, STATUS: 1, LAST_REVIEWED: 23390 }, // One row already carries a special missing, so a demo can show a change // from one special missing to another (the DIFF compares them). { ID: 2, AMOUNT: 95, SCORE: 91, GRADE: '.b', REF: 1002, RATING: '.a', STATUS: 2, LAST_REVIEWED: 23435 }, // STATUS carries the special missing that its own SOFTSELECT dropdown // lists, which is what makes the dropdown worth demonstrating. { ID: 3, AMOUNT: 430, SCORE: 76, GRADE: '.c', REF: 1003, RATING: 3, STATUS: '.a', LAST_REVIEWED: 23466 }, { ID: 4, AMOUNT: 88, SCORE: 88, GRADE: '.a', REF: 1004, RATING: 4, STATUS: 3, LAST_REVIEWED: 23502 }, { ID: 5, AMOUNT: 210, SCORE: 95, GRADE: '.b', REF: 1005, RATING: 5, STATUS: 1, LAST_REVIEWED: 23557 }, { ID: 6, AMOUNT: 65, SCORE: 64, GRADE: '.c', REF: 1006, RATING: 2, STATUS: 3, LAST_REVIEWED: 23561 }, { ID: 7, AMOUNT: 150, SCORE: 73, GRADE: '.a', REF: 1007, RATING: 3, STATUS: 2, LAST_REVIEWED: 23608 }, { ID: 8, AMOUNT: 300, SCORE: 99, GRADE: '.b', REF: 1008, RATING: 5, STATUS: 1, LAST_REVIEWED: 23621 } ], // Hook demo pair: DEMO_MIRROR is an EMPTY mirror of DEMO_ORDERS, registered // with pre/post edit hooks (services/hooks/demo_mirror_*.js). The pre-edit // hook shows the live rows of DEMO_ORDERS; the post-edit hook routes a // changeset submitted against the mirror to DEMO_ORDERS. DEMO_ORDERS: [ { ORDER_ID: 1001, CUSTOMER: 'Acme Corp', REGION: 'EU', AMOUNT: 450, STATUS: 'NEW' }, { ORDER_ID: 1002, CUSTOMER: 'Borealis Ltd', REGION: 'EU', AMOUNT: 980.5, STATUS: 'OPEN' }, { ORDER_ID: 1003, CUSTOMER: 'Cobalt GmbH', REGION: 'EU', AMOUNT: 620, STATUS: 'CLOSED' }, { ORDER_ID: 1004, CUSTOMER: 'Delta Systems', REGION: 'US', AMOUNT: 4500, STATUS: 'NEW' } ], DEMO_MIRROR: [], // Derived variable demo - REGION and LINE_VALUE are not columns of this // table, they are computed at read time from MPE_DERIVED rows. DERIVED_DEMO: [ { ID: 1, STATE: 'CA', QTY: 2, PRICE: 10.5 }, { ID: 2, STATE: 'NY', QTY: 1, PRICE: 99 }, { ID: 3, STATE: 'OR', QTY: 5, PRICE: 3 }, { ID: 4, STATE: 'TX', QTY: 3, PRICE: 7.25 } ] } // Schemas for the TESTDATA tables, matching the old inline getdata.js payload // that the Cypress editor specs were calibrated against. const testSchema = { // Hook demo pair (see DEMO_ORDERS / DEMO_MIRROR in testTables). The mirror // has the same shape as the real table, so the pre-edit hook can hand its rows // straight to the grid. DEMO_ORDERS: [ { name: 'ORDER_ID', type: 'N', length: 8, format: '', label: 'Order Id', notnull: true }, { name: 'CUSTOMER', type: 'C', length: 20, format: '', label: 'Customer', notnull: false }, { name: 'REGION', type: 'C', length: 8, format: '', label: 'Region', notnull: false }, { name: 'AMOUNT', type: 'N', length: 8, format: '', label: 'Amount', notnull: false }, { name: 'STATUS', type: 'C', length: 12, format: '', label: 'Status', notnull: false } ], DEMO_MIRROR: [ { name: 'ORDER_ID', type: 'N', length: 8, format: '', label: 'Order Id', notnull: true }, { name: 'CUSTOMER', type: 'C', length: 20, format: '', label: 'Customer', notnull: false }, { name: 'REGION', type: 'C', length: 8, format: '', label: 'Region', notnull: false }, { name: 'AMOUNT', type: 'N', length: 8, format: '', label: 'Amount', notnull: false }, { name: 'STATUS', type: 'C', length: 12, format: '', label: 'Status', notnull: false } ], MPE_X_NEW: [ { name: 'PRIMARY_KEY_FIELD', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'SOME_CHAR', type: 'C', length: 32767, format: '', label: 'Some Character Column', notnull: false }, { name: 'SOME_DROPDOWN', type: 'C', length: 128, format: '', label: 'SOME_DROPDOWN', notnull: false }, { name: 'SOME_HARDSELECT', type: 'C', length: 128, format: '', label: 'SOME_HARDSELECT', notnull: false }, { name: 'SOME_NUM', type: 'N', length: 8, format: '', label: '', notnull: false }, { name: 'SOME_DATE', type: 'N', length: 8, format: 'date9.', label: 'Some Date', notnull: false }, { name: 'SOME_DATETIME', type: 'N', length: 8, format: 'datetime19.', label: 'SOME_DATETIME', notnull: false }, { name: 'SOME_TIME', type: 'N', length: 8, format: 'time8.', label: 'SOME_TIME', notnull: false }, { name: 'SOME_SHORTNUM', type: 'N', length: 4, format: '', label: 'SOME_SHORTNUM', notnull: false }, { name: 'SOME_BESTNUM', type: 'N', length: 8, format: 'best.', label: 'SOME_BESTNUM', notnull: false }, { name: 'READONLY_COL', type: 'C', length: 200, format: '', label: 'READONLY_COL', notnull: false }, { name: 'HIDDEN_COL', type: 'C', length: 200, format: '', label: 'HIDDEN_COL', notnull: false }, { name: 'ROUND_COL', type: 'N', length: 8, format: '', label: 'ROUND_COL', notnull: false }, { name: 'NUMFMT_COL', type: 'N', length: 8, format: '', label: 'NUMFMT_COL', notnull: false }, { name: 'REGEX_HARD_COL', type: 'C', length: 128, format: '', label: 'REGEX_HARD_COL', notnull: false }, { name: 'REGEX_SOFT_COL', type: 'C', length: 128, format: '', label: 'REGEX_SOFT_COL', notnull: false }, { name: 'REGEX_BOTH_COL', type: 'C', length: 128, format: '', label: 'REGEX_BOTH_COL', notnull: false } ], MPE_X_FORMULA_TEST: [ { name: 'PRIMARY_KEY_FIELD', type: 'N', length: 8, format: '', label: '', notnull: true }, { name: 'A_COL', type: 'N', length: 8, format: '', label: 'A_COL', notnull: false }, { name: 'B_COL', type: 'N', length: 8, format: '', label: 'B_COL', notnull: false }, { name: 'FORMULA_HARD_COL', type: 'C', length: 128, format: '', label: 'FORMULA_HARD_COL', notnull: false }, { name: 'FORMULA_SOFT_COL', type: 'C', length: 128, format: '', label: 'FORMULA_SOFT_COL', notnull: false }, { name: 'ROW_STATUS_COL', type: 'C', length: 128, format: '', label: 'ROW_STATUS_COL', notnull: false }, { name: 'USER_NAME_COL', type: 'C', length: 128, format: '', label: 'USER_NAME_COL', notnull: false }, { name: 'ORIG_VALUE_COL', type: 'C', length: 128, format: '', label: 'ORIG_VALUE_COL', notnull: false }, { name: 'CHANGE_SUMMARY_COL', type: 'C', length: 128, format: '', label: 'CHANGE_SUMMARY_COL', notnull: false }, { name: 'PLAIN_TEXT_COL', type: 'C', length: 128, format: '', label: 'PLAIN_TEXT_COL', notnull: false } ], MPE_X_FORMULA_PK_TEST: [ { name: 'PK_HARDFORMULA_COL', type: 'N', length: 8, format: '', label: 'PK_HARDFORMULA_COL', notnull: true }, { name: 'PK_SOFTFORMULA_COL', type: 'C', length: 128, format: '', label: 'PK_SOFTFORMULA_COL', notnull: true }, { name: 'A_COL', type: 'N', length: 8, format: '', label: 'A_COL', notnull: false }, { name: 'B_COL', type: 'N', length: 8, format: '', label: 'B_COL', notnull: false } ], DEMO_01: [ { name: 'ID', type: 'N', length: 8, format: '', label: 'ID', notnull: true }, { name: 'AMOUNT', type: 'N', length: 8, format: '', label: 'Amount', notnull: false }, { name: 'SCORE', type: 'N', length: 8, format: '', label: 'Score', notnull: false }, { name: 'GRADE', type: 'N', length: 8, format: '', label: 'Grade', notnull: false }, { name: 'REF', type: 'N', length: 8, format: '', label: 'Reference', notnull: false }, { name: 'RATING', type: 'N', length: 8, format: '', label: 'Rating', notnull: false }, { name: 'STATUS', type: 'N', length: 8, format: '', label: 'Status', notnull: false }, { name: 'LAST_REVIEWED', type: 'N', length: 8, format: 'date9.', label: 'Last reviewed', notnull: false } ], DERIVED_DEMO: [ { name: 'ID', type: 'N', length: 8, format: '', label: 'ID', notnull: true }, { name: 'STATE', type: 'C', length: 2, format: '', label: 'State', notnull: false }, { name: 'QTY', type: 'N', length: 8, format: '', label: 'Quantity', notnull: false }, { name: 'PRICE', type: 'N', length: 8, format: 'dollar12.2', label: 'Price', notnull: false } ] } // Register the TESTDATA tables in MPE_TABLES and add their DQ rules to // MPE_VALIDATIONS, the same way mpe_makedata.sas configures a real site. // The tests open these tables from the nav tree and edit/submit them, so // they need MPE_TABLES registrations (buskey, loadtype) to be editable. tables.MPE_TABLES.push( { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'MPE_X_NEW', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'PRIMARY_KEY_FIELD', notes: 'DQ rule demo table' }, { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'MPE_X_FORMULA_TEST', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'PRIMARY_KEY_FIELD', notes: 'Formula demo table' }, { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'MPE_X_FORMULA_PK_TEST', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'PK_HARDFORMULA_COL PK_SOFTFORMULA_COL', notes: 'Formula PK demo table' }, { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'DEMO_01', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'ID', notes: 'Compact rule demo table (eight columns)' }, { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'DERIVED_DEMO', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'ID', notes: 'Derived variable demo table' }, { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'DEMO_ORDERS', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'ORDER_ID', notes: 'Hook demo - the real table the mirror points at' }, { tx_from: 0, tx_to: 127490111999, libref: testDataLibref, dsn: 'DEMO_MIRROR', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'ORDER_ID', notes: 'Hook demo - an empty mirror whose hooks show and route DEMO_ORDERS', pre_edit_hook: 'services/hooks/demo_mirror_preedit', post_edit_hook: 'services/hooks/demo_mirror_postedit' } ) // Grant EDIT/APPROVE access on TESTDATA tables to the admin group, mirroring // the AllUsers VIEW + dc-admin EDIT/APPROVE rows that MPE_SECURITY carries // for DC_JSLIB tables. tables.MPE_SECURITY.push( { tx_from: 0, tx_to: 127490111999, libref: '*ALL*', dsn: '*ALL*', access_level: 'EDIT', sas_group: adminGroup }, { tx_from: 0, tx_to: 127490111999, libref: '*ALL*', dsn: '*ALL*', access_level: 'APPROVE', sas_group: adminGroup } ) // DQ rules for the TESTDATA tables. These mirror the dqrules arrays the old // inline getdata.js emitted, which the editor specs assert against. const testValidations = [ // MPE_X_NEW { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'PRIMARY_KEY_FIELD', rule_type: 'NOTNULL', rule_value: '' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'SOME_NUM', rule_type: 'HARDSELECT_HOOK', rule_value: 'services/validations/mpe_x_test.some_num' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'SOME_HARDSELECT', rule_type: 'HARDSELECT', rule_value: '' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'READONLY_COL', rule_type: 'READONLY', rule_value: 'Readonly default' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'HIDDEN_COL', rule_type: 'HIDDEN', rule_value: 'Hidden default' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'ROUND_COL', rule_type: 'ROUND', rule_value: '2' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'NUMFMT_COL', rule_type: 'NUMBER_FORMAT', rule_value: '{"style":"currency","currency":"EUR"}' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'REGEX_HARD_COL', rule_type: 'HARDREGEX', rule_value: '/[\\w.]+@[\\w]+\\.[a-z]{2,}/' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'REGEX_SOFT_COL', rule_type: 'SOFTREGEX', rule_value: '/[A-Z]{1,2}\\d{1,2}[A-Z]?\\s?\\d[A-Z]{2}/' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'REGEX_BOTH_COL', rule_type: 'HARDREGEX', rule_value: '/^[A-Z0-9_-]+$/' }, { base_lib: testDataLibref, base_ds: 'MPE_X_NEW', base_col: 'REGEX_BOTH_COL', rule_type: 'SOFTREGEX', rule_value: '/^.{5,10}$/' }, // MPE_X_FORMULA_TEST { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'PRIMARY_KEY_FIELD', rule_type: 'NOTNULL', rule_value: '' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'FORMULA_HARD_COL', rule_type: 'HARDFORMULA', rule_value: '=A_COL * B_COL' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'FORMULA_SOFT_COL', rule_type: 'SOFTFORMULA', rule_value: '=A_COL + B_COL' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'ROW_STATUS_COL', rule_type: 'SOFTFORMULA', rule_value: '=DC.ROW_STATUS' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'USER_NAME_COL', rule_type: 'SOFTFORMULA', rule_value: '=DC.USER_NAME' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'ORIG_VALUE_COL', rule_type: 'SOFTFORMULA', rule_value: '=DC.ORIG_VALUE' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_TEST', base_col: 'CHANGE_SUMMARY_COL', rule_type: 'SOFTFORMULA', rule_value: '=IF( DC.ROW_STATUS ="U","unedited", DC.USER_NAME &" changed from "& DC.ORIG_VALUE )' }, // MPE_X_FORMULA_PK_TEST { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_PK_TEST', base_col: 'PK_HARDFORMULA_COL', rule_type: 'HARDFORMULA', rule_value: '=A_COL * B_COL' }, { base_lib: testDataLibref, base_ds: 'MPE_X_FORMULA_PK_TEST', base_col: 'PK_SOFTFORMULA_COL', rule_type: 'SOFTFORMULA', rule_value: '="PK-" & A_COL' }, // DEMO_01 - the compact rule demo table. A rule per column so each behaviour is // visible in isolation: a numeric floor, a numeric ceiling, a floor and a // ceiling expressed in special missings, a pattern on a numeric column, and a // dropdown whose list is taken from the column itself (the library.member.column // form the docs describe) so it can list the special missing that column holds. // ID carries no rule: it is the table's buskey, and Data Controller applies NOT // NULL to a primary key by itself. { base_lib: testDataLibref, base_ds: 'DEMO_01', base_col: 'AMOUNT', rule_type: 'MINVAL', rule_value: '1' }, { base_lib: testDataLibref, base_ds: 'DEMO_01', base_col: 'SCORE', rule_type: 'MAXVAL', rule_value: '100' }, // A range expressed in special missings, so it is the SAS order of the missing // values that decides it: .A is the floor and .C the ceiling, which takes .B // and refuses .D. { base_lib: testDataLibref, base_ds: 'DEMO_01', base_col: 'GRADE', rule_type: 'MINVAL', rule_value: '.A' }, { base_lib: testDataLibref, base_ds: 'DEMO_01', base_col: 'GRADE', rule_type: 'MAXVAL', rule_value: '.C' }, { base_lib: testDataLibref, base_ds: 'DEMO_01', base_col: 'REF', rule_type: 'SOFTREGEX', rule_value: '/^[0-9]+$/' }, { base_lib: testDataLibref, base_ds: 'DEMO_01', base_col: 'STATUS', rule_type: 'SOFTSELECT', rule_value: testDataLibref + '.DEMO_01.STATUS' }, // Hook demo: the mirror carries its OWN rule set, separate from the real // table's - which is the whole point of routing edits through a mirror. { base_lib: testDataLibref, base_ds: 'DEMO_MIRROR', base_col: 'AMOUNT', rule_type: 'MAXVAL', rule_value: '2000' }, { base_lib: testDataLibref, base_ds: 'DEMO_ORDERS', base_col: 'AMOUNT', rule_type: 'MAXVAL', rule_value: '100000' } ] for (const v of testValidations) { tables.MPE_VALIDATIONS.push({ tx_from: 0, tx_to: 127490111999, ...v, rule_active: 1 }) } // Selectbox values for the TESTDATA demo dropdowns (HARDSELECT/SOME_HARDSELECT) const testSelectboxBase = { select_lib: testDataLibref, select_ds: 'MPE_X_NEW', ver_from_dttm: 0, ver_to_dttm: 127490111999 } tables.MPE_SELECTBOX.push( { ...testSelectboxBase, selectbox_rk: 1001, base_column: 'SOME_HARDSELECT', selectbox_value: 'Alpha', selectbox_order: 1 }, { ...testSelectboxBase, selectbox_rk: 1002, base_column: 'SOME_HARDSELECT', selectbox_value: 'Bravo', selectbox_order: 2 }, { ...testSelectboxBase, selectbox_rk: 1003, base_column: 'SOME_HARDSELECT', selectbox_value: 'Charlie', selectbox_order: 3 }, { ...testSelectboxBase, selectbox_rk: 1004, base_column: 'SOME_DROPDOWN', selectbox_value: 'Option 1', selectbox_order: 1 }, { ...testSelectboxBase, selectbox_rk: 1005, base_column: 'SOME_DROPDOWN', selectbox_value: 'Option 2', selectbox_order: 2 }, { ...testSelectboxBase, selectbox_rk: 1006, base_column: 'SOME_DROPDOWN', selectbox_value: 'Option 3', selectbox_order: 3 } ) // Write one JSON file per test table with metadata + rows for (const [tableName, rows] of Object.entries(testTables)) { const tableFile = nodePath.resolve( testDataDir, tableName.toLowerCase() + '.json' ) const tableData = { name: tableName, columns: testSchema[tableName] || [], rows: rows } fs.writeFileSync(tableFile, JSON.stringify(tableData, null, 2)) } console.log('TESTDATA data dir: ' + testDataDir) // ─── DC996664 library: extra libref for the multi-load Cypress E2E fixtures ── // The multi_load_test_1/2.xlsx fixture files have sheet names like // DC996664.MPE_X_TEST, DC996664.MPE_TABLES, DC996664.MPE_VALIDATIONS. // Those libref.table combos must exist in MPE_TABLES (so startupservice // returns them in sasdatasets and the multi-load sheet matcher accepts // them) and have their own data folder (so viewlibs lists the libref). const multiLoadLibref = 'DC996664' const multiLoadDataDir = nodePath.resolve( driveRoot, 'files', appLoc, 'data', multiLoadLibref ) if (!fs.existsSync(multiLoadDataDir)) { fs.mkdirSync(multiLoadDataDir, { recursive: true }) } tables.MPE_TABLES.push( { tx_from: 0, tx_to: 127490111999, libref: multiLoadLibref, dsn: 'MPE_X_TEST', num_of_approvals_required: 1, loadtype: 'UPDATE', buskey: 'PRIMARY_KEY_FIELD', notes: 'Multi-load fixture table' }, { tx_from: 0, tx_to: 127490111999, libref: multiLoadLibref, dsn: 'MPE_TABLES', num_of_approvals_required: 1, loadtype: 'TXTEMPORAL', buskey: 'LIBREF DSN', var_txfrom: 'TX_FROM', var_txto: 'TX_TO', notes: 'Multi-load fixture table' } ) console.log(multiLoadLibref + ' data dir: ' + multiLoadDataDir) // Write one JSON file per table with metadata + rows for (const [tableName, rows] of Object.entries(tables)) { const tableFile = nodePath.resolve(dataDir, tableName.toLowerCase() + '.json') const tableData = { name: tableName, columns: schema[tableName] || [], rows: rows } fs.writeFileSync(tableFile, JSON.stringify(tableData, null, 2)) } // Copy DC_JSLIB table files into DC996664 (same schema/rows) so the // multi-load fixtures can fetch getdata for DC996664.MPE_X_TEST etc. // Must run after the DC_JSLIB write loop above. for (const tableName of ['MPE_X_TEST', 'MPE_TABLES']) { const srcFile = nodePath.resolve(dataDir, tableName.toLowerCase() + '.json') const dstFile = nodePath.resolve( multiLoadDataDir, tableName.toLowerCase() + '.json' ) try { const data = JSON.parse( fs.readFileSync(srcFile, { encoding: 'utf8' }).toString() ) fs.writeFileSync(dstFile, JSON.stringify(data, null, 2)) } catch (err) { console.log( 'Warning: could not copy ' + tableName + ' to ' + multiLoadLibref + ': ' + err.message ) } } console.log('DC data dir: ' + dataDir) console.log('DCLIB: ' + dcLibref) console.log('ADMIN: ' + adminGroup) // Write settings (what the real settings.sas would contain) as a JS module at // services/settings.js, mirroring how makedata.sas writes // services/public/settings.sas on the real backend. Services eval() it to // pick up dc_libref, dc_admin_group, dc_staging_area and dcpath. const settings = { dc_libref: dcLibref, dc_admin_group: adminGroup, dc_staging_area: dataDir + '/dc_staging', dc_macros: dataDir + '/dc_macros', mpelib: dcLibref, dcpath: dataDir } const settingsFile = nodePath.resolve( driveRoot, 'files', appLoc, 'services', 'settings.js' ) // `var` (not const/let) so that eval'ing the file in a service's scope makes // dcSettings visible to the reader, same as the dcMockUtils functions. fs.writeFileSync( settingsFile, 'var dcSettings = ' + JSON.stringify(settings, null, 2) + '\n' ) // Delete makedata from the Drive so the frontend polling detects completion // The frontend checks if makedata.sas is still in appLoc/services/admin/ const makedataFilePath = nodePath.resolve( driveRoot, 'files', appLoc, 'services', 'admin', 'makedata.sas' ) const makedataJsPath = nodePath.resolve( driveRoot, 'files', appLoc, 'services', 'admin', 'makedata.js' ) try { if (fs.existsSync(makedataFilePath)) { fs.unlinkSync(makedataFilePath) console.log('makedata.sas deleted (self-destruct)') } if (fs.existsSync(makedataJsPath)) { fs.unlinkSync(makedataJsPath) console.log('makedata.js deleted (self-destruct)') } } catch (err) { console.log('Warning: could not delete makedata file: ' + err.message) } // Return HTML response (makedata is called as a URL redirect, not via adapter) _webout = `

Data Controller Config

The following items have been successfully configured:

  • Library Location (${dataDir})
  • Table Creation (${dcLibref} library)
  • Data Controller Admin Group (${adminGroup})

Next Steps:

  1. Launch Data Controller
` break } } catch (err) { // mpAbort already wrote and stopped the program; anything else is a refusal // or a failure of the seeding, which the SAS service reports the same way if (err && err.mockAbort) throw err mpAbort(err && err.message ? err.message : String(err), _program) } } catch (err) { // mpAbort has already written the abort response, which is what the client // reads; anything else is a real failure and belongs in the log if (!(err && err.mockAbort)) throw err }