Classes
cs.fnd.date
Created by: Wayne Stewart (Claude Opus 5) (2026-08-14) The Fnd_Date module as a class, so a host can reach it through the class store instead of the method names.
In a host: cs.fnd.date.new().toISO(Current date; Current time) Inside Foundation: cs.date.new().toISO(Current date; Current time)
The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.
Design decisions and assumptions:
- Every function delegates to the Fnd_Date_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk.
- Stateless, so new() is cheap and instances are interchangeable. What little module state there is lives in Storage.Fnd.Date and Fnd.Date.
- Named for what they do rather than transcribing the method names, so Fnd_Date_DateAndTimeToISO becomes toISO and Fnd_Date_ISOtoDate becomes dateFromISO.
- Fnd_Date_Calendar and Fnd_Date_EntryFilter are not here. Both take a pointer to a form object and only mean anything inside a running form, which is not what a class store instance is for.
info
info($infoRequested_t : Text)->$result_t : Text
The module's own labels — "name" and "version".
toISO
toISO($date_d : Date; $time_h : Time)->$result_t : Text
A date alone gives YYYY-MM-DD, a date and time the joined form. A null date with a time gives the time alone; a null date alone gives "".
dateFromISO
dateFromISO($isoDate_t : Text)->$result_d : Date
Reads YYYY-MM-DD and YYYY-MM-DDThh:mm:ss alike. 4D's own Date() will not take the first of those, which is why this is not a wrapper over it.
timeFromISO
timeFromISO($isoDateTime_t : Text)->$result_h : Time
Reads the time out of a stamp, including one carrying milliseconds or a zone suffix. The suffix is dropped rather than applied, so no silent conversion from UTC happens.
localTimestamp
localTimestamp()->$result_t : Text
Local wall-clock time, YYYY-MM-DDThh:mm:ss.mmm, with no zone suffix. Comparable with other stamps from here, not with a UTC one.
fromParts
fromParts($year_i : Integer; $month_i : Integer; $day_i : Integer)->$result_d : Date
Out of range parts roll over rather than being refused: month 13 is January of the next year, day 0 the last day of the previous month.
fromString
fromString($theDate_t : Text; $dateFormat_t : Text)->$result_d : Date
Unlike fromParts, this refuses a month above 12 or a day above 31, and gives the null date instead. Pass a format such as "D/M/Y" to read the string as something other than the machine's own setting.
toString
toString($theDate_t : Date; $relativeTo_d : Date; $dateFormat_t : Text)->$result_t : Text
"Today", "Tomorrow" or "Yesterday" where they apply, localized; the null date gives "". Everything else is formatted to the given format.
endOfMonth
endOfMonth($theDate_d : Date)->$result_d : Date
The last day of the month the date falls in.
monthName
monthName($monthNumber_i : Integer)->$result_t : Text
Localized. Anything outside 1 to 12 gives "Error".
systemDateFormat
systemDateFormat()->$result_t : Text
"M/D/Y" or "D/M/Y" and so on, for the machine this is running on.
roundTime
roundTime($theTime_h : Time; $option_h : Time)->$result_h : Time
No option, or 1, rounds to the nearest quarter hour; 2 rounds down.
roundTimeDown
roundTimeDown($theTime_h : Time)->$result_h : Time
Down to the quarter hour, however close the next one is.
roundTimeNear
roundTimeNear($theTime_h : Time)->$result_h : Time
The quarter is held for ten minutes past it before the next is reached, and the last five minutes of the day give 23:59 rather than midnight.
cs.fnd.fnd
info
info($infoRequested_t : Text)->$result_t : Text
The component's own labels — "name" and "version". Anything else answers "Component Did Not Recognize Request".
getCurrentTable
getCurrentTable->$result_ptr : Pointer
The table this instance was told to work on, or Null if it was never set.
setCurrentTable
setCurrentTable($table_ptr : Pointer)->$result_ptr : Pointer
Records the table to work on, and returns it.
getCurrentFormType
getCurrentFormType->$result_i : Integer
The form type this instance was told to work on. Fnd_Gen_NoForm when none.
setComponentInfo
setComponentInfo($key_t : Text; $value_t : Text)->$result_t : Text
Publishes one label for another component to read. The store lives on the Form object, so this only works while a form is loaded.
getComponentInfo
getComponentInfo($key_t : Text)->$result_t : Text
Reads back a label another component published. Empty when there is none, or when no form is loaded.
componentCheck
componentCheck($calling_t : Text; $required_t : Text)->$result_b : Boolean
True when the required component answers. False alerts the developer first, and does not stop the caller — test the result and decide.
cs.fnd.Fnd_PrefEntity
Created by: Wayne Stewart, Created: 2026-04-28 Entity extension for the [Fnd_Pref] dataclass.
Adds typed value access on top of the (Type, Value) column pair. Value is stored as text; Type records the original 4D type so it can be decoded on read. Supported types: Is text, Is longint, Is real, Is boolean, Is object.
typedValue
typedValue() : Variant
setTypedValue
setTypedValue($value : Variant)
Encodes $value into (Type, Value) on this entity. Caller saves. Numerics stored as plain text. Booleans stored as "true" / "false". Objects stored as pretty-printed JSON.
cs.fnd.log
Created by WBS, 2026-09-12 (FND-26) Logging access for hosts: cs.fnd.log.new(). No shared singleton syntax. Delegates to methods; enabled/selection remain in the calling process. A future 21 singleton can use the same functions without sharing process state.
enable
enable($enabled_b : Boolean)->$result_b : Boolean
Read or set the current process enable flag.
config
config($options_o : Object)->$result_o : Object
Read or update application defaults; declared logs keep their settings.
declareLog
declareLog($label_t : Text; $file_t : Text; $folder_t : Text; $options_o : Object; $dedicated_b : Boolean)
Declare once; optional dedicated writer defaults to False.
useLog
useLog($label_t : Text)
Empty/omitted selects default; does not alter enable state.
label
label()->$result_t : Text
Current process log label.
overrideLevel
overrideLevel($level_i : Integer; $application_b : Boolean)->$result_i : Integer
No arguments reads effective threshold. Optional True sets application scope.
addEntry
addEntry($message_v : Variant; $options_o : Object)
Text or a collection of text columns, plus optional entry metadata.
flush
flush($label_t : Text)
Queue a flush; no completion acknowledgement.
closeLog
closeLog($label_t : Text)
Flush and close a label, or all logs when omitted.
createTable
createTable()->$result_o : Object
Explicit only; interpreted host required. Inspect restartRequired.
shutdown
shutdown()
Call after producers finish, outside a logger worker.
extension
extension($value_t : Text)->$result_t : Text
Omit to read; pass text to update through Fnd_Log_Extension.
fileName
fileName($value_t : Text)->$result_t : Text
Omit to read; pass text to update through Fnd_Log_FileName.
path
path($value_t : Text)->$result_t : Text
Omit to read; pass text to update through Fnd_Log_Path.
maximumSize
maximumSize($bytes_i : Integer)->$result_i : Integer
Get/set rollover size; zero disables rollover.
info
info($request_t : Text)->$result_t : Text
Existing module name/version/logging query API.
cs.fnd.pref
Created by: Wayne Stewart (Claude Opus 5) (2026-08-14) The Fnd_Pref module as a class, so a host can reach it through the class store instead of the method names.
In a host: cs.fnd.pref.new().getText("Report: Last Folder"; "")
Inside Foundation: cs.pref.new().getText("Report: Last Folder"; "")
The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.
Not to be confused with cs.Fnd_Pref, which is the DataClass extension for the [Fnd_Pref] table and belongs to the host that owns the table. This one is the module's API and belongs to the component.
Design decisions and assumptions:
- Every function delegates to the Fnd_Pref_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk.
- Stateless, so new() is cheap and instances are interchangeable. Module state lives in Storage.Fnd.Pref, shared by both routes.
- getWindow is the one place the shape changes rather than passing through. The method writes through four pointers, which is not something to publish on a modern API, so this returns {left; top; right; bottom} - or Null when nothing is stored, which the pointer form signals by leaving the caller's variables alone.
- The scope argument is a constant or a label, the same Variant the methods take. On a getter it only says where to store a default it has to create; on remove it says where to delete from. See the method headers.
- 4D 20 LTS has no singletons, so a host instantiates: cs.fnd.pref.new(). From 21 a shared singleton would allow cs.fnd.pref.me, and the functions below would not change.
info
info($infoRequested_t : Text)->$result_t : Text
The module's own labels — "name" and "version".
path
path()->$result_t : Text
Where the local preferences file is, or would be.
userName
userName($name_t : Text)->$result_t : Text
The name the server preferences are owned by. Setting it reloads.
save
save()
Writes the local file and the user's server preferences. Called on quit.
getText
getText($name_t : Text; $default_t : Text; $scope_v : Variant)->$result_t : Text
The stored text, or the default. Passing a default stores it when the preference does not exist yet; the scope says where.
getBoolean
getBoolean($name_t : Text; $default_b : Boolean; $scope_v : Variant)->$result_b : Boolean
As getText, for a Boolean.
getLongInt
getLongInt($name_t : Text; $default_i : Integer; $scope_v : Variant)->$result_i : Integer
As getText, for an Integer.
getReal
getReal($name_t : Text; $default_r : Real; $scope_v : Variant)->$result_r : Real
As getText, for a Real.
getObject
getObject($name_t : Text; $default_o : Object; $scope_v : Variant)->$result_o : Object
As getText, for an Object.
getWindow
getWindow($name_t : Text)->$result_o : Object
The stored rectangle as {left; top; right; bottom}, or Null when there is none. Fnd_Pref_GetWindow signals that by leaving the caller's variables untouched, so the four are seeded with something no window could hold and the result is Null if the seed survived.
setText
setText($name_t : Text; $value_t : Text; $scope_v : Variant)
Stores the value. The scope decides local or server; the default is the module's, see the method header.
setBoolean
setBoolean($name_t : Text; $value_b : Boolean; $scope_v : Variant)
As setText, for a Boolean.
setLongInt
setLongInt($name_t : Text; $value_i : Integer; $scope_v : Variant)
As setText, for an Integer.
setReal
setReal($name_t : Text; $value_r : Real; $scope_v : Variant)
As setText, for a Real.
setObject
setObject($name_t : Text; $value_o : Object; $scope_v : Variant)
As setText, for an Object.
setWindow
setWindow($name_t : Text; $rect_o : Object)
Pass {left; top; right; bottom}, or nothing for the frontmost window of the current process.
remove
remove($name_t : Text; $scope_v : Variant)->$result_b : Boolean
True if there was one to delete. The scope says where to delete from.
cs.fnd.pswd
Created by: Wayne Stewart (Claude Opus 5) (2026-08-14) The Fnd_Pswd module as a class, so a host can reach it through the class store instead of the method names.
In a host: cs.fnd.pswd.new().generate({length: 16})
Inside Foundation: cs.pswd.new().generate({length: 16})
The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.
Design decisions and assumptions:
- Every function delegates to the Fnd_Pswd_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk.
- Stateless, so new() is cheap and instances are interchangeable. Module state lives in Storage.Fnd.Pswd, shared by both routes.
- generate() taking an options object is the one to reach for: it touches no shared state, so it is safe from a worker and from two processes at once. The setters below change the stored defaults and are not.
- 4D 20 LTS has no singletons, so a host instantiates: cs.fnd.pswd.new(). From 21 a shared singleton would allow cs.fnd.pswd.me, and the functions below would not change.
info
info($infoRequested_t : Text)->$result_t : Text
The module's own labels — "name" and "version".
generate
generate($options_o : Object)->$result_t : Text
Pass nothing for the stored settings, or an object to override them for this call only: {type; length; minLength; maxLength; useUppercase; useLowercase; useNumbers; useSymbols; customCharacters; excludedCharacters; requireEachClass}
validCharacters
validCharacters($options_o : Object)->$result_t : Text
The alphabet a generation would draw from, under the same options.
strength
strength($password_t : Text; $options_o : Object)->$result_o : Object
{ length ; poolSize ; bits ; rating }. Pass {type} when it is known, or a pronounceable password is weighed on its characters and overstated.
dialog
dialog()->$result_t : Text
Shows the generator dialog. Returns "" if it was cancelled.
useUppercase
useUppercase($use_b : Boolean)->$result_b : Boolean
Reads the stored default, or sets it when passed a value.
useLowercase
useLowercase($use_b : Boolean)->$result_b : Boolean
Reads the stored default, or sets it when passed a value.
useNumbers
useNumbers($use_b : Boolean)->$result_b : Boolean
Reads the stored default, or sets it when passed a value.
useSymbols
useSymbols($use_b : Boolean)->$result_b : Boolean
Reads the stored default, or sets it when passed a value.
customCharacters
customCharacters($characters_t : Text)->$result_t : Text
Setting characters turns the custom set on; setting none turns it off.
excludeCharacters
excludeCharacters($characters_t : Text)->$result_t : Text
Matched exactly, so excluding "o" leaves "O" alone.
minLength
minLength($characters_i : Integer; $limit_i : Integer)->$result_i : Integer
Carries the maximum up with it rather than leaving the pair inverted.
maxLength
maxLength($characters_i : Integer; $limit_i : Integer)->$result_i : Integer
Carries the minimum down with it, the mirror of minLength.
cs.fnd.text
Created by: Wayne Stewart (Claude Opus 5) (2026-08-13) WBS, 2026-09-12 - Expose existing whitespace trim through the class. The Fnd_Text module as a class, so a host can reach it through the class store instead of the method names.
In a host: cs.fnd.text.new().capitalize("hello world")
Inside Foundation: cs.text.new().capitalize("hello world")
The namespace is the "Component namespace in the class store" setting, which is "fnd" here. It governs how the host sees these classes; inside the component they are plain cs.<name>.
Design decisions and assumptions:
- Every function delegates to the Fnd_Text_ method of the same behaviour. The methods remain the implementation, so the class cannot drift from them and adds no behavioural risk. The direction can invert later, one function at a time, without either API changing.
- Stateless, so new() is cheap and instances are interchangeable. Module state lives in Storage.Fnd.Text, shared by both routes.
- 4D 20 LTS has no singletons, so a host instantiates: cs.fnd.text.new(). From 21 a shared singleton would allow cs.fnd.text.me, and the functions below would not change.
- Named for what they do rather than transcribing the method names, so Fnd_Text_TextToMD5 becomes toMD5 and Fnd_Text_Base64ToText becomes fromBase64.
info
info($infoRequested_t : Text)->$result_t : Text
The module's own labels — "name" and "version".
capitalize
capitalize($theText_t : Text; $options_i : Integer)->$result_t : Text
Book title capitalisation. Option 4 skips the exclude word list.
capitalizeExclude
capitalizeExclude($words_c : Collection)->$result_c : Collection
Pass a collection to replace the exclude word list, or nothing to read it.
padSpaces
padSpaces($theText_t : Text; $length_i : Integer)->$result_t : Text
Pads with spaces, or truncates, to exactly $length_i characters.
stripSpaces
stripSpaces($theText_t : Text; $options_i : Integer; $altSpaces_t : Text)->$result_t : Text
1 leading, 2 trailing, 4 doubles, added together. Default is 1+2.
trim
trim($theText_t : Text)->$result_t : Text
Trim both ends using Fnd_Text_Trim's whitespace set; preserve NBSP.
wrap
wrap($theText_t : Text; $lineLength_i : Integer)->$result_t : Text
Wraps at the last space before the limit, joined by carriage returns.
equalStrings
equalStrings($stringOne_t : Text; $stringTwo_t : Text)->$result_b : Boolean
Case and diacritic sensitive, unlike 4D's = operator.
formatNumber
formatNumber($theNumber_t : Text; $theFormat_t : Text)->$result_t : Text
Strips punctuation from the number, then applies the 4D number format.
toMD5
toMD5($theText_t : Text; $charset_t : Text)->$result_t : Text
Defaults to ISO-8859-1, which is what Foundation has always hashed.
md5Encoding
md5Encoding($charset_t : Text)->$result_t : Text
Sets the charset every later toMD5 uses, or reads it when passed nothing.
toBase64
toBase64($theText_t : Text)->$result_t : Text
Base64 on one line: BASE64 ENCODE does not wrap at 76 characters.
fromBase64
fromBase64($theText_t : Text)->$result_t : Text
The reverse of toBase64.
encodeBase64
encodeBase64($theBlob_x : Blob)->$result_x : Blob
Takes and returns a blob, rather than the pointer the method wants.
decodeBase64
decodeBase64($theBlob_x : Blob)->$result_x : Blob
Takes and returns a blob, rather than the pointer the method wants.