<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>question Any fancy method to wrap code in such a way you can use same syntax for both client/server script in Community Central forum</title>
    <link>https://www.servicenow.com/community/community-central-forum/any-fancy-method-to-wrap-code-in-such-a-way-you-can-use-same/m-p/3582128#M7608</link>
    <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any fancy method to wrap code in such a way you can use same syntax for both client/server script&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;First of all you may ask why..&amp;nbsp;&lt;/P&gt;&lt;P&gt;Known limitations of the below:&lt;/P&gt;&lt;H3&gt;Important limitations&lt;/H3&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;What you want Possible with identical syntax? Notes &lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;Basic props (ID, name, first/last, hasRole)&lt;/TD&gt;&lt;TD&gt;Yes&lt;/TD&gt;&lt;TD&gt;Perfect for the facade&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Email, groups, department, custom fields&lt;/TD&gt;&lt;TD&gt;No&lt;/TD&gt;&lt;TD&gt;Not present on &lt;SPAN&gt;g_user&lt;/SPAN&gt;. You still need GlideAjax or Display BR + &lt;SPAN&gt;g_scratchpad&lt;/SPAN&gt; on client&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;SPAN&gt;hasRoleExactly&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Client only&lt;/TD&gt;&lt;TD&gt;Server has different behaviour around elevated privileges&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Async needs (extra data)&lt;/TD&gt;&lt;TD&gt;Syntax diverges&lt;/TD&gt;&lt;TD&gt;Client becomes promise/callback based&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Security-critical checks&lt;/TD&gt;&lt;TD&gt;Prefer server only&lt;/TD&gt;&lt;TD&gt;Client checks are easily bypassed&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I recognize there may be some limitations but..&lt;/P&gt;&lt;P&gt;see below&amp;nbsp;&lt;/P&gt;&lt;P&gt;--------------------&lt;/P&gt;&lt;H3&gt;Main User-Related Equivalents&lt;/H3&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;Purpose / Functionality Server-side (gs) Client-side Notes &lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;Current user sys_id&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUserID()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.userID&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact match&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Username (login name)&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUserName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.userName&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;First name&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getFirstName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.firstName&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Last name&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getLastName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.lastName&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Full / Display name&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUserDisplayName()&lt;/SPAN&gt; or &lt;SPAN&gt;gs.getUser().getFullName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.fullName&lt;/SPAN&gt; (or &lt;SPAN&gt;firstName + ' ' + lastName&lt;/SPAN&gt;)&lt;/TD&gt;&lt;TD&gt;Mostly exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Email&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getEmail()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Not cached in &lt;SPAN&gt;g_user&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Has role&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.hasRole('itil')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.hasRole('itil')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Client version returns &lt;SPAN&gt;true&lt;/SPAN&gt; if user has admin&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Has exact role (ignore admin)&lt;/TD&gt;&lt;TD&gt;—&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.hasRoleExactly('itil')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Client-only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Has any of multiple roles&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.hasRole('itil', 'admin')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.hasRoles('itil', 'admin')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Similar&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Is member of group&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().isMemberOf('Service Desk')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Server only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;List of my groups&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getMyGroups()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Server only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Department / Company / Manager&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getDepartmentID()&lt;/SPAN&gt; (and similar)&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Server only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Any other user field&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getRecord().getValue('title')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt; (or query)&lt;/TD&gt;&lt;TD&gt;Prefer server&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Full user object&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Limited cached properties only&lt;/TD&gt;&lt;TD&gt;Full object is server-only&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;H3&gt;Other Common Pairs&lt;/H3&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;Purpose Server-side Client-side &lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;Info / Log message&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.info()&lt;/SPAN&gt;, &lt;SPAN&gt;gs.log()&lt;/SPAN&gt;, &lt;SPAN&gt;gs.addInfoMessage()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;console.log()&lt;/SPAN&gt;, &lt;SPAN&gt;g_form.addInfoMessage()&lt;/SPAN&gt;, &lt;SPAN&gt;jslog()&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Error message&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.addErrorMessage()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_form.addErrorMessage()&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;System property&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getProperty('name')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Via &lt;SPAN&gt;g_scratchpad&lt;/SPAN&gt; or GlideAjax&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Form field get/set&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;current.field&lt;/SPAN&gt; (GlideRecord)&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_form.getValue()&lt;/SPAN&gt; / &lt;SPAN&gt;g_form.setValue()&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Show/hide field&lt;/TD&gt;&lt;TD&gt;—&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_form.setVisible('field', true/false)&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Make field read-only&lt;/TD&gt;&lt;TD&gt;—&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;g_form.setReadOnly('field', true)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;--------------&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;Important Notes&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;&lt;SPAN&gt;gs&lt;/SPAN&gt; does not exist on the client.&lt;/STRONG&gt; Using it in a Client Script or UI Policy will break the script.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;&lt;SPAN&gt;g_user&lt;/SPAN&gt;&lt;/STRONG&gt; is a lightweight, read-only cached subset of the current user. It is available in Client Scripts, UI Policies, and client UI Actions.&lt;/LI&gt;&lt;LI&gt;Data &lt;STRONG&gt;not&lt;/STRONG&gt; available on the client (email, groups, department, custom fields, system properties, etc.):&lt;UL&gt;&lt;LI&gt;Best option for form load: &lt;STRONG&gt;Display Business Rule&lt;/STRONG&gt; → put values into &lt;SPAN&gt;g_scratchpad.xxx = value;&lt;/SPAN&gt; → read them in an &lt;SPAN&gt;onLoad&lt;/SPAN&gt; Client Script.&lt;/LI&gt;&lt;LI&gt;On-demand: Use &lt;STRONG&gt;GlideAjax&lt;/STRONG&gt; to call a Script Include.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;LI&gt;Always do security / authorization checks on the &lt;STRONG&gt;server&lt;/STRONG&gt;. Client-side checks (&lt;SPAN&gt;g_user.hasRole&lt;/SPAN&gt;, etc.) are for UX only and can be bypassed.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;This covers the common “get user etc.” cases developers mix up most often.&lt;/P&gt;&lt;P&gt;---------&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;**Yes, but only approximately — and only for the overlapping subset of methods.**&lt;/P&gt;&lt;P&gt;There is **no official ServiceNow API** that gives you truly identical executable syntax on both server and client. The two environments are completely separate (server-side Rhino/JS vs browser sandbox), so `gs` is simply undefined on the client and `g_user` is undefined on the server.&lt;/P&gt;&lt;P&gt;### Closest practical solution: Thin facade / wrapper&lt;/P&gt;&lt;P&gt;You create a small utility object (or set of functions) that presents the **same method names** in both environments. Your business logic then calls the wrapper with nearly identical syntax.&lt;/P&gt;&lt;P&gt;#### Example – `UserUtil` pattern&lt;/P&gt;&lt;P&gt;**Server-side** (put this in a Script Include):&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;var UserUtil = Class.create();&lt;BR /&gt;UserUtil.prototype = {&lt;BR /&gt;getID: function() {&lt;BR /&gt;return gs.getUserID();&lt;BR /&gt;},&lt;BR /&gt;getUserName: function() {&lt;BR /&gt;return gs.getUserName();&lt;BR /&gt;},&lt;BR /&gt;getFirstName: function() {&lt;BR /&gt;return gs.getUser().getFirstName();&lt;BR /&gt;},&lt;BR /&gt;getLastName: function() {&lt;BR /&gt;return gs.getUser().getLastName();&lt;BR /&gt;},&lt;BR /&gt;getFullName: function() {&lt;BR /&gt;return gs.getUserDisplayName();&lt;BR /&gt;},&lt;BR /&gt;hasRole: function(role) {&lt;BR /&gt;return gs.hasRole(role);&lt;BR /&gt;},&lt;BR /&gt;// Add more as needed&lt;BR /&gt;type: 'UserUtil'&lt;BR /&gt;};&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;**Client-side** (put the equivalent in a UI Script, or just paste into Client Scripts / UI Policies):&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;var UserUtil = {&lt;BR /&gt;getID: function() {&lt;BR /&gt;return g_user.userID;&lt;BR /&gt;},&lt;BR /&gt;getUserName: function() {&lt;BR /&gt;return g_user.userName;&lt;BR /&gt;},&lt;BR /&gt;getFirstName: function() {&lt;BR /&gt;return g_user.firstName;&lt;BR /&gt;},&lt;BR /&gt;getLastName: function() {&lt;BR /&gt;return g_user.lastName;&lt;BR /&gt;},&lt;BR /&gt;getFullName: function() {&lt;BR /&gt;return g_user.fullName || (g_user.firstName + ' ' + g_user.lastName);&lt;BR /&gt;},&lt;BR /&gt;hasRole: function(role) {&lt;BR /&gt;return g_user.hasRole(role); // note: returns true for admin&lt;BR /&gt;}&lt;BR /&gt;// hasRoleExactly is client-only, so you can add a note or omit it&lt;BR /&gt;};&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;Now your calling code looks almost the same in both places:&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;var userId = UserUtil.getID();&lt;BR /&gt;var name = UserUtil.getUserName();&lt;BR /&gt;if (UserUtil.hasRole('itil')) { ... }&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;### Alternative: Environment-detection helper (for mixed contexts)&lt;/P&gt;&lt;P&gt;Useful in UI Actions (which can run client or server) or shared snippets:&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;function getCurrentUserID() {&lt;BR /&gt;if (typeof gs !== 'undefined' &amp;amp;&amp;amp; gs.getUserID) {&lt;BR /&gt;return gs.getUserID();&lt;BR /&gt;}&lt;BR /&gt;if (typeof g_user !== 'undefined') {&lt;BR /&gt;return g_user.userID;&lt;BR /&gt;}&lt;BR /&gt;return null;&lt;BR /&gt;}&lt;/P&gt;&lt;P&gt;// Same pattern for other methods&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;### Important limitations&lt;/P&gt;&lt;P&gt;| What you want | Possible with identical syntax? | Notes |&lt;BR /&gt;|--------------------------------|----------------------------------|-------|&lt;BR /&gt;| Basic props (ID, name, first/last, hasRole) | Yes | Perfect for the facade |&lt;BR /&gt;| Email, groups, department, custom fields | No | Not present on `g_user`. You still need GlideAjax or Display BR + `g_scratchpad` on client |&lt;BR /&gt;| `hasRoleExactly` | Client only | Server has different behaviour around elevated privileges |&lt;BR /&gt;| Async needs (extra data) | Syntax diverges | Client becomes promise/callback based |&lt;BR /&gt;| Security-critical checks | Prefer server only | Client checks are easily bypassed |&lt;/P&gt;&lt;P&gt;### Recommendation&lt;/P&gt;&lt;P&gt;- For the common “get user ID / name / has role” cases → the thin `UserUtil` facade works well and keeps calling code clean.&lt;BR /&gt;- For anything more (email, group membership, system properties, etc.) → accept that the client path will be different (GlideAjax or pre-load via Display Business Rule).&lt;BR /&gt;- Keep security and data integrity logic on the server; use the client side only for UX.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sat, 01 Aug 2026 05:45:51 GMT</pubDate>
    <dc:creator>EltonA</dc:creator>
    <dc:date>2026-08-01T05:45:51Z</dc:date>
    <item>
      <title>Any fancy method to wrap code in such a way you can use same syntax for both client/server script</title>
      <link>https://www.servicenow.com/community/community-central-forum/any-fancy-method-to-wrap-code-in-such-a-way-you-can-use-same/m-p/3582128#M7608</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Any fancy method to wrap code in such a way you can use same syntax for both client/server script&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;First of all you may ask why..&amp;nbsp;&lt;/P&gt;&lt;P&gt;Known limitations of the below:&lt;/P&gt;&lt;H3&gt;Important limitations&lt;/H3&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;What you want Possible with identical syntax? Notes &lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;Basic props (ID, name, first/last, hasRole)&lt;/TD&gt;&lt;TD&gt;Yes&lt;/TD&gt;&lt;TD&gt;Perfect for the facade&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Email, groups, department, custom fields&lt;/TD&gt;&lt;TD&gt;No&lt;/TD&gt;&lt;TD&gt;Not present on &lt;SPAN&gt;g_user&lt;/SPAN&gt;. You still need GlideAjax or Display BR + &lt;SPAN&gt;g_scratchpad&lt;/SPAN&gt; on client&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;SPAN&gt;hasRoleExactly&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Client only&lt;/TD&gt;&lt;TD&gt;Server has different behaviour around elevated privileges&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Async needs (extra data)&lt;/TD&gt;&lt;TD&gt;Syntax diverges&lt;/TD&gt;&lt;TD&gt;Client becomes promise/callback based&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Security-critical checks&lt;/TD&gt;&lt;TD&gt;Prefer server only&lt;/TD&gt;&lt;TD&gt;Client checks are easily bypassed&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I recognize there may be some limitations but..&lt;/P&gt;&lt;P&gt;see below&amp;nbsp;&lt;/P&gt;&lt;P&gt;--------------------&lt;/P&gt;&lt;H3&gt;Main User-Related Equivalents&lt;/H3&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;Purpose / Functionality Server-side (gs) Client-side Notes &lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;Current user sys_id&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUserID()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.userID&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact match&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Username (login name)&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUserName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.userName&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;First name&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getFirstName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.firstName&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Last name&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getLastName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.lastName&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Full / Display name&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUserDisplayName()&lt;/SPAN&gt; or &lt;SPAN&gt;gs.getUser().getFullName()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.fullName&lt;/SPAN&gt; (or &lt;SPAN&gt;firstName + ' ' + lastName&lt;/SPAN&gt;)&lt;/TD&gt;&lt;TD&gt;Mostly exact&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Email&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getEmail()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Not cached in &lt;SPAN&gt;g_user&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Has role&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.hasRole('itil')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.hasRole('itil')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Client version returns &lt;SPAN&gt;true&lt;/SPAN&gt; if user has admin&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Has exact role (ignore admin)&lt;/TD&gt;&lt;TD&gt;—&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.hasRoleExactly('itil')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Client-only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Has any of multiple roles&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.hasRole('itil', 'admin')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_user.hasRoles('itil', 'admin')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Similar&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Is member of group&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().isMemberOf('Service Desk')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Server only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;List of my groups&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getMyGroups()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Server only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Department / Company / Manager&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getDepartmentID()&lt;/SPAN&gt; (and similar)&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt;&lt;/TD&gt;&lt;TD&gt;Server only&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Any other user field&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser().getRecord().getValue('title')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;STRONG&gt;None&lt;/STRONG&gt; (or query)&lt;/TD&gt;&lt;TD&gt;Prefer server&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Full user object&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getUser()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Limited cached properties only&lt;/TD&gt;&lt;TD&gt;Full object is server-only&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;H3&gt;Other Common Pairs&lt;/H3&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;DIV&gt;Purpose Server-side Client-side &lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;Info / Log message&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.info()&lt;/SPAN&gt;, &lt;SPAN&gt;gs.log()&lt;/SPAN&gt;, &lt;SPAN&gt;gs.addInfoMessage()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;console.log()&lt;/SPAN&gt;, &lt;SPAN&gt;g_form.addInfoMessage()&lt;/SPAN&gt;, &lt;SPAN&gt;jslog()&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Error message&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.addErrorMessage()&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_form.addErrorMessage()&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;System property&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;gs.getProperty('name')&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;Via &lt;SPAN&gt;g_scratchpad&lt;/SPAN&gt; or GlideAjax&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Form field get/set&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;current.field&lt;/SPAN&gt; (GlideRecord)&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_form.getValue()&lt;/SPAN&gt; / &lt;SPAN&gt;g_form.setValue()&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Show/hide field&lt;/TD&gt;&lt;TD&gt;—&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;g_form.setVisible('field', true/false)&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;Make field read-only&lt;/TD&gt;&lt;TD&gt;—&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;g_form.setReadOnly('field', true)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;--------------&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H3&gt;Important Notes&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;STRONG&gt;&lt;SPAN&gt;gs&lt;/SPAN&gt; does not exist on the client.&lt;/STRONG&gt; Using it in a Client Script or UI Policy will break the script.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;&lt;SPAN&gt;g_user&lt;/SPAN&gt;&lt;/STRONG&gt; is a lightweight, read-only cached subset of the current user. It is available in Client Scripts, UI Policies, and client UI Actions.&lt;/LI&gt;&lt;LI&gt;Data &lt;STRONG&gt;not&lt;/STRONG&gt; available on the client (email, groups, department, custom fields, system properties, etc.):&lt;UL&gt;&lt;LI&gt;Best option for form load: &lt;STRONG&gt;Display Business Rule&lt;/STRONG&gt; → put values into &lt;SPAN&gt;g_scratchpad.xxx = value;&lt;/SPAN&gt; → read them in an &lt;SPAN&gt;onLoad&lt;/SPAN&gt; Client Script.&lt;/LI&gt;&lt;LI&gt;On-demand: Use &lt;STRONG&gt;GlideAjax&lt;/STRONG&gt; to call a Script Include.&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;LI&gt;Always do security / authorization checks on the &lt;STRONG&gt;server&lt;/STRONG&gt;. Client-side checks (&lt;SPAN&gt;g_user.hasRole&lt;/SPAN&gt;, etc.) are for UX only and can be bypassed.&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;This covers the common “get user etc.” cases developers mix up most often.&lt;/P&gt;&lt;P&gt;---------&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;**Yes, but only approximately — and only for the overlapping subset of methods.**&lt;/P&gt;&lt;P&gt;There is **no official ServiceNow API** that gives you truly identical executable syntax on both server and client. The two environments are completely separate (server-side Rhino/JS vs browser sandbox), so `gs` is simply undefined on the client and `g_user` is undefined on the server.&lt;/P&gt;&lt;P&gt;### Closest practical solution: Thin facade / wrapper&lt;/P&gt;&lt;P&gt;You create a small utility object (or set of functions) that presents the **same method names** in both environments. Your business logic then calls the wrapper with nearly identical syntax.&lt;/P&gt;&lt;P&gt;#### Example – `UserUtil` pattern&lt;/P&gt;&lt;P&gt;**Server-side** (put this in a Script Include):&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;var UserUtil = Class.create();&lt;BR /&gt;UserUtil.prototype = {&lt;BR /&gt;getID: function() {&lt;BR /&gt;return gs.getUserID();&lt;BR /&gt;},&lt;BR /&gt;getUserName: function() {&lt;BR /&gt;return gs.getUserName();&lt;BR /&gt;},&lt;BR /&gt;getFirstName: function() {&lt;BR /&gt;return gs.getUser().getFirstName();&lt;BR /&gt;},&lt;BR /&gt;getLastName: function() {&lt;BR /&gt;return gs.getUser().getLastName();&lt;BR /&gt;},&lt;BR /&gt;getFullName: function() {&lt;BR /&gt;return gs.getUserDisplayName();&lt;BR /&gt;},&lt;BR /&gt;hasRole: function(role) {&lt;BR /&gt;return gs.hasRole(role);&lt;BR /&gt;},&lt;BR /&gt;// Add more as needed&lt;BR /&gt;type: 'UserUtil'&lt;BR /&gt;};&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;**Client-side** (put the equivalent in a UI Script, or just paste into Client Scripts / UI Policies):&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;var UserUtil = {&lt;BR /&gt;getID: function() {&lt;BR /&gt;return g_user.userID;&lt;BR /&gt;},&lt;BR /&gt;getUserName: function() {&lt;BR /&gt;return g_user.userName;&lt;BR /&gt;},&lt;BR /&gt;getFirstName: function() {&lt;BR /&gt;return g_user.firstName;&lt;BR /&gt;},&lt;BR /&gt;getLastName: function() {&lt;BR /&gt;return g_user.lastName;&lt;BR /&gt;},&lt;BR /&gt;getFullName: function() {&lt;BR /&gt;return g_user.fullName || (g_user.firstName + ' ' + g_user.lastName);&lt;BR /&gt;},&lt;BR /&gt;hasRole: function(role) {&lt;BR /&gt;return g_user.hasRole(role); // note: returns true for admin&lt;BR /&gt;}&lt;BR /&gt;// hasRoleExactly is client-only, so you can add a note or omit it&lt;BR /&gt;};&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;Now your calling code looks almost the same in both places:&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;var userId = UserUtil.getID();&lt;BR /&gt;var name = UserUtil.getUserName();&lt;BR /&gt;if (UserUtil.hasRole('itil')) { ... }&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;### Alternative: Environment-detection helper (for mixed contexts)&lt;/P&gt;&lt;P&gt;Useful in UI Actions (which can run client or server) or shared snippets:&lt;/P&gt;&lt;P&gt;```javascript&lt;BR /&gt;function getCurrentUserID() {&lt;BR /&gt;if (typeof gs !== 'undefined' &amp;amp;&amp;amp; gs.getUserID) {&lt;BR /&gt;return gs.getUserID();&lt;BR /&gt;}&lt;BR /&gt;if (typeof g_user !== 'undefined') {&lt;BR /&gt;return g_user.userID;&lt;BR /&gt;}&lt;BR /&gt;return null;&lt;BR /&gt;}&lt;/P&gt;&lt;P&gt;// Same pattern for other methods&lt;BR /&gt;```&lt;/P&gt;&lt;P&gt;### Important limitations&lt;/P&gt;&lt;P&gt;| What you want | Possible with identical syntax? | Notes |&lt;BR /&gt;|--------------------------------|----------------------------------|-------|&lt;BR /&gt;| Basic props (ID, name, first/last, hasRole) | Yes | Perfect for the facade |&lt;BR /&gt;| Email, groups, department, custom fields | No | Not present on `g_user`. You still need GlideAjax or Display BR + `g_scratchpad` on client |&lt;BR /&gt;| `hasRoleExactly` | Client only | Server has different behaviour around elevated privileges |&lt;BR /&gt;| Async needs (extra data) | Syntax diverges | Client becomes promise/callback based |&lt;BR /&gt;| Security-critical checks | Prefer server only | Client checks are easily bypassed |&lt;/P&gt;&lt;P&gt;### Recommendation&lt;/P&gt;&lt;P&gt;- For the common “get user ID / name / has role” cases → the thin `UserUtil` facade works well and keeps calling code clean.&lt;BR /&gt;- For anything more (email, group membership, system properties, etc.) → accept that the client path will be different (GlideAjax or pre-load via Display Business Rule).&lt;BR /&gt;- Keep security and data integrity logic on the server; use the client side only for UX.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 01 Aug 2026 05:45:51 GMT</pubDate>
      <guid>https://www.servicenow.com/community/community-central-forum/any-fancy-method-to-wrap-code-in-such-a-way-you-can-use-same/m-p/3582128#M7608</guid>
      <dc:creator>EltonA</dc:creator>
      <dc:date>2026-08-01T05:45:51Z</dc:date>
    </item>
    <item>
      <title>Re: Any fancy method to wrap code in such a way you can use same syntax for both client/server scrip</title>
      <link>https://www.servicenow.com/community/community-central-forum/any-fancy-method-to-wrap-code-in-such-a-way-you-can-use-same/m-p/3582130#M7609</link>
      <description>&lt;P&gt;I forgot to mention, so this was more out of curiousity, but there does seem to be a lot to memorize, like a different debug function name for a client versus a server script etc,&amp;nbsp;&lt;/P&gt;&lt;P&gt;I'm assuming people are going to say this method would have so many loopholes it wouldnt be viable, but just curious if there were a more sophisticated solution , that handles the loopholes / known limitations etc&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;Pretty sure this would break something and not be viable for production, but if someone had a modified version of the client or server side classes, e.g. gs but with helper functions with the same name as client scripts style , which call its own functions.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Maybe if ServiceNow themselves would make helper functions to make the exact syntax in client vs server script.. lol , but that would basically nullify a ton of documentations etc, unless..&amp;nbsp; this was a separate helper class entirely and optional to use it, in the same way we can choose (in some cases GlideRecord vs GlideQuery)&lt;/P&gt;</description>
      <pubDate>Sat, 01 Aug 2026 06:36:37 GMT</pubDate>
      <guid>https://www.servicenow.com/community/community-central-forum/any-fancy-method-to-wrap-code-in-such-a-way-you-can-use-same/m-p/3582130#M7609</guid>
      <dc:creator>EltonA</dc:creator>
      <dc:date>2026-08-01T06:36:37Z</dc:date>
    </item>
  </channel>
</rss>

